Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SORRY! This type (NQPMu) does not support associative operations (PosgreSQL) #106

Open
lefth opened this issue Oct 26, 2017 · 4 comments
Open

Comments

@lefth
Copy link

lefth commented Oct 26, 2017

It seems DBIish with Pg does not work across multiple files. I've tested this on Windows 10 and Linux, using the September release of rakudo. The test case is:

Importer.pm6 contains:

use DbConn;

DbConn.pm6 contains:

use DBIish;
DBIish.connect('Pg');

cd to the directory where you put the scripts, and run:

rm -r ./.precomp; perl6 -I. -MImporter -e 'say 5'

In my testing, an old .precomp directory sometimes prevented the various tests from failing.

When I fiddle with the code to get it to work, I often see this error instead:

Missing serialize REPR function for REPR ConditionVariable (Lock::ConditionVariable)

The problems go away when I only use DBIish within a single script. Unfortunately, that's too clumsy to be a usable workaround.

@jonathanstowe
Copy link
Member

jonathanstowe commented Oct 26, 2017

This isn't a problem with DBIish per-se, but rather with what you are asking Rakudo to do here (though I would agree that the error is very far from awesome.)

What is happening with code like this is that the DBIish.connect('Pg'); is being evaluated at compile time and the result being stored (or attermpted to be,) in the serialized bytecode. This is almost certainly not what you want. Rather you probably want to put the connect in a subroutine (or method) that can be called at runtime when you want it. So e.g. Your "Importer.pm" being:

use DbConn;

say buzz;

And the DbConn:

use DBIish;

our sub buzz  {
        DBIish.connect('Pg');
}

Which works Fine:

jns:~/tmp$ perl6 -I. -MImporter -e 'say 5'
(my \DBDish::Pg::Connection_140702392094192 = DBDish::Pg::Connection.new(AutoCommit => Any, in_transaction => Bool::False, Converter => DBDish::TypeConverter.new, dynamic-types => {"1000" => Bool, "1001" => Buf, "1005" => Array[Int], "1007" => Array[Int], "1009" => Array[Str], "1015" => Str, "1021" => Array[Num], "1022" => Array[Num], "1028" => Array[Int], "1042" => Str, "1043" => Str, "1082" => Date, "1083" => Str, "1114" => DateTime, "114" => Str, "1184" => DateTime, "1186" => Duration, "1263" => Array[Str], "142" => Str, "16" => Bool, "17" => Buf, "1700" => Rat, "18" => Str, "19" => Str, "20" => Int, "21" => Int, "23" => Int, "25" => Str, "26" => Str, "2950" => Str, "2951" => Str, "700" => Num, "701" => Num, "705" => Any, "790" => Str}, Statements => {}, last-sth-id => Any, last-rows => Any, parent => DBDish::Pg.new(Version => v0.1.7, Connections => {"DBDish::Pg::Connection|140702392094192" => DBDish::Pg::Connection_140702392094192}, parent => DBDish::ErrorHandling.new(parent => Any, PrintError => Bool, RaiseError => Bool), PrintError => Bool::False, RaiseError => Bool::True), PrintError => Bool, RaiseError => Bool))

@lefth
Copy link
Author

lefth commented Oct 26, 2017

@jonathanstowe Wow, with such a serious explanation, it's a wonder it sometimes works! (And yes, it does sometimes work to define database handles at the top level in a module. I was doing the same thing with MongoDB, and somehow it works. Sometimes.)

So how can this error be improved? Can rakudo catch the error at a higher level and give an error message like what you just told me? (I.e., "Top level variables are serialized at compilation time. [name] serializes as NQPMu, so try defining it at runtime in a function.") Or cut out the details: "Only simpler types are allowed as top-level variables. Could not serialize: [name]".

Obviously I should file this as a feature request in Rakudo, but is that approach/solution reasonable? Because I think we must prevent people from making this mistake if people are to get a good early impression from Perl 6.

@b2gills
Copy link

b2gills commented Oct 27, 2017

It might work if the precompiled form can't be found. That could be the reason it sometimes works.

I think it would work if you wrote INIT DBIish.connect('Pg');

@lefth
Copy link
Author

lefth commented Oct 27, 2017

@b2gills I realized I need a per-thread connection, so it's already become something more sophisticated. Right now I'm more interested in how to make Rakudo's error message better. This seems like it should be a high level complaint, not a low level one.

By the way, this is what the DB handle init code became:

my Lock $db-lock;
INIT {
  $db-lock .= new;
}

# Get a per-thread database connection.
our sub dbh() is export {
  state %connections;
  my $dbh := %connections{$*THREAD.id};
  $db-lock.protect: {
    if !$dbh.defined {
      $dbh = DBIish.connect('Pg', :host<127.0.0.1>, :port(5432), :database<postgres>,
        :user<postgres>, :password<PASSWORD>);
    }
  };
  return $dbh;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants