The PostgreSQL adapter works both with the C-based (www.postgresql.jp/interfaces/ruby/) and the Ruby-base (available both as gem and from rubyforge.org/frs/?group_id=234&release_id=1145) drivers.
Options:
- :host — Defaults to localhost
- :port — Defaults to 5432
- :username — Defaults to nothing
- :password — Defaults to nothing
- :database — The name of the database. No default, must be provided.
- :schema_search_path — An optional schema search path for the connection given as a string of comma-separated schema names. This is backward-compatible with the :schema_order option.
- :encoding — An optional client encoding that is using in a SET client_encoding TO <encoding> call on connection.
- :min_messages — An optional client min messages that is using in a SET client_min_messages TO <min_messages> call on connection.
- :allow_concurrency — If true, use async query methods so Ruby threads don‘t deadlock; otherwise, use blocking query methods.
- active?
- adapter_name
- add_column
- add_order_by_for_association_limiting!
- default_sequence_name
- disconnect!
- distinct
- native_database_types
- new
- pk_and_sequence_for
- quote
- quote_column_name
- quoted_date
- reconnect!
- rename_table
- reset_pk_sequence!
- supports_migrations?
- table_alias_length
| BYTEA_COLUMN_TYPE_OID | = | 17 |
| NUMERIC_COLUMN_TYPE_OID | = | 1700 |
| TIMESTAMPOID | = | 1114 |
| TIMESTAMPTZOID | = | 1184 |
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 55
55: def initialize(connection, logger, config = {})
56: super(connection, logger)
57: @config = config
58: @async = config[:allow_concurrency]
59: configure_connection
60: end
Is this connection alive and ready for queries?
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 63
63: def active?
64: if @connection.respond_to?(:status)
65: @connection.status == PGconn::CONNECTION_OK
66: else
67: @connection.query 'SELECT 1'
68: true
69: end
70: # postgres-pr raises a NoMethodError when querying if no conn is available
71: rescue PGError, NoMethodError
72: false
73: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 51
51: def adapter_name
52: 'PostgreSQL'
53: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 321
321: def add_column(table_name, column_name, type, options = {})
322: default = options[:default]
323: notnull = options[:null] == false
324:
325: # Add the column.
326: execute("ALTER TABLE #{table_name} ADD COLUMN #{column_name} #{type_to_sql(type, options[:limit])}")
327:
328: # Set optional default. If not null, update nulls to the new default.
329: if options_include_default?(options)
330: change_column_default(table_name, column_name, default)
331: if notnull
332: execute("UPDATE #{table_name} SET #{column_name}=#{quote(default, options[:column])} WHERE #{column_name} IS NULL")
333: end
334: end
335:
336: if notnull
337: execute("ALTER TABLE #{table_name} ALTER #{column_name} SET NOT NULL")
338: end
339: end
ORDER BY clause for the passed order option.
PostgreSQL does not allow arbitrary ordering when using DISTINCT ON, so we work around this by wrapping the sql as a sub-select and ordering in that query.
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 408
408: def add_order_by_for_association_limiting!(sql, options)
409: return sql if options[:order].blank?
410:
411: order = options[:order].split(',').collect { |s| s.strip }.reject(&:blank?)
412: order.map! { |s| 'DESC' if s =~ /\bdesc$/i }
413: order = order.zip((0...order.size).to_a).map { |s,i| "id_list.alias_#{i} #{s}" }.join(', ')
414:
415: sql.replace "SELECT * FROM (#{sql}) AS id_list ORDER BY #{order}"
416: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 245
245: def default_sequence_name(table_name, pk = nil)
246: default_pk, default_seq = pk_and_sequence_for(table_name)
247: default_seq || "#{table_name}_#{pk || default_pk || 'id'}_seq"
248: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 84
84: def disconnect!
85: # Both postgres and postgres-pr respond to :close
86: @connection.close rescue nil
87: end
SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
PostgreSQL requires the ORDER BY columns in the select list for distinct queries, and requires that the ORDER BY include the distinct column.
distinct("posts.id", "posts.created_at desc")
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 389
389: def distinct(columns, order_by)
390: return "DISTINCT #{columns}" if order_by.blank?
391:
392: # construct a clean list of column names from the ORDER BY clause, removing
393: # any asc/desc modifiers
394: order_columns = order_by.split(',').collect { |s| s.split.first }
395: order_columns.delete_if &:blank?
396: order_columns = order_columns.zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" }
397:
398: # return a DISTINCT ON() clause that's distinct on the columns we want but includes
399: # all the required columns for the ORDER BY to work properly
400: sql = "DISTINCT ON (#{columns}) #{columns}, "
401: sql << order_columns * ', '
402: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 89
89: def native_database_types
90: {
91: :primary_key => "serial primary key",
92: :string => { :name => "character varying", :limit => 255 },
93: :text => { :name => "text" },
94: :integer => { :name => "integer" },
95: :float => { :name => "float" },
96: :decimal => { :name => "decimal" },
97: :datetime => { :name => "timestamp" },
98: :timestamp => { :name => "timestamp" },
99: :time => { :name => "time" },
100: :date => { :name => "date" },
101: :binary => { :name => "bytea" },
102: :boolean => { :name => "boolean" }
103: }
104: end
Find a table‘s primary key and sequence.
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 270
270: def pk_and_sequence_for(table)
271: # First try looking for a sequence with a dependency on the
272: # given table's primary key.
273: result = query("SELECT attr.attname, name.nspname, seq.relname\nFROM pg_class seq,\npg_attribute attr,\npg_depend dep,\npg_namespace name,\npg_constraint cons\nWHERE seq.oid = dep.objid\nAND seq.relnamespace = name.oid\nAND seq.relkind = 'S'\nAND attr.attrelid = dep.refobjid\nAND attr.attnum = dep.refobjsubid\nAND attr.attrelid = cons.conrelid\nAND attr.attnum = cons.conkey[1]\nAND cons.contype = 'p'\nAND dep.refobjid = '\#{table}'::regclass\n", 'PK and serial sequence')[0]
274:
275: if result.nil? or result.empty?
276: # If that fails, try parsing the primary key's default value.
277: # Support the 7.x and 8.0 nextval('foo'::text) as well as
278: # the 8.1+ nextval('foo'::regclass).
279: # TODO: assumes sequence is in same schema as table.
280: result = query("SELECT attr.attname, name.nspname, split_part(def.adsrc, '''', 2)\nFROM pg_class t\nJOIN pg_namespace name ON (t.relnamespace = name.oid)\nJOIN pg_attribute attr ON (t.oid = attrelid)\nJOIN pg_attrdef def ON (adrelid = attrelid AND adnum = attnum)\nJOIN pg_constraint cons ON (conrelid = adrelid AND adnum = conkey[1])\nWHERE t.oid = '\#{table}'::regclass\nAND cons.contype = 'p'\nAND def.adsrc ~* 'nextval'\n", 'PK and custom sequence')[0]
281: end
282: # check for existence of . in sequence name as in public.foo_sequence. if it does not exist, return unqualified sequence
283: # We cannot qualify unqualified sequences, as rails doesn't qualify any table access, using the search path
284: [result.first, result.last]
285: rescue
286: nil
287: end
QUOTING ==================================================
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 116
116: def quote(value, column = nil)
117: if value.kind_of?(String) && column && column.type == :binary
118: "'#{escape_bytea(value)}'"
119: else
120: super
121: end
122: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 124
124: def quote_column_name(name)
125: %("#{name}")
126: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 128
128: def quoted_date(value)
129: value.strftime("%Y-%m-%d %H:%M:%S.#{sprintf("%06d", value.usec)}")
130: end
Close then reopen the connection.
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 76
76: def reconnect!
77: # TODO: postgres-pr doesn't have PGconn#reset.
78: if @connection.respond_to?(:reset)
79: @connection.reset
80: configure_connection
81: end
82: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 317
317: def rename_table(name, new_name)
318: execute "ALTER TABLE #{name} RENAME TO #{new_name}"
319: end
Resets sequence to the max value of the table‘s pk if present.
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 251
251: def reset_pk_sequence!(table, pk = nil, sequence = nil)
252: unless pk and sequence
253: default_pk, default_sequence = pk_and_sequence_for(table)
254: pk ||= default_pk
255: sequence ||= default_sequence
256: end
257: if pk
258: if sequence
259: select_value "SELECT setval('\#{sequence}', (SELECT COALESCE(MAX(\#{pk})+(SELECT increment_by FROM \#{sequence}), (SELECT min_value FROM \#{sequence})) FROM \#{table}), false)\n", 'Reset sequence'
260: else
261: @logger.warn "#{table} has primary key #{pk} with no default sequence" if @logger
262: end
263: end
264: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 106
106: def supports_migrations?
107: true
108: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 110
110: def table_alias_length
111: 63
112: end