lib/pg_conn.rb in pg_conn-0.6.1 vs lib/pg_conn.rb in pg_conn-0.7.0
- old
+ new
@@ -47,12 +47,11 @@
# Name of database
def name() @pg_connection.db end
alias_method :database, :name # Obsolete
- # Database manipulation methods: #exist?, #create, #drop, #list. It is
- # named 'rdbms' because #database is already defined
+ # Database manipulation methods: #exist?, #create, #drop, #list
attr_reader :rdbms
# Role manipulation methods: #exist?, #create, #drop, #list
attr_reader :role
@@ -62,10 +61,21 @@
# The transaction timestamp of the most recent SQL statement executed by
# #exec or #transaction block
attr_reader :timestamp
+ # PG::Error object if the last statement failed; otherwise nil
+ attr_reader :err
+
+ # Last error message. The error message is the first line of the PG error
+ # message that may contain additional info. It doesn't contain a
+ # terminating newline
+ def errmsg = err && err.message.sub(/\n.*/m, "")
+
+ # The line number of the last PG::Error. It is not always present
+ def errline() err && err.message =~ /\n\s*LINE\s+(\d+):/m and $1.to_i end
+
# :call-seq:
# initialize(dbname = nil, user = nil, field_name_class: Symbol)
# initialize(connection_hash, field_name_class: Symbol)
# initialize(connection_string, field_name_class: Symbol)
# initialize(host, port, dbname, user, password, field_name_class: Symbol)
@@ -77,24 +87,24 @@
# The possible keys of the connection hash are :host, :port, :dbname, :user,
# and :password. The connection string can either be a space-separated list
# of <key>=<value> pairs with the same keys as the hash, or a URI with the
# format 'postgres[ql]://[user[:password]@][host][:port][/name]
#
- # The :field_name_class option controls the Ruby type of column names. It can be
- # Symbol (the default) or String. The :timestamp option is used
- # internally to set the timestamp for transactions
- #
# If given an array argument, PgConn will not connect to the database and
# instead write its commands to the array. In this case, methods extracting
# values from the database (eg. #value) will return nil or raise an
# exception
#
# The last variant is used to establish a PgConn from an existing
# connection. It doesn't change the connection settings and is not
# recommended except in cases where you want to piggyback on an existing
# connection (eg. a Rails connection)
#
+ # The :field_name_class option controls the Ruby type of column names. It can be
+ # Symbol (the default) or String. The :timestamp option is used
+ # internally to set the timestamp for transactions
+ #
# Note that the connection hash and the connection string may support more
# parameters than documented here. Consult
# https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING
# for the full list
#
@@ -476,13 +486,14 @@
end
end
# Execute SQL statement(s) in a transaction and return the number of
# affected records (if any). Also sets #timestamp unless a transaction is
- # already in progress. The +sql+ argument can be a String or an arbitrarily
- # nested array of strings. The empty array is a NOP but the empty string is
- # not.
+ # already in progress. The +sql+ argument can be a command (String) or an
+ # arbitrarily nested array of commands. Note that you can't have commands
+ # that span multiple lines. The empty array is a NOP but the empty string
+ # is not.
#
# #exec pass Postgres exceptions to the caller unless :fail is false. If
# fail is false #exec instead return nil but note that postgres doesn't
# ignore it so that if you're inside a transaction, the transaction will be
# in an error state and if you're also using subtransactions the whole
@@ -493,14 +504,14 @@
transaction(commit: commit) { execute(sql, fail: fail, silent: silent) }
end
# Execute SQL statement(s) without a transaction block and return the
# number of affected records (if any). This used to call procedures that
- # may manipulate transactions. The +sql+ argument can be a String or
- # an arbitrarily nested array of strings. The empty array is a NOP but the
- # empty string is not. #exec pass Postgres exceptions to the caller unless
- # :fail is false in which case it returns nil
+ # may manipulate transactions. The +sql+ argument can be a SQL command or
+ # an arbitrarily nested array of commands. The empty array is a NOP but the
+ # empty string is not. #execute pass Postgres exceptions to the caller
+ # unless :fail is false in which case it returns nil
#
# TODO: Handle postgres exceptions wrt transaction state and stack
def execute(sql, fail: true, silent: false)
if @pg_connection
pg_exec(sql, fail: fail, silent: silent)&.cmd_tuples
@@ -587,11 +598,11 @@
result = nil
begin
push_transaction
result = yield
rescue PgConn::Rollback
- pop_trancaction(commit: false)
+ pop_transaction(commit: false)
return nil
# FIXME: Rescue other postgres errors and wipe-out stack
end
pop_transaction(commit: commit)
result
@@ -624,29 +635,31 @@
end
else
PG::Connection.new *args, **opts
end
end
-
+
# :call-seq:
# pg_exec(string)
# pg_exec(array)
#
- # +arg+ can be a statement or an array of statements. The statements are
- # concatenated before being sent to the server. It returns a PG::Result
- # object or nil if +arg+ was empty. #exec pass Postgres exceptions to the
- # caller unless :fail is false
+ # Execute statement(s) on the server. If the argument is an array of
+ # commands, the commands are concatenated with ';' before being sent to the
+ # server. #pg_exec returns a PG::Result object or nil if +arg+ was empty.
+ # #exec pass Postgres exceptions to the caller unless :fail is false
#
# FIXME: Error message prints the last statement but what if another
# statement failed?
#
- # TODO WILD: Parse sql and split it into statements that are executed
- # one-by-one so we're able to pinpoint errors in the source
+ # TODO: Connsider executing statements one-by-one so we're able to
+ # pin-point Postgres errors without a line number. This may be expensive,
+ # though
#
# TODO: Fix silent by not handling exceptions
def pg_exec(arg, fail: true, silent: false)
if @pg_connection
+ @err = nil
begin
last_stmt = nil # To make the current SQL statement visible to the rescue clause. FIXME Not used?
if arg.is_a?(String)
return nil if arg == ""
last_stmt = arg
@@ -657,10 +670,11 @@
last_stmt = stmts.last
@pg_connection.exec(stmts.join(";\n"))
end
rescue PG::Error => ex
+ @err = ex
if fail
if !silent # FIXME Why do we handle this?
$stderr.puts arg
$stderr.puts ex.message
$stderr.flush
@@ -668,9 +682,10 @@
raise
else
return nil
end
end
+
else # @pg_commands is defined
if arg.is_a?(String)
@pg_commands << arg if arg != ""
else
@pg_commands.concat(arg)