Class: IronTrail::DbFunctions

Inherits:
Object
  • Object
show all
Defined in:
lib/iron_trail/db_functions.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(connection) ⇒ DbFunctions



7
8
9
# File 'lib/iron_trail/db_functions.rb', line 7

def initialize(connection)
  @connection = connection
end

Instance Attribute Details

#connectionObject (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 = "    SELECT c.relname AS \"table\"\n    FROM \"pg_class\" c INNER JOIN \"pg_namespace\" ns\n    ON (ns.oid = c.relnamespace)\n    WHERE ns.nspname=\#{connection.quote(schema)}\n      AND c.relkind IN ('r', 'p')\n      AND NOT c.relispartition\n    ORDER BY \"table\" ASC;\n  SQL\n\n  connection.execute(stmt).map { |row| row['table'] }\nend\n"

#collect_tables_tracking_statusObject



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_namesObject

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 = "    SELECT DISTINCT(\"event_object_table\") AS \"table\"\n    FROM \"information_schema\".\"triggers\"\n    WHERE \"trigger_name\"='iron_trail_log_changes' AND \"event_object_schema\"='public'\n    ORDER BY \"table\" ASC;\n  SQL\n\n  connection.execute(stmt).map { |row| row['table'] }\nend\n"

#disable_for_all_ignored_tablesObject



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 = "    DROP TRIGGER \"iron_trail_log_changes\" ON\n    \#{connection.quote_table_name(table_name)}\n  SQL\n\n  connection.execute(stmt)\nend\n"

#enable_for_all_missing_tablesObject



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 = "    CREATE TRIGGER \"iron_trail_log_changes\" AFTER INSERT OR UPDATE OR DELETE ON\n    \#{connection.quote_table_name(table_name)}\n    FOR EACH ROW EXECUTE FUNCTION irontrail_log_row();\n  SQL\n\n  connection.execute(stmt)\nend\n"

#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 = "    SELECT 1 FROM \"pg_proc\" p\n    INNER JOIN \"pg_namespace\" ns\n    ON (ns.oid = p.pronamespace)\n    WHERE p.\"proname\"=\#{connection.quote(function)}\n      AND ns.\"nspname\"=\#{connection.quote(schema)}\n    LIMIT 1;\n  SQL\n\n  connection.execute(stmt).to_a.count > 0\nend\n"

#install_functionsObject

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_functionObject



18
19
20
21
# File 'lib/iron_trail/db_functions.rb', line 18

def irontrail_log_row_function
  path = File.expand_path('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_countObject



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