pg_fts 0.0.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,503 @@
1
+ # many documents, one link, many links, one source
2
+ class PG::FTS::Index::MOMO
3
+ attr_reader :table, :fields, :catalog,
4
+ :document, :link,
5
+ :key, :foreign_key, :forlink_key,
6
+ :name
7
+ alias source table
8
+
9
+ include PG::FTS::Index
10
+ include PG::FTS::Naming
11
+ include PG::FTS::TSVector
12
+
13
+ # rubocop:disable Metrics/ParameterLists, Metrics/CyclomaticComplexity
14
+ def initialize(table, *fields,
15
+ document: nil, link: nil,
16
+ key: nil, foreign_key: nil, forlink_key: nil,
17
+ catalog: nil,
18
+ as: nil)
19
+ @table = table
20
+ @fields = fields
21
+ @catalog = catalog || PG::FTS.catalog
22
+ @document = document || fail(ArgumentError, ':document required')
23
+ @link = link || fail(ArgumentError, ':link required')
24
+ @key = key || :id
25
+ @foreign_key = foreign_key || :"#{table}_id"
26
+ @forlink_key = forlink_key || :"#{link}_id"
27
+ @name = as
28
+ end
29
+ # rubocop:enable Metrics/ParameterLists, Metrics/CyclomaticComplexity
30
+
31
+ def build_query
32
+ <<-SQL.gsub(/^ {4}/, '')
33
+ INSERT INTO "#{PG::FTS.table}" (
34
+ "document_id",
35
+ "document_table",
36
+ "source_id",
37
+ "source_table",
38
+ "tsv")
39
+ SELECT "#{document}"."#{key}",
40
+ '#{document}',
41
+ "#{source}"."#{key}",
42
+ '#{source}',
43
+ #{ts_vector(source)}
44
+ FROM "#{document}", "#{source}", "#{link}"
45
+ WHERE "#{document}"."#{forlink_key}" = "#{link}"."#{key}"
46
+ AND "#{link}"."#{foreign_key}" = "#{source}"."#{key}";
47
+ SQL
48
+ end
49
+
50
+ def on_source_insert_query
51
+ <<-SQL.gsub(/^ {4}/, '')
52
+ INSERT INTO "#{PG::FTS.table}" (
53
+ "document_id",
54
+ "document_table",
55
+ "source_id",
56
+ "source_table",
57
+ "tsv")
58
+ SELECT
59
+ "#{document}"."#{key}",
60
+ '#{document}',
61
+ NEW."#{key}",
62
+ '#{source}',
63
+ #{ts_vector}
64
+ FROM "#{document}", "#{link}"
65
+ WHERE "#{document}"."#{forlink_key}" = "#{link}"."#{key}"
66
+ AND "#{link}"."#{foreign_key}" = NEW."#{key}";
67
+ SQL
68
+ end
69
+
70
+ def on_source_insert_procedure
71
+ <<-SQL.gsub(/^ {4}/, '')
72
+ CREATE FUNCTION "#{on_source_insert_procedure_name}"()
73
+ RETURNS TRIGGER AS $$
74
+ BEGIN
75
+ #{on_source_insert_query.gsub(/^/, ' ')}
76
+ RETURN NEW;
77
+ END;
78
+ $$ LANGUAGE plpgsql;
79
+ SQL
80
+ end
81
+
82
+ def on_source_update_query
83
+ <<-SQL.gsub(/^ {4}/, '')
84
+ UPDATE "#{PG::FTS.table}"
85
+ SET
86
+ "tsv" = (#{ts_vector}),
87
+ "document_table" = '#{document}',
88
+ "document_id" = "#{document}"."#{key}"
89
+ FROM "#{document}", "#{link}"
90
+ WHERE "#{document}"."#{forlink_key}" = "#{link}"."#{key}"
91
+ AND "#{link}"."#{foreign_key}" = NEW."#{key}"
92
+ AND "#{PG::FTS.table}"."source_id" = OLD."#{key}"
93
+ AND "#{PG::FTS.table}"."source_table" = '#{source}'
94
+ AND "#{PG::FTS.table}"."document_id" = "#{document}"."#{key}"
95
+ AND "#{PG::FTS.table}"."document_table" = '#{document}';
96
+ SQL
97
+ end
98
+
99
+ def on_source_update_procedure
100
+ <<-SQL.gsub(/^ {4}/, '')
101
+ CREATE FUNCTION "#{on_source_update_procedure_name}"()
102
+ RETURNS TRIGGER AS $$
103
+ BEGIN
104
+ #{on_source_update_query.gsub(/^/, ' ')}
105
+ RETURN NEW;
106
+ END;
107
+ $$ LANGUAGE plpgsql;
108
+ SQL
109
+ end
110
+
111
+ def on_source_delete_query
112
+ <<-SQL.gsub(/^ {4}/, '')
113
+ DELETE FROM "#{PG::FTS.table}"
114
+ WHERE "#{PG::FTS.table}"."source_id" = OLD."#{key}"
115
+ AND "#{PG::FTS.table}"."source_table" = '#{source}'
116
+ AND "#{PG::FTS.table}"."document_table" = '#{document}';
117
+ SQL
118
+ end
119
+
120
+ def on_source_delete_procedure
121
+ <<-SQL.gsub(/^ {4}/, '')
122
+ CREATE FUNCTION "#{on_source_delete_procedure_name}"()
123
+ RETURNS TRIGGER AS $$
124
+ BEGIN
125
+ #{on_source_delete_query.gsub(/^/, ' ')}
126
+ RETURN OLD;
127
+ END;
128
+ $$ LANGUAGE plpgsql;
129
+ SQL
130
+ end
131
+
132
+ def on_source_truncate_query
133
+ <<-SQL.gsub(/^ {4}/, '')
134
+ DELETE FROM "#{PG::FTS.table}"
135
+ WHERE "#{PG::FTS.table}"."source_table" = '#{source}'
136
+ AND "#{PG::FTS.table}"."document_table" = '#{document}';
137
+ SQL
138
+ end
139
+
140
+ def on_source_truncate_procedure
141
+ <<-SQL.gsub(/^ {4}/, '')
142
+ CREATE FUNCTION "#{on_source_truncate_procedure_name}"()
143
+ RETURNS TRIGGER AS $$
144
+ BEGIN
145
+ #{on_source_truncate_query.gsub(/^/, ' ')}
146
+ RETURN NULL;
147
+ END;
148
+ $$ LANGUAGE plpgsql;
149
+ SQL
150
+ end
151
+
152
+ def on_source_insert_trigger
153
+ <<-SQL.gsub(/^ {4}/, '')
154
+ CREATE TRIGGER "#{on_source_insert_trigger_name}"
155
+ AFTER INSERT ON "#{source}"
156
+ FOR EACH ROW
157
+ EXECUTE PROCEDURE "#{on_source_insert_procedure_name}"();
158
+ SQL
159
+ end
160
+
161
+ def on_source_update_trigger
162
+ <<-SQL.gsub(/^ {4}/, '')
163
+ CREATE TRIGGER "#{on_source_update_trigger_name}"
164
+ AFTER UPDATE ON "#{source}"
165
+ FOR EACH ROW
166
+ EXECUTE PROCEDURE "#{on_source_update_procedure_name}"();
167
+ SQL
168
+ end
169
+
170
+ def on_source_delete_trigger
171
+ <<-SQL.gsub(/^ {4}/, '')
172
+ CREATE TRIGGER "#{on_source_delete_trigger_name}"
173
+ AFTER DELETE ON "#{source}"
174
+ FOR EACH ROW
175
+ EXECUTE PROCEDURE "#{on_source_delete_procedure_name}"();
176
+ SQL
177
+ end
178
+
179
+ def on_source_truncate_trigger
180
+ <<-SQL.gsub(/^ {4}/, '')
181
+ CREATE TRIGGER "#{on_source_truncate_trigger_name}"
182
+ AFTER TRUNCATE ON "#{source}"
183
+ FOR EACH STATEMENT
184
+ EXECUTE PROCEDURE "#{on_source_truncate_procedure_name}"();
185
+ SQL
186
+ end
187
+
188
+ def on_document_insert_query
189
+ <<-SQL.gsub(/^ {4}/, '')
190
+ INSERT INTO "#{PG::FTS.table}" (
191
+ "document_id",
192
+ "document_table",
193
+ "source_id",
194
+ "source_table",
195
+ "tsv")
196
+ SELECT
197
+ NEW."#{key}",
198
+ '#{document}',
199
+ "#{source}"."#{key}",
200
+ '#{source}',
201
+ #{ts_vector(source)}
202
+ FROM "#{source}", "#{link}"
203
+ WHERE "#{source}"."#{key}" = "#{link}"."#{foreign_key}"
204
+ AND "#{link}"."#{key}" = NEW."#{forlink_key}";
205
+ SQL
206
+ end
207
+
208
+ def on_document_insert_procedure
209
+ <<-SQL.gsub(/^ {4}/, '')
210
+ CREATE FUNCTION "#{on_document_insert_procedure_name}"()
211
+ RETURNS TRIGGER AS $$
212
+ BEGIN
213
+ IF NEW."#{forlink_key}" IS NULL THEN
214
+ RETURN NEW;
215
+ END IF;
216
+ #{on_document_insert_query.gsub(/^/, ' ')}
217
+ RETURN NEW;
218
+ END;
219
+ $$ LANGUAGE plpgsql;
220
+ SQL
221
+ end
222
+
223
+ def on_document_update_query
224
+ <<-SQL.gsub(/^ {4}/, '')
225
+ UPDATE "#{PG::FTS.table}"
226
+ SET
227
+ "tsv" = (#{ts_vector(source)}),
228
+ "source_table" = '#{source}',
229
+ "source_id" = "#{source}"."#{key}"
230
+ FROM "#{source}" AS "OLD_#{source}", "#{source}",
231
+ "#{link}" AS "OLD_#{link}", "#{link}"
232
+ WHERE "OLD_#{source}"."#{key}" = "OLD_#{link}"."#{foreign_key}"
233
+ AND "OLD_#{link}"."#{key}" = OLD."#{forlink_key}"
234
+ AND "#{source}"."#{key}" = "#{link}"."#{foreign_key}"
235
+ AND "#{link}"."#{key}" = NEW."#{forlink_key}"
236
+ AND "#{PG::FTS.table}"."source_id" = "OLD_#{link}"."#{foreign_key}"
237
+ AND "#{PG::FTS.table}"."source_table" = '#{source}'
238
+ AND "#{PG::FTS.table}"."document_id" = OLD."#{key}"
239
+ AND "#{PG::FTS.table}"."document_table" = '#{document}';
240
+ SQL
241
+ end
242
+
243
+ def on_document_update_procedure
244
+ <<-SQL.gsub(/^ {4}/, '')
245
+ CREATE FUNCTION "#{on_document_update_procedure_name}"()
246
+ RETURNS TRIGGER AS $$
247
+ BEGIN
248
+ IF NEW."#{forlink_key}" IS NULL AND OLD."#{forlink_key}" IS NULL THEN
249
+ RETURN NEW;
250
+ END IF;
251
+ IF NEW."#{forlink_key}" IS NULL THEN
252
+ #{on_document_delete_query.gsub(/^/, ' ')}
253
+ RETURN NEW;
254
+ END IF;
255
+ IF OLD."#{forlink_key}" IS NULL THEN
256
+ #{on_document_insert_query.gsub(/^/, ' ')}
257
+ RETURN NEW;
258
+ END IF;
259
+ #{on_document_update_query.gsub(/^/, ' ')}
260
+ IF NOT FOUND THEN
261
+ #{on_document_insert_query.gsub(/^/, ' ')}
262
+ IF NOT FOUND THEN
263
+ #{on_document_delete_query.gsub(/^/, ' ')}
264
+ END IF;
265
+ RETURN NEW;
266
+ END IF;
267
+ RETURN NEW;
268
+ END;
269
+ $$ LANGUAGE plpgsql;
270
+ SQL
271
+ end
272
+
273
+ def on_document_delete_query
274
+ <<-SQL.gsub(/^ {4}/, '')
275
+ DELETE FROM "#{PG::FTS.table}"
276
+ USING "#{link}"
277
+ WHERE "#{link}"."#{key}" = OLD."#{forlink_key}"
278
+ AND "#{PG::FTS.table}"."source_id" = "#{link}"."#{foreign_key}"
279
+ AND "#{PG::FTS.table}"."source_table" = '#{source}'
280
+ AND "#{PG::FTS.table}"."document_id" = OLD."#{key}"
281
+ AND "#{PG::FTS.table}"."document_table" = '#{document}';
282
+ SQL
283
+ end
284
+
285
+ def on_document_delete_procedure
286
+ <<-SQL.gsub(/^ {4}/, '')
287
+ CREATE FUNCTION "#{on_document_delete_procedure_name}"()
288
+ RETURNS TRIGGER AS $$
289
+ BEGIN
290
+ #{on_document_delete_query.gsub(/^/, ' ')}
291
+ RETURN OLD;
292
+ END;
293
+ $$ LANGUAGE plpgsql;
294
+ SQL
295
+ end
296
+
297
+ def on_document_truncate_query
298
+ <<-SQL.gsub(/^ {4}/, '')
299
+ DELETE FROM "#{PG::FTS.table}"
300
+ WHERE "#{PG::FTS.table}"."source_table" = '#{source}'
301
+ AND "#{PG::FTS.table}"."document_table" = '#{document}';
302
+ SQL
303
+ end
304
+
305
+ def on_document_truncate_procedure
306
+ <<-SQL.gsub(/^ {4}/, '')
307
+ CREATE FUNCTION "#{on_document_truncate_procedure_name}"()
308
+ RETURNS TRIGGER AS $$
309
+ BEGIN
310
+ #{on_document_truncate_query.gsub(/^/, ' ')}
311
+ RETURN NULL;
312
+ END;
313
+ $$ LANGUAGE plpgsql;
314
+ SQL
315
+ end
316
+
317
+ def on_document_insert_trigger
318
+ <<-SQL.gsub(/^ {4}/, '')
319
+ CREATE TRIGGER "#{on_document_insert_trigger_name}"
320
+ AFTER INSERT ON "#{document}"
321
+ FOR EACH ROW
322
+ EXECUTE PROCEDURE "#{on_document_insert_procedure_name}"();
323
+ SQL
324
+ end
325
+
326
+ def on_document_update_trigger
327
+ <<-SQL.gsub(/^ {4}/, '')
328
+ CREATE TRIGGER "#{on_document_update_trigger_name}"
329
+ AFTER UPDATE ON "#{document}"
330
+ FOR EACH ROW
331
+ EXECUTE PROCEDURE "#{on_document_update_procedure_name}"();
332
+ SQL
333
+ end
334
+
335
+ def on_document_delete_trigger
336
+ <<-SQL.gsub(/^ {4}/, '')
337
+ CREATE TRIGGER "#{on_document_delete_trigger_name}"
338
+ AFTER DELETE ON "#{document}"
339
+ FOR EACH ROW
340
+ EXECUTE PROCEDURE "#{on_document_delete_procedure_name}"();
341
+ SQL
342
+ end
343
+
344
+ def on_document_truncate_trigger
345
+ <<-SQL.gsub(/^ {4}/, '')
346
+ CREATE TRIGGER "#{on_document_truncate_trigger_name}"
347
+ AFTER TRUNCATE ON "#{document}"
348
+ FOR EACH STATEMENT
349
+ EXECUTE PROCEDURE "#{on_document_truncate_procedure_name}"();
350
+ SQL
351
+ end
352
+
353
+ def on_link_insert_query
354
+ <<-SQL.gsub(/^ {4}/, '')
355
+ INSERT INTO "#{PG::FTS.table}" (
356
+ "document_id",
357
+ "document_table",
358
+ "source_id",
359
+ "source_table",
360
+ "tsv")
361
+ SELECT
362
+ "#{document}"."#{key}",
363
+ '#{document}',
364
+ "#{source}"."#{key}",
365
+ '#{source}',
366
+ #{ts_vector(source)}
367
+ FROM "#{document}", "#{source}"
368
+ WHERE "#{document}"."#{forlink_key}" = NEW."#{key}"
369
+ AND "#{source}"."#{key}" = NEW."#{foreign_key}";
370
+ SQL
371
+ end
372
+
373
+ def on_link_insert_procedure
374
+ <<-SQL.gsub(/^ {4}/, '')
375
+ CREATE FUNCTION "#{on_link_insert_procedure_name}"()
376
+ RETURNS TRIGGER AS $$
377
+ BEGIN
378
+ #{on_link_insert_query.gsub(/^/, ' ')}
379
+ RETURN NEW;
380
+ END;
381
+ $$ LANGUAGE plpgsql;
382
+ SQL
383
+ end
384
+
385
+ def on_link_update_query
386
+ <<-SQL.gsub(/^ {4}/, '')
387
+ UPDATE "#{PG::FTS.table}"
388
+ SET
389
+ "tsv" = (#{ts_vector(source)}),
390
+ "document_table" = '#{document}',
391
+ "document_id" = "#{document}"."#{key}",
392
+ "source_table" = '#{source}',
393
+ "source_id" = NEW."#{foreign_key}"
394
+ FROM "#{document}", "#{link}", "#{source}"
395
+ WHERE "#{document}"."#{forlink_key}" = OLD."#{key}"
396
+ AND NEW."#{foreign_key}" = "#{source}"."#{key}"
397
+ AND "#{PG::FTS.table}"."source_id" = OLD."#{foreign_key}"
398
+ AND "#{PG::FTS.table}"."source_table" = '#{source}'
399
+ AND "#{PG::FTS.table}"."document_id" = "#{document}"."#{key}"
400
+ AND "#{PG::FTS.table}"."document_table" = '#{document}';
401
+ SQL
402
+ end
403
+
404
+ def on_link_update_procedure
405
+ <<-SQL.gsub(/^ {4}/, '')
406
+ CREATE FUNCTION "#{on_link_update_procedure_name}"()
407
+ RETURNS TRIGGER AS $$
408
+ BEGIN
409
+ #{on_link_update_query.gsub(/^/, ' ')}
410
+ IF NOT FOUND THEN
411
+ #{on_link_insert_query.gsub(/^/, ' ')}
412
+ IF NOT FOUND THEN
413
+ #{on_link_delete_query.gsub(/^/, ' ')}
414
+ END IF;
415
+ RETURN NEW;
416
+ END IF;
417
+ RETURN NEW;
418
+ END;
419
+ $$ LANGUAGE plpgsql;
420
+ SQL
421
+ end
422
+
423
+ def on_link_delete_query
424
+ <<-SQL.gsub(/^ {4}/, '')
425
+ DELETE FROM "#{PG::FTS.table}"
426
+ USING "#{link}", "#{document}", "#{source}"
427
+ WHERE OLD."#{key}" = "#{document}"."#{forlink_key}"
428
+ AND OLD."#{foreign_key}" = "#{source}"."#{key}"
429
+ AND "#{PG::FTS.table}"."source_id" = "#{source}"."#{key}"
430
+ AND "#{PG::FTS.table}"."source_table" = '#{source}'
431
+ AND "#{PG::FTS.table}"."document_id" = "#{document}"."#{key}"
432
+ AND "#{PG::FTS.table}"."document_table" = '#{document}';
433
+ SQL
434
+ end
435
+
436
+ def on_link_delete_procedure
437
+ <<-SQL.gsub(/^ {4}/, '')
438
+ CREATE FUNCTION "#{on_link_delete_procedure_name}"()
439
+ RETURNS TRIGGER AS $$
440
+ BEGIN
441
+ #{on_link_delete_query.gsub(/^/, ' ')}
442
+ RETURN OLD;
443
+ END;
444
+ $$ LANGUAGE plpgsql;
445
+ SQL
446
+ end
447
+
448
+ def on_link_truncate_query
449
+ <<-SQL.gsub(/^ {4}/, '')
450
+ DELETE FROM "#{PG::FTS.table}"
451
+ WHERE "#{PG::FTS.table}"."source_table" = '#{source}'
452
+ AND "#{PG::FTS.table}"."document_table" = '#{document}';
453
+ SQL
454
+ end
455
+
456
+ def on_link_truncate_procedure
457
+ <<-SQL.gsub(/^ {4}/, '')
458
+ CREATE FUNCTION "#{on_link_truncate_procedure_name}"()
459
+ RETURNS TRIGGER AS $$
460
+ BEGIN
461
+ #{on_link_truncate_query.gsub(/^/, ' ')}
462
+ RETURN NULL;
463
+ END;
464
+ $$ LANGUAGE plpgsql;
465
+ SQL
466
+ end
467
+
468
+ def on_link_insert_trigger
469
+ <<-SQL.gsub(/^ {4}/, '')
470
+ CREATE TRIGGER "#{on_link_insert_trigger_name}"
471
+ AFTER INSERT ON "#{link}"
472
+ FOR EACH ROW
473
+ EXECUTE PROCEDURE "#{on_link_insert_procedure_name}"();
474
+ SQL
475
+ end
476
+
477
+ def on_link_update_trigger
478
+ <<-SQL.gsub(/^ {4}/, '')
479
+ CREATE TRIGGER "#{on_link_update_trigger_name}"
480
+ AFTER UPDATE ON "#{link}"
481
+ FOR EACH ROW
482
+ EXECUTE PROCEDURE "#{on_link_update_procedure_name}"();
483
+ SQL
484
+ end
485
+
486
+ def on_link_delete_trigger
487
+ <<-SQL.gsub(/^ {4}/, '')
488
+ CREATE TRIGGER "#{on_link_delete_trigger_name}"
489
+ AFTER DELETE ON "#{link}"
490
+ FOR EACH ROW
491
+ EXECUTE PROCEDURE "#{on_link_delete_procedure_name}"();
492
+ SQL
493
+ end
494
+
495
+ def on_link_truncate_trigger
496
+ <<-SQL.gsub(/^ {4}/, '')
497
+ CREATE TRIGGER "#{on_link_truncate_trigger_name}"
498
+ AFTER TRUNCATE ON "#{link}"
499
+ FOR EACH STATEMENT
500
+ EXECUTE PROCEDURE "#{on_link_truncate_procedure_name}"();
501
+ SQL
502
+ end
503
+ end