Skip to content

Commit

Permalink
Quote every column name plus cleanup of update query
Browse files Browse the repository at this point in the history
Quote every column name plus cleanup of update query
  • Loading branch information
Ladas committed Aug 16, 2018
1 parent d221841 commit f97643e
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 38 deletions.
4 changes: 3 additions & 1 deletion app/models/manager_refresh/save_collection/saver/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def initialize(inventory_collection)
# Private attrs
@model_class = inventory_collection.model_class
@table_name = @model_class.table_name
@q_table_name = get_connection.quote_table_name(@table_name)
@primary_key = @model_class.primary_key
@arel_primary_key = @model_class.arel_attribute(@primary_key)
@unique_index_keys = inventory_collection.unique_index_keys
Expand Down Expand Up @@ -117,7 +118,8 @@ def transform_to_hash!(all_attribute_keys, hash)

attr_reader :unique_index_keys, :unique_index_keys_to_s, :select_keys, :unique_db_primary_keys, :unique_db_indexes,
:primary_key, :arel_primary_key, :record_key_method, :pure_sql_records_fetching, :select_keys_indexes,
:batch_size, :batch_size_for_persisting, :model_class, :serializable_keys, :deserializable_keys, :pg_types, :table_name
:batch_size, :batch_size_for_persisting, :model_class, :serializable_keys, :deserializable_keys, :pg_types, :table_name,
:q_table_name

# Saves the InventoryCollection
#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,17 @@ def build_update_query(all_attribute_keys, hashes)
all_attribute_keys_array = all_attribute_keys.to_a.delete_if { |x| %i(created_at created_on).include?(x) }
all_attribute_keys_array << :id

# If there is not version attribute, the version conditions will be ignored
version_attribute = if supports_remote_data_timestamp?(all_attribute_keys)
:resource_timestamp
elsif supports_remote_data_version?(all_attribute_keys)
:resource_version
end

update_query = update_query_beginning(all_attribute_keys_array)
update_query += update_query_reset_version_columns(all_attribute_keys)
update_query += update_query_reset_version_columns(version_attribute)
update_query += update_query_from_values(hashes, all_attribute_keys_array, connection)
update_query += update_query_version_conditions(all_attribute_keys)
update_query += update_query_version_conditions(version_attribute)
update_query += update_query_returning

_log.debug("Building update query for #{inventory_collection} of size #{inventory_collection.size}...Complete")
Expand All @@ -43,15 +50,18 @@ def update_query_beginning(all_attribute_keys_array)
SQL
end

def update_query_reset_version_columns(all_attribute_keys)
if supports_remote_data_timestamp?(all_attribute_keys)
def update_query_reset_version_columns(version_attribute)
if version_attribute
attr_partial = version_attribute.to_s.pluralize # Changes resource_version/timestamp to resource_versions/timestamps
attr_partial_max = "#{attr_partial}_max"

# Quote the column names
attr_partial = quote_column_name(attr_partial)
attr_partial_max = quote_column_name(attr_partial_max)

# Full row update will reset the partial update timestamps
<<-SQL
, resource_timestamps = '{}', resource_timestamps_max = NULL
SQL
elsif supports_remote_data_version?(all_attribute_keys)
<<-SQL
, resource_versions = '{}', resource_versions_max = NULL
, #{attr_partial} = '{}', #{attr_partial_max} = NULL
SQL
else
""
Expand All @@ -68,28 +78,26 @@ def update_query_from_values(hashes, all_attribute_keys_array, connection)
VALUES
#{values}
) AS updated_values (#{all_attribute_keys_array.map { |x| quote_column_name(x) }.join(",")})
WHERE updated_values.id = #{table_name}.id
WHERE updated_values.id = #{q_table_name}.id
SQL
end

def update_query_version_conditions(all_attribute_keys)
# This conditional will avoid rewriting new data by old data. But we want it only when remote_data_timestamp is
# a part of the data, since for the fake records, we just want to update ems_ref.
if supports_remote_data_timestamp?(all_attribute_keys)
<<-SQL
AND (
updated_values.resource_timestamp IS NULL OR (
(#{table_name}.resource_timestamp IS NULL OR updated_values.resource_timestamp > #{table_name}.resource_timestamp) AND
(#{table_name}.resource_timestamps_max IS NULL OR updated_values.resource_timestamp >= #{table_name}.resource_timestamps_max)
)
)
SQL
elsif supports_remote_data_version?(all_attribute_keys)
def update_query_version_conditions(version_attribute)
if version_attribute
# This conditional will avoid rewriting new data by old data. But we want it only when version_attribute is
# a part of the data, since for the fake records, we just want to update ems_ref.
attr_partial = version_attribute.to_s.pluralize # Changes resource_version/timestamp to resource_versions/timestamps
attr_partial_max = "#{attr_partial}_max"

# Quote the column names
attr_full = quote_column_name(version_attribute)
attr_partial_max = quote_column_name(attr_partial_max)

<<-SQL
AND (
updated_values.resource_version IS NULL OR (
(#{table_name}.resource_version IS NULL OR updated_values.resource_version > #{table_name}.resource_version) AND
(#{table_name}.resource_versions_max IS NULL OR updated_values.resource_version >= #{table_name}.resource_versions_max)
updated_values.#{attr_full} IS NULL OR (
(#{q_table_name}.#{attr_full} IS NULL OR updated_values.#{attr_full} > #{q_table_name}.#{attr_full}) AND
(#{q_table_name}.#{attr_partial_max} IS NULL OR updated_values.#{attr_full} >= #{q_table_name}.#{attr_partial_max})
)
)
SQL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def insert_query_insert_values(hashes, all_attribute_keys_array, connection)
col_names = all_attribute_keys_array.map { |x| quote_column_name(x) }.join(",")

<<-SQL
INSERT INTO #{table_name} (#{col_names})
INSERT INTO #{q_table_name} (#{col_names})
VALUES
#{values}
SQL
Expand Down Expand Up @@ -124,14 +124,13 @@ def full_update_condition(attr_full)
, #{attr_partial} = '{}', #{attr_partial_max} = NULL
WHERE EXCLUDED.#{attr_full} IS NULL OR (
(#{table_name}.#{attr_full} IS NULL OR EXCLUDED.#{attr_full} > #{table_name}.#{attr_full}) AND
(#{table_name}.#{attr_partial_max} IS NULL OR EXCLUDED.#{attr_full} >= #{table_name}.#{attr_partial_max})
(#{q_table_name}.#{attr_full} IS NULL OR EXCLUDED.#{attr_full} > #{q_table_name}.#{attr_full}) AND
(#{q_table_name}.#{attr_partial_max} IS NULL OR EXCLUDED.#{attr_full} >= #{q_table_name}.#{attr_partial_max})
)
SQL
end

def partial_update_condition(attr_full, column_name)
# column_name = quote_column_name(column_name)
attr_partial = attr_full.to_s.pluralize # Changes resource_version/timestamp to resource_versions/timestamps
attr_partial_max = "#{attr_partial}_max"
cast = if attr_full == :resource_timestamp
Expand All @@ -144,15 +143,16 @@ def partial_update_condition(attr_full, column_name)
attr_full = quote_column_name(attr_full)
attr_partial = quote_column_name(attr_partial)
attr_partial_max = quote_column_name(attr_partial_max)
# TODO(lsmola) how to quote 'column_name', seems like basic column quoting doesn't work on jsob
column_name = get_connection.quote_string(column_name.to_s)
q_table_name = get_connection.quote_table_name(table_name)

<<-SQL
, #{attr_partial} = #{table_name}.#{attr_partial} || ('{"#{column_name}": "' || EXCLUDED.#{attr_partial_max}::#{cast} || '"}')::jsonb
, #{attr_partial_max} = greatest(#{table_name}.#{attr_partial_max}::#{cast}, EXCLUDED.#{attr_partial_max}::#{cast})
, #{attr_partial} = #{q_table_name}.#{attr_partial} || ('{"#{column_name}": "' || EXCLUDED.#{attr_partial_max}::#{cast} || '"}')::jsonb
, #{attr_partial_max} = greatest(#{q_table_name}.#{attr_partial_max}::#{cast}, EXCLUDED.#{attr_partial_max}::#{cast})
WHERE EXCLUDED.#{attr_partial_max} IS NULL OR (
(#{table_name}.#{attr_full} IS NULL OR EXCLUDED.#{attr_partial_max} > #{table_name}.#{attr_full}) AND (
(#{table_name}.#{attr_partial}->>'#{column_name}')::#{cast} IS NULL OR
EXCLUDED.#{attr_partial_max}::#{cast} > (#{table_name}.#{attr_partial}->>'#{column_name}')::#{cast}
(#{q_table_name}.#{attr_full} IS NULL OR EXCLUDED.#{attr_partial_max} > #{q_table_name}.#{attr_full}) AND (
(#{q_table_name}.#{attr_partial}->>'#{column_name}')::#{cast} IS NULL OR
EXCLUDED.#{attr_partial_max}::#{cast} > (#{q_table_name}.#{attr_partial}->>'#{column_name}')::#{cast}
)
)
SQL
Expand All @@ -171,7 +171,7 @@ def insert_query_returning_timestamps
# updated
if inventory_collection.internal_timestamp_columns.present?
<<-SQL
, #{inventory_collection.internal_timestamp_columns.join(",")}
, #{inventory_collection.internal_timestamp_columns.map { |x| quote_column_name(x) }.join(",")}
SQL
end
else
Expand Down

0 comments on commit f97643e

Please sign in to comment.