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,1571 @@
1
+ =begin
2
+ = PL/Ruby
3
+
4
+ * ((<Defining function in PL Ruby>))
5
+ * ((<Function returning SET (SFRM Materialize)>))
6
+ * ((<Function returning SET (ExprMultiResult)>))
7
+ * ((<Trigger procedures in PL Ruby>))
8
+ * ((<plruby_singleton_methods>))
9
+ * ((<Conversion>))
10
+ * ((<Class and modules>))
11
+ * ((<module PL>)) : general module
12
+ * ((<class PL::Plan>)) : class for prepared plans
13
+ * ((<class PL::Cursor>)) : class for cursors
14
+ * ((<class PL::Transaction>)) : class for transactions (8.0)
15
+ * ((<class BitString>))
16
+ * ((<class Tinterval>))
17
+ * ((<class NetAddr>))
18
+ * ((<class MacAddr>))
19
+ * ((<class Box>))
20
+ * ((<class Circle>))
21
+ * ((<class Path>))
22
+ * ((<class Point>))
23
+ * ((<class Polygon>))
24
+ * ((<class Segment>))
25
+
26
+ PL/Ruby is a loadable procedural language for the PostgreSQL database
27
+ system that enables the Ruby language to create functions and trigger
28
+ procedures.
29
+
30
+ Functions and triggers are defined as singleton methods of the module
31
+ PLtemp.
32
+
33
+ = WARNING
34
+ ((*if PL/Ruby was compiled with ((%--disable-conversion%)),
35
+ all arguments (to the function or the triggers) are passed as string
36
+ values, except for NULL values represented by ((%Qnil%)).*))
37
+ ((*In this case you must explicitely call a conversion function (like to_i)
38
+ if you want to use an argument as an integer*))
39
+
40
+ == Defining function in PL Ruby
41
+
42
+ To create a function in the PL/Ruby language use the syntax
43
+
44
+ CREATE FUNCTION funcname(arguments_type) RETURNS type AS '
45
+
46
+ # PL/Ruby function body
47
+
48
+ ' LANGUAGE 'plruby';
49
+
50
+ when calling the function in a query, the arguments are given
51
+ in the array ((%args%)). To create a little max
52
+ function returning the higher of two int4 values write :
53
+
54
+ CREATE FUNCTION ruby_max(int4, int4) RETURNS int4 AS '
55
+ if args[0] > args[1]
56
+ return args[0]
57
+ else
58
+ return args[1]
59
+ end
60
+ ' LANGUAGE 'plruby';
61
+
62
+ Tuple arguments are given as hash. Here is an example that defines
63
+ the overpaid_2 function (as found in the older Postgres documentation)
64
+ in PL/Ruby.
65
+
66
+ CREATE FUNCTION overpaid_2 (EMP) RETURNS bool AS '
67
+ args[0]["salary"] > 200000 ||
68
+ (args[0]["salary"] > 100000 && args[0]["age"] < 30)
69
+ ' LANGUAGE 'plruby';
70
+
71
+ === Warning : with PostgreSQL >= 7.4 "array" are given as a ruby Array
72
+
73
+ For example to define a function (int4[], int4) and return int4[],
74
+ in version < 7.4 you write
75
+
76
+ CREATE FUNCTION ruby_int4_accum(_int4, int4) RETURNS _int4 AS '
77
+ if /\\{(\\d+),(\\d+)\\}/ =~ args[0]
78
+ a, b = $1, $2
79
+ newsum = a + args[1]
80
+ newcnt = b + 1
81
+ else
82
+ raise "unexpected value #{args[0]}"
83
+ end
84
+ "{#{newsum},#{newcnt}}"
85
+ ' LANGUAGE 'plruby';
86
+
87
+ This must now (>= 7.4) be written
88
+
89
+ CREATE FUNCTION ruby_int4_accum(_int4, int4) RETURNS _int4 AS '
90
+ a = args[0]
91
+ [a[0] + args[1], a[1] + 1]
92
+ ' LANGUAGE 'plruby';
93
+
94
+ === Release PostgreSQL 8.0
95
+
96
+ With this version, plruby can have named arguments and the previous functions
97
+ can be written
98
+
99
+ CREATE FUNCTION ruby_max(a int4, b int4) RETURNS int4 AS '
100
+ if a > b
101
+ a
102
+ else
103
+ b
104
+ end
105
+ ' LANGUAGE 'plruby';
106
+
107
+
108
+ CREATE FUNCTION overpaid_2 (emp EMP) RETURNS bool AS '
109
+ emp["salary"] > 200000 ||
110
+ (emp["salary"] > 100000 && emp["age"] < 30)
111
+ ' LANGUAGE 'plruby';
112
+
113
+ With this version, you can also use transaction. For example
114
+
115
+ plruby_test=# create table tu (a int, b int);
116
+ CREATE TABLE
117
+ plruby_test=# create or replace function tt(abort bool) returns bool as '
118
+ plruby_test'# transaction do |txn|
119
+ plruby_test'# PL.exec("insert into tu values (1, 2)")
120
+ plruby_test'# transaction do |txn1|
121
+ plruby_test'# PL.exec("insert into tu values (3, 4)")
122
+ plruby_test'# txn1.abort
123
+ plruby_test'# end
124
+ plruby_test'# PL.exec("insert into tu values (5, 6)")
125
+ plruby_test'# txn.abort if abort
126
+ plruby_test'# end
127
+ plruby_test'# abort
128
+ plruby_test'# ' language 'plruby';
129
+ CREATE FUNCTION
130
+ plruby_test=#
131
+ plruby_test=# select tt(true);
132
+ tt
133
+ ----
134
+ t
135
+ (1 row)
136
+
137
+ plruby_test=# select * from tu;
138
+ a | b
139
+ ---+---
140
+ (0 rows)
141
+
142
+ plruby_test=# select tt(false);
143
+ tt
144
+ ----
145
+ f
146
+ (1 row)
147
+
148
+ plruby_test=# select * from tu;
149
+ a | b
150
+ ---+---
151
+ 1 | 2
152
+ 5 | 6
153
+ (2 rows)
154
+
155
+ plruby_test=#
156
+
157
+
158
+ == Function returning SET (SFRM Materialize)
159
+
160
+ The return type must be declared as SETOF
161
+
162
+ The function must call ((%yield%)) to return rows or return a String which
163
+ must be a valid SELECT statement
164
+
165
+ For example to concatenate 2 rows create the function
166
+
167
+ plruby_test=# CREATE FUNCTION tu(varchar) RETURNS setof record
168
+ plruby_test-# AS '
169
+ plruby_test'# size = PL.column_name(args[0]).size
170
+ plruby_test'# res = nil
171
+ plruby_test'# PL::Plan.new("select * from #{args[0]}",
172
+ plruby_test'# "block" => 50).each do |row|
173
+ plruby_test'# if res.nil?
174
+ plruby_test'# res = row.values
175
+ plruby_test'# else
176
+ plruby_test'# res.concat row.values
177
+ plruby_test'# yield res
178
+ plruby_test'# res = nil
179
+ plruby_test'# end
180
+ plruby_test'# end
181
+ plruby_test'# if res
182
+ plruby_test'# res.concat Array.new(size)
183
+ plruby_test'# yield res
184
+ plruby_test'# end
185
+ plruby_test'# ' language 'plruby';
186
+ CREATE FUNCTION
187
+ plruby_test=#
188
+ plruby_test=# select * from tt;
189
+ a | b
190
+ ---+----
191
+ 1 | 2
192
+ 3 | 4
193
+ 5 | 6
194
+ 7 | 8
195
+ 9 | 10
196
+ (5 rows)
197
+
198
+ plruby_test=# select * from tu('tt') as tbl(a int, b int, c int, d int);
199
+ a | b | c | d
200
+ ---+----+---+---
201
+ 1 | 2 | 3 | 4
202
+ 5 | 6 | 7 | 8
203
+ 9 | 10 | |
204
+ (3 rows)
205
+
206
+ plruby_test=#
207
+
208
+ == Function returning SET (ExprMultiResult)
209
+
210
+ The return type must be declared as SETOF
211
+
212
+ The function is called until it returns nil
213
+
214
+ The method PL#context and PL#context= give the possibility to store information
215
+ between the call
216
+
217
+ For example
218
+
219
+ plruby_test=# create or replace function vv(int) returns setof int as '
220
+ plruby_test'# i = PL.context || 0
221
+ plruby_test'# if i >= args[0]
222
+ plruby_test'# nil
223
+ plruby_test'# else
224
+ plruby_test'# PL.context = i + 1
225
+ plruby_test'# end
226
+ plruby_test'# ' language plruby;
227
+ CREATE FUNCTION
228
+ plruby_test=#
229
+ plruby_test=# select * from uu;
230
+ b
231
+ ---
232
+ 2
233
+ (1 row)
234
+
235
+ plruby_test=#
236
+ plruby_test=# select *,vv(3) from uu;
237
+ b | vv
238
+ ---+----
239
+ 2 | 1
240
+ 2 | 2
241
+ 2 | 3
242
+ (3 rows)
243
+
244
+ plruby_test=#
245
+
246
+ == Trigger procedures in PL Ruby
247
+
248
+ Trigger procedures are defined in Postgres as functions without
249
+ arguments and a return type of trigger. In PL/Ruby the procedure is
250
+ called with 4 arguments :
251
+
252
+ :new (hash, tainted)
253
+ an hash containing the values of the new table row on INSERT/UPDATE
254
+ actions, or empty on DELETE.
255
+ :old (hash, tainted)
256
+ an hash containing the values of the old table row on UPDATE/DELETE
257
+ actions, or empty on INSERT
258
+ :args (array, tainted, frozen)
259
+ An array of the arguments to the procedure as given in the CREATE
260
+ TRIGGER statement
261
+ :tg (hash, tainted, frozen)
262
+ The following keys are defined
263
+
264
+ :name
265
+ The name of the trigger from the CREATE TRIGGER statement.
266
+
267
+ :relname
268
+ The name of the relation who has fired the trigger
269
+
270
+ :relid
271
+ The object ID of the table that caused the trigger procedure to be invoked.
272
+
273
+ :relatts
274
+ An array containing the name of the tables field.
275
+
276
+ :when
277
+ The constant ((%PL::BEFORE%)), ((%PL::AFTER%)) or
278
+ ((%PL::UNKNOWN%)) depending on the event of the trigger call.
279
+
280
+ :level
281
+ The constant ((%PL::ROW%)) or ((%PL::STATEMENT%))
282
+ depending on the event of the trigger call.
283
+
284
+ :op
285
+ The constant ((%PL::INSERT%)), ((%PL::UPDATE%)) or
286
+ ((%PL::DELETE%)) depending on the event of the trigger call.
287
+
288
+
289
+ The return value from a trigger procedure is one of the constant
290
+ ((%PL::OK%)) or ((%PL::SKIP%)), or an hash. If the
291
+ return value is ((%PL::OK%)), the normal operation
292
+ (INSERT/UPDATE/DELETE) that fired this trigger will take
293
+ place. Obviously, ((%PL::SKIP%)) tells the trigger manager to
294
+ silently suppress the operation. The hash tells
295
+ PL/Ruby to return a modified row to the trigger manager that will be
296
+ inserted instead of the one given in ((%new%)) (INSERT/UPDATE
297
+ only). Needless to say that all this is only meaningful when the
298
+ trigger is BEFORE and FOR EACH ROW.
299
+
300
+ Here's a little example trigger procedure that forces an integer
301
+ value in a table to keep track of the # of updates that are performed
302
+ on the row. For new row's inserted, the value is initialized to 0 and
303
+ then incremented on every update operation :
304
+
305
+ CREATE FUNCTION trigfunc_modcount() RETURNS TRIGGER AS '
306
+ case tg["op"]
307
+ when PL::INSERT
308
+ new[args[0]] = 0
309
+ when PL::UPDATE
310
+ new[args[0]] = old[args[0]] + 1
311
+ else
312
+ return PL::OK
313
+ end
314
+ new
315
+ ' LANGUAGE 'plruby';
316
+
317
+ CREATE TABLE mytab (num int4, modcnt int4, descr text);
318
+
319
+ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
320
+ FOR EACH ROW EXECUTE PROCEDURE trigfunc_modcount('modcnt');
321
+
322
+
323
+
324
+ A more complex example (extract from test_setup.sql in the distribution)
325
+ which use the global variable ((%$Plans%)) to store a prepared
326
+ plan
327
+
328
+ create function trig_pkey2_after() returns trigger as '
329
+ if ! $Plans.key?("plan_dta2_upd")
330
+ $Plans["plan_dta2_upd"] =
331
+ PL::Plan.new("update T_dta2
332
+ set ref1 = $3, ref2 = $4
333
+ where ref1 = $1 and ref2 = $2",
334
+ ["int4", "varchar", "int4", "varchar" ]).save
335
+ $Plans["plan_dta2_del"] =
336
+ PL::Plan.new("delete from T_dta2
337
+ where ref1 = $1 and ref2 = $2",
338
+ ["int4", "varchar"]).save
339
+ end
340
+
341
+ old_ref_follow = false
342
+ old_ref_delete = false
343
+
344
+ case tg["op"]
345
+ when PL::UPDATE
346
+ new["key2"] = new["key2"].upcase
347
+ old_ref_follow = (new["key1"] != old["key1"]) ||
348
+ (new["key2"] != old["key2"])
349
+ when PL::DELETE
350
+ old_ref_delete = true
351
+ end
352
+
353
+ if old_ref_follow
354
+ n = $Plans["plan_dta2_upd"].exec([old["key1"], old["key2"], new["key1"],
355
+ new["key2"]])
356
+ warn "updated #{n} entries in T_dta2 for new key in T_pkey2" if n != 0
357
+ end
358
+
359
+ if old_ref_delete
360
+ n = $Plans["plan_dta2_del"].exec([old["key1"], old["key2"]])
361
+ warn "deleted #{n} entries from T_dta2" if n != 0
362
+ end
363
+
364
+ PL::OK
365
+ ' language 'plruby';
366
+
367
+ create trigger pkey2_after after update or delete on T_pkey2
368
+ for each row execute procedure
369
+ trig_pkey2_after();
370
+
371
+
372
+ == plruby_singleton_methods
373
+
374
+ Sometime it can be usefull to define methods (in pure Ruby) which can be
375
+ called from a PL/Ruby function or a PL/Ruby trigger.
376
+
377
+ In this case, you have 2 possibilities
378
+
379
+ * the "stupid" way (({:-) :-) :-)}))
380
+
381
+ just close the current definition of the function (or trigger) with a
382
+ (({end})) and define your singleton method without the final (({end}))
383
+
384
+ Here a small and useless example
385
+
386
+ plruby_test=# CREATE FUNCTION tutu() RETURNS int4 AS '
387
+ plruby_test'# toto(1, 3) + toto(4, 4)
388
+ plruby_test'# end
389
+ plruby_test'#
390
+ plruby_test'# def PLtemp.toto(a, b)
391
+ plruby_test'# a + b
392
+ plruby_test'# ' LANGUAGE 'plruby';
393
+ CREATE
394
+ plruby_test=# select tutu();
395
+ tutu
396
+ ----
397
+ 12
398
+ (1 row)
399
+
400
+ plruby_test=#
401
+
402
+
403
+ * create a table plruby_singleton_methods with the columns (name, args, body)
404
+
405
+ At load time, PL/Ruby look if it exist a table plruby_singleton_methods and if
406
+ found try, for each row, to define singleton methods with the template :
407
+
408
+
409
+ def PLtemp.#{name} (#{args})
410
+ #{body}
411
+ end
412
+
413
+ The previous example can be written (you have a more complete example in
414
+ test/plp/test_setup.sql)
415
+
416
+
417
+ plruby_test=# SELECT * FROM plruby_singleton_methods;
418
+ name|args|body
419
+ ----+----+-----
420
+ toto|a, b|a + b
421
+ (1 row)
422
+
423
+ plruby_test=# CREATE FUNCTION tutu() RETURNS int4 AS '
424
+ plruby_test'# toto(1, 3) + toto(4, 4)
425
+ plruby_test'# ' LANGUAGE 'plruby';
426
+ CREATE
427
+ plruby_test=# select tutu();
428
+ tutu
429
+ ----
430
+ 12
431
+ (1 row)
432
+
433
+ plruby_test=#
434
+
435
+ * Another example, if PLRuby was compiled with --enable-conversion and it
436
+ exist a column with the name '***' then it can create a singleton method
437
+ from a PLRuby function
438
+
439
+
440
+ plruby_test=# select * from plruby_singleton_methods;
441
+ name | args | body
442
+ ------+------+------
443
+ *** | |
444
+ (1 row)
445
+
446
+ plruby_test=# create function add_value(int, int) returns int as '
447
+ plruby_test'# args[0] + args[1]
448
+ plruby_test'# ' language 'plruby';
449
+ CREATE FUNCTION
450
+ plruby_test=#
451
+ plruby_test=# select add_value(10, 2);
452
+ add_value
453
+ -----------
454
+ 12
455
+ (1 row)
456
+
457
+ plruby_test=#
458
+ plruby_test=# create function add_one(int) returns int as '
459
+ plruby_test'# add_value(args[0], 1)
460
+ plruby_test'# ' language 'plruby';
461
+ CREATE FUNCTION
462
+ plruby_test=#
463
+ plruby_test=# select add_one(11);
464
+ add_one
465
+ ---------
466
+ 12
467
+ (1 row)
468
+
469
+ plruby_test=#
470
+
471
+ == Conversion
472
+
473
+ If the conversions was not disabled (--disable-conversion), the following
474
+ conversions are made
475
+
476
+ PostgreSQL Ruby
477
+ ---------- ----
478
+ OID Fixnum
479
+ INT2OID Fixnum
480
+ INT4OID Fixnum
481
+ INT8OID Fixnum (or Bignum)
482
+ FLOAT4OID Float
483
+ FLOAT8OID Float
484
+ CASHOID Float
485
+ NUMERICOID Float
486
+ BOOLOID true, false
487
+ ABSTIMEOID Time
488
+ RELTIMEOID Time
489
+ TIMEOID Time
490
+ TIMETZOID Time
491
+ TIMESTAMPOID Time
492
+ TIMESTAMPTZOID Time
493
+ DATEOID Time
494
+ INTERVALOID Time
495
+ TINTERVALOID Tinterval (new Ruby class)
496
+ BITOID BitString (new Ruby class)
497
+ VARBITOID BitString (new Ruby class)
498
+ INETOID NetAddr (new Ruby class)
499
+ CIDROID NetAddr (new Ruby class)
500
+ MACADDROID MacAddr (new Ruby class)
501
+ POINTOID Point (new Ruby class)
502
+ LSEGOID Segment (new Ruby class)
503
+ BOXOID Box (new Ruby class)
504
+ PATHOID Path (new Ruby class)
505
+ POLYGONOID Polygon (new Ruby class)
506
+ CIRCLEOID Circle (new Ruby class)
507
+
508
+ all others OID are converted to a String object
509
+
510
+
511
+ == Class and modules
512
+
513
+ === Global
514
+
515
+ --- transaction {|txn| }
516
+ create a new transaction, yield an object ((%PL::Transaction%))
517
+
518
+ --- warn [level], message
519
+ Ruby interface to PostgreSQL elog()
520
+
521
+ Possible value for ((%level%)) are ((%NOTICE%)), ((%DEBUG%)) and ((%NOIND%))
522
+
523
+ Use ((%raise()%)) if you want to simulate ((%elog(ERROR, "...")%))
524
+
525
+ --- $Plans (hash, tainted)
526
+ can be used to store prepared plans.
527
+
528
+ === module PL
529
+
530
+ general module
531
+
532
+ --- args_type
533
+ Return the type of the arguments given to the function
534
+
535
+ --- column_name(table)
536
+ Return the name of the columns for the table
537
+
538
+ --- column_type(table)
539
+ return the type of the columns for the table
540
+
541
+ --- context
542
+ Return the context (or nil) associated with a SETOF function
543
+ (ExprMultiResult)
544
+
545
+ --- context=
546
+ Set the context for a SETOF function (ExprMultiResult)
547
+
548
+ --- quote(string)
549
+
550
+ Duplicates all occurences of single quote and backslash
551
+ characters. It should be used when variables are used in the query
552
+ string given to spi_exec or spi_prepare (not for the value list on
553
+ execp).
554
+
555
+ --- result_name
556
+ Return the name of the columns for a function returning a SETOF
557
+
558
+ --- result_type
559
+ Return the type of the columns for a function returning a SETOF
560
+ or the type of the return value
561
+
562
+ --- result_size
563
+ Return the number of columns for a function returning a SETOF
564
+
565
+ --- result_description
566
+ Return the table description given to a function returning a SETOF
567
+
568
+ --- exec(string [, count [, type]])
569
+ --- spi_exec(string [, count [, type]])
570
+
571
+ Call parser/planner/optimizer/executor for query. The optional
572
+ ((%count%)) value tells spi_exec the maximum number of rows to be
573
+ processed by the query.
574
+
575
+ :SELECT
576
+ If the query is a SELECT statement, an array is return (if count is
577
+ not specified or with a value > 1). Each element of this array is an
578
+ hash where the key is the column name.
579
+
580
+ If type is specified it can take the value
581
+
582
+ * "array" return for each column an array with the element
583
+ ["name", "value", "type", "len", "typeid"]
584
+ * "hash" return for each column an hash with the keys
585
+ {"name", "value", "type", "len", "typeid"}
586
+ * "value" return all values
587
+
588
+ For example this procedure display all rows in the table pg_table.
589
+
590
+ CREATE FUNCTION pg_table_dis() RETURNS int4 AS '
591
+ res = PLruby.exec("select * from pg_class")
592
+ res.each do |x|
593
+ warn "======================"
594
+ x.each do |y, z|
595
+ warn "name = #{y} -- value = #{z}"
596
+ end
597
+ warn "======================"
598
+ end
599
+ return res.size
600
+ ' LANGUAGE 'plruby';
601
+
602
+ A block can be specified, in this case a call to yield() will be
603
+ made.
604
+
605
+ If count is specified with the value 1, only the first row (or
606
+ FALSE if it fail) is returned as a hash. Here a little example :
607
+
608
+
609
+ CREATE FUNCTION pg_table_dis() RETURNS int4 AS '
610
+ PL.exec("select * from pg_class", 1) { |y, z|
611
+ warn "name = #{y} -- value = #{z}"
612
+ }
613
+ return 1
614
+ ' LANGUAGE 'plruby';
615
+
616
+ Another example with count = 1
617
+
618
+ create table T_pkey1 (
619
+ skey1 int4,
620
+ skey2 varchar(20),
621
+ stxt varchar(40)
622
+ );
623
+
624
+ create function toto() returns bool as '
625
+ warn("=======")
626
+ PL.exec("select * from T_pkey1", 1, "hash") do |a|
627
+ warn(a.inspect)
628
+ end
629
+ warn("=======")
630
+ PL.exec("select * from T_pkey1", 1, "array") do |a|
631
+ warn(a.inspect)
632
+ end
633
+ warn("=======")
634
+ PL.exec("select * from T_pkey1", 1) do |a|
635
+ warn(a.inspect)
636
+ end
637
+ warn("=======")
638
+ return true
639
+ ' language 'plruby';
640
+
641
+
642
+ plruby_test=# select toto();
643
+ NOTICE: =======
644
+ NOTICE: {"name"=>"skey1", "typeid"=>23, "type"=>"int4", "value"=>"12", "len"=>4}
645
+ NOTICE: {"name"=>"skey2", "typeid"=>1043, "type"=>"varchar", "value"=>"a", "len"=>20}
646
+ NOTICE: {"name"=>"stxt", "typeid"=>1043, "type"=>"varchar", "value"=>"b", "len"=>40}
647
+ NOTICE: =======
648
+ NOTICE: ["skey1", "12", "int4", 4, 23]
649
+ NOTICE: ["skey2", "a", "varchar", 20, 1043]
650
+ NOTICE: ["stxt", "b", "varchar", 40, 1043]
651
+ NOTICE: =======
652
+ NOTICE: ["skey1", "12"]
653
+ NOTICE: ["skey2", "a"]
654
+ NOTICE: ["stxt", "b"]
655
+ NOTICE: =======
656
+ toto
657
+ ------
658
+ t
659
+ (1 row)
660
+
661
+ plruby_test=#
662
+
663
+
664
+ :SELECT INTO, INSERT, UPDATE, DELETE
665
+ return the number of rows insered, updated, deleted, ...
666
+
667
+ :UTILITY
668
+ return TRUE
669
+
670
+ --- prepare(string[, types])
671
+ --- spi_prepare(string[, types])
672
+ --- prepare(string, "types" => types, "count" => count, "output" => type, "tmp" => true)
673
+
674
+ Deprecated : See ((%PL::Plan::new%)) and ((%PL::Plan#save%))
675
+
676
+ Prepares AND SAVES a query plan for later execution. It is a bit
677
+ different from the C level SPI_prepare in that the plan is
678
+ automatically copied to the toplevel memory context.
679
+
680
+ If the query references arguments, the type names must be given as a
681
+ Ruby array of strings. The return value from prepare is a
682
+ ((%PL::Plan%)) object to be used in subsequent calls to
683
+ ((%PL::Plan#exec%)).
684
+
685
+ If the hash given has the keys ((%count%)), ((%output%)) these values
686
+ will be given to the subsequent calls to ((%each%))
687
+
688
+ === class PL::Plan
689
+
690
+ class for prepared plan
691
+
692
+ --- initialize(string, "types" => types, "count" => count, "output" => type, "save" => false)
693
+
694
+ Prepares a query plan for later execution.
695
+
696
+ If the query references arguments, the type names must be given as a
697
+ Ruby array of strings.
698
+
699
+ If the hash given has the keys ((%output%)), ((%count%)) these values
700
+ will be given to the subsequent calls to ((%each%))
701
+
702
+ If ((%"save"%)) as a true value, the plan will be saved
703
+
704
+
705
+ --- exec(values, [count [, type]])
706
+ --- execp(values, [count [, type]])
707
+ --- exec("values" => values, "count" => count, "output" => type)
708
+ --- execp("values" => values, "count" => count, "output" => type)
709
+
710
+ Execute a prepared plan from ((%PL::PLan::new%)) with variable
711
+ substitution. The optional ((%count%)) value tells
712
+ ((%PL::Plan#exec%)) the maximum number of rows to be processed by the
713
+ query.
714
+
715
+ If there was a typelist given to ((%PL::Plan::new%)), an array
716
+ of ((%values%)) of exactly the same length must be given to
717
+ ((%PL::Plan#exec%)) as first argument. If the type list on
718
+ ((%PL::Plan::new%)) was empty, this argument must be omitted.
719
+
720
+ If the query is a SELECT statement, the same as described for
721
+ ((%PL#exec%)) happens for the loop-body and the variables for
722
+ the fields selected.
723
+
724
+ If type is specified it can take the values
725
+ * "array" return an array with the element ["name", "value", "type", "len", "typeid"]
726
+ * "hash" return an hash with the keys {"name", "value", "type", "len", "typeid"}
727
+ * "value" return an array with all values
728
+
729
+ Here's an example for a PL/Ruby function using a prepared plan :
730
+
731
+ CREATE FUNCTION t1_count(int4, int4) RETURNS int4 AS '
732
+ if ! $Plans.key?("plan")
733
+ # prepare the saved plan on the first call
734
+ $Plans["plan"] = PL::Plan.new("SELECT count(*) AS cnt FROM t1
735
+ WHERE num >= $1 AND num <= $2",
736
+ ["int4", "int4"]).save
737
+ end
738
+ n = $Plans["plan"].exec([args[0], args[1]], 1)
739
+ n["cnt"]
740
+ ' LANGUAGE 'plruby';
741
+
742
+ --- cursor(name = nil, "values" => values, "output" => type)
743
+
744
+ Create a new object PL::Cursor
745
+
746
+ If output is specified it can take the values
747
+ * "array" return an array with the element ["name", "value", "type", "len", "typeid"]
748
+ * "hash" return an hash with the keys {"name", "value", "type", "len", "typeid"}
749
+ * "value" return an array with all values
750
+
751
+ If there was a typelist given to ((%PL::Plan::new%)), an array
752
+ of ((%values%)) of exactly the same length must be given to
753
+ ((%PL::Plan#cursor%))
754
+
755
+ --- each(values, [count [, type ]]) { ... }
756
+ --- fetch(values, [count [, type ]]) { ... }
757
+ --- each("values" => values, "count" => count, "output" => type) { ... }
758
+ --- fetch("values" => values, "count" => count, "output" => type) { ... }
759
+
760
+ Same then #exec but a call to SPI_cursor_open(), SPI_cursor_fetch() is made.
761
+
762
+ Can be used only with a block and a SELECT statement
763
+
764
+ create function toto() returns bool as '
765
+ plan = PL::Plan.new("select * from T_pkey1")
766
+ warn "=====> ALL"
767
+ plan.each do |x|
768
+ warn(x.inspect)
769
+ end
770
+ warn "=====> FIRST 2"
771
+ plan.each("count" => 2) do |x|
772
+ warn(x.inspect)
773
+ end
774
+ return true
775
+ ' language 'plruby';
776
+
777
+ plruby_test=# select * from T_pkey1;
778
+ skey1 | skey2 | stxt
779
+ -------+-------+------
780
+ 12 | a | b
781
+ 24 | c | d
782
+ 36 | e | f
783
+ (3 rows)
784
+
785
+ plruby_test=#
786
+ plruby_test=# select toto();
787
+ NOTICE: =====> ALL
788
+ NOTICE: {"skey1"=>"12", "skey2"=>"a", "stxt"=>"b"}
789
+ NOTICE: {"skey1"=>"24", "skey2"=>"c", "stxt"=>"d"}
790
+ NOTICE: {"skey1"=>"36", "skey2"=>"e", "stxt"=>"f"}
791
+ NOTICE: =====> FIRST 2
792
+ NOTICE: {"skey1"=>"12", "skey2"=>"a", "stxt"=>"b"}
793
+ NOTICE: {"skey1"=>"24", "skey2"=>"c", "stxt"=>"d"}
794
+ toto
795
+ ------
796
+ t
797
+ (1 row)
798
+
799
+ plruby_test=#
800
+
801
+ --- release
802
+
803
+ Release a query plan
804
+
805
+ --- save
806
+
807
+ Save a query plan for later execution. The plan is copied to the
808
+ toplevel memory context.
809
+
810
+ === class PL::Cursor
811
+
812
+ A cursor is created with the method PL::Plan#cursor
813
+
814
+ --- close
815
+
816
+ Closes a cursor
817
+
818
+ --- each {|row| ... }
819
+
820
+ Iterate over all rows (forward)
821
+
822
+ --- fetch(count = 1)
823
+ --- row(count = 1)
824
+
825
+ Fetches some rows from a cursor
826
+
827
+ if count > 0 fetch forward else backward
828
+
829
+ --- move(count)
830
+
831
+ Move a cursor : if count > 0 move forward else backward
832
+
833
+ --- reverse_each {|row| ... }
834
+
835
+ Iterate over all rows (backward)
836
+
837
+ --- rewind
838
+
839
+ Positions the cursor at the beginning of the table
840
+
841
+ === class PL::Transaction
842
+
843
+ a transaction is created with the global function ((%transaction()%)). Only
844
+ available with PostgreSQL >= 8.0
845
+
846
+ --- abort
847
+ Abort the transaction
848
+
849
+ --- commit
850
+ Commit the transaction
851
+
852
+
853
+ === class BitString
854
+
855
+ The class BitString implement the PostgreSQL type ((|bit|))
856
+ and ((|bit varying|))
857
+
858
+ The modules Comparable and Enumerable are included
859
+
860
+ --- from_string(string, length = strlen(string))
861
+
862
+ Convert a ((|String|)) to a ((|BitString|))
863
+
864
+ --- <=>(other)
865
+
866
+ comparison function for 2 ((|BitString|)) objects
867
+
868
+ All bits are considered and additional zero bits may make one string
869
+ smaller/larger than the other, even if their zero-padded values would
870
+ be the same.
871
+
872
+ --- +(other)
873
+
874
+ Concatenate ((|self|)) and ((|other|))
875
+
876
+ --- &(other)
877
+
878
+ AND operator
879
+
880
+ --- |(other)
881
+
882
+ OR operator
883
+
884
+ --- ^(other)
885
+
886
+ XOR operator
887
+
888
+ --- ~
889
+
890
+ NOT operator
891
+
892
+ --- <<(lshft)
893
+
894
+ LEFT SHIFT operator
895
+
896
+ --- >>(rshft)
897
+
898
+ RIGHT SHIFT operator
899
+
900
+ --- [](*args)
901
+
902
+ Element reference with the same syntax that for a ((|String|)) object
903
+
904
+ Return a ((|BitString|)) or a ((|Fixnum|)) 0, 1
905
+
906
+ bitstring[fixnum]
907
+ bitstring[fixnum, fixnum]
908
+ bitstring[range]
909
+ bitstring[regexp]
910
+ bitstring[regexp, fixnum]
911
+ bitstring[string]
912
+ bitstring[other_bitstring]
913
+
914
+ --- []=(*args)
915
+
916
+ Element assignment with the same syntax that for a ((|String|)) object
917
+
918
+ bitstring[fixnum] = fixnum
919
+ bitstring[fixnum] = string_or_bitstring
920
+ bitstring[fixnum, fixnum] = string_or_bitstring
921
+ bitstring[range] = string_or_bitstring
922
+ bitstring[regexp] = string_or_bitstring
923
+ bitstring[regexp, fixnum] = string_or_bitstring
924
+ bitstring[other_str] = string_or_bitstring
925
+
926
+ --- concat(other)
927
+
928
+ append ((|other|)) to ((|self|))
929
+
930
+ --- each
931
+
932
+ iterate other each bit
933
+
934
+ --- include?(other)
935
+
936
+ return ((|true|)) if ((|other|)) is included in ((|self|))
937
+
938
+ --- index(other)
939
+
940
+ return the position of ((|other|)) in ((|self|))
941
+
942
+ return ((|nil|)) if ((|other|)) is not included in ((|self|))
943
+
944
+ --- initialize(init, nbits = -1)
945
+
946
+ create a new ((|BitString|)) object with ((|nbits|)) bits
947
+
948
+ ((|init|)) can be a ((|Fixnum|)) or a ((|String|))
949
+
950
+ For a ((|String|)) the first character can be 'x', 'X' for and
951
+ hexadecimal representation, or 'b', 'B' for a binary representation.
952
+ The default is a binary representation
953
+
954
+ --- length
955
+
956
+ return the length of ((|self|)) in bits
957
+
958
+ --- octet_length
959
+
960
+ return the length of ((|self|)) in octets
961
+
962
+ --- push(other)
963
+
964
+ append ((|other|)) to ((|self|))
965
+
966
+ --- to_i
967
+
968
+ convert ((|self|)) to a ((|Fixnum|))
969
+
970
+ --- to_s
971
+
972
+ convert ((|self|)) to a ((|String|))
973
+
974
+ === class NetAddr
975
+
976
+ The class NetAddr implement the PostgreSQL type ((|inet|))
977
+ and ((|cidr|))
978
+
979
+ The module Comparable is included
980
+
981
+ --- from_string(string, cidr = false)
982
+ Convert a ((|String|)) to a ((|NetAddr|))
983
+
984
+ --- <=>(other)
985
+ comparison function for 2 ((|NetAddr|)) objects
986
+
987
+ comparison is first on the common bits of the network part, then on
988
+ the length of the network part, and then on the whole unmasked address.
989
+
990
+ --- abbrev
991
+ return the abbreviated display format as a ((|String|)) object
992
+
993
+ --- broadcast
994
+ return the broadcast address from the network
995
+
996
+ --- contain?(other)
997
+ return true if ((|other|)) is included in ((|self|))
998
+
999
+ --- contain_or_equal?(other)
1000
+ return true if ((|other|)) is included in ((|self|)), or equal
1001
+
1002
+ --- contained?(other)
1003
+ return true if ((|self|)) is included in ((|other|))
1004
+
1005
+ --- contained_or_equal?(other)
1006
+ return true if ((|self|)) is included in ((|other|)), or equal
1007
+
1008
+ --- family
1009
+ return the String "AF_INET" or "AF_INET6"
1010
+
1011
+ --- first
1012
+ return the first address in the network
1013
+
1014
+ --- host
1015
+ extract the IP address and return it as a ((|String|))
1016
+
1017
+ --- hostmask
1018
+ return the host mask for network
1019
+
1020
+ --- initialize(string, cidr = false)
1021
+ create a ((|NetAddr|)) from a ((|String|))
1022
+
1023
+ --- last
1024
+ return the last address in the network
1025
+
1026
+ --- masklen
1027
+ return the length of the netmask
1028
+
1029
+ --- netmask
1030
+ return the netmask for the network
1031
+
1032
+ --- network
1033
+ return the network part of the address
1034
+
1035
+ --- set_masklen(len)
1036
+ return a new ((|NetAddr|)) with netmask length ((|len|))
1037
+
1038
+ --- to_s
1039
+ return the string representation of the address
1040
+
1041
+ === class MacAddr
1042
+
1043
+ The MacAddr implement the PostgreSQL type ((|macaddr|))
1044
+
1045
+ The module Comparable is included
1046
+
1047
+ --- from_string(string, cidr = false)
1048
+ Convert a ((|String|)) to a ((|MacAddr|))
1049
+
1050
+ --- <=>(other)
1051
+ comparison function for 2 ((|MacAddr|)) objects
1052
+
1053
+ --- initialize(string)
1054
+ create a ((|MacAddr|)) from a ((|String|))
1055
+
1056
+ --- to_s
1057
+ return the string representation of the MAC address
1058
+
1059
+ --- truncate
1060
+ return a new object with the last 3 bytes set to zero
1061
+
1062
+ === class Tinterval
1063
+
1064
+ The Tinterval implement the PostgreSQL type ((|tinterval|))
1065
+
1066
+ --- from_string(string)
1067
+ Convert a ((|String|)) (PostgreSQL representation)
1068
+ to a ((|Tinterval|))
1069
+
1070
+ --- high
1071
+ return a ((|Time|)) which is the high value of the interval
1072
+
1073
+ --- high=(time)
1074
+ set the high value for the interval
1075
+
1076
+ --- initialize(low, high)
1077
+ create a ((|Tinterval|)) with the 2 ((|Time|)) objects
1078
+ ((|low|)) and ((|high|))
1079
+
1080
+ --- low
1081
+ return a ((|Time|)) which is the low value of the interval
1082
+
1083
+ --- low=(time)
1084
+ set the low value for the interval
1085
+
1086
+ --- to_s
1087
+ return the string representation of the object
1088
+
1089
+ === class Box
1090
+
1091
+ The Box implement the PostgreSQL type ((|box|))
1092
+
1093
+ The module Comparable is included
1094
+
1095
+ --- from_string(string)
1096
+ Convert a ((|String|)) (PostgreSQL representation)
1097
+ to a ((|Box|)) object
1098
+
1099
+ --- +(point)
1100
+ translate (right, up) ((|self|))
1101
+
1102
+ --- -(point)
1103
+ translate (left, down) ((|self|))
1104
+
1105
+ --- *(point)
1106
+ scale and rotate ((|self|))
1107
+
1108
+ --- /(point)
1109
+ scale and rotate ((|self|))
1110
+
1111
+ --- ===(other)
1112
+ return true if the 2 boxes ((|self|)) and ((|other|)) are identical
1113
+
1114
+ --- <=>(other)
1115
+ comparison operator for 2 Box based on the area of the 2 objects, i.e.
1116
+ self.area <=> box.area
1117
+
1118
+ --- above?(other)
1119
+ return true if ((|self|)) is above ((|other|))
1120
+
1121
+ --- area
1122
+ return the area of the Box
1123
+
1124
+ --- below?(other)
1125
+ return true if ((|self|)) is below ((|other|))
1126
+
1127
+ --- center
1128
+ return the center point of the Box
1129
+
1130
+ --- closest(other)
1131
+ closest point to ((|other|))
1132
+
1133
+ ((|other|)) can be a Point, or Segment
1134
+
1135
+ --- contain?(other)
1136
+ return true if ((|self|)) contain ((|other|))
1137
+
1138
+ --- contained?(other)
1139
+ return true if ((|self|)) is contained by ((|other|))
1140
+
1141
+ --- diagonal
1142
+ return a line Segment which happens to be the
1143
+ positive-slope diagonal of Box
1144
+
1145
+ --- height
1146
+ return the height of the Box (vertical magnitude)
1147
+
1148
+ --- in?(other)
1149
+ return true if ((|self|)) is contained by ((|other|))
1150
+
1151
+ --- initialize(*args)
1152
+ create a new Box object
1153
+
1154
+ ((|args|)) can be 2 Point objects (low, high) or 4 Float objects
1155
+ (low.x, low.y, high.x, high.y)
1156
+
1157
+ --- intersection(other)
1158
+ returns the overlapping portion of two boxes,
1159
+ or ((|nil|)) if they do not intersect.
1160
+
1161
+ --- intersect?(segment)
1162
+ returns true if the Segment ((|segment|))
1163
+ intersect with the Box
1164
+
1165
+ Segment completely inside box counts as intersection.
1166
+ If you want only segments crossing box boundaries,
1167
+ try converting Box to Path first.
1168
+
1169
+
1170
+ --- left?(other)
1171
+ return true if ((|self|)) is strictly left of ((|other|))
1172
+
1173
+ --- overlap?(other)
1174
+ return true if ((|self|)) overlap ((|other|))
1175
+
1176
+ --- overleft?(other)
1177
+ return true if the right edge of ((|self|)) is to the left of
1178
+ the right edge of ((|other|))
1179
+
1180
+ --- overright?(other)
1181
+ return true if the left edge of ((|self|)) is to the right of
1182
+ the left edge of ((|other|))
1183
+
1184
+ --- right?(other)
1185
+ return true if ((|self|)) is strictly right of ((|other|))
1186
+
1187
+ --- same?(other)
1188
+ return true if the 2 boxes ((|self|)) and ((|other|)) are identical
1189
+
1190
+ --- to_circle
1191
+ convert a Box to a Circle
1192
+
1193
+ --- to_point
1194
+ return the center Point of the Box
1195
+
1196
+ --- to_polygon
1197
+ convert a Box to a Polygon
1198
+
1199
+ --- to_segment
1200
+ return a line Segment which happens to be the
1201
+ positive-slope diagonal of Box
1202
+
1203
+ --- width
1204
+ return the width of the Box (horizontal magnitude)
1205
+
1206
+ === class Path
1207
+
1208
+ The Path implement the PostgreSQL type ((|path|))
1209
+
1210
+ The module Comparable is included
1211
+
1212
+ --- from_string(string)
1213
+ Convert a ((|String|)) (PostgreSQL representation)
1214
+ to a ((|Path|))
1215
+
1216
+ --- <<(path)
1217
+ concatenate the two paths (only if they are both open)
1218
+
1219
+ --- +(point)
1220
+ translate (right, up) ((|self|))
1221
+
1222
+ --- -(point)
1223
+ translate (left, down) ((|self|))
1224
+
1225
+ --- *(point)
1226
+ scale and rotate ((|self|))
1227
+
1228
+ --- /(point)
1229
+ scale and rotate ((|self|))
1230
+
1231
+ --- <=>(other)
1232
+ comparison function based on the path cardinality, i.e.
1233
+ self.npoints <=> other.npoints
1234
+
1235
+ --- close
1236
+ make a closed path
1237
+
1238
+ --- closed?
1239
+ return true if ((|self|)) is a closed path
1240
+
1241
+ --- concat(path)
1242
+ concatenate the two paths (only if they are both open)
1243
+
1244
+ --- initialize(points, closed = false)
1245
+ create a new Path object from the Array of Point ((|points|))
1246
+
1247
+ --- length
1248
+ return the length of ((|self|))
1249
+
1250
+ --- npoints
1251
+ return the path cardinality
1252
+
1253
+ --- open
1254
+ make an open path
1255
+
1256
+ --- to_polygon
1257
+ convert ((|self|)) to a Polygon object
1258
+
1259
+ === class Point
1260
+
1261
+ The Point implement the PostgreSQL type ((|point|))
1262
+
1263
+ The module Comparable is included
1264
+
1265
+ --- from_string(string)
1266
+ Convert a ((|String|)) (PostgreSQL representation)
1267
+ to a ((|Point|))
1268
+
1269
+ --- +(point)
1270
+ translate (right, up) ((|self|))
1271
+
1272
+ --- -(point)
1273
+ translate (left, down) ((|self|))
1274
+
1275
+ --- *(point)
1276
+ scale and rotate ((|self|))
1277
+
1278
+ --- /(point)
1279
+ scale and rotate ((|self|))
1280
+
1281
+ --- [](indice)
1282
+ return the coordinate
1283
+
1284
+ ((|indice|)) can have the value 0 or 1
1285
+
1286
+ --- []=(indice, value)
1287
+ set the coordinate
1288
+
1289
+ ((|indice|)) can have the value 0 or 1
1290
+
1291
+ --- ==(other)
1292
+ return true if ((|self|)) and ((|other|)) are the same,
1293
+ i.e. self.x == other.x && self.y == other.y
1294
+
1295
+ --- above?(other)
1296
+ return true if ((|self|)) is above ((|other|)),
1297
+ i.e. self.y > other.y
1298
+
1299
+ --- below?(other)
1300
+ return true if ((|self|)) is below ((|other|)),
1301
+ i.e. self.y < other.y
1302
+
1303
+ --- contained?(other)
1304
+ return true if ((|self|)) is contained in ((|other|))
1305
+
1306
+ ((|other|)) can be Point, Polygon or a Circle object
1307
+
1308
+ --- horizontal?(other)
1309
+ return true if ((|self|)) and ((|other|)) are horizontal,
1310
+ i.e. self.y == other.y
1311
+
1312
+ --- in?(other)
1313
+ return true if ((|self|)) is contained in ((|other|))
1314
+
1315
+ ((|other|)) can be Point, Polygon or a Circle object
1316
+
1317
+ --- initialize(x, y)
1318
+ create a Point with the 2 Float object (x, y)
1319
+
1320
+ --- left?(other)
1321
+ return true if ((|self|)) is at the left of ((|other|)),
1322
+ i.e. self.x < other.x
1323
+
1324
+ --- on?(other)
1325
+ return true if ((|self|)) is on ((|other|))
1326
+
1327
+ ((|other|)) can be Point, Segment, Box or Path object
1328
+
1329
+ --- right?(other)
1330
+ return true if ((|self|)) is at the right of ((|other|)),
1331
+ i.e. self.x > other.x
1332
+
1333
+ --- vertical?(other)
1334
+ return true if ((|self|)) and ((|other|)) are vertical,
1335
+ i.e. self.x == other.x
1336
+
1337
+ --- x
1338
+ return ((|x|)) for ((|self|))
1339
+
1340
+ --- x=(value)
1341
+ set the ((|x|)) value for ((|self|))
1342
+
1343
+ --- y
1344
+ return ((|y|)) for ((|self|))
1345
+
1346
+ --- y=(value)
1347
+ set the ((|y|)) value for ((|self|))
1348
+
1349
+ === class Segment
1350
+
1351
+ The Segment implement the PostgreSQL type ((|lseg|))
1352
+
1353
+ The module Comparable is included
1354
+
1355
+ --- from_string(string)
1356
+ Convert a ((|String|)) (PostgreSQL representation)
1357
+ to a ((|Segment|))
1358
+
1359
+ --- <=>(other)
1360
+ comparison function for the 2 segments, returns
1361
+
1362
+ 0 if self[0] == other[0] && self[1] == other[1]
1363
+
1364
+ 1 if distance(self[0], self[1]) > distance(other[0], other[1])
1365
+
1366
+ -1 if distance(self[0], self[1]) < distance(other[0], other[1])
1367
+
1368
+ --- center
1369
+ return the center of the segment
1370
+
1371
+ --- closest(other)
1372
+ closest point to other
1373
+
1374
+ ((|other|)) can be a Point, Segment or Box
1375
+
1376
+ With a point, take the closest endpoint
1377
+ if the point is left, right, above, or below the segment, otherwise
1378
+ find the intersection point of the segment and its perpendicular through
1379
+ the point.
1380
+
1381
+ --- horizontal?
1382
+ returns true if ((|self|)) is a horizontal Segment
1383
+
1384
+ --- initialize(point0, point1)
1385
+ create a Segment from the 2 Point p0, p1
1386
+
1387
+ --- intersect?(other)
1388
+ returns true if ((|self|)) and ((|other|)) intersect
1389
+
1390
+ --- intersection(other)
1391
+ returns the Point where the 2 Segment ((|self|)) and ((|other|))
1392
+ intersect or nil
1393
+
1394
+ --- length
1395
+ return the length of ((|self|)), i.e. the distnace between the 2 points
1396
+
1397
+ --- on?(other)
1398
+ return true if ((|self|)) is on ((|other|))
1399
+
1400
+ ((|other|)) can be a Segment, or a Box object
1401
+
1402
+ --- parallel?(other)
1403
+ returns true if the 2 Segment ((|self|)) and ((|other|))
1404
+ are parallel
1405
+
1406
+ --- perpendicular?(other)
1407
+ returns true if ((|self|)) is perpendicular to ((|other|))
1408
+
1409
+ --- to_point
1410
+ conversion function to a Point, return the center of the segment
1411
+
1412
+ --- vertical?
1413
+ returns true if ((|self|)) is a vertical Segment
1414
+ === class Polygon
1415
+
1416
+ The Polygon implement the PostgreSQL type ((|polygon|))
1417
+
1418
+ --- from_string(string)
1419
+ Convert a ((|String|)) (PostgreSQL representation)
1420
+ to a ((|Polygon|))
1421
+
1422
+ --- ==(other)
1423
+ return true if ((|self|)) is the same as ((|other|)), i.e. all
1424
+ the points are the same
1425
+
1426
+ --- center
1427
+ return the center of ((|self|)), i.e. create a circle and return its
1428
+ center
1429
+
1430
+ --- contain?(other)
1431
+ return true if ((|self|)) contains ((|other|))
1432
+
1433
+ ((|other|)) can be a Point or a Polygon
1434
+
1435
+ --- contained?(other)
1436
+ return true if ((|self|)) is contained in ((|other|)) by determining
1437
+ if ((|self|)) bounding box is contained by ((|other|))'s bounding box.
1438
+
1439
+ --- in?(other)
1440
+ return true if ((|self|)) is contained in ((|other|)) by determining
1441
+ if ((|self|)) bounding box is contained by ((|other|))'s bounding box.
1442
+
1443
+ --- initialize(points, closed = false)
1444
+ create a new Polygon object from the Array of Point ((|points|))
1445
+
1446
+ --- left?(other)
1447
+ return true if ((|self|)) is strictly left of ((|other|)), i.e.
1448
+ the right most point of ((|self|)) is left of the left
1449
+ most point of ((|other|))
1450
+
1451
+ --- overleft?(other)
1452
+ return true if ((|self|)) is overlapping or left of ((|other|)),
1453
+ i.e. the left most point of ((|self|)) is left of the right
1454
+ most point of ((|other|))
1455
+
1456
+ --- overright?(other)
1457
+ return true if ((|self|)) is overlapping or right of ((|other|)),
1458
+ i.e. the right most point of ((|self|)) is right of the left
1459
+ most point of ((|other|))
1460
+
1461
+ --- overlap?(other)
1462
+ return true if ((|self|)) and ((|other|)) overlap by determining if
1463
+ their bounding boxes overlap.
1464
+
1465
+ --- npoints
1466
+ return the number of points in ((|self|))
1467
+
1468
+ --- right?(other)
1469
+ return true if ((|self|)) is strictly right of ((|other|)), i.e.
1470
+ the left most point of ((|self|)) is right of the left
1471
+ most point of ((|other|))
1472
+
1473
+ --- same?(other)
1474
+ return true if ((|self|)) is the same as ((|other|)), i.e. all
1475
+ the points are the same
1476
+
1477
+ --- to_box
1478
+ convert ((|self|)) to a Box
1479
+
1480
+ --- to_circle
1481
+ convert ((|self|)) to a Circle
1482
+
1483
+ --- to_path
1484
+ convert ((|self|)) to a Path
1485
+
1486
+ --- to_point
1487
+ convert ((|self|)) to a Point by returning its center
1488
+
1489
+ === class Circle
1490
+
1491
+ The Circle implement the PostgreSQL type ((|circle|))
1492
+
1493
+ The module Comparable is included
1494
+
1495
+ --- from_string(string)
1496
+ Convert a ((|String|)) (PostgreSQL representation)
1497
+ to a ((|Circle|))
1498
+
1499
+ --- +(point)
1500
+ translate (right, up) ((|self|))
1501
+
1502
+ --- -(point)
1503
+ translate (left, down) ((|self|))
1504
+
1505
+ --- *(point)
1506
+ scale and rotate ((|self|))
1507
+
1508
+ --- /(point)
1509
+ scale and rotate ((|self|))
1510
+
1511
+ --- <=>(other)
1512
+ comparison function based on area,
1513
+ i.e. self.area <=> other.area
1514
+
1515
+ --- area
1516
+ return the area
1517
+
1518
+ --- above?(other)
1519
+ return true if ((|self|)) is entirely above ((|other|))
1520
+
1521
+ --- below?(other)
1522
+ return true if ((|self|)) is entirely below ((|other|))
1523
+
1524
+ --- contain?(other)
1525
+ return true if ((|self|)) contain ((|other|))
1526
+
1527
+ --- contained?(other)
1528
+ return true if ((|self|)) is contained in ((|other|))
1529
+
1530
+ --- diameter
1531
+ return the diameter
1532
+
1533
+ --- initialize(center, radius)
1534
+ create a Circle object with ((|center|)) and ((|radius|))
1535
+
1536
+ ((|center|)) can be a Point or an Array [x, y]
1537
+
1538
+ --- overlap?(other)
1539
+ return true if ((|self|)) overlap ((|other|))
1540
+
1541
+ --- overleft?(other)
1542
+ return true if the right edge of ((|self|)) is to the left of
1543
+ the right edge of ((|other|))
1544
+
1545
+ --- left?(other)
1546
+ return true if ((|self|)) is strictly left of ((|other|))
1547
+
1548
+ --- overright?(other)
1549
+ return true if the left edge of ((|self|)) is to the right of
1550
+ the left edge of ((|other|))
1551
+
1552
+ --- radius
1553
+ return the radius
1554
+
1555
+ --- right?(other)
1556
+ return true if ((|self|)) is strictly right of ((|other|))
1557
+
1558
+ --- same?(other)
1559
+ return true if ((|self|)) is the same than ((|other|)), i.e.
1560
+ self.center == other.center && self.radius == other.radius
1561
+
1562
+ --- to_box
1563
+ convert ((|self|)) to a Box
1564
+
1565
+ --- to_point
1566
+ convert ((|self|)) to a Point by returning its center
1567
+
1568
+ --- to_polygon(npts)
1569
+ convert ((|self|)) to a Polygon with ((|npts|)) Points
1570
+
1571
+ =end