crystal-pg
crystal-pg copied to clipboard
Strange exception
Can you share the code for your add_db
postgres UDF? Or a simplified version that gives the same crystal error?
I've done a bit more digging, and it seems that the exception is due to the notices raised during function execution. I created two small test functions:
log=# create function foo() returns text as $$ begin raise notice 'hello'; return 'abcde'; end; $$ language plpgsql;
CREATE FUNCTION
log=# select foo();
NOTICE: hello
foo
-------
abcde
(1 row)
log=# create or replace function foo2() returns text as $$ begin return 'abcde'; end; $$ language plpgsql;
CREATE FUNCTION
In a crystal program, 'select foo()' causes the exception whereas 'select foo2()' does not.
I added:
SET client_min_messages=WARNING;
to my function and problem solved.
Happy now !!!
Oh interesting. This is defiantly an edge case I didn't come across when implementing the pg protocol, that should be addressed.
Thanks Will. While you have the hood open, another edge case (due to my stupidity):
require "db"
require "pg"
def blah
uri = URI.new
uri.scheme = "postgres"
uri.user = ENV["PGUSER"]
uri.password = ENV["PGPASSWORD"]?
uri.host = ENV["PGHOST"]?
uri.port = ENV["PGPORT"]?.try &.to_i
uri.path = "/" + ENV["PGDATABASE"]
DB.open uri do |db|
puts "Connected to DB"
db.transaction do |trx|
puts "Transaction started"
trx.connection.query "SELECT 'abc'" do |rset|
trx.commit
end
end
end
end
blah()
It is caused by the commit inside the query block:
[~/git/pg_csvlog]$ crystal t.cr
Connected to DB
Transaction started
Unhandled exception: Expected PQ::Frame::ParseComplete but got PQ::Frame::Unknown(@type='D', @bytes=Bytes[0, 1, 0, 0, 0, 3, 97, 98, 99]) (Exception)
from lib/pg/src/pq/connection.cr:296:7 in 'expect_frame'
from lib/pg/src/pq/connection.cr:294:5 in 'expect_frame'
from lib/pg/src/pg/statement.cr:18:5 in 'perform_query'
from lib/pg/src/pg/statement.cr:35:14 in 'perform_exec'
from lib/db/src/db/statement.cr:97:14 in 'perform_exec_and_release'
from lib/db/src/db/statement.cr:67:7 in 'exec'
from lib/db/src/db/query_methods.cr:263:7 in 'exec'
from lib/db/src/db/connection.cr:98:7 in 'perform_commit_transaction'
from lib/db/src/db/transaction.cr:50:7 in 'commit'
from t.cr:17:9 in 'blah'
from t.cr:23:1 in '__crystal_main'
from /usr/local/Cellar/crystal-lang/0.25.0/src/crystal/main.cr:104:5 in 'main_user_code'
from /usr/local/Cellar/crystal-lang/0.25.0/src/crystal/main.cr:93:7 in 'main'
from /usr/local/Cellar/crystal-lang/0.25.0/src/crystal/main.cr:133:3 in 'main'
that D frame is your data row (1 column, length 3, then ascii 97 for 'a' and so on) but coming at an unexpected time with the block there. This one is probably because the stdlib interface was added a little later.
I'm not 100% sure what is expected to work or not work inside a query block, but it shouldn't be an unexpected frame error, either way.