Module: ActiveRecord::Materialized::WriteOutbox::Triggers::PostgreSQL

Defined in:
lib/activerecord/materialized/write_outbox.rb

Overview

Postgres: a single trigger function branches on TG_OP and fires for all three events. jsonb_build_object(...)::text so the images land in the text outbox columns.

Class Method Summary collapse

Class Method Details

.function(connection, table, ops) ⇒ Object

The dollar-quoted ($fn$) body avoids escaping the single quotes in the JSON key literals. ops is indexed by event: insert, then update, then destroy.



326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
# File 'lib/activerecord/materialized/write_outbox.rb', line 326

def function(connection, table, ops)
  insert, update, destroy = ops
  <<~SQL.squish
    CREATE OR REPLACE FUNCTION #{connection.quote_column_name("#{SharedSql.trigger_base(table)}_fn")}()
    RETURNS trigger AS $fn$
    BEGIN
      IF (TG_OP = 'INSERT') THEN #{SharedSql.insert_values(connection, table, insert)};
      ELSIF (TG_OP = 'UPDATE') THEN #{SharedSql.insert_values(connection, table, update)};
      ELSE #{SharedSql.insert_values(connection, table, destroy)};
      END IF;
      RETURN NULL;
    END;
    $fn$ LANGUAGE plpgsql
  SQL
end

.install!(connection, table, key_columns) ⇒ Object



303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/activerecord/materialized/write_outbox.rb', line 303

def install!(connection, table, key_columns)
  uninstall!(connection, table)
  base = SharedSql.trigger_base(table)
  before = "#{SharedSql.json_object(connection, 'jsonb_build_object', 'OLD', key_columns)}::text"
  after = "#{SharedSql.json_object(connection, 'jsonb_build_object', 'NEW', key_columns)}::text"
  connection.execute(function(connection, table, SharedSql.ops(before, after)))
  connection.execute(<<~SQL.squish)
    CREATE TRIGGER #{connection.quote_column_name(base)}
    AFTER INSERT OR UPDATE OR DELETE ON #{connection.quote_table_name(table)}
    FOR EACH ROW EXECUTE FUNCTION #{connection.quote_column_name("#{base}_fn")}()
  SQL
end

.uninstall!(connection, table) ⇒ Object



316
317
318
319
320
321
322
# File 'lib/activerecord/materialized/write_outbox.rb', line 316

def uninstall!(connection, table)
  base = SharedSql.trigger_base(table)
  connection.execute(
    "DROP TRIGGER IF EXISTS #{connection.quote_column_name(base)} ON #{connection.quote_table_name(table)}"
  )
  connection.execute("DROP FUNCTION IF EXISTS #{connection.quote_column_name("#{base}_fn")}()")
end