ODBC initialization issues

I have successfully used ODBC.jl to retrieve data from a PostgreSQL server in the past (on Ubuntu). I’m trying to recreate my setup on Arch Linux, and running into problems when I load the ODBC package. I am using the same odbcinst.ini and odbc.ini files (in /etc), and I have the psqlodbc v9.03.0400-2 and unixodbc v2.3.4-2 Arch packages installed.

julia> using ODBC
ERROR: InitError: ccall: could not find function SQLAllocHandle in library 
 in SQLAllocHandle(::Int16, ::Ptr{Void}, ::Base.RefValue{Ptr{Void}}) at ~/.julia/v0.5/ODBC/src/API.jl:63
during initialization of module ODBC

This is on Julia v0.5.1 and ODBC.jl v0.5.2.

Outside of Julia, I am able to connect to the database and retrieve queries using isql, and my installed drivers show up when I using odbcinst -q -d:

> odbcinst -q -d
[PostgreSQL ANSI]
[PostgreSQL Unicode]

I expect this is a setup error on my end, but I’m not quite sure how to go about fixing it. I’d appreciate any suggestions.

Thanks in advance!

Most likely there’s some problem detecting the correct ODBC shared library. For linux, the library names that are tried are

lib_choices = ["libodbc", "libodbc.so", "libodbc.so.1", "libodbc.so.2", "libodbc.so.3"]

You can check which one is selected by doing

using ODBC
ODBC.API.odbc_dm

If you can tell which library should be getting set (maybe by looking in /usr/lib/), then you can do

ODBC.API.setODBC(libname)

to actually set the library.

When I check ODBC.API.odbc_dm, I get

julia> using ODBC
julia> ODBC.API.odbc_dm
""

So it doesn’t seem to be finding anything. When I look in /usr/lib, I get

> cd /usr/lib
> ls *odbc*
libodbccr.so        libodbcinst.so        libodbc.so        psqlodbcw.so
libodbccr.so.2      libodbcinst.so.2      libodbc.so.2
libodbccr.so.2.0.0  libodbcinst.so.2.0.0  libodbc.so.2.0.0

tdbcodbc1.0.4:
libtdbcodbc1.0.4.so  pkgIndex.tcl  tdbcodbc.tcl

So the library is present. After using ODBC, I tried to set the library manually, using libodbc, libodbc.so and /usr/lib/libodbc.so. I get a warning about redefining constant odbc_dm that I’m not worried about, but if I try ODBC.listdrivers() or ODBC.listdsns(), I get

ERROR: UndefVarError: ENV not defined
 in listdrivers() at ~/.julia/v0.5/ODBC/src/ODBC.jl:72
 in eval_user_input(::Any, ::Base.REPL.REPLBackend) at ./REPL.jl:64
 in macro expansion at ./REPL.jl:95 [inlined]
 in (::Base.REPL.##3#4{Base.REPL.REPLBackend})() at ./event.jl:68

Do you have any other suggestions? Thanks again.

Maybe the library wasn’t present when you first installed the package? Call Pkg.build("ODBC") to run the detection script again.

The library was not present when I installed the package (oops). But rebuilding ODBC doesn’t seem to run the detection script:

julia> Pkg.build("ODBC")
INFO: Building DecFP

Then using ODBC gives me the same errors as above, and ODBC.API.odbc_dm is an empty string.

Some build results will be cached in, for example, the deps/deps.jl file. One easy way to delete those is:

cd ~/.julia/v0.5/ODBC
git clean -f -x

Warning: this will delete any files inside the ODBC package directory which are not committed in git. If you have any new files or local modifications to that package, don’t do this.

After running git clean, you should be able to run Pkg.build("ODBC") in julia and get a clean re-build.

Unfortunately that didn’t work. But for some reason deleting the directory and running Pkg.update() to reinstall it did work. It now detects my drivers and DSNs correctly.

Thanks for the help everyone!

Ah yes, I guess the current form of setODBC isn’t quite enough if you’re actually going to redefine the library, it needs to, rather, be something like

function setODBC(x)
    eval(ODBC.API, :(odbc_dm = $x))
    eval(ODBC, :(ENV = ODBC.ODBCAllocHandle(ODBC.API.SQL_HANDLE_ENV, ODBC.API.SQL_NULL_HANDLE))
end