Class: IronTrail::DbFunctions
- Inherits:
-
Object
- Object
- IronTrail::DbFunctions
- Defined in:
- lib/iron_trail/db_functions.rb
Instance Attribute Summary collapse
-
#connection ⇒ Object
readonly
Returns the value of attribute connection.
Instance Method Summary collapse
- #collect_all_tables(schema: 'public') ⇒ Object
- #collect_tables_tracking_status ⇒ Object
-
#collect_tracked_table_names ⇒ Object
Queries the database information schema and returns an array with all table names that have the “iron_trail_log_changes” trigger enabled.
- #disable_for_all_ignored_tables ⇒ Object
- #disable_tracking_for_table(table_name) ⇒ Object
- #enable_for_all_missing_tables ⇒ Object
- #enable_tracking_for_table(table_name) ⇒ Object
- #function_present?(function: 'irontrail_log_row', schema: 'public') ⇒ Boolean
-
#initialize(connection) ⇒ DbFunctions
constructor
A new instance of DbFunctions.
-
#install_functions ⇒ Object
Creates the SQL functions in the DB.
- #irontrail_log_row_function ⇒ Object
- #remove_functions(cascade:) ⇒ Object
- #trigger_errors_count ⇒ Object
Constructor Details
#initialize(connection) ⇒ DbFunctions
Returns a new instance of DbFunctions.
7 8 9 |
# File 'lib/iron_trail/db_functions.rb', line 7 def initialize(connection) @connection = connection end |
Instance Attribute Details
#connection ⇒ Object (readonly)
Returns the value of attribute connection.
5 6 7 |
# File 'lib/iron_trail/db_functions.rb', line 5 def connection @connection end |
Instance Method Details
#collect_all_tables(schema: 'public') ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/iron_trail/db_functions.rb', line 64 def collect_all_tables(schema: 'public') # query pg_class rather than information schema because this way # we can get only regular tables and ignore partitions. stmt = <<~SQL SELECT c.relname AS "table" FROM "pg_class" c INNER JOIN "pg_namespace" ns ON (ns.oid = c.relnamespace) WHERE ns.nspname=#{connection.quote(schema)} AND c.relkind IN ('r', 'p') AND NOT c.relispartition ORDER BY "table" ASC; SQL connection.execute(stmt).map { |row| row['table'] } end |
#collect_tables_tracking_status ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/iron_trail/db_functions.rb', line 98 def collect_tables_tracking_status ignored_tables = OWN_TABLES + (IronTrail.config.ignored_tables || []) all_tables = collect_all_tables - ignored_tables tracked_tables = collect_tracked_table_names - ignored_tables { tracked: tracked_tables, missing: all_tables - tracked_tables } end |
#collect_tracked_table_names ⇒ Object
Queries the database information schema and returns an array with all table names that have the “iron_trail_log_changes” trigger enabled.
This effectively returns all tables which are currently being tracked by IronTrail.
28 29 30 31 32 33 34 35 36 37 |
# File 'lib/iron_trail/db_functions.rb', line 28 def collect_tracked_table_names stmt = <<~SQL SELECT DISTINCT("event_object_table") AS "table" FROM "information_schema"."triggers" WHERE "trigger_name"='iron_trail_log_changes' AND "event_object_schema"='public' ORDER BY "table" ASC; SQL connection.execute(stmt).map { |row| row['table'] } end |
#disable_for_all_ignored_tables ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/iron_trail/db_functions.rb', line 86 def disable_for_all_ignored_tables affected_tables = collect_tracked_table_names & ( OWN_TABLES + (IronTrail.config.ignored_tables || []) ) affected_tables.each do |table_name| disable_tracking_for_table(table_name) end affected_tables end |
#disable_tracking_for_table(table_name) ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/iron_trail/db_functions.rb', line 110 def disable_tracking_for_table(table_name) # Note: will disable even if table is ignored as this allows # one to fix ignored tables mnore easily. Since the table is already # ignored, it is an expected destructive operation. stmt = <<~SQL DROP TRIGGER "iron_trail_log_changes" ON #{connection.quote_table_name(table_name)} SQL connection.execute(stmt) end |
#enable_for_all_missing_tables ⇒ Object
80 81 82 83 84 |
# File 'lib/iron_trail/db_functions.rb', line 80 def enable_for_all_missing_tables collect_tables_tracking_status[:missing].each do |table_name| enable_tracking_for_table(table_name) end end |
#enable_tracking_for_table(table_name) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/iron_trail/db_functions.rb', line 123 def enable_tracking_for_table(table_name) return false if IronTrail.ignore_table?(table_name) stmt = <<~SQL CREATE TRIGGER "iron_trail_log_changes" AFTER INSERT OR UPDATE OR DELETE ON #{connection.quote_table_name(table_name)} FOR EACH ROW EXECUTE FUNCTION irontrail_log_row(); SQL connection.execute(stmt) end |
#function_present?(function: 'irontrail_log_row', schema: 'public') ⇒ Boolean
39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/iron_trail/db_functions.rb', line 39 def function_present?(function: 'irontrail_log_row', schema: 'public') stmt = <<~SQL SELECT 1 FROM "pg_proc" p INNER JOIN "pg_namespace" ns ON (ns.oid = p.pronamespace) WHERE p."proname"=#{connection.quote(function)} AND ns."nspname"=#{connection.quote(schema)} LIMIT 1; SQL connection.execute(stmt).to_a.count > 0 end |
#install_functions ⇒ Object
Creates the SQL functions in the DB. It will not run the function or create any triggers.
13 14 15 16 |
# File 'lib/iron_trail/db_functions.rb', line 13 def install_functions sql = irontrail_log_row_function connection.execute(sql) end |
#irontrail_log_row_function ⇒ Object
18 19 20 21 |
# File 'lib/iron_trail/db_functions.rb', line 18 def irontrail_log_row_function path = File.('irontrail_log_row_function.sql', __dir__) File.read(path) end |
#remove_functions(cascade:) ⇒ Object
52 53 54 55 56 57 |
# File 'lib/iron_trail/db_functions.rb', line 52 def remove_functions(cascade:) query = +"DROP FUNCTION irontrail_log_row" query << " CASCADE" if cascade connection.execute(query) end |
#trigger_errors_count ⇒ Object
59 60 61 62 |
# File 'lib/iron_trail/db_functions.rb', line 59 def trigger_errors_count stmt = 'SELECT COUNT(*) AS c FROM "irontrail_trigger_errors"' connection.execute(stmt).first['c'] end |