globegit-postgresql-plruby 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/Changes +121 -0
  2. data/README.markdown +155 -0
  3. data/Rakefile +48 -0
  4. data/docs/plruby.rb +1931 -0
  5. data/ex_trans.sql +33 -0
  6. data/extconf.rb +267 -0
  7. data/plruby.html +1454 -0
  8. data/plruby.rd +1571 -0
  9. data/postgresql-plruby.gemspec +56 -0
  10. data/src/conversions.h +5 -0
  11. data/src/conversions/basic/conversions.h +25 -0
  12. data/src/conversions/basic/extconf.rb +8 -0
  13. data/src/conversions/basic/plruby_basic.c +357 -0
  14. data/src/conversions/bitstring/bitstring.sql +75 -0
  15. data/src/conversions/bitstring/conversions.h +15 -0
  16. data/src/conversions/bitstring/extconf.rb +8 -0
  17. data/src/conversions/bitstring/plruby_bitstring.c +579 -0
  18. data/src/conversions/convcommon.h +129 -0
  19. data/src/conversions/datetime/conversions.h +13 -0
  20. data/src/conversions/datetime/extconf.rb +8 -0
  21. data/src/conversions/datetime/plruby_datetime.c +269 -0
  22. data/src/conversions/geometry/conversions.h +37 -0
  23. data/src/conversions/geometry/extconf.rb +8 -0
  24. data/src/conversions/geometry/geometry.sql +196 -0
  25. data/src/conversions/geometry/plruby_geometry.c +2494 -0
  26. data/src/conversions/network/conversions.h +21 -0
  27. data/src/conversions/network/extconf.rb +8 -0
  28. data/src/conversions/network/network.sql +63 -0
  29. data/src/conversions/network/plruby_network.c +537 -0
  30. data/src/package.h +20 -0
  31. data/src/plpl.c +1708 -0
  32. data/src/plplan.c +893 -0
  33. data/src/plruby.c +1676 -0
  34. data/src/plruby.h +324 -0
  35. data/src/pltrans.c +388 -0
  36. data/test/conv_bitstring/b.rb +45 -0
  37. data/test/conv_bitstring/runtest +26 -0
  38. data/test/conv_bitstring/test.expected.73 +148 -0
  39. data/test/conv_bitstring/test.expected.74 +148 -0
  40. data/test/conv_bitstring/test.expected.80 +148 -0
  41. data/test/conv_bitstring/test.expected.81 +148 -0
  42. data/test/conv_bitstring/test.expected.82 +148 -0
  43. data/test/conv_bitstring/test.expected.83 +148 -0
  44. data/test/conv_bitstring/test.expected.84 +148 -0
  45. data/test/conv_bitstring/test.out +148 -0
  46. data/test/conv_bitstring/test_mklang.sql +8 -0
  47. data/test/conv_bitstring/test_queries.sql +63 -0
  48. data/test/conv_bitstring/test_queries.sql.in +63 -0
  49. data/test/conv_geometry/b.rb +45 -0
  50. data/test/conv_geometry/runtest +26 -0
  51. data/test/conv_geometry/test.expected.73 +265 -0
  52. data/test/conv_geometry/test.expected.74 +265 -0
  53. data/test/conv_geometry/test.expected.80 +265 -0
  54. data/test/conv_geometry/test.expected.81 +265 -0
  55. data/test/conv_geometry/test.expected.82 +265 -0
  56. data/test/conv_geometry/test.expected.83 +265 -0
  57. data/test/conv_geometry/test.expected.84 +265 -0
  58. data/test/conv_geometry/test.out +265 -0
  59. data/test/conv_geometry/test_mklang.sql +8 -0
  60. data/test/conv_geometry/test_queries.sql +194 -0
  61. data/test/conv_geometry/test_queries.sql.in +194 -0
  62. data/test/conv_network/b.rb +45 -0
  63. data/test/conv_network/runtest +26 -0
  64. data/test/conv_network/test.expected.73 +213 -0
  65. data/test/conv_network/test.expected.74 +237 -0
  66. data/test/conv_network/test.expected.80 +237 -0
  67. data/test/conv_network/test.expected.81 +237 -0
  68. data/test/conv_network/test.expected.82 +237 -0
  69. data/test/conv_network/test.expected.83 +237 -0
  70. data/test/conv_network/test.expected.84 +237 -0
  71. data/test/conv_network/test.out +237 -0
  72. data/test/conv_network/test_mklang.sql +8 -0
  73. data/test/conv_network/test_queries.sql +60 -0
  74. data/test/conv_network/test_queries.sql.in +60 -0
  75. data/test/plp/b.rb +34 -0
  76. data/test/plp/runtest +29 -0
  77. data/test/plp/test.expected.73 +472 -0
  78. data/test/plp/test.expected.74 +472 -0
  79. data/test/plp/test.expected.75 +472 -0
  80. data/test/plp/test.expected.80 +472 -0
  81. data/test/plp/test.expected.81 +472 -0
  82. data/test/plp/test.expected.82 +472 -0
  83. data/test/plp/test.expected.83 +472 -0
  84. data/test/plp/test.expected.84 +472 -0
  85. data/test/plp/test.out +472 -0
  86. data/test/plp/test_mklang.sql +8 -0
  87. data/test/plp/test_queries.sql +273 -0
  88. data/test/plp/test_setup.sql +931 -0
  89. data/test/plp/test_setup.sql.in +931 -0
  90. data/test/plt/b.rb +34 -0
  91. data/test/plt/runtest +29 -0
  92. data/test/plt/test.expected.73 +178 -0
  93. data/test/plt/test.expected.74 +178 -0
  94. data/test/plt/test.expected.75 +178 -0
  95. data/test/plt/test.expected.80 +178 -0
  96. data/test/plt/test.expected.81 +178 -0
  97. data/test/plt/test.expected.82 +178 -0
  98. data/test/plt/test.expected.83 +164 -0
  99. data/test/plt/test.expected.84 +168 -0
  100. data/test/plt/test.out +168 -0
  101. data/test/plt/test_mklang.sql +8 -0
  102. data/test/plt/test_queries.sql +72 -0
  103. data/test/plt/test_setup.sql +252 -0
  104. data/test/plt/test_setup.sql.in +252 -0
  105. data/test/range/b.rb +45 -0
  106. data/test/range/runtest +26 -0
  107. data/test/range/test.expected.73 +396 -0
  108. data/test/range/test.expected.73.in +396 -0
  109. data/test/range/test.expected.74 +396 -0
  110. data/test/range/test.expected.74.in +396 -0
  111. data/test/range/test.expected.75 +396 -0
  112. data/test/range/test.expected.75.in +396 -0
  113. data/test/range/test.expected.80 +396 -0
  114. data/test/range/test.expected.81 +397 -0
  115. data/test/range/test.expected.82 +397 -0
  116. data/test/range/test.expected.83 +397 -0
  117. data/test/range/test.expected.84 +399 -0
  118. data/test/range/test.out +399 -0
  119. data/test/range/test_mklang.sql +8 -0
  120. data/test/range/test_queries.sql +249 -0
  121. data/test/range/test_queries.sql.in +249 -0
  122. metadata +207 -0
@@ -0,0 +1,931 @@
1
+
2
+ create table Room (
3
+ roomno varchar(8),
4
+ comment text
5
+ );
6
+
7
+ create unique index Room_rno on Room using btree (roomno varchar_ops);
8
+
9
+
10
+ create table WSlot (
11
+ slotname varchar(20),
12
+ roomno varchar(8),
13
+ slotlink varchar(20),
14
+ backlink varchar(20)
15
+ );
16
+
17
+ create unique index WSlot_name on WSlot using btree (slotname varchar_ops);
18
+
19
+
20
+ create table PField (
21
+ name text,
22
+ comment text
23
+ );
24
+
25
+ create unique index PField_name on PField using btree (name text_ops);
26
+
27
+
28
+ create table PSlot (
29
+ slotname varchar(20),
30
+ pfname text,
31
+ slotlink varchar(20),
32
+ backlink varchar(20)
33
+ );
34
+
35
+ create unique index PSlot_name on PSlot using btree (slotname varchar_ops);
36
+
37
+
38
+ create table PLine (
39
+ slotname varchar(20),
40
+ phonenumber varchar(20),
41
+ comment text,
42
+ backlink varchar(20)
43
+ );
44
+
45
+ create unique index PLine_name on PLine using btree (slotname varchar_ops);
46
+
47
+
48
+ create table Hub (
49
+ name varchar(14),
50
+ comment text,
51
+ nslots int4
52
+ );
53
+
54
+ create unique index Hub_name on Hub using btree (name varchar_ops);
55
+
56
+
57
+ create table HSlot (
58
+ slotname varchar(20),
59
+ hubname varchar(14),
60
+ slotno int4,
61
+ slotlink varchar(20)
62
+ );
63
+
64
+ create unique index HSlot_name on HSlot using btree (slotname varchar_ops);
65
+ create index HSlot_hubname on HSlot using btree (hubname varchar_ops);
66
+
67
+
68
+ create table System (
69
+ name text,
70
+ comment text
71
+ );
72
+
73
+ create unique index System_name on System using btree (name text_ops);
74
+
75
+
76
+ create table IFace (
77
+ slotname varchar(20),
78
+ sysname text,
79
+ ifname text,
80
+ slotlink varchar(20)
81
+ );
82
+
83
+ create unique index IFace_name on IFace using btree (slotname varchar_ops);
84
+
85
+
86
+ create table PHone (
87
+ slotname varchar(20),
88
+ comment text,
89
+ slotlink varchar(20)
90
+ );
91
+
92
+ create unique index PHone_name on PHone using btree (slotname varchar_ops);
93
+
94
+
95
+ -- ************************************************************
96
+ -- * AFTER UPDATE on Room
97
+ -- * - If room no changes let wall slots follow
98
+ -- ************************************************************
99
+ create function tg_room_au() returns trigger as '
100
+ if !$Plans[tg["name"]]
101
+ $Plans[tg["name"]] = PL::Plan.new("update WSlot set roomno = $1
102
+ where roomno = $2",
103
+ ["varchar", "varchar"]).save
104
+ end
105
+ if new["roomno"] != old["roomno"]
106
+ $Plans[tg["name"]].exec(new["roomno"], old["roomno"])
107
+ end
108
+ PL::OK
109
+ ' language 'plruby';
110
+
111
+ create trigger tg_room_au after update
112
+ on Room for each row execute procedure tg_room_au();
113
+
114
+
115
+ -- ************************************************************
116
+ -- * AFTER DELETE on Room
117
+ -- * - delete wall slots in this room
118
+ -- ************************************************************
119
+ create function tg_room_ad() returns trigger as '
120
+ if ! $Plans.key?(tg["name"])
121
+ $Plans[tg["name"]] = PL::Plan.new("delete from WSlot
122
+ where roomno = $1",
123
+ ["varchar"]).save
124
+ end
125
+ $Plans[tg["name"]].exec([old["roomno"]])
126
+ PL::OK
127
+ ' language 'plruby';
128
+
129
+ create trigger tg_room_ad after delete
130
+ on Room for each row execute procedure tg_room_ad();
131
+
132
+
133
+ -- ************************************************************
134
+ -- * BEFORE INSERT or UPDATE on WSlot
135
+ -- * - Check that room exists
136
+ -- ************************************************************
137
+ create function tg_wslot_biu() returns trigger as '
138
+ if !$Plans.key?(tg["name"])
139
+ $Plans[tg["name"]] =
140
+ PL::Plan.new("select count(*) as cnt from Room
141
+ where roomno = $1", ["varchar"]).save
142
+ end
143
+ n = $Plans[tg["name"]].exec([new["roomno"]], 1)
144
+ if ! n["cnt"]
145
+ raise "Room #{new[''roomno'']} does not exist"
146
+ end
147
+ PL::OK
148
+ ' language 'plruby';
149
+
150
+ create trigger tg_wslot_biu before insert or update
151
+ on WSlot for each row execute procedure tg_wslot_biu();
152
+
153
+
154
+ -- ************************************************************
155
+ -- * AFTER UPDATE on PField
156
+ -- * - Let PSlots of this field follow
157
+ -- ************************************************************
158
+ create function tg_pfield_au() returns trigger as '
159
+ if !$Plans.key?(tg["name"])
160
+ $Plans[tg["name"]] =
161
+ PL::Plan.new("update PSlot set pfname = $1
162
+ where pfname = $2", ["text", "text"]).save
163
+ end
164
+ if new["name"] != old["name"]
165
+ $Plans[tg["name"]].exec([new["name"], old["name"]])
166
+ end
167
+ PL::OK
168
+ ' language 'plruby';
169
+
170
+ create trigger tg_pfield_au after update
171
+ on PField for each row execute procedure tg_pfield_au();
172
+
173
+
174
+ -- ************************************************************
175
+ -- * AFTER DELETE on PField
176
+ -- * - Remove all slots of this patchfield
177
+ -- ************************************************************
178
+ create function tg_pfield_ad() returns trigger as '
179
+ if ! $Plans.key?(tg["name"])
180
+ $Plans[tg["name"]] = PL::Plan.new("delete from PSlot
181
+ where pfname = $1",
182
+ ["text"]).save
183
+ end
184
+ $Plans[tg["name"]].exec([old["name"]])
185
+ PL::OK
186
+ ' language 'plruby';
187
+
188
+ create trigger tg_pfield_ad after delete
189
+ on PField for each row execute procedure tg_pfield_ad();
190
+
191
+
192
+ -- ************************************************************
193
+ -- * BEFORE INSERT or UPDATE on PSlot
194
+ -- * - Ensure that our patchfield does exist
195
+ -- ************************************************************
196
+ create function tg_pslot_biu() returns trigger as '
197
+ if ! $Plans.key?(tg["name"])
198
+ $Plans[tg["name"]] = PL::Plan.new("select count(*) as cnt
199
+ from PField where name = $1",
200
+ ["text"]).save
201
+ end
202
+ if ! $Plans[tg["name"]].exec([new["name"]], 1)["cnt"]
203
+ raise "Patchfield #{new[''name'']} does not exist"
204
+ end
205
+ PL::OK
206
+ ' language 'plruby';
207
+
208
+ create trigger tg_pslot_biu before insert or update
209
+ on PSlot for each row execute procedure tg_pslot_biu();
210
+
211
+
212
+ -- ************************************************************
213
+ -- * AFTER UPDATE on System
214
+ -- * - If system name changes let interfaces follow
215
+ -- ************************************************************
216
+ create function tg_system_au() returns trigger as '
217
+ if ! $Plans.key?(tg["name"])
218
+ $Plans[tg["name"]] = PL::Plan.new("update IFace set sysname = $1
219
+ where sysname = $2",
220
+ ["text", "text"]).save
221
+ end
222
+ if new["name"] != old["name"]
223
+ $Plans[tg["name"]].exec([new["name"], old["name"]])
224
+ end
225
+ PL::OK
226
+ ' language 'plruby';
227
+
228
+ create trigger tg_system_au after update
229
+ on System for each row execute procedure tg_system_au();
230
+
231
+
232
+ -- ************************************************************
233
+ -- * BEFORE INSERT or UPDATE on IFace
234
+ -- * - set the slotname to IF.sysname.ifname
235
+ -- ************************************************************
236
+ create function tg_iface_biu() returns trigger as '
237
+ if ! $Plans.key?(tg["name"])
238
+ $Plans[tg["name"]] = PL::Plan.new("select count(*) as cnt from system
239
+ where name = $1", ["text"]).save
240
+ end
241
+ if ! $Plans[tg["name"]].exec([new["sysname"]], 1)["cnt"]
242
+ raise "system #{new[''sysname'']} does not exist"
243
+ end
244
+ sname = "IF.#{new[''sysname'']}.#{new[''ifname'']}"
245
+ if sname.size > 20
246
+ raise "IFace slotname #{sname} too long (20 char max)"
247
+ end
248
+ new["slotname"] = sname
249
+ new
250
+ ' language 'plruby';
251
+
252
+ create trigger tg_iface_biu before insert or update
253
+ on IFace for each row execute procedure tg_iface_biu();
254
+
255
+
256
+ -- ************************************************************
257
+ -- * AFTER INSERT or UPDATE or DELETE on Hub
258
+ -- * - insert/delete/rename slots as required
259
+ -- ************************************************************
260
+ create function tg_hub_a() returns trigger as '
261
+ if ! $Plans.key?(tg["name"])
262
+ $Plans[tg["name"]] = PL::Plan.new("update HSlot set hubname = $1
263
+ where hubname = $2",
264
+ ["varchar", "varchar"]).save
265
+ end
266
+ case tg["op"]
267
+ when PL::INSERT
268
+ hub_adjustslots(new["name"], 0, new["nslots"].to_i)
269
+ when PL::UPDATE
270
+ if old["name"] != new["name"]
271
+ $Plans[tg["name"]].exec([new["name"], old["name"]])
272
+ end
273
+ hub_adjustslots(new["name"], old["nslots"].to_i, new["nslots"].to_i)
274
+ when PL::DELETE
275
+ hub_adjustslots(old["name"], old["nslots"].to_i, 0)
276
+ end
277
+ PL::OK
278
+ ' language 'plruby';
279
+
280
+ create trigger tg_hub_a after insert or update or delete
281
+ on Hub for each row execute procedure tg_hub_a();
282
+
283
+ -- ************************************************************
284
+ -- * BEFORE INSERT or UPDATE on HSlot
285
+ -- * - prevent from manual manipulation
286
+ -- * - set the slotname to HS.hubname.slotno
287
+ -- ************************************************************
288
+ create function tg_hslot_biu() returns trigger as '
289
+ if ! $Plans.key?(tg["name"])
290
+ $Plans[tg["name"]] =
291
+ PL::Plan.new("select * from Hub where name = $1", ["varchar"]).save
292
+ end
293
+ hubrec = $Plans[tg["name"]].exec([new["hubname"]],1)
294
+ if !hubrec || new["slotno"].to_i < 1 ||
295
+ new["slotno"].to_i > hubrec["nslots"].to_i
296
+ raise "no manual manipulation of HSlot"
297
+ end
298
+ if (tg["og"] == PL::UPDATE) && (new["hubname"] != old["hubname"]) &&
299
+ $Plans[tg["name"]].exec([old["hubname"]], 1)
300
+ raise "no manual manipulation of HSlot"
301
+ end
302
+ sname = "HS.#{new[''hubname'']}.#{new[''slotno'']}"
303
+ if sname.size > 20
304
+ raise "HSlot slotname #{sname} too long (20 char max)"
305
+ end
306
+ new["slotname"] = sname
307
+ new
308
+ ' language 'plruby';
309
+
310
+ create trigger tg_hslot_biu before insert or update
311
+ on HSlot for each row execute procedure tg_hslot_biu();
312
+
313
+
314
+ -- ************************************************************
315
+ -- * BEFORE DELETE on HSlot
316
+ -- * - prevent from manual manipulation
317
+ -- ************************************************************
318
+ create function tg_hslot_bd() returns trigger as '
319
+ if ! $Plans.key?(tg["name"])
320
+ $Plans[tg["name"]] =
321
+ PL::Plan.new("select * from Hub where name = $1", ["varchar"]).save
322
+ end
323
+ hubrec = $Plans[tg["name"]].exec([old["hubname"]],1)
324
+ if !hubrec || old["slotno"].to_i > hubrec["nslots"].to_i
325
+ return PL::OK
326
+ end
327
+ raise "no manual manipulation of HSlot"
328
+ ' language 'plruby';
329
+
330
+ create trigger tg_hslot_bd before delete
331
+ on HSlot for each row execute procedure tg_hslot_bd();
332
+
333
+
334
+ -- ************************************************************
335
+ -- * BEFORE INSERT on all slots
336
+ -- * - Check name prefix
337
+ -- ************************************************************
338
+ create function tg_chkslotname() returns trigger as '
339
+ if new["slotname"][0, 2] != args[0]
340
+ raise "slotname must begin with #{args[0]}"
341
+ end
342
+ PL::OK
343
+ ' language 'plruby';
344
+
345
+ create trigger tg_chkslotname before insert
346
+ on PSlot for each row execute procedure tg_chkslotname('PS');
347
+
348
+ create trigger tg_chkslotname before insert
349
+ on WSlot for each row execute procedure tg_chkslotname('WS');
350
+
351
+ create trigger tg_chkslotname before insert
352
+ on PLine for each row execute procedure tg_chkslotname('PL');
353
+
354
+ create trigger tg_chkslotname before insert
355
+ on IFace for each row execute procedure tg_chkslotname('IF');
356
+
357
+ create trigger tg_chkslotname before insert
358
+ on PHone for each row execute procedure tg_chkslotname('PH');
359
+
360
+
361
+ -- ************************************************************
362
+ -- * BEFORE INSERT or UPDATE on all slots with slotlink
363
+ -- * - Set slotlink to empty string if NULL value given
364
+ -- ************************************************************
365
+ create function tg_chkslotlink() returns trigger as '
366
+ if ! new["slotlink"]
367
+ new["slotlink"] = ""
368
+ return new
369
+ end
370
+ PL::OK
371
+ ' language 'plruby';
372
+
373
+ create trigger tg_chkslotlink before insert or update
374
+ on PSlot for each row execute procedure tg_chkslotlink();
375
+
376
+ create trigger tg_chkslotlink before insert or update
377
+ on WSlot for each row execute procedure tg_chkslotlink();
378
+
379
+ create trigger tg_chkslotlink before insert or update
380
+ on IFace for each row execute procedure tg_chkslotlink();
381
+
382
+ create trigger tg_chkslotlink before insert or update
383
+ on HSlot for each row execute procedure tg_chkslotlink();
384
+
385
+ create trigger tg_chkslotlink before insert or update
386
+ on PHone for each row execute procedure tg_chkslotlink();
387
+
388
+
389
+ -- ************************************************************
390
+ -- * BEFORE INSERT or UPDATE on all slots with backlink
391
+ -- * - Set backlink to empty string if NULL value given
392
+ -- ************************************************************
393
+ create function tg_chkbacklink() returns trigger as '
394
+ if ! new["backlink"]
395
+ new["backlink"] = ""
396
+ return new
397
+ end
398
+ PL::OK
399
+ ' language 'plruby';
400
+
401
+ create trigger tg_chkbacklink before insert or update
402
+ on PSlot for each row execute procedure tg_chkbacklink();
403
+
404
+ create trigger tg_chkbacklink before insert or update
405
+ on WSlot for each row execute procedure tg_chkbacklink();
406
+
407
+ create trigger tg_chkbacklink before insert or update
408
+ on PLine for each row execute procedure tg_chkbacklink();
409
+
410
+
411
+ -- ************************************************************
412
+ -- * BEFORE UPDATE on PSlot
413
+ -- * - do delete/insert instead of update if name changes
414
+ -- ************************************************************
415
+ create function tg_pslot_bu() returns trigger as '
416
+ if ! $Plans.key?("pslot_bu_del")
417
+ $Plans["pslot_bu_del"] =
418
+ PL::Plan.new("delete from PSlot where slotname = $1",
419
+ ["varchar"]).save
420
+ $Plans["pslot_bu_ins"] =
421
+ PL::Plan.new("insert into PSlot
422
+ (slotname, pfname, slotlink, backlink)
423
+ values ($1, $2, $3, $4)",
424
+ ["varchar", "varchar", "varchar", "varchar"]).save
425
+ end
426
+ if new["slotname"] != old["slotname"]
427
+ $Plans["pslot_bu_del"].exec([old["slotname"]])
428
+ $Plans["pslot_bu_ins"].exec([new["slotname"], new["pfname"],
429
+ new["slotlink"], new["backlink"]])
430
+ return PL::SKIP
431
+ end
432
+ PL::OK
433
+ ' language 'plruby';
434
+
435
+ create trigger tg_pslot_bu before update
436
+ on PSlot for each row execute procedure tg_pslot_bu();
437
+
438
+
439
+ -- ************************************************************
440
+ -- * BEFORE UPDATE on WSlot
441
+ -- * - do delete/insert instead of update if name changes
442
+ -- ************************************************************
443
+ create function tg_wslot_bu() returns trigger as '
444
+ if ! $Plans.key?("wslot_bu_del")
445
+ $Plans["wslot_bu_del"] =
446
+ PL::Plan.new("delete from WSlot where slotname = $1",
447
+ ["varchar"]).save
448
+ $Plans["wslot_bu_ins"] =
449
+ PL::Plan.new("insert into WSlot
450
+ (slotname, roomno, slotlink, backlink)
451
+ values ($1, $2, $3, $4)",
452
+ ["varchar", "int4", "varchar", "varchar"]).save
453
+ end
454
+ if new["slotname"] != old["slotname"]
455
+ $Plans["wslot_bu_del"].exec([old["slotname"]])
456
+ $Plans["wslot_bu_ins"].exec([new["slotname"], new["roomno"],
457
+ new["slotlink"], new["backlink"]])
458
+ return PL::SKIP
459
+ end
460
+ PL::OK
461
+ ' language 'plruby';
462
+
463
+ create trigger tg_wslot_bu before update
464
+ on WSlot for each row execute procedure tg_Wslot_bu();
465
+
466
+
467
+ -- ************************************************************
468
+ -- * BEFORE UPDATE on PLine
469
+ -- * - do delete/insert instead of update if name changes
470
+ -- ************************************************************
471
+ create function tg_pline_bu() returns trigger as '
472
+ if ! $Plans.key?("pline_bu_del")
473
+ $Plans["pline_bu_del"] =
474
+ PL::Plan.new("delete from Pline where slotname = $1",
475
+ ["varchar"]).save
476
+ $Plans["pline_bu_ins"] =
477
+ PL::Plan.new("insert into Pline
478
+ (slotname, phonenumber, comment, backlink)
479
+ values ($1, $2, $3, $4)",
480
+ ["varchar", "int4", "varchar", "varchar"]).save
481
+ end
482
+ if new["slotname"] != old["slotname"]
483
+ $Plans["pline_bu_del"].exec([old["slotname"]])
484
+ $Plans["pline_bu_ins"].exec([new["slotname"], new["phonenumber"],
485
+ new["comment"], new["backlink"]])
486
+ return PL::SKIP
487
+ end
488
+ PL::OK
489
+ ' language 'plruby';
490
+
491
+ create trigger tg_pline_bu before update
492
+ on PLine for each row execute procedure tg_pline_bu();
493
+
494
+
495
+ -- ************************************************************
496
+ -- * BEFORE UPDATE on IFace
497
+ -- * - do delete/insert instead of update if name changes
498
+ -- ************************************************************
499
+ create function tg_iface_bu() returns trigger as '
500
+ if ! $Plans.key?("iface_bu_del")
501
+ $Plans["iface_bu_del"] =
502
+ PL::Plan.new("delete from Iface where slotname = $1",
503
+ ["varchar"]).save
504
+ $Plans["iface_bu_ins"] =
505
+ PL::Plan.new("insert into Iface
506
+ (slotname, sysname, ifname, slotlink)
507
+ values ($1, $2, $3, $4)",
508
+ ["varchar", "varchar", "varchar", "varchar"]).save
509
+ end
510
+ if new["slotname"] != old["slotname"]
511
+ $Plans["iface_bu_del"].exec([old["slotname"]])
512
+ $Plans["iface_bu_ins"].exec([new["slotname"], new["sysname"],
513
+ new["ifname"], new["slotlink"]])
514
+ return PL::SKIP
515
+ end
516
+ PL::OK
517
+ ' language 'plruby';
518
+
519
+ create trigger tg_iface_bu before update
520
+ on IFace for each row execute procedure tg_iface_bu();
521
+
522
+
523
+ -- ************************************************************
524
+ -- * BEFORE UPDATE on HSlot
525
+ -- * - do delete/insert instead of update if name changes
526
+ -- ************************************************************
527
+ create function tg_hslot_bu() returns trigger as '
528
+ if ! $Plans.key?("hslot_bu_del")
529
+ $Plans["hslot_bu_del"] =
530
+ PL::Plan.new("delete from Hslot where slotname = $1",
531
+ ["varchar"]).save
532
+ $Plans["hslot_bu_ins"] =
533
+ PL::Plan.new("insert into Hslot
534
+ (slotname, hubname, slotno, slotlink)
535
+ values ($1, $2, $3, $4)",
536
+ ["varchar", "varchar", "int4", "varchar"]).save
537
+ end
538
+ if new["slotname"] != old["slotname"]
539
+ $Plans["hslot_bu_del"].exec([old["slotname"]])
540
+ $Plans["hslot_bu_ins"].exec([new["slotname"], new["hubname"],
541
+ new["slotno"], new["slotlink"]])
542
+ return PL::SKIP
543
+ end
544
+ PL::OK
545
+ ' language 'plruby';
546
+
547
+ create trigger tg_hslot_bu before update
548
+ on HSlot for each row execute procedure tg_hslot_bu();
549
+
550
+
551
+ -- ************************************************************
552
+ -- * BEFORE UPDATE on PHone
553
+ -- * - do delete/insert instead of update if name changes
554
+ -- ************************************************************
555
+ create function tg_phone_bu() returns trigger as '
556
+ if ! $Plans.key?("phone_bu_del")
557
+ $Plans["phone_bu_del"] =
558
+ PL::Plan.new("delete from Phone where slotname = $1",
559
+ ["varchar"]).save
560
+ $Plans["phone_bu_ins"] =
561
+ PL::Plan.new("insert into Phone
562
+ (slotname, comment, slotlink)
563
+ values ($1, $2, $3)",
564
+ ["varchar", "varchar", "varchar"]).save
565
+ end
566
+ if new["slotname"] != old["slotname"]
567
+ $Plans["phone_bu_del"].exec([old["slotname"]])
568
+ $Plans["phone_bu_ins"].exec([new["slotname"], new["comment"],
569
+ new["slotlink"]])
570
+ return PL::SKIP
571
+ end
572
+ ' language 'plruby';
573
+
574
+ create trigger tg_phone_bu before update
575
+ on PHone for each row execute procedure tg_phone_bu();
576
+
577
+
578
+ -- ************************************************************
579
+ -- * AFTER INSERT or UPDATE or DELETE on slot with backlink
580
+ -- * - Ensure that the opponent correctly points back to us
581
+ -- ************************************************************
582
+ create function tg_backlink_a() returns trigger as '
583
+ case tg["op"]
584
+ when PL::INSERT
585
+ if ! new["backlink"].empty?
586
+ backlink_set(new["backlink"], new["slotname"])
587
+ end
588
+ when PL::UPDATE
589
+ if new["backlink"] != old["backlink"]
590
+ if ! old["backlink"].empty?
591
+ backlink_unset(old["backlink"], old["slotname"])
592
+ end
593
+ if ! new["backlink"].empty?
594
+ backlink_set(new["backlink"], new["slotname"])
595
+ end
596
+ else
597
+ if new["slotname"] != old["slotname"] && ! new["backlink"].empty?
598
+ slotlink_set(new["backlink"], new["slotname"])
599
+ end
600
+ end
601
+ when PL::DELETE
602
+ if ! old["backlink"].empty?
603
+ backlink_unset(old["backlink"], old["slotname"]);
604
+ end
605
+ end
606
+ PL::OK
607
+ ' language 'plruby';
608
+
609
+
610
+ create trigger tg_backlink_a after insert or update or delete
611
+ on PSlot for each row execute procedure tg_backlink_a('PS');
612
+
613
+ create trigger tg_backlink_a after insert or update or delete
614
+ on WSlot for each row execute procedure tg_backlink_a('WS');
615
+
616
+ create trigger tg_backlink_a after insert or update or delete
617
+ on PLine for each row execute procedure tg_backlink_a('PL');
618
+
619
+ -- ************************************************************
620
+ -- * AFTER INSERT or UPDATE or DELETE on slot with slotlink
621
+ -- * - Ensure that the opponent correctly points back to us
622
+ -- ************************************************************
623
+ create function tg_slotlink_a() returns trigger as '
624
+ case tg["op"]
625
+ when PL::INSERT
626
+ if ! new["slotlink"].empty?
627
+ slotlink_set(new["slotlink"], new["slotname"])
628
+ end
629
+ when PL::UPDATE
630
+ if new["slotlink"] != old["slotlink"]
631
+ if ! old["slotlink"].empty?
632
+ stlotlink_unset(old["slotlink"], old["slotname"])
633
+ end
634
+ if ! new["slotlink"].empty?
635
+ slotlink_set(new["slotlink"], new["slotname"])
636
+ end
637
+ else
638
+ if new["slotname"] != old["slotname"] && ! new["slotlink"].empty?
639
+ slotlink_set(new["slotlink"], new["slotname"])
640
+ end
641
+ end
642
+ when PL::DELETE
643
+ if ! old["slotlink"].empty?
644
+ stlotlink_unset(old["slotlink"], old["slotname"])
645
+ end
646
+ end
647
+ PL::OK
648
+ ' language 'plruby';
649
+
650
+
651
+ create trigger tg_slotlink_a after insert or update or delete
652
+ on PSlot for each row execute procedure tg_slotlink_a('PS');
653
+
654
+ create trigger tg_slotlink_a after insert or update or delete
655
+ on WSlot for each row execute procedure tg_slotlink_a('WS');
656
+
657
+ create trigger tg_slotlink_a after insert or update or delete
658
+ on IFace for each row execute procedure tg_slotlink_a('IF');
659
+
660
+ create trigger tg_slotlink_a after insert or update or delete
661
+ on HSlot for each row execute procedure tg_slotlink_a('HS');
662
+
663
+ create trigger tg_slotlink_a after insert or update or delete
664
+ on PHone for each row execute procedure tg_slotlink_a('PH');
665
+
666
+ -- ************************************************************
667
+ -- * Describe the backside of a patchfield slot
668
+ -- ************************************************************
669
+ create function pslot_backlink_view(varchar)
670
+ returns text as '
671
+ if ! $Plans.key?("pslot_view")
672
+ $Plans["pslot_view"] =
673
+ PL::Plan.new("select * from PSlot where slotname = $1",
674
+ ["varchar"]).save
675
+ end
676
+ rec = $Plans["pslot_view"].exec([args[0]], 1)
677
+ return "" if ! rec
678
+ return "-" if rec["backlink"].empty?
679
+ bltype = rec["backlink"][0, 2]
680
+ case bltype
681
+ when "PL"
682
+ rec = PL.exec("select * from PLine where slotname = ''#{rec[''backlink'']}''", 1)
683
+ retval = "Phone line #{rec[''phonenumber''].strip}"
684
+ if ! rec["comment"].empty?
685
+ retval << " (#{rec[''comment'']})"
686
+ end
687
+ return retval
688
+ when "WS"
689
+ rec = PL.exec("select * from WSlot where slotname = ''#{rec[''backlink'']}''", 1)
690
+ retval = "#{rec[''slotname''].strip} in room "
691
+ retval << rec["roomno"].strip + " -> "
692
+ rec = PL.exec("select wslot_slotlink_view(''#{rec[''slotname'']}''::varchar) as ws_result", 1)
693
+ return retval + rec["ws_result"]
694
+ end
695
+ rec["backlink"]
696
+ ' language 'plruby';
697
+
698
+
699
+ -- ************************************************************
700
+ -- * Describe the front of a patchfield slot
701
+ -- ************************************************************
702
+ create function pslot_slotlink_view(varchar)
703
+ returns text as '
704
+ if ! $Plans.key?("pslot_view")
705
+ $Plans["pslot_view"] =
706
+ PL::Plan.new("select * from PSlot where slotname = $1",
707
+ ["varchar"]).save
708
+ end
709
+ rec = $Plans["pslot_view"].exec([args[0]], 1)
710
+ return "" if ! rec
711
+ return "-" if rec["slotlink"].empty?
712
+ case rec["slotlink"][0, 2]
713
+ when "PS"
714
+ retval = rec["slotlink"].strip + " -> "
715
+ rec = PL.exec("select pslot_backlink_view(''#{rec[''slotlink'']}''::varchar) as bac", 1)
716
+ return retval + rec["bac"]
717
+ when "HS"
718
+ comm = PL.exec("select comment from Hub H, HSlot HS
719
+ where HS.slotname = ''#{rec[''slotlink'']}''
720
+ and H.name = HS.hubname", 1)
721
+ retval = ""
722
+ if ! comm["comment"].empty?
723
+ retval << comm["comment"]
724
+ end
725
+ retval << " slot "
726
+ comm = PL.exec("select slotno from HSlot
727
+ where slotname = ''#{rec[''slotlink'']}''", 1)
728
+ return retval + comm["slotno"].to_s
729
+ end
730
+ rec["slotlink"]
731
+ ' language 'plruby';
732
+
733
+
734
+ -- ************************************************************
735
+ -- * Describe the front of a wall connector slot
736
+ -- ************************************************************
737
+ create function wslot_slotlink_view(varchar)
738
+ returns text as '
739
+ if ! $Plans.key?("wslot_view")
740
+ $Plans["wslot_view"] =
741
+ PL::Plan.new("select * from WSlot where slotname = $1",
742
+ ["varchar"]).save
743
+ end
744
+ rec = $Plans["wslot_view"].exec([args[0]], 1)
745
+ return "" if ! rec
746
+ return "-" if rec["slotlink"].empty?
747
+ case rec["slotlink"][0, 2]
748
+ when "PH"
749
+ rec = PL.exec("select * from PHone where slotname = ''#{rec[''slotlink'']}''", 1)
750
+ retval = "Phone " + rec["slotname"].strip
751
+ if ! rec["comment"].empty?
752
+ retval << " (#{rec[''comment'']})"
753
+ end
754
+ return retval
755
+ when "IF"
756
+ ifrow = PL.exec("select * from IFace where slotname = ''#{rec[''slotlink'']}''", 1)
757
+ syrow = PL.exec("select * from System where name = ''#{ifrow[''sysname'']}''", 1)
758
+ retval = syrow["name"] + " IF " + ifrow["ifname"]
759
+ if ! syrow["comment"].empty?
760
+ retval << " (#{syrow[''comment'']})"
761
+ end
762
+ return retval
763
+ end
764
+ rec["slotlink"]
765
+ ' language 'plruby';
766
+
767
+
768
+
769
+ -- ************************************************************
770
+ -- * View of a patchfield describing backside and patches
771
+ -- ************************************************************
772
+ create view Pfield_v1 as select PF.pfname, PF.slotname,
773
+ pslot_backlink_view(PF.slotname) as backside,
774
+ pslot_slotlink_view(PF.slotname) as patch
775
+ from PSlot PF;
776
+
777
+
778
+ --
779
+ --
780
+ --
781
+
782
+ create table plruby_singleton_methods (
783
+ name varchar(60),
784
+ args varchar(60),
785
+ body text,
786
+ comment text
787
+ );
788
+
789
+
790
+ create unique index plr_s_m_i on plruby_singleton_methods (name);
791
+
792
+ insert into plruby_singleton_methods values
793
+ ('hub_adjustslots', 'name, oldsl, newsl', '
794
+ if ! $Plans.key?("hub_adjust_del")
795
+ $Plans["hub_adjust_del"] =
796
+ PL::Plan.new("delete from HSlot
797
+ where hubname = $1 and slotno > $2",
798
+ ["varchar", "int4"]).save
799
+ $Plans["hub_adjust_ins"] =
800
+ PL::Plan.new("insert into HSlot (slotname, hubname, slotno, slotlink)
801
+ values ($1, $2, $3, $4)",
802
+ ["varchar", "varchar", "int4", "varchar"]).save
803
+ end
804
+ return if oldsl == newsl
805
+ if newsl < oldsl
806
+ $Plans["hub_adjust_del"].exec([name, newsl])
807
+ else
808
+ (oldsl+1).upto(newsl) do |x|
809
+ $Plans["hub_adjust_ins"].exec(["HS.dummy", name, x, ""])
810
+ end
811
+ end
812
+ ', 'Support function to add/remove slots of Hub');
813
+
814
+ insert into plruby_singleton_methods values
815
+ ('backlink_set', 'myname, blname', '
816
+ mytype = myname[0, 2]
817
+ link = mytype + blname[0, 2]
818
+ if link == "PLPL"
819
+ raise "backlink between two phone lines does not make sense"
820
+ end
821
+ if link == "PLWS" || link == "WSPL"
822
+ raise "direct link of phone line to wall slot not permitted"
823
+ end
824
+ rel = case mytype
825
+ when "PS"
826
+ "PSlot"
827
+ when "WS"
828
+ "WSlot"
829
+ when "PL"
830
+ "PLine"
831
+ else
832
+ raise "illegal backlink beginning with #{mytype}"
833
+ end
834
+ rec = PL.exec("select * from #{rel} where slotname = ''#{myname}''", 1)
835
+ if ! rec
836
+ raise "#{myname} does not exist in #{rel}"
837
+ end
838
+ if rec["backlink"] != blname
839
+ PL.exec("update #{rel} set backlink = ''#{blname}''
840
+ where slotname = ''#{myname}''")
841
+ end
842
+ ', ' Support function to set the opponents backlink field
843
+ if it does not already point to the requested slot');
844
+
845
+ insert into plruby_singleton_methods values
846
+ ('backlink_unset' , 'myname, blname', '
847
+ rel = case myname[0, 2]
848
+ when "PS"
849
+ "PSlot"
850
+ when "WS"
851
+ "WSlot"
852
+ when "PL"
853
+ "PLine"
854
+ else
855
+ raise "illegal backlink beginning with #{myname[0, 2]}"
856
+ end
857
+ rec = PL.exec("select * from #{rel} where slotname = ''#{myname}''", 1)
858
+ return if ! rec
859
+ if rec["backlink"] == blname
860
+ PL.exec("update #{rel} set backlink = ''''
861
+ where slotname = ''#{myname}''")
862
+ end
863
+ ', ' Support function to clear out the backlink field if
864
+ it still points to specific slot');
865
+
866
+ insert into plruby_singleton_methods values
867
+ ('slotlink_set', 'myname, blname', '
868
+ mytype = myname[0, 2]
869
+ link = mytype + blname[0, 2]
870
+ if link == "PHPH"
871
+ raise "slotlink between two phones does not make sense"
872
+ end
873
+ if link == "PHHS" || link == "HSPH"
874
+ raise "link of phone to hub does not make sense"
875
+ end
876
+ if link == "PHIF" || link == "IFPH"
877
+ raise "link of phone to hub does not make sense"
878
+ end
879
+ if link == "PSWS" || link == "WSPS"
880
+ raise "slotlink from patchslot to wallslot not permitted"
881
+ end
882
+ rel = case mytype
883
+ when "PS"
884
+ "PSlot"
885
+ when "WS"
886
+ "WSlot"
887
+ when "IF"
888
+ "IFace"
889
+ when "HS"
890
+ "HSlot"
891
+ when "PH"
892
+ "PHone"
893
+ else
894
+ raise "illegal slotlink beginning with <#{mytype}>"
895
+ end
896
+ rec = PL.exec("select * from #{rel} where slotname = ''#{myname}''", 1)
897
+ if ! rec
898
+ raise "#{myname} does not exists in #{rel}"
899
+ end
900
+ if rec["slotlink"] != blname
901
+ PL.exec("update #{rel} set slotlink = ''#{blname}''
902
+ where slotname = ''#{myname}''")
903
+ end
904
+ ', ' Support function to set the opponents slotlink field
905
+ if it does not already point to the requested slot');
906
+
907
+ insert into plruby_singleton_methods values
908
+ ('slotlink_unset', 'myname, blname', '
909
+ rel = case myname[0, 2]
910
+ when "PS"
911
+ "PSlot"
912
+ when "WS"
913
+ "WSlot"
914
+ when "IF"
915
+ "IFace"
916
+ when "HS"
917
+ "HSlot"
918
+ when "PH"
919
+ "PHone"
920
+ else
921
+ raise "illegal slotlink beginning with #{myname[0, 2]}"
922
+ end
923
+ rec = PL.exec("select * from #{rel} where slotname = ''#{myname}''", 1)
924
+ return if ! rec
925
+ if rec["slotlink"] == blname
926
+ PL.exec("update #{rel} set slotlink = ''''
927
+ where slotname = ''#{myname}''")
928
+ end
929
+ ', ' Support function to clear out the slotlink field if
930
+ it still points to specific slot');
931
+