globegit-postgresql-plruby 0.5.4

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.
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,8 @@
1
+
2
+ create function plruby_call_handler() returns language_handler
3
+ as '/home/dberger/Repositories/postgresql-plruby/src/plruby.so'
4
+ language 'C';
5
+
6
+ create trusted procedural language 'plruby'
7
+ handler plruby_call_handler
8
+ lancompiler 'PL/Ruby';
@@ -0,0 +1,273 @@
1
+
2
+ --
3
+ -- First we build the house - so we create the rooms
4
+ --
5
+ insert into Room values ('001', 'Entrance');
6
+ insert into Room values ('002', 'Office');
7
+ insert into Room values ('003', 'Office');
8
+ insert into Room values ('004', 'Technical');
9
+ insert into Room values ('101', 'Office');
10
+ insert into Room values ('102', 'Conference');
11
+ insert into Room values ('103', 'Restroom');
12
+ insert into Room values ('104', 'Technical');
13
+ insert into Room values ('105', 'Office');
14
+ insert into Room values ('106', 'Office');
15
+
16
+ --
17
+ -- Second we install the wall connectors
18
+ --
19
+ insert into WSlot values ('WS.001.1a', '001', '', '');
20
+ insert into WSlot values ('WS.001.1b', '001', '', '');
21
+ insert into WSlot values ('WS.001.2a', '001', '', '');
22
+ insert into WSlot values ('WS.001.2b', '001', '', '');
23
+ insert into WSlot values ('WS.001.3a', '001', '', '');
24
+ insert into WSlot values ('WS.001.3b', '001', '', '');
25
+
26
+ insert into WSlot values ('WS.002.1a', '002', '', '');
27
+ insert into WSlot values ('WS.002.1b', '002', '', '');
28
+ insert into WSlot values ('WS.002.2a', '002', '', '');
29
+ insert into WSlot values ('WS.002.2b', '002', '', '');
30
+ insert into WSlot values ('WS.002.3a', '002', '', '');
31
+ insert into WSlot values ('WS.002.3b', '002', '', '');
32
+
33
+ insert into WSlot values ('WS.003.1a', '003', '', '');
34
+ insert into WSlot values ('WS.003.1b', '003', '', '');
35
+ insert into WSlot values ('WS.003.2a', '003', '', '');
36
+ insert into WSlot values ('WS.003.2b', '003', '', '');
37
+ insert into WSlot values ('WS.003.3a', '003', '', '');
38
+ insert into WSlot values ('WS.003.3b', '003', '', '');
39
+
40
+ insert into WSlot values ('WS.101.1a', '101', '', '');
41
+ insert into WSlot values ('WS.101.1b', '101', '', '');
42
+ insert into WSlot values ('WS.101.2a', '101', '', '');
43
+ insert into WSlot values ('WS.101.2b', '101', '', '');
44
+ insert into WSlot values ('WS.101.3a', '101', '', '');
45
+ insert into WSlot values ('WS.101.3b', '101', '', '');
46
+
47
+ insert into WSlot values ('WS.102.1a', '102', '', '');
48
+ insert into WSlot values ('WS.102.1b', '102', '', '');
49
+ insert into WSlot values ('WS.102.2a', '102', '', '');
50
+ insert into WSlot values ('WS.102.2b', '102', '', '');
51
+ insert into WSlot values ('WS.102.3a', '102', '', '');
52
+ insert into WSlot values ('WS.102.3b', '102', '', '');
53
+
54
+ insert into WSlot values ('WS.105.1a', '105', '', '');
55
+ insert into WSlot values ('WS.105.1b', '105', '', '');
56
+ insert into WSlot values ('WS.105.2a', '105', '', '');
57
+ insert into WSlot values ('WS.105.2b', '105', '', '');
58
+ insert into WSlot values ('WS.105.3a', '105', '', '');
59
+ insert into WSlot values ('WS.105.3b', '105', '', '');
60
+
61
+ insert into WSlot values ('WS.106.1a', '106', '', '');
62
+ insert into WSlot values ('WS.106.1b', '106', '', '');
63
+ insert into WSlot values ('WS.106.2a', '106', '', '');
64
+ insert into WSlot values ('WS.106.2b', '106', '', '');
65
+ insert into WSlot values ('WS.106.3a', '106', '', '');
66
+ insert into WSlot values ('WS.106.3b', '106', '', '');
67
+
68
+ --
69
+ -- Now create the patch fields and their slots
70
+ --
71
+ insert into PField values ('PF0_1', 'Wallslots basement');
72
+
73
+ --
74
+ -- The cables for these will be made later, so they are unconnected for now
75
+ --
76
+ insert into PSlot values ('PS.base.a1', 'PF0_1', '', '');
77
+ insert into PSlot values ('PS.base.a2', 'PF0_1', '', '');
78
+ insert into PSlot values ('PS.base.a3', 'PF0_1', '', '');
79
+ insert into PSlot values ('PS.base.a4', 'PF0_1', '', '');
80
+ insert into PSlot values ('PS.base.a5', 'PF0_1', '', '');
81
+ insert into PSlot values ('PS.base.a6', 'PF0_1', '', '');
82
+
83
+ --
84
+ -- These are already wired to the wall connectors
85
+ --
86
+ insert into PSlot values ('PS.base.b1', 'PF0_1', '', 'WS.002.1a');
87
+ insert into PSlot values ('PS.base.b2', 'PF0_1', '', 'WS.002.1b');
88
+ insert into PSlot values ('PS.base.b3', 'PF0_1', '', 'WS.002.2a');
89
+ insert into PSlot values ('PS.base.b4', 'PF0_1', '', 'WS.002.2b');
90
+ insert into PSlot values ('PS.base.b5', 'PF0_1', '', 'WS.002.3a');
91
+ insert into PSlot values ('PS.base.b6', 'PF0_1', '', 'WS.002.3b');
92
+
93
+ insert into PSlot values ('PS.base.c1', 'PF0_1', '', 'WS.003.1a');
94
+ insert into PSlot values ('PS.base.c2', 'PF0_1', '', 'WS.003.1b');
95
+ insert into PSlot values ('PS.base.c3', 'PF0_1', '', 'WS.003.2a');
96
+ insert into PSlot values ('PS.base.c4', 'PF0_1', '', 'WS.003.2b');
97
+ insert into PSlot values ('PS.base.c5', 'PF0_1', '', 'WS.003.3a');
98
+ insert into PSlot values ('PS.base.c6', 'PF0_1', '', 'WS.003.3b');
99
+
100
+ --
101
+ -- This patchfield will be renamed later into PF0_2 - so its
102
+ -- slots references in pfname should follow
103
+ --
104
+ insert into PField values ('PF0_X', 'Phonelines basement');
105
+
106
+ insert into PSlot values ('PS.base.ta1', 'PF0_X', '', '');
107
+ insert into PSlot values ('PS.base.ta2', 'PF0_X', '', '');
108
+ insert into PSlot values ('PS.base.ta3', 'PF0_X', '', '');
109
+ insert into PSlot values ('PS.base.ta4', 'PF0_X', '', '');
110
+ insert into PSlot values ('PS.base.ta5', 'PF0_X', '', '');
111
+ insert into PSlot values ('PS.base.ta6', 'PF0_X', '', '');
112
+
113
+ insert into PSlot values ('PS.base.tb1', 'PF0_X', '', '');
114
+ insert into PSlot values ('PS.base.tb2', 'PF0_X', '', '');
115
+ insert into PSlot values ('PS.base.tb3', 'PF0_X', '', '');
116
+ insert into PSlot values ('PS.base.tb4', 'PF0_X', '', '');
117
+ insert into PSlot values ('PS.base.tb5', 'PF0_X', '', '');
118
+ insert into PSlot values ('PS.base.tb6', 'PF0_X', '', '');
119
+
120
+ insert into PField values ('PF1_1', 'Wallslots 1st floor');
121
+
122
+ insert into PSlot values ('PS.1st.a1', 'PF1_1', '', 'WS.101.1a');
123
+ insert into PSlot values ('PS.1st.a2', 'PF1_1', '', 'WS.101.1b');
124
+ insert into PSlot values ('PS.1st.a3', 'PF1_1', '', 'WS.101.2a');
125
+ insert into PSlot values ('PS.1st.a4', 'PF1_1', '', 'WS.101.2b');
126
+ insert into PSlot values ('PS.1st.a5', 'PF1_1', '', 'WS.101.3a');
127
+ insert into PSlot values ('PS.1st.a6', 'PF1_1', '', 'WS.101.3b');
128
+
129
+ insert into PSlot values ('PS.1st.b1', 'PF1_1', '', 'WS.102.1a');
130
+ insert into PSlot values ('PS.1st.b2', 'PF1_1', '', 'WS.102.1b');
131
+ insert into PSlot values ('PS.1st.b3', 'PF1_1', '', 'WS.102.2a');
132
+ insert into PSlot values ('PS.1st.b4', 'PF1_1', '', 'WS.102.2b');
133
+ insert into PSlot values ('PS.1st.b5', 'PF1_1', '', 'WS.102.3a');
134
+ insert into PSlot values ('PS.1st.b6', 'PF1_1', '', 'WS.102.3b');
135
+
136
+ insert into PSlot values ('PS.1st.c1', 'PF1_1', '', 'WS.105.1a');
137
+ insert into PSlot values ('PS.1st.c2', 'PF1_1', '', 'WS.105.1b');
138
+ insert into PSlot values ('PS.1st.c3', 'PF1_1', '', 'WS.105.2a');
139
+ insert into PSlot values ('PS.1st.c4', 'PF1_1', '', 'WS.105.2b');
140
+ insert into PSlot values ('PS.1st.c5', 'PF1_1', '', 'WS.105.3a');
141
+ insert into PSlot values ('PS.1st.c6', 'PF1_1', '', 'WS.105.3b');
142
+
143
+ insert into PSlot values ('PS.1st.d1', 'PF1_1', '', 'WS.106.1a');
144
+ insert into PSlot values ('PS.1st.d2', 'PF1_1', '', 'WS.106.1b');
145
+ insert into PSlot values ('PS.1st.d3', 'PF1_1', '', 'WS.106.2a');
146
+ insert into PSlot values ('PS.1st.d4', 'PF1_1', '', 'WS.106.2b');
147
+ insert into PSlot values ('PS.1st.d5', 'PF1_1', '', 'WS.106.3a');
148
+ insert into PSlot values ('PS.1st.d6', 'PF1_1', '', 'WS.106.3b');
149
+
150
+ --
151
+ -- Now we wire the wall connectors 1a-2a in room 001 to the
152
+ -- patchfield. In the second update we make an error, and
153
+ -- correct it after
154
+ --
155
+ update PSlot set backlink = 'WS.001.1a' where slotname = 'PS.base.a1';
156
+ update PSlot set backlink = 'WS.001.1b' where slotname = 'PS.base.a3';
157
+ select * from WSlot where roomno = '001' order by slotname;
158
+ select * from PSlot where slotname ~ 'PS.base.a' order by slotname;
159
+ update PSlot set backlink = 'WS.001.2a' where slotname = 'PS.base.a3';
160
+ select * from WSlot where roomno = '001' order by slotname;
161
+ select * from PSlot where slotname ~ 'PS.base.a' order by slotname;
162
+ update PSlot set backlink = 'WS.001.1b' where slotname = 'PS.base.a2';
163
+ select * from WSlot where roomno = '001' order by slotname;
164
+ select * from PSlot where slotname ~ 'PS.base.a' order by slotname;
165
+
166
+ --
167
+ -- Same procedure for 2b-3b but this time updating the WSlot instead
168
+ -- of the PSlot. Due to the triggers the result is the same:
169
+ -- WSlot and corresponding PSlot point to each other.
170
+ --
171
+ update WSlot set backlink = 'PS.base.a4' where slotname = 'WS.001.2b';
172
+ update WSlot set backlink = 'PS.base.a6' where slotname = 'WS.001.3a';
173
+ select * from WSlot where roomno = '001' order by slotname;
174
+ select * from PSlot where slotname ~ 'PS.base.a' order by slotname;
175
+ update WSlot set backlink = 'PS.base.a6' where slotname = 'WS.001.3b';
176
+ select * from WSlot where roomno = '001' order by slotname;
177
+ select * from PSlot where slotname ~ 'PS.base.a' order by slotname;
178
+ update WSlot set backlink = 'PS.base.a5' where slotname = 'WS.001.3a';
179
+ select * from WSlot where roomno = '001' order by slotname;
180
+ select * from PSlot where slotname ~ 'PS.base.a' order by slotname;
181
+
182
+ insert into PField values ('PF1_2', 'Phonelines 1st floor');
183
+
184
+ insert into PSlot values ('PS.1st.ta1', 'PF1_2', '', '');
185
+ insert into PSlot values ('PS.1st.ta2', 'PF1_2', '', '');
186
+ insert into PSlot values ('PS.1st.ta3', 'PF1_2', '', '');
187
+ insert into PSlot values ('PS.1st.ta4', 'PF1_2', '', '');
188
+ insert into PSlot values ('PS.1st.ta5', 'PF1_2', '', '');
189
+ insert into PSlot values ('PS.1st.ta6', 'PF1_2', '', '');
190
+
191
+ insert into PSlot values ('PS.1st.tb1', 'PF1_2', '', '');
192
+ insert into PSlot values ('PS.1st.tb2', 'PF1_2', '', '');
193
+ insert into PSlot values ('PS.1st.tb3', 'PF1_2', '', '');
194
+ insert into PSlot values ('PS.1st.tb4', 'PF1_2', '', '');
195
+ insert into PSlot values ('PS.1st.tb5', 'PF1_2', '', '');
196
+ insert into PSlot values ('PS.1st.tb6', 'PF1_2', '', '');
197
+
198
+ --
199
+ -- Fix the wrong name for patchfield PF0_2
200
+ --
201
+ update PField set name = 'PF0_2' where name = 'PF0_X';
202
+
203
+ select * from PSlot order by slotname;
204
+ select * from WSlot order by slotname;
205
+
206
+ --
207
+ -- Install the central phone system and create the phone numbers.
208
+ -- They are weired on insert to the patchfields. Again the
209
+ -- triggers automatically tell the PSlots to update their
210
+ -- backlink field.
211
+ --
212
+ insert into PLine values ('PL.001', '-0', 'Central call', 'PS.base.ta1');
213
+ insert into PLine values ('PL.002', '-101', '', 'PS.base.ta2');
214
+ insert into PLine values ('PL.003', '-102', '', 'PS.base.ta3');
215
+ insert into PLine values ('PL.004', '-103', '', 'PS.base.ta5');
216
+ insert into PLine values ('PL.005', '-104', '', 'PS.base.ta6');
217
+ insert into PLine values ('PL.006', '-106', '', 'PS.base.tb2');
218
+ insert into PLine values ('PL.007', '-108', '', 'PS.base.tb3');
219
+ insert into PLine values ('PL.008', '-109', '', 'PS.base.tb4');
220
+ insert into PLine values ('PL.009', '-121', '', 'PS.base.tb5');
221
+ insert into PLine values ('PL.010', '-122', '', 'PS.base.tb6');
222
+ insert into PLine values ('PL.015', '-134', '', 'PS.1st.ta1');
223
+ insert into PLine values ('PL.016', '-137', '', 'PS.1st.ta3');
224
+ insert into PLine values ('PL.017', '-139', '', 'PS.1st.ta4');
225
+ insert into PLine values ('PL.018', '-362', '', 'PS.1st.tb1');
226
+ insert into PLine values ('PL.019', '-363', '', 'PS.1st.tb2');
227
+ insert into PLine values ('PL.020', '-364', '', 'PS.1st.tb3');
228
+ insert into PLine values ('PL.021', '-365', '', 'PS.1st.tb5');
229
+ insert into PLine values ('PL.022', '-367', '', 'PS.1st.tb6');
230
+ insert into PLine values ('PL.028', '-501', 'Fax entrance', 'PS.base.ta2');
231
+ insert into PLine values ('PL.029', '-502', 'Fax 1st floor', 'PS.1st.ta1');
232
+
233
+ --
234
+ -- Buy some phones, plug them into the wall and patch the
235
+ -- phone lines to the corresponding patchfield slots.
236
+ --
237
+ insert into PHone values ('PH.hc001', 'Hicom standard', 'WS.001.1a');
238
+ update PSlot set slotlink = 'PS.base.ta1' where slotname = 'PS.base.a1';
239
+ insert into PHone values ('PH.hc002', 'Hicom standard', 'WS.002.1a');
240
+ update PSlot set slotlink = 'PS.base.ta5' where slotname = 'PS.base.b1';
241
+ insert into PHone values ('PH.hc003', 'Hicom standard', 'WS.002.2a');
242
+ update PSlot set slotlink = 'PS.base.tb2' where slotname = 'PS.base.b3';
243
+ insert into PHone values ('PH.fax001', 'Canon fax', 'WS.001.2a');
244
+ update PSlot set slotlink = 'PS.base.ta2' where slotname = 'PS.base.a3';
245
+
246
+ --
247
+ -- Install a hub at one of the patchfields, plug a computers
248
+ -- ethernet interface into the wall and patch it to the hub.
249
+ --
250
+ insert into Hub values ('base.hub1', 'Patchfield PF0_1 hub', 16);
251
+ insert into System values ('orion', 'PC');
252
+ insert into IFace values ('IF', 'orion', 'eth0', 'WS.002.1b');
253
+ update PSlot set slotlink = 'HS.base.hub1.1' where slotname = 'PS.base.b2';
254
+
255
+ --
256
+ -- Now we take a look at the patchfield
257
+ --
258
+ select * from PField_v1 where pfname = 'PF0_1' order by slotname;
259
+ select * from PField_v1 where pfname = 'PF0_2' order by slotname;
260
+
261
+ --
262
+ -- Finally we want errors
263
+ --
264
+ insert into PField values ('PF1_1', 'should fail due to unique index');
265
+ update PSlot set backlink = 'WS.not.there' where slotname = 'PS.base.a1';
266
+ update PSlot set backlink = 'XX.illegal' where slotname = 'PS.base.a1';
267
+ update PSlot set slotlink = 'PS.not.there' where slotname = 'PS.base.a1';
268
+ update PSlot set slotlink = 'XX.illegal' where slotname = 'PS.base.a1';
269
+ insert into HSlot values ('HS', 'base.hub1', 1, '');
270
+ insert into HSlot values ('HS', 'base.hub1', 20, '');
271
+ delete from HSlot;
272
+ insert into IFace values ('IF', 'notthere', 'eth0', '');
273
+ insert into IFace values ('IF', 'orion', 'ethernet_interface_name_too_long', '');
@@ -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
+