globegit-postgresql-plruby 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/Changes +121 -0
  2. data/README.markdown +155 -0
  3. data/Rakefile +48 -0
  4. data/docs/plruby.rb +1931 -0
  5. data/ex_trans.sql +33 -0
  6. data/extconf.rb +267 -0
  7. data/plruby.html +1454 -0
  8. data/plruby.rd +1571 -0
  9. data/postgresql-plruby.gemspec +56 -0
  10. data/src/conversions.h +5 -0
  11. data/src/conversions/basic/conversions.h +25 -0
  12. data/src/conversions/basic/extconf.rb +8 -0
  13. data/src/conversions/basic/plruby_basic.c +357 -0
  14. data/src/conversions/bitstring/bitstring.sql +75 -0
  15. data/src/conversions/bitstring/conversions.h +15 -0
  16. data/src/conversions/bitstring/extconf.rb +8 -0
  17. data/src/conversions/bitstring/plruby_bitstring.c +579 -0
  18. data/src/conversions/convcommon.h +129 -0
  19. data/src/conversions/datetime/conversions.h +13 -0
  20. data/src/conversions/datetime/extconf.rb +8 -0
  21. data/src/conversions/datetime/plruby_datetime.c +269 -0
  22. data/src/conversions/geometry/conversions.h +37 -0
  23. data/src/conversions/geometry/extconf.rb +8 -0
  24. data/src/conversions/geometry/geometry.sql +196 -0
  25. data/src/conversions/geometry/plruby_geometry.c +2494 -0
  26. data/src/conversions/network/conversions.h +21 -0
  27. data/src/conversions/network/extconf.rb +8 -0
  28. data/src/conversions/network/network.sql +63 -0
  29. data/src/conversions/network/plruby_network.c +537 -0
  30. data/src/package.h +20 -0
  31. data/src/plpl.c +1708 -0
  32. data/src/plplan.c +893 -0
  33. data/src/plruby.c +1676 -0
  34. data/src/plruby.h +324 -0
  35. data/src/pltrans.c +388 -0
  36. data/test/conv_bitstring/b.rb +45 -0
  37. data/test/conv_bitstring/runtest +26 -0
  38. data/test/conv_bitstring/test.expected.73 +148 -0
  39. data/test/conv_bitstring/test.expected.74 +148 -0
  40. data/test/conv_bitstring/test.expected.80 +148 -0
  41. data/test/conv_bitstring/test.expected.81 +148 -0
  42. data/test/conv_bitstring/test.expected.82 +148 -0
  43. data/test/conv_bitstring/test.expected.83 +148 -0
  44. data/test/conv_bitstring/test.expected.84 +148 -0
  45. data/test/conv_bitstring/test.out +148 -0
  46. data/test/conv_bitstring/test_mklang.sql +8 -0
  47. data/test/conv_bitstring/test_queries.sql +63 -0
  48. data/test/conv_bitstring/test_queries.sql.in +63 -0
  49. data/test/conv_geometry/b.rb +45 -0
  50. data/test/conv_geometry/runtest +26 -0
  51. data/test/conv_geometry/test.expected.73 +265 -0
  52. data/test/conv_geometry/test.expected.74 +265 -0
  53. data/test/conv_geometry/test.expected.80 +265 -0
  54. data/test/conv_geometry/test.expected.81 +265 -0
  55. data/test/conv_geometry/test.expected.82 +265 -0
  56. data/test/conv_geometry/test.expected.83 +265 -0
  57. data/test/conv_geometry/test.expected.84 +265 -0
  58. data/test/conv_geometry/test.out +265 -0
  59. data/test/conv_geometry/test_mklang.sql +8 -0
  60. data/test/conv_geometry/test_queries.sql +194 -0
  61. data/test/conv_geometry/test_queries.sql.in +194 -0
  62. data/test/conv_network/b.rb +45 -0
  63. data/test/conv_network/runtest +26 -0
  64. data/test/conv_network/test.expected.73 +213 -0
  65. data/test/conv_network/test.expected.74 +237 -0
  66. data/test/conv_network/test.expected.80 +237 -0
  67. data/test/conv_network/test.expected.81 +237 -0
  68. data/test/conv_network/test.expected.82 +237 -0
  69. data/test/conv_network/test.expected.83 +237 -0
  70. data/test/conv_network/test.expected.84 +237 -0
  71. data/test/conv_network/test.out +237 -0
  72. data/test/conv_network/test_mklang.sql +8 -0
  73. data/test/conv_network/test_queries.sql +60 -0
  74. data/test/conv_network/test_queries.sql.in +60 -0
  75. data/test/plp/b.rb +34 -0
  76. data/test/plp/runtest +29 -0
  77. data/test/plp/test.expected.73 +472 -0
  78. data/test/plp/test.expected.74 +472 -0
  79. data/test/plp/test.expected.75 +472 -0
  80. data/test/plp/test.expected.80 +472 -0
  81. data/test/plp/test.expected.81 +472 -0
  82. data/test/plp/test.expected.82 +472 -0
  83. data/test/plp/test.expected.83 +472 -0
  84. data/test/plp/test.expected.84 +472 -0
  85. data/test/plp/test.out +472 -0
  86. data/test/plp/test_mklang.sql +8 -0
  87. data/test/plp/test_queries.sql +273 -0
  88. data/test/plp/test_setup.sql +931 -0
  89. data/test/plp/test_setup.sql.in +931 -0
  90. data/test/plt/b.rb +34 -0
  91. data/test/plt/runtest +29 -0
  92. data/test/plt/test.expected.73 +178 -0
  93. data/test/plt/test.expected.74 +178 -0
  94. data/test/plt/test.expected.75 +178 -0
  95. data/test/plt/test.expected.80 +178 -0
  96. data/test/plt/test.expected.81 +178 -0
  97. data/test/plt/test.expected.82 +178 -0
  98. data/test/plt/test.expected.83 +164 -0
  99. data/test/plt/test.expected.84 +168 -0
  100. data/test/plt/test.out +168 -0
  101. data/test/plt/test_mklang.sql +8 -0
  102. data/test/plt/test_queries.sql +72 -0
  103. data/test/plt/test_setup.sql +252 -0
  104. data/test/plt/test_setup.sql.in +252 -0
  105. data/test/range/b.rb +45 -0
  106. data/test/range/runtest +26 -0
  107. data/test/range/test.expected.73 +396 -0
  108. data/test/range/test.expected.73.in +396 -0
  109. data/test/range/test.expected.74 +396 -0
  110. data/test/range/test.expected.74.in +396 -0
  111. data/test/range/test.expected.75 +396 -0
  112. data/test/range/test.expected.75.in +396 -0
  113. data/test/range/test.expected.80 +396 -0
  114. data/test/range/test.expected.81 +397 -0
  115. data/test/range/test.expected.82 +397 -0
  116. data/test/range/test.expected.83 +397 -0
  117. data/test/range/test.expected.84 +399 -0
  118. data/test/range/test.out +399 -0
  119. data/test/range/test_mklang.sql +8 -0
  120. data/test/range/test_queries.sql +249 -0
  121. data/test/range/test_queries.sql.in +249 -0
  122. metadata +207 -0
@@ -0,0 +1,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