From f45eb88593e5b15e06006a0bb6674c68e050743b Mon Sep 17 00:00:00 2001 From: Uri Mikhli Date: Wed, 13 Apr 2016 21:53:26 -0400 Subject: [PATCH 1/3] extract the sql names, values and pairs so we can work on them independently --- lib/upsert/merge_function/postgresql.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/upsert/merge_function/postgresql.rb b/lib/upsert/merge_function/postgresql.rb index d7ea270..c8d7337 100644 --- a/lib/upsert/merge_function/postgresql.rb +++ b/lib/upsert/merge_function/postgresql.rb @@ -103,6 +103,10 @@ def update_column_definitions def create! Upsert.logger.info "[upsert] Creating or replacing database function #{name.inspect} on table #{table_name.inspect} for selector #{selector_keys.map(&:inspect).join(', ')} and setter #{setter_keys.map(&:inspect).join(', ')}" first_try = true + + names = setter_column_definitions.map(&:quoted_name).join(', ') + values = setter_column_definitions.map(&:to_setter_value).join(', ') + update_pair = update_column_definitions.map(&:to_setter).join(', ') connection.execute(%{ CREATE OR REPLACE FUNCTION #{name}(#{(selector_column_definitions.map(&:to_selector_arg) + setter_column_definitions.map(&:to_setter_arg) + hstore_delete_handlers.map(&:to_arg)).join(', ')}) RETURNS VOID AS $$ @@ -111,7 +115,7 @@ def create! BEGIN LOOP -- first try to update the key - UPDATE #{quoted_table_name} SET #{update_column_definitions.map(&:to_setter).join(', ')} + UPDATE #{quoted_table_name} SET #{update_pair} WHERE #{selector_column_definitions.map(&:to_selector).join(' AND ') }; IF found THEN #{hstore_delete_handlers.map(&:to_pgsql).join(' ')} @@ -121,7 +125,7 @@ def create! -- if someone else inserts the same key concurrently, -- we could get a unique-key failure BEGIN - INSERT INTO #{quoted_table_name}(#{setter_column_definitions.map(&:quoted_name).join(', ')}) VALUES (#{setter_column_definitions.map(&:to_setter_value).join(', ')}); + INSERT INTO #{quoted_table_name}(#{names}) VALUES (#{values}); #{hstore_delete_handlers.map(&:to_pgsql).join(' ')} RETURN; EXCEPTION WHEN unique_violation THEN From e287013c22b2a671abf27387e18ae3c910dbb234 Mon Sep 17 00:00:00 2001 From: Uri Mikhli Date: Wed, 13 Apr 2016 21:55:06 -0400 Subject: [PATCH 2/3] check that the rails timestamp vars are present and if so add appropriate field/values to the sql. --- lib/upsert/merge_function/postgresql.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/upsert/merge_function/postgresql.rb b/lib/upsert/merge_function/postgresql.rb index c8d7337..af932ec 100644 --- a/lib/upsert/merge_function/postgresql.rb +++ b/lib/upsert/merge_function/postgresql.rb @@ -91,10 +91,12 @@ def selector_column_definitions end def setter_column_definitions + @time_stamp_cols = column_definitions.select{|cd| cd.name == 'created_at' || cd.name == 'updated_at'} column_definitions.select { |cd| setter_keys.include?(cd.name) } end def update_column_definitions + @update_time_stamp_cols = column_definitions.select{|cd| cd.name == 'updated_at'} setter_column_definitions.select { |cd| cd.name !~ CREATED_COL_REGEX } end @@ -107,6 +109,15 @@ def create! names = setter_column_definitions.map(&:quoted_name).join(', ') values = setter_column_definitions.map(&:to_setter_value).join(', ') update_pair = update_column_definitions.map(&:to_setter).join(', ') + if @time_stamp_cols.count > 0 + names += ', created_at, updated_at' + values += ", now(), now()" + end + @time_stamp_cols=[] + if @update_time_stamp_cols.count > 0 + update_pair += ", updated_at = now()" + end + @update_time_stamp_cols=[] connection.execute(%{ CREATE OR REPLACE FUNCTION #{name}(#{(selector_column_definitions.map(&:to_selector_arg) + setter_column_definitions.map(&:to_setter_arg) + hstore_delete_handlers.map(&:to_arg)).join(', ')}) RETURNS VOID AS $$ From 307845d72acccc522f5189067ee422fc2615acd4 Mon Sep 17 00:00:00 2001 From: Uri Mikhli Date: Wed, 13 Apr 2016 21:56:35 -0400 Subject: [PATCH 3/3] give credit for idea...https://github.com/seamusabshere/upsert/pull/65 --- lib/upsert/merge_function/postgresql.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/upsert/merge_function/postgresql.rb b/lib/upsert/merge_function/postgresql.rb index af932ec..2441ea5 100644 --- a/lib/upsert/merge_function/postgresql.rb +++ b/lib/upsert/merge_function/postgresql.rb @@ -109,6 +109,7 @@ def create! names = setter_column_definitions.map(&:quoted_name).join(', ') values = setter_column_definitions.map(&:to_setter_value).join(', ') update_pair = update_column_definitions.map(&:to_setter).join(', ') + #Solution based on based on https://github.com/seamusabshere/upsert/pull/65 if @time_stamp_cols.count > 0 names += ', created_at, updated_at' values += ", now(), now()"