raku-community-modules / DBIish

Database interface for Raku
89 stars 31 forks source link

DBIish: DBDish::Pg needs 'pq', not found #229

Closed gdonald closed 2 years ago

gdonald commented 2 years ago

I cannot connect to my local Postgres database. I get the error:

DBIish: DBDish::Pg needs 'pq', not found

I cannot find any DBIish documentation for what to install to get 'pq'. I assume it means I need libpq, which I already have:

> brew install libpq
Warning: libpq 14.3 is already installed and up-to-date.
To reinstall 14.3, run:
  brew reinstall libpq

Is there something else I should install?

Thanks.

rbt commented 2 years ago

DBIish uses NativeLibs to perform the library search:

constant LIB = NativeLibs::Searcher.at-runtime('pq', 'PQstatus', 5);

I believe the "5" is the version. What is the full libpq name in your environment?

This is mine (Ubuntu):

rbt:~$ find /usr -name libpq.*
/usr/lib/x86_64-linux-gnu/pkgconfig/libpq.pc
/usr/lib/x86_64-linux-gnu/libpq.so
/usr/lib/x86_64-linux-gnu/libpq.so.5
/usr/lib/x86_64-linux-gnu/libpq.a
/usr/lib/x86_64-linux-gnu/libpq.so.5.14
gdonald commented 2 years ago

This is mine:

> brew list libpq                                                                                                                                               ─╯
/usr/local/Cellar/libpq/14.3/bin/clusterdb
/usr/local/Cellar/libpq/14.3/bin/createdb
/usr/local/Cellar/libpq/14.3/bin/createuser
/usr/local/Cellar/libpq/14.3/bin/dropdb
/usr/local/Cellar/libpq/14.3/bin/dropuser
/usr/local/Cellar/libpq/14.3/bin/ecpg
/usr/local/Cellar/libpq/14.3/bin/initdb
/usr/local/Cellar/libpq/14.3/bin/pg_amcheck
/usr/local/Cellar/libpq/14.3/bin/pg_archivecleanup
/usr/local/Cellar/libpq/14.3/bin/pg_basebackup
/usr/local/Cellar/libpq/14.3/bin/pg_checksums
/usr/local/Cellar/libpq/14.3/bin/pg_config
/usr/local/Cellar/libpq/14.3/bin/pg_controldata
/usr/local/Cellar/libpq/14.3/bin/pg_ctl
/usr/local/Cellar/libpq/14.3/bin/pg_dump
/usr/local/Cellar/libpq/14.3/bin/pg_dumpall
/usr/local/Cellar/libpq/14.3/bin/pg_isready
/usr/local/Cellar/libpq/14.3/bin/pg_receivewal
/usr/local/Cellar/libpq/14.3/bin/pg_recvlogical
/usr/local/Cellar/libpq/14.3/bin/pg_resetwal
/usr/local/Cellar/libpq/14.3/bin/pg_restore
/usr/local/Cellar/libpq/14.3/bin/pg_rewind
/usr/local/Cellar/libpq/14.3/bin/pg_test_fsync
/usr/local/Cellar/libpq/14.3/bin/pg_test_timing
/usr/local/Cellar/libpq/14.3/bin/pg_upgrade
/usr/local/Cellar/libpq/14.3/bin/pg_verifybackup
/usr/local/Cellar/libpq/14.3/bin/pg_waldump
/usr/local/Cellar/libpq/14.3/bin/pgbench
/usr/local/Cellar/libpq/14.3/bin/psql
/usr/local/Cellar/libpq/14.3/bin/reindexdb
/usr/local/Cellar/libpq/14.3/bin/vacuumdb
/usr/local/Cellar/libpq/14.3/include/libpq/libpq-fs.h
/usr/local/Cellar/libpq/14.3/include/postgresql/ (818 files)
/usr/local/Cellar/libpq/14.3/include/ (23 files)
/usr/local/Cellar/libpq/14.3/lib/libecpg.6.14.dylib
/usr/local/Cellar/libpq/14.3/lib/libecpg_compat.3.14.dylib
/usr/local/Cellar/libpq/14.3/lib/libpgtypes.3.14.dylib
/usr/local/Cellar/libpq/14.3/lib/libpq.5.14.dylib
/usr/local/Cellar/libpq/14.3/lib/pkgconfig/ (4 files)
/usr/local/Cellar/libpq/14.3/lib/ (16 other files)
/usr/local/Cellar/libpq/14.3/share/doc/ (1139 files)
/usr/local/Cellar/libpq/14.3/share/man/ (294 files)
/usr/local/Cellar/libpq/14.3/share/postgresql/ (2 files)
rbt commented 2 years ago

I don't have a Mac, so I took some time to setup a Github workflow test using macos-latest, and got something that passes the Pg portions of the tests (SQLite fails).

I think this change to DBIish might fix your issue. NativeLibs uses platform-library-name(), which isn't documented, but I think it tries the specifically provided version strings instead of looking at partial strings. So, since you have libpq.5.14, and not libpq.5, this might do the trick

diff --git a/lib/DBDish/Pg/Native.rakumod b/lib/DBDish/Pg/Native.rakumod
index 0f52599..cf3bd9c 100644
--- a/lib/DBDish/Pg/Native.rakumod
+++ b/lib/DBDish/Pg/Native.rakumod
@@ -5,7 +5,7 @@ use NativeCall;
 use NativeLibs;
 use NativeHelpers::Blob;

-constant LIB = NativeLibs::Searcher.at-runtime('pq', 'PQstatus', 5);
+constant LIB = NativeLibs::Searcher.at-runtime('pq', 'PQstatus', [5, '5.14']);

 #------------ My Visible Types

brew install postgresql has some additional libpq names installed, so it didn't require the above change. If the above patch doesn't work, you might try this package instead.

/usr/local/Cellar/libpq/14.3/lib/libpq.5.dylib
/usr/local/Cellar/libpq/14.3/lib/libpq.5.14.dylib
/usr/local/Cellar/libpq/14.3/lib/libpq.dylib
/usr/local/Cellar/libpq/14.3/lib/libpq.a
gdonald commented 2 years ago

Thanks for the quick response.

I patched my local DBIish as suggested:

> git diff
diff --git a/lib/DBDish/Pg/Native.rakumod b/lib/DBDish/Pg/Native.rakumod
index 0f52599..cbc5f1a 100644
--- a/lib/DBDish/Pg/Native.rakumod
+++ b/lib/DBDish/Pg/Native.rakumod
@@ -5,7 +5,8 @@ use NativeCall;
 use NativeLibs;
 use NativeHelpers::Blob;

-constant LIB = NativeLibs::Searcher.at-runtime('pq', 'PQstatus', 5);
+constant LIB = NativeLibs::Searcher.at-runtime('pq', 'PQstatus', [5, '5.14']);

 #------------ My Visible Types

Then I installed it:

> zef install ./DBIish --/test
===> Searching for missing dependencies: NativeLibs
===> Installing: DBIish:ver<0.6.1>
===> Installing: DBIish:ver<0.6.5>:auth<zef:raku-community-modules>:api<1>

I'm not sure why the 0.6.1 version is also getting installed, I was also getting that installing non-local DBIish.

Seems to be installed:

> zef list --installed | grep ^DBIish
===> Found via /Users/gd/rakudo/share/perl6/site
===> Found via /Users/gd/rakudo/share/perl6/core
DBIish:ver<0.6.1>
DBIish:ver<0.6.5>:auth<zef:raku-community-modules>:api<1>

Then I still get the error:

DBIish: DBDish::Pg needs 'pq', not found

Next I tried brew install postgresql and I end up with the files you listed:

> brew list postgresql | grep libpq
/opt/homebrew/Cellar/postgresql/14.3/lib/postgresql/libpqwalreceiver.so
/opt/homebrew/Cellar/postgresql/14.3/lib/pkgconfig/libpq.pc
/opt/homebrew/Cellar/postgresql/14.3/lib/libpq.5.dylib
/opt/homebrew/Cellar/postgresql/14.3/lib/libpq.5.14.dylib
/opt/homebrew/Cellar/postgresql/14.3/lib/libpq.dylib
/opt/homebrew/Cellar/postgresql/14.3/lib/libpq.a

Unfortunately this did not help either, I still get the same error.

rbt commented 2 years ago

Hrm.

What does this return on your platform? I'm expecting libpq.5.dylib.

say $*VM.platform-library-name('pq'.IO, version => Version.new('5')).Str;

I assume this is either an issue with Raku, or NativeLibs, or a dyld (or how Raku uses it) problem? But I'm not sure which or the best way to debug such a thing.

gdonald commented 2 years ago
> raku
Welcome to Rakudo™ v2022.04.
Implementing the Raku® Programming Language v6.d.
Built on MoarVM version 2022.04.

To exit type 'exit' or '^D'
[0] > $*VM.platform-library-name('pq'.IO, version => Version.new('5')).Str
libpq.5.dylib
rbt commented 2 years ago

This gives me a Block. I think you'll get an exception, though it should find libpq.5.dylib.

use NativeLibs; say NativeLibs::Searcher.at-runtime('pq', 'PQstatus', '5');

Try this one too please, just to ensure we cover everything.

use NativeLibs; say NativeLibs::Searcher.at-runtime('pq', 'PQstatus', '5.14');
gdonald commented 2 years ago
> raku
Welcome to Rakudo™ v2022.04.
Implementing the Raku® Programming Language v6.d.
Built on MoarVM version 2022.04.

To exit type 'exit' or '^D'
[0] > use NativeLibs;
Nil
[1] > NativeLibs::Searcher.at-runtime('pq', 'PQstatus', '5');
->  { #`(Block|5698014690760) ... }
[2] > NativeLibs::Searcher.at-runtime('pq', 'PQstatus', '5.14');
->  { #`(Block|5698014691336) ... }
rbt commented 2 years ago

Hmm. Okay, DBIish overwrites 2 potential errors thrown by NativeLibs with the message you're receiving.

Can you modify handle-library-exception so we can see which one it is?

diff --git a/lib/DBIish.rakumod b/lib/DBIish.rakumod
index 054bf11..0125d0f 100755
--- a/lib/DBIish.rakumod
+++ b/lib/DBIish.rakumod
@@ -83,12 +83,14 @@ method !handle-library-exception($ex, $drivername) {
         ^ "Cannot locate symbol '" <-[ ' ]>* "' in native library "
         ( "'" <-[ ' ]> * "'" )
         / {
+            say $_.message;
             X::DBIish::LibraryMissing.new(:library($/[0]), :driver($drivername)).fail;
         }
         when $_.message ~~ m/
         ^ "Cannot locate native library "
         ( "'" <-[ ' ]> * "'" )
         / {
+            say $_.message;
             X::DBIish::LibraryMissing.new(:library($/[0]), :driver($drivername)).fail;
         }
         default {
gdonald commented 2 years ago

Looks like I'm hitting the second one:

Cannot locate native library 'pq': dlopen(pq, 0x000A): tried: '//Users/gd/rakudo/lib/pq' (no such file), '//Users/gd/rakudo/lib/pq' (no such file), 'pq' (no such file), '/usr/local/lib/pq' (no such file), '/usr/lib/pq' (no such file), '/Users/gd/workspace/raku/ORM-ActiveRecord/pq' (no such file)
DBIish: DBDish::Pg needs 'pq', not found
rbt commented 2 years ago

That seems helpful. The "tried: ..." portion was provided by dlerror() after the dlopen() attempt. So those paths are what the system tried, and it doesn't include the places where libpq was installed.

From the manpage, there are a number of environment variables.

https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlopen.3.html#//apple_ref/doc/man/3/dlopen

Perhaps you need something like this: export DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:/opt/homebrew/Cellar/postgresql/14.3/lib/"

gdonald commented 2 years ago

That got it working. Thanks for all the help.