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_SAVEPOINT =
'SAVEPOINT autopoint_%d'.freeze
SQL_COMMIT =
'COMMIT'.freeze
SQL_ROLLBACK_TO_SAVEPOINT =
'ROLLBACK TO SAVEPOINT autopoint_%d'.freeze
SQL_ROLLBACK =
'ROLLBACK'.freeze
SQL_RELEASE_SAVEPOINT =
'RELEASE SAVEPOINT autopoint_%d'.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_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



205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/sequel_core/adapters/postgres.rb', line 205

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



224
225
226
# File 'lib/sequel_core/adapters/postgres.rb', line 224

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

#disconnectObject



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

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

#drop_table_sql(name) ⇒ Object



380
381
382
# File 'lib/sequel_core/adapters/postgres.rb', line 380

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

#execute(sql, &block) ⇒ Object



242
243
244
245
246
247
248
249
250
# File 'lib/sequel_core/adapters/postgres.rb', line 242

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



295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/sequel_core/adapters/postgres.rb', line 295

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



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/sequel_core/adapters/postgres.rb', line 361

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



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

def insert_result(conn, table, values)
  begin
    result = conn.last_insert_id(table)
    return result if result
  rescue PGError => e
    raise(Error, e.message) unless RE_CURRVAL_ERROR.match(e.message)
  end
  
  case values
  when Hash
    values[primary_key_for_table(conn, table)]
  when Array
    values.first
  else
    nil
  end
end

#locksObject



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

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



252
253
254
255
# File 'lib/sequel_core/adapters/postgres.rb', line 252

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

#serial_primary_key_optionsObject



357
358
359
# File 'lib/sequel_core/adapters/postgres.rb', line 357

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

#server_versionObject



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

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



232
233
234
# File 'lib/sequel_core/adapters/postgres.rb', line 232

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

#transactionObject



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/sequel_core/adapters/postgres.rb', line 315

def transaction
  @pool.hold do |conn|
    conn.transaction_depth = 0 if conn.transaction_depth.nil?
    if conn.transaction_depth > 0
      log_info(SQL_SAVEPOINT % conn.transaction_depth)
      conn.execute(SQL_SAVEPOINT % conn.transaction_depth)
    else
      log_info(SQL_BEGIN)
      conn.execute(SQL_BEGIN)
    end
    begin
      conn.transaction_depth += 1
      yield conn
    rescue ::Exception => e
      if conn.transaction_depth > 1
        log_info(SQL_ROLLBACK_TO_SAVEPOINT % [conn.transaction_depth - 1])
        conn.execute(SQL_ROLLBACK_TO_SAVEPOINT % [conn.transaction_depth - 1])
      else
        log_info(SQL_ROLLBACK)
        conn.execute(SQL_ROLLBACK) rescue nil
      end
      raise convert_pgerror(e) unless Error::Rollback === e
    ensure
      unless e
        begin
          if conn.transaction_depth < 2
            log_info(SQL_COMMIT)
            conn.execute(SQL_COMMIT)
          else
            log_info(SQL_RELEASE_SAVEPOINT % [conn.transaction_depth - 1])
            conn.execute(SQL_RELEASE_SAVEPOINT % [conn.transaction_depth - 1])
          end
        rescue => e
          log_info(e.message)
          raise convert_pgerror(e)
        end
      end
      conn.transaction_depth -= 1
    end
  end
end