# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 69 def primary_key(table_name) [database.primary_key(table_name)] .compact .map(&:to_sym) end
class Terrestrial::Adapters::SequelPostgresAdapter
Attributes
database[R]
Public Class Methods
new(database)
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 31 def initialize(database) @database = database end
Public Instance Methods
[](table_name)
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 43 def [](table_name) Dataset.new(database[table_name]) end
changes_sql(record)
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 59 def changes_sql(record) generate_upsert_sql(record) rescue Object => e raise UpsertError.new(record.namespace, record.to_h, e) end
conflict_fields(table_name)
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 65 def conflict_fields(table_name) primary_key(table_name) end
delete(record)
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 55 def delete(record) database[record.namespace].where(record.identity).delete end
primary_key(table_name)
click to toggle source
relation_fields(relation_name)
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 85 def relation_fields(relation_name) database[relation_name].columns end
relations()
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 81 def relations database.tables - [:schema_migrations] end
schema(relation_name)
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 89 def schema(relation_name) database.schema(relation_name) end
unique_indexes(table_name)
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 75 def unique_indexes(table_name) database.indexes(table_name).map { |_name, data| data.fetch(:columns) } end
upsert(record)
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 47 def upsert(record) row = perform_upsert_returning_row(record) record.on_upsert(row) nil rescue Object => e raise UpsertError.new(record.namespace, record.to_h, e) end
Private Instance Methods
generate_upsert_sql(record)
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 102 def generate_upsert_sql(record) table_name = record.namespace update_attributes = record.updatable? && record.updatable_attributes primary_key_fields = primary_key(table_name) missing_not_null_fields = database.schema(table_name) .reject { |field_name, _| record.attributes.keys.include?(field_name) } .select { |_field_name, properties| allow_null = properties.fetch(:allow_null, true) not_null = !allow_null default = properties.fetch(:default, nil) no_default = !default not_null && no_default } .map(&:first) .reject { |field_name| record.identity_fields.include?(field_name) } missing_not_null_attrs = missing_not_null_fields .map { |field_name| [field_name, database[table_name].select(field_name).where(record.identity)] } .to_h # TODO: investigate if failing to find a private key results in extra schema queries if primary_key_fields.any? if record.id? conflict_fields = primary_key_fields else return database[table_name] .returning(Sequel.lit("*")) .insert_sql(record.insertable.merge(missing_not_null_attrs)) end else u_idxs = unique_indexes(table_name) if u_idxs.any? conflict_fields = u_idxs.first end end upsert_args = { update: update_attributes } if conflict_fields && conflict_fields.any? upsert_args.merge!(target: conflict_fields) end # TODO: Use specific field list instead of Sequel.lit("*") database[table_name] .insert_conflict(**upsert_args) .returning(Sequel.lit("*")) .insert_sql(record.insertable.merge(missing_not_null_attrs)) end
perform_upsert_returning_row(record)
click to toggle source
# File lib/terrestrial/adapters/sequel_postgres_adapter.rb, line 95 def perform_upsert_returning_row(record) sql = generate_upsert_sql(record) result = database[sql] .to_a .fetch(0) { {} } end