|
|
@ -65,20 +65,53 @@ module LPGAR |
|
|
|
|
|
|
|
# Return either an existing Record or create a new one. |
|
|
|
# @param data [Hash{String => Object}] row data |
|
|
|
def new(data) |
|
|
|
# @param syncless [Boolean] do not perform any communication with PG |
|
|
|
# @return [Object] new record object |
|
|
|
def new(data, syncless: false) |
|
|
|
check_instantiable |
|
|
|
ident = Digest::MD5.hexdigest(data.values_at(*cols_pk).join) |
|
|
|
if @instances[ident] |
|
|
|
if @instances[ident] and @instances[ident].weakref_alive? |
|
|
|
@instances[ident].sync |
|
|
|
@instances[ident] |
|
|
|
end |
|
|
|
|
|
|
|
new_record = super(data) |
|
|
|
create(new_record) unless new_record.sync |
|
|
|
unless syncless |
|
|
|
synced = new_record.sync |
|
|
|
insert_query(new_record) unless synced |
|
|
|
end |
|
|
|
track_instance(new_record) |
|
|
|
new_record |
|
|
|
end |
|
|
|
|
|
|
|
# Explicitly create a new record. Returns nil if exists. |
|
|
|
# @param data [Hash{String => Object}] row data |
|
|
|
# @return [(Object,nil)] new record object or nil if exists |
|
|
|
def create(data) |
|
|
|
instance = new(data, syncless: true) |
|
|
|
return if instance.sync |
|
|
|
|
|
|
|
insert_query(instance) |
|
|
|
instance |
|
|
|
end |
|
|
|
|
|
|
|
# Explicitly request an existing record. Returns nil if doesn't exist. |
|
|
|
# @param data [Hash{String => Object}] row data |
|
|
|
# @return [(Object,nil)] new record object or nil if doesn't exist. |
|
|
|
def get(data) |
|
|
|
instance = new(data, syncless: true) |
|
|
|
instance if instance.sync |
|
|
|
end |
|
|
|
|
|
|
|
# Map returned rows from a query to an array of objects of this table. |
|
|
|
# @param query [String] raw postgresql query |
|
|
|
# @return [Array(Object)] array of records of this table |
|
|
|
def map(query) |
|
|
|
conn.exec(query).map do |row| |
|
|
|
new(row, syncless: true) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
# Change row identity |
|
|
|
# Should not be called directly in most cases. |
|
|
|
# @param original [String] original row identity |
|
|
@ -91,15 +124,15 @@ module LPGAR |
|
|
|
# Create sync query. |
|
|
|
# @return [String] |
|
|
|
def sync_query |
|
|
|
return @_memo_query if @_memo_query |
|
|
|
return @sync_query if @sync_query |
|
|
|
|
|
|
|
selector = @cols_pk.map.with_index do |pk, index| |
|
|
|
"#{pk} = $#{index + 1}" |
|
|
|
selector = @cols_pk.map.with_index do |key, index| |
|
|
|
"#{key} = $#{index + 1}" |
|
|
|
end.join " AND " |
|
|
|
@_memo_query = <<~QUERY |
|
|
|
@sync_query = <<~QUERY |
|
|
|
SELECT * FROM #{@table_name} |
|
|
|
WHERE #{selector} |
|
|
|
LIMIT 1 |
|
|
|
LIMIT 1; |
|
|
|
QUERY |
|
|
|
end |
|
|
|
|
|
|
@ -139,6 +172,8 @@ module LPGAR |
|
|
|
end |
|
|
|
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize |
|
|
|
|
|
|
|
private |
|
|
|
|
|
|
|
# Check if Record is properly set up. |
|
|
|
# @raise [StandardError] rasied if class is not properly set up |
|
|
|
def check_instantiable |
|
|
@ -166,7 +201,7 @@ module LPGAR |
|
|
|
end |
|
|
|
|
|
|
|
# Create a new record by "INSERT" |
|
|
|
def create(record) |
|
|
|
def insert_query(record) |
|
|
|
recbody = record.instance_variable_get("@data") |
|
|
|
# @sg-ignore |
|
|
|
conn.exec(<<~QUERY, recbody.values) |
|
|
@ -336,7 +371,7 @@ module LPGAR |
|
|
|
@conn = conn |
|
|
|
@instances = {} |
|
|
|
end |
|
|
|
new_class.class_exec(&block) |
|
|
|
new_class.class_exec(&block) if block |
|
|
|
new_class |
|
|
|
end |
|
|
|
|
|
|
|