lib/pg_conn.rb in pg_conn-0.26.2 vs lib/pg_conn.rb in pg_conn-0.27.0
- old
+ new
@@ -248,11 +248,11 @@
# Quote argument as an identifier. The argument should be a non-nil string
# or a symbol
def quote_identifier(s)
s = s.to_s if s.is_a?(Symbol)
- @pg_connection.escape_identifier(s)
+ @pg_connection.escape_identifier(s).gsub(/\./, '"."').sub(/"\*"/, "*")
end
# Quote identifiers and concatenate them using ',' as separator
def quote_identifiers(idents) = idents.map { |ident| quote_identifier(ident) }.join(", ")
@@ -337,182 +337,167 @@
# exist?(table, id)
# eists?(table, where_clause)
#
# Return true iff the query returns exactly one record. Use '!empty?' to
# check if the query returns one or more records
- def exist?(*args)
- arg1, arg2 = *args
- query =
- case arg2
- when Integer; "select from #{arg1} where id = #{arg2}"
- when String; "select from #{arg1} where #{arg2}"
- when NilClass; arg1
- end
- count(query) == 1
+ def exist?(*query)
+ !empty?(*query)
end
# :call-seq:
# count(query)
# count(table, where_clause = nil)
#
# Return true if the table or the result of the query is empty
- def empty?(arg, where_clause = nil)
- if arg =~ /\s/
- value "select count(*) from (#{arg} limit 1) as inner_query"
- elsif where_clause
- value "select count(*) from (select 1 from #{arg} where #{where_clause} limit 1) as inner_query"
- else
- value "select count(*) from (select 1 from #{arg} limit 1) as inner_query"
- end == 0
+ def empty?(*query)
+ inner_query = parse_query *query
+ self.value("select count(*) from (#{inner_query} limit 1) as \"inner_query\"") == 0
end
# :call-seq:
# count(query)
# count(table_name, where_clause = nil)
#
# The number of records in the table or in the query
- def count(arg, where_clause = nil)
- if arg =~ /\s/
- value("select count(*) from (#{arg}) as inner_query")
- else
- value("select count(*) from #{arg}" + (where_clause ? " where #{where_clause}" : ""))
- end
+ def count(*query)
+ inner_query = parse_query *query
+ value("select count(*) from (#{inner_query}) as inner_query")
end
- # TODO
- # Query variants
- # (sql) - simple SQL statement
- # (schema = nil, table, id-or-where-clause = nil, field-or-fields)
- #
-
# Return a single value. It is an error if the query doesn't return a
- # single record with a single column. If :transaction is true, the query
- # will be executed in a transaction and also be committed if :commit is
- # true (this is the default). It can also be used to execute 'insert'
- # statements with a 'returning' clause
- def value(query) #, transaction: false, commit: true)
- r = pg_exec(query)
+ # single record with a single column.
+ #
+ # TODO If :transaction is true, the query will be executed in a
+ # transaction and also be committed if :commit is true (this is the
+ # default). It can also be used to execute 'insert' statements with a
+ # 'returning' clause
+ def value(*query) #, transaction: false, commit: true)
+ r = pg_exec(parse_query *query)
check_1c(r)
check_1r(r)
r.values[0][0]
end
# Like #value but returns nil if no record was found. It is still an error
# if the query returns more than one column
- def value?(query) #, transaction: false, commit: true)
- r = pg_exec(query)
+ def value?(*query) #, transaction: false, commit: true)
+ r = pg_exec(parse_query *query)
check_1c(r)
return nil if r.ntuples == 0
check_1r(r)
r.values[0][0]
end
# Return an array of values. It is an error if the query returns records
- # with more than one column. If :transaction is true, the query will be
- # executed in a transaction and be committed it :commit is true (the
- # default). This can be used in 'insert ... returning ...' statements
- def values(query)
- r = pg_exec(query)
+ # with more than one column.
+ #
+ # TODO If :transaction is true, the query will be executed in a
+ # transaction and be committed it :commit is true (the default). This can
+ # be used in 'insert ... returning ...' statements
+ def values(*query)
+ r = pg_exec(parse_query *query)
check_1c(r)
r.column_values(0)
end
# Return an array of column values. It is an error if the query returns
- # more than one record. If :transaction is true, the query will be executed
+ # more than one record.
+ #
+ # TODO If :transaction is true, the query will be executed
# in a transaction and be committed it :commit is true (the default). This
# can be used in 'insert ... returning ...' statements
- def tuple(query)
- r = pg_exec(query)
+ def tuple(*query)
+ r = pg_exec(parse_query *query)
check_1r(r)
r.values[0]
end
# Like #tuple but returns nil if no record was found
- def tuple?(query)
- r = pg_exec(query)
+ def tuple?(*query)
+ r = pg_exec(parse_query *query)
return nil if r.ntuples == 0
check_1r(r)
r.values[0]
end
# Return an array of tuples. If :transaction is true, the query will be
# executed in a transaction and be committed it :commit is true (the
# default). This can be used in 'insert ... returning ...' statements
- def tuples(query)
- pg_exec(query).values
+ def tuples(*query)
+ pg_exec(parse_query *query).values
end
# Return a single-element hash from column name to value. It is an error
# if the query returns more than one record or more than one column. Note
- # that you will probably prefer to use #value instead when you expect only
- # a single field
- def field(query)
- r = pg_exec(query)
+ # that you will probably prefer to use #value instead when you query a
+ # single field
+ def field(*query)
+ r = pg_exec(parse_query *query)
check_1c(r)
check_1r(r)
r.tuple(0).to_h
end
# Like #field but returns nil if no record was found
- def field?(query)
- r = pg_exec(query)
+ def field?(*query)
+ r = pg_exec(parse_query *query)
check_1c(r)
return nil if r.ntuples == 0
check_1r(r)
r.tuple(0).to_h
end
# Return an array of single-element hashes from column name to value. It
# is an error if the query returns records with more than one column. Note
# that you will probably prefer to use #values instead when you expect only
# single-column records
- def fields(query)
- r = pg_exec(query)
+ def fields(*query)
+ r = pg_exec(parse_query *query)
check_1c(r)
r.each.to_a.map(&:to_h)
end
# Return a hash from column name (a Symbol) to field value. It is an error if
# the query returns more than one record. It blows up if a column name is
# not a valid ruby symbol
- def record(query)
- r = pg_exec(query)
+ def record(*query)
+ r = pg_exec(parse_query *query)
check_1r(r)
r.tuple(0).to_h
end
# Like #record but returns nil if no record was found
- def record?(query)
- r = pg_exec(query)
+ def record?(*query)
+ r = pg_exec(parse_query *query)
return nil if r.ntuples == 0
check_1r(r)
r.tuple(0).to_h
end
# Return an array of hashes from column name to field value
- def records(query)
- r = pg_exec(query)
+ def records(*query)
+ r = pg_exec(parse_query *query)
r.each.to_a.map(&:to_h)
end
# Return a record as a OpenStruct object. It is an error if the query
# returns more than one record. It blows up if a column name is not a valid
# ruby symbol
- def struct(query)
- OpenStruct.new(**record(query))
+ def struct(*query)
+ OpenStruct.new(**record(parse_query *query))
end
# Like #struct but returns nil if no record was found
- def struct?(query)
- args = record?(query)
+ def struct?(*query)
+ args = record?(parse_query *query)
return nil if args.nil?
OpenStruct.new(**args)
end
# Return an array of OpenStruct objects
- def structs(query)
- records(query).map { |record| OpenStruct.new(**record) }
+ def structs(*query)
+ records(parse_query *query).map { |record| OpenStruct.new(**record) }
end
# Return a hash from the record id column to record (hash from column name
# to field value) If the :key_column option is defined it will be used
# instead of id as the key It is an error if the id field value is not
@@ -992,9 +977,38 @@
if array
"array[#{literals.join(', ')}]::#{pg_type}[]"
else
literals.first
end
+ end
+
+ # :call-seq
+ # parse_query(query)
+ # parse_query(table, id_or_where_clause = "true", fields = [])
+ #
+ # Parse a query. Used in query-functions (#value etc.). The fields argument
+ # can be a list of fields or arrays of fields
+ #
+ def parse_query(*args)
+ args.size > 0 or raise ArgumentError
+ return args.first if args.size == 1 && args.first =~ / /
+
+ table = args.shift
+ where_clause = "true"
+ fields = []
+ case args.first
+ when Integer; where_clause = "id = #{args.shift}"
+ when String; where_clause = args.shift
+ when Symbol; fields << args.shift
+ when Array; fields = args.shift
+ when nil; where_clause = "true"
+ else
+ raise ArgumentError
+ end
+ fields.concat args.flatten
+ field_list = fields.empty? ? "*" : self.quote_identifiers(fields)
+
+ "select #{field_list} from #{table} where #{where_clause}"
end
# :call-seq:
# pg_exec(string)
# pg_exec(array)