€200 Bounty: Help me package an odbc driver

Not a traditional job, but a small bounty.
A friend gave me access to his database(Progress OpenEdge) through odbc.
But I’m unable to package it in nix.

I could use some help.

https://discourse.nixos.org/t/packaging-odbc-driver-for-progress

Hi,

Not fully there yet, but I managed to run the command proinst _overly using the following shell.nix:

let
  pkgs = import <nixpkgs> {};
  unixodbc-progress-openedge = pkgs.stdenv.mkDerivation {
    name = "OpenEdge";
    src = ./PROGRESS_OE_12.2_LNX_64_SQLCLIENTACCESS.tar.gz;

    sourceRoot = ".";
    installPhase = ''
      mkdir -p $out/bin

      mv JavaVersion.ini JvmProperties.class common dbtools env-vars icupsc inst_hlp install.tab installd.ini intlsets.txt itermcap juniper namesvr perl pmame progress.cfg proinst proupdt secclnt seccmn sqlcom sqljdbc sqlodbc wscmn $out/bin
      mv _ovrly $out/bin
    '';

    nativeBuildInputs = with pkgs; [
      autoPatchelfHook
    ];
    buildInputs = with pkgs; [
      stdenv.cc.cc.lib
      unzip
    ];
  };
in with pkgs;
  stdenv.mkDerivation {
  name = "project-depending-on-unixODBC-cache";
  buildInputs = [
    unixodbc-progress-openedge
  ];
}

nix-shell shell.nix --command " TERM=xterm proinst _ovrly"

I hope this helps a bit.

I looked at the other archive, it ships a 11MB binary script that tries to figure out your entire system to install its requirement. That looks really difficult to package for nixos …

1 Like

Maybe this route could work.
If I run the installer once and extract the necessary files and add those to my declarative nixos config.

I was able to run it and answer the promps. It placed many files on the system.
I think the relevant folder is:

├── bin
│   └── pgtestlib
├── fixes.txt
├── ICULicense.txt
├── include
│   ├── license.txt
│   ├── odbcinst.h
│   ├── qesqlext.h
│   ├── sqlext.h
│   ├── sql.h
│   ├── sqltypes.h
│   ├── sqlucode.h
│   └── sqlunx.h
├── lib
│   ├── libodbcinst.so
│   ├── libodbc.so
│   ├── libpgicu27.so
│   ├── libpgmback.so
│   ├── libpgssl27.so
│   ├── odbccurs.so
│   ├── pgoe27.so
│   ├── pgtrc27.so
│   └── vscnctdlg.so
├── locale
│   └── en_US
│       └── LC_MESSAGES
│           ├── odbc.m
│           ├── odbc.po
│           ├── pgmback.mo
│           ├── pgmback.po
│           ├── pgoe27.mo
│           └── pgoe27.po
├── NOTICES.TXT
├── ODBC64README.TXT
├── PGODBC.LIC
└── samples
    ├── demo
    │   ├── demoodbc
    │   ├── demoodbc.c
    │   ├── driver_connect
    │   ├── driver_connect.cc
    │   └── Makefile
    └── example
        ├── example
        ├── example64.txt
        ├── example.c
        ├── example.h
        ├── example.mak
        └── odbc.ini

I tried using libodbc.so directly as a driver in an odbc connection,

{:ok,_ref} = :odbc.connect(~c"Driver=/persist/progress/d/odbc/lib/libodbc.so;Server=192.168.1.2;Port=12345;Database=XYZ;Uid=readname;Pwd=pass123",[])

but it didn’t work.

** (MatchError) no match of right hand side value: {:error, ~c"[unixODBC][Driver Manager]Can't open lib '/persist/progress/d/odbc/lib/libodbc.so' : file not found SQLSTATE IS: 01000 Connection to database failed."}

I guess it needs to be packaged and added to unixodbc?

It does build, but I keep getting the same error?

** (MatchError) no match of right hand side value: {:error, ~c"[unixODBC][Driver Manager]Can't open lib '/nix/store/7pw0fjsayfi4m53nf069b17knq8kbm3c-progress-openedge-odbc-driver-12.2/lib/pgoe27.so' : file not found SQLSTATE IS: 01000 Connection to database failed."}
{
  stdenv,
  lib,
  unixODBC,
  openssl,
}:
stdenv.mkDerivation rec {
  pname = "progress-openedge-odbc-driver";
  version = "12.2";
  src = ./progress-odbc.tar.gz;

  # Work around the "unpacker appears to have produced no directories"
  # case that happens when the archive doesn't have a subdirectory.
  sourceRoot = ".";

  installPhase = ''
    runHook preInstall

    mkdir -p $out/lib
    cp -r lib/* $out/lib

    runHook postInstall
  '';

  postFixup = ''
    echo "---postFixup---"
    patchelf --set-rpath ${
      lib.makeLibraryPath [
        unixODBC
        openssl
        stdenv.cc.cc
      ]
    } \
      $out/lib/pgoe27.so
  '';

  passthru = {
    fancyName = "ProgressOpenedgeDriver";
    driver = "lib/pgoe27.so";
  };

  meta = with lib; {
    description = "ODBC driver for Progress OpenEdge";
    homepage = "http://progress.com";
    license = licenses.unfree;
    platforms = platforms.linux;
  };
}
{
  config,
  lib,
  pkgs,
  ...
}:
with lib;
{
  config = {
    environment.systemPackages = with pkgs; [
      unixODBC
      pkgs.lun.progress-openedge-odbc-driver
    ];
    environment.unixODBCDrivers = with pkgs; [
      unixODBCDrivers.psql
      pkgs.lun.progress-openedge-odbc-driver
    ];
  };
}

Assuming the file path named in the ‘file not found’ message does actually exist, it probably needs to be patchelf’d. That’s a frequent cause of mysterious ‘file not found’ messages. I see you’re only patching pgoe27.so; you should probably instead add autoPatchelfHook to the nativeBuildInputs of your derivation, which should seek out and patch all of the libraries in your derivation.

2 Likes

Thank you, I added autoPatchelfhook.
Could add most inputs except for 1.
I think libXm is not in nixpkgs.

       > auto-patchelf: 2 dependencies could not be satisfied
       > error: auto-patchelf could not satisfy dependency libXm.so.3 wanted by /nix/store/4ygggry27pwq9sl7nz9hyi9zdg5a0df6-progress-openedge-odbc-driver-12.2/lib/vscnctdlg.so
       > error: auto-patchelf could not satisfy dependency libXm.so.3 wanted by /nix/store/4ygggry27pwq9sl7nz9hyi9zdg5a0df6-progress-openedge-odbc-driver-12.2/lib/libpgmback.so

for now I removed

    rm $out/lib/vscnctdlg.so
    rm $out/lib/libpgmback.so

It seems they’re not necessary.

I no longer get the ‘not found’ error

I hope this error is because my connection string isn’t according to their standard. I’ll have a look

** (MatchError) no match of right hand side value: {:error, ~c"[DataDirect][ODBC 20101 driver]6015[DataDirect][ODBC 20101 driver]6013 SQLSTATE IS: 60 Connection to database failed."}
    (stdlib 6.1.2) erl_eval.erl:652: :erl_eval.expr/6
    iex:6: (file)

FYI libXm seems to be in motif package.

Bounty was split in 2.

Thank you all.