Class: Sequel::Postgres::Database

Inherits:
Database show all
Defined in:
lib/sequel_core/adapters/postgres.rb

Constant Summary collapse

RELATION_QUERY =
{:from => [:pg_class], :select => [:relname]}.freeze
RELATION_FILTER =
"(relkind = 'r') AND (relname !~ '^pg|sql')".freeze
SYSTEM_TABLE_REGEXP =
/^pg|sql/.freeze
RE_CURRVAL_ERROR =
/currval of sequence "(.*)" is not yet defined in this session/.freeze
SQL_BEGIN =
'BEGIN'.freeze
SQL_COMMIT =
'COMMIT'.freeze
SQL_ROLLBACK =
'ROLLBACK'.freeze

Constants inherited from Database

Database::ADAPTERS

Constants included from Schema::SQL

Schema::SQL::AUTOINCREMENT, Schema::SQL::CASCADE, Schema::SQL::COMMA_SEPARATOR, Schema::SQL::NOT_NULL, Schema::SQL::NO_ACTION, Schema::SQL::NULL, Schema::SQL::PRIMARY_KEY, Schema::SQL::RESTRICT, Schema::SQL::SET_DEFAULT, Schema::SQL::SET_NULL, Schema::SQL::TYPES, Schema::SQL::UNDERSCORE, Schema::SQL::UNIQUE, Schema::SQL::UNSIGNED

Instance Attribute Summary

Attributes inherited from Database

#loggers, #opts, #pool, #quote_identifiers

Instance Method Summary collapse

Methods inherited from Database

#<<, #[], adapter_class, adapter_scheme, #add_column, #add_index, #alter_table, connect, #create_or_replace_view, #create_table, #create_table!, #create_view, #drop_column, #drop_index, #drop_table, #drop_view, #fetch, #from, #get, #initialize, #inspect, #log_info, #logger, #logger=, #multi_threaded?, #query, quote_identifiers=, #quote_identifiers?, #rename_column, #rename_table, #select, set_adapter_scheme, #set_column_default, #set_column_type, single_threaded=, #single_threaded?, #synchronize, #table_exists?, #test_connection, #typecast_value, #uri, uri_to_options

Methods included from Schema::SQL

#alter_table_sql, #alter_table_sql_list, #auto_increment_sql, #column_definition_sql, #column_list_sql, #constraint_definition_sql, #create_table_sql_list, #default_index_name, #filter_expr, #index_list_sql_list, #literal, #on_delete_clause, #quote_identifier, #rename_table_sql, #schema, #schema_utility_dataset, #type_literal

Constructor Details

This class inherits a constructor from Sequel::Database

Instance Method Details

#connectObject



188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/sequel_core/adapters/postgres.rb', line 188

def connect
  conn = Adapter.connect(
    @opts[:host] || 'localhost',
    @opts[:port] || 5432,
    '', '',
    @opts[:database],
    @opts[:user],
    @opts[:password]
  )
  if encoding = @opts[:encoding] || @opts[:charset]
    conn.set_client_encoding(encoding)
  end
  conn
end

#dataset(opts = nil) ⇒ Object



207
208
209
# File 'lib/sequel_core/adapters/postgres.rb', line 207

def dataset(opts = nil)
  Postgres::Dataset.new(self, opts)
end

#disconnectObject



203
204
205
# File 'lib/sequel_core/adapters/postgres.rb', line 203

def disconnect
  @pool.disconnect {|c| c.finish}
end

#drop_table_sql(name) ⇒ Object



350
351
352
# File 'lib/sequel_core/adapters/postgres.rb', line 350

def drop_table_sql(name)
  "DROP TABLE #{name} CASCADE"
end

#execute(sql, &block) ⇒ Object



225
226
227
228
229
230
231
232
233
# File 'lib/sequel_core/adapters/postgres.rb', line 225

def execute(sql, &block)
  begin
    log_info(sql)
    @pool.hold {|conn| conn.execute(sql, &block)}
  rescue => e
    log_info(e.message)
    raise convert_pgerror(e)
  end
end

#execute_insert(sql, table, values) ⇒ Object



280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/sequel_core/adapters/postgres.rb', line 280

def execute_insert(sql, table, values)
  begin 
    log_info(sql)
    @pool.hold do |conn|
      conn.execute(sql)
      insert_result(conn, table, values)
    end
  rescue => e
    log_info(e.message)
    raise convert_pgerror(e)
  end
end

#index_definition_sql(table_name, index) ⇒ Object



331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/sequel_core/adapters/postgres.rb', line 331

def index_definition_sql(table_name, index)
  index_name = index[:name] || default_index_name(table_name, index[:columns])
  expr = literal(Array(index[:columns]))
  unique = "UNIQUE " if index[:unique]
  index_type = index[:type]
  filter = index[:where] || index[:filter]
  filter = " WHERE #{filter_expr(filter)}" if filter
  case index_type
  when :full_text
    lang = index[:language] ? "#{literal(index[:language])}, " : ""
    cols = index[:columns].map {|c| literal(c)}.join(" || ")
    expr = "(to_tsvector(#{lang}#{cols}))"
    index_type = :gin
  when :spatial
    index_type = :gist
  end
  "CREATE #{unique}INDEX #{index_name} ON #{table_name} #{"USING #{index_type} " if index_type}#{expr}#{filter}"
end

#insert_result(conn, table, values) ⇒ Object



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/sequel_core/adapters/postgres.rb', line 242

def insert_result(conn, table, values)
  begin
    result = conn.last_insert_id(table)
    return result if result
  rescue PGError => e
    # An error could occur if the inserted values include a primary key
    # value, while the primary key is serial.
    raise Error.new(e.message =~ RE_CURRVAL_ERROR ? "Could not return primary key value for the inserted record. Are you specifying a primary key value for a serial primary key?" : e.message)
  end
  
  case values
  when Hash
    values[primary_key_for_table(conn, table)]
  when Array
    values.first
  else
    nil
  end
end

#locksObject



219
220
221
222
223
# File 'lib/sequel_core/adapters/postgres.rb', line 219

def locks
  dataset.from("pg_class, pg_locks").
    select("pg_class.relname, pg_locks.*").
    filter("pg_class.relfilenode=pg_locks.relation")
end

#primary_key_for_table(conn, table) ⇒ Object



235
236
237
238
# File 'lib/sequel_core/adapters/postgres.rb', line 235

def primary_key_for_table(conn, table)
  @primary_keys ||= {}
  @primary_keys[table] ||= conn.primary_key(table)
end

#serial_primary_key_optionsObject



327
328
329
# File 'lib/sequel_core/adapters/postgres.rb', line 327

def serial_primary_key_options
  {:primary_key => true, :type => :serial}
end

#server_versionObject



262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/sequel_core/adapters/postgres.rb', line 262

def server_version
  return @server_version if @server_version
  @server_version = pool.hold do |conn|
    if conn.respond_to?(:server_version)
      begin
        conn.server_version
      rescue StandardError
        nil
      end
    end
  end
  unless @server_version
    m = /PostgreSQL (\d+)\.(\d+)\.(\d+)/.match(get(:version[]))
    @server_version = (m[1].to_i * 10000) + (m[2].to_i * 100) + m[3].to_i
  end
  @server_version
end

#tablesObject



215
216
217
# File 'lib/sequel_core/adapters/postgres.rb', line 215

def tables
  dataset(RELATION_QUERY).filter(RELATION_FILTER).map {|r| r[:relname].to_sym}
end

#transactionObject



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
# File 'lib/sequel_core/adapters/postgres.rb', line 297

def transaction
  @pool.hold do |conn|
    if conn.transaction_in_progress
      yield conn
    else
      log_info(SQL_BEGIN)
      conn.execute(SQL_BEGIN)
      begin
        conn.transaction_in_progress = true
        yield
      rescue ::Exception => e
        log_info(SQL_ROLLBACK)
        conn.execute(SQL_ROLLBACK) rescue nil
        raise convert_pgerror(e) unless Error::Rollback === e
      ensure
        unless e
          begin
            log_info(SQL_COMMIT)
            conn.execute(SQL_COMMIT)
          rescue => e
            log_info(e.message)
            raise convert_pgerror(e)
          end
        end
        conn.transaction_in_progress = nil
      end
    end
  end
end