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.
- data/Changes +121 -0
- data/README.markdown +155 -0
- data/Rakefile +48 -0
- data/docs/plruby.rb +1931 -0
- data/ex_trans.sql +33 -0
- data/extconf.rb +267 -0
- data/plruby.html +1454 -0
- data/plruby.rd +1571 -0
- data/postgresql-plruby.gemspec +56 -0
- data/src/conversions.h +5 -0
- data/src/conversions/basic/conversions.h +25 -0
- data/src/conversions/basic/extconf.rb +8 -0
- data/src/conversions/basic/plruby_basic.c +357 -0
- data/src/conversions/bitstring/bitstring.sql +75 -0
- data/src/conversions/bitstring/conversions.h +15 -0
- data/src/conversions/bitstring/extconf.rb +8 -0
- data/src/conversions/bitstring/plruby_bitstring.c +579 -0
- data/src/conversions/convcommon.h +129 -0
- data/src/conversions/datetime/conversions.h +13 -0
- data/src/conversions/datetime/extconf.rb +8 -0
- data/src/conversions/datetime/plruby_datetime.c +269 -0
- data/src/conversions/geometry/conversions.h +37 -0
- data/src/conversions/geometry/extconf.rb +8 -0
- data/src/conversions/geometry/geometry.sql +196 -0
- data/src/conversions/geometry/plruby_geometry.c +2494 -0
- data/src/conversions/network/conversions.h +21 -0
- data/src/conversions/network/extconf.rb +8 -0
- data/src/conversions/network/network.sql +63 -0
- data/src/conversions/network/plruby_network.c +537 -0
- data/src/package.h +20 -0
- data/src/plpl.c +1708 -0
- data/src/plplan.c +893 -0
- data/src/plruby.c +1676 -0
- data/src/plruby.h +324 -0
- data/src/pltrans.c +388 -0
- data/test/conv_bitstring/b.rb +45 -0
- data/test/conv_bitstring/runtest +26 -0
- data/test/conv_bitstring/test.expected.73 +148 -0
- data/test/conv_bitstring/test.expected.74 +148 -0
- data/test/conv_bitstring/test.expected.80 +148 -0
- data/test/conv_bitstring/test.expected.81 +148 -0
- data/test/conv_bitstring/test.expected.82 +148 -0
- data/test/conv_bitstring/test.expected.83 +148 -0
- data/test/conv_bitstring/test.expected.84 +148 -0
- data/test/conv_bitstring/test.out +148 -0
- data/test/conv_bitstring/test_mklang.sql +8 -0
- data/test/conv_bitstring/test_queries.sql +63 -0
- data/test/conv_bitstring/test_queries.sql.in +63 -0
- data/test/conv_geometry/b.rb +45 -0
- data/test/conv_geometry/runtest +26 -0
- data/test/conv_geometry/test.expected.73 +265 -0
- data/test/conv_geometry/test.expected.74 +265 -0
- data/test/conv_geometry/test.expected.80 +265 -0
- data/test/conv_geometry/test.expected.81 +265 -0
- data/test/conv_geometry/test.expected.82 +265 -0
- data/test/conv_geometry/test.expected.83 +265 -0
- data/test/conv_geometry/test.expected.84 +265 -0
- data/test/conv_geometry/test.out +265 -0
- data/test/conv_geometry/test_mklang.sql +8 -0
- data/test/conv_geometry/test_queries.sql +194 -0
- data/test/conv_geometry/test_queries.sql.in +194 -0
- data/test/conv_network/b.rb +45 -0
- data/test/conv_network/runtest +26 -0
- data/test/conv_network/test.expected.73 +213 -0
- data/test/conv_network/test.expected.74 +237 -0
- data/test/conv_network/test.expected.80 +237 -0
- data/test/conv_network/test.expected.81 +237 -0
- data/test/conv_network/test.expected.82 +237 -0
- data/test/conv_network/test.expected.83 +237 -0
- data/test/conv_network/test.expected.84 +237 -0
- data/test/conv_network/test.out +237 -0
- data/test/conv_network/test_mklang.sql +8 -0
- data/test/conv_network/test_queries.sql +60 -0
- data/test/conv_network/test_queries.sql.in +60 -0
- data/test/plp/b.rb +34 -0
- data/test/plp/runtest +29 -0
- data/test/plp/test.expected.73 +472 -0
- data/test/plp/test.expected.74 +472 -0
- data/test/plp/test.expected.75 +472 -0
- data/test/plp/test.expected.80 +472 -0
- data/test/plp/test.expected.81 +472 -0
- data/test/plp/test.expected.82 +472 -0
- data/test/plp/test.expected.83 +472 -0
- data/test/plp/test.expected.84 +472 -0
- data/test/plp/test.out +472 -0
- data/test/plp/test_mklang.sql +8 -0
- data/test/plp/test_queries.sql +273 -0
- data/test/plp/test_setup.sql +931 -0
- data/test/plp/test_setup.sql.in +931 -0
- data/test/plt/b.rb +34 -0
- data/test/plt/runtest +29 -0
- data/test/plt/test.expected.73 +178 -0
- data/test/plt/test.expected.74 +178 -0
- data/test/plt/test.expected.75 +178 -0
- data/test/plt/test.expected.80 +178 -0
- data/test/plt/test.expected.81 +178 -0
- data/test/plt/test.expected.82 +178 -0
- data/test/plt/test.expected.83 +164 -0
- data/test/plt/test.expected.84 +168 -0
- data/test/plt/test.out +168 -0
- data/test/plt/test_mklang.sql +8 -0
- data/test/plt/test_queries.sql +72 -0
- data/test/plt/test_setup.sql +252 -0
- data/test/plt/test_setup.sql.in +252 -0
- data/test/range/b.rb +45 -0
- data/test/range/runtest +26 -0
- data/test/range/test.expected.73 +396 -0
- data/test/range/test.expected.73.in +396 -0
- data/test/range/test.expected.74 +396 -0
- data/test/range/test.expected.74.in +396 -0
- data/test/range/test.expected.75 +396 -0
- data/test/range/test.expected.75.in +396 -0
- data/test/range/test.expected.80 +396 -0
- data/test/range/test.expected.81 +397 -0
- data/test/range/test.expected.82 +397 -0
- data/test/range/test.expected.83 +397 -0
- data/test/range/test.expected.84 +399 -0
- data/test/range/test.out +399 -0
- data/test/range/test_mklang.sql +8 -0
- data/test/range/test_queries.sql +249 -0
- data/test/range/test_queries.sql.in +249 -0
- metadata +207 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rbconfig'
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |spec|
|
|
5
|
+
spec.name = 'globegit-postgresql-plruby'
|
|
6
|
+
spec.version = '0.5.4'
|
|
7
|
+
spec.authors = ['Akinori MUSHA', 'Guy Decoux']
|
|
8
|
+
spec.license = 'Ruby'
|
|
9
|
+
spec.email = 'akinori@musha.org'
|
|
10
|
+
spec.homepage = 'https://github.com/knu/postgresql-plruby'
|
|
11
|
+
spec.summary = 'Enable Ruby for use as a procedural language within PostgreSQL'
|
|
12
|
+
spec.test_files = Dir['test/test*']
|
|
13
|
+
spec.extensions = ['extconf.rb']
|
|
14
|
+
spec.files = Dir['**/*'].reject{ |f| f.include?('git') || f.include?('tmp') }
|
|
15
|
+
|
|
16
|
+
spec.rubyforge_project = 'plruby'
|
|
17
|
+
|
|
18
|
+
spec.extra_rdoc_files = [
|
|
19
|
+
'README.markdown',
|
|
20
|
+
'Changes'
|
|
21
|
+
] + Dir['ext/*.c']
|
|
22
|
+
|
|
23
|
+
spec.description = <<-EOF
|
|
24
|
+
PL/Ruby is a loadable procedural language for the PostgreSQL database
|
|
25
|
+
system that enables the Ruby language to create functions and trigger
|
|
26
|
+
procedures.
|
|
27
|
+
EOF
|
|
28
|
+
|
|
29
|
+
plruby_bin = 'plruby.' + Config::CONFIG['DLEXT']
|
|
30
|
+
plruby_dir = File.join('postgresql-plruby-' + spec.version.to_s, 'src')
|
|
31
|
+
path_to_binary = File.join(Gem.dir, 'gems', plruby_dir, plruby_bin)
|
|
32
|
+
|
|
33
|
+
possible_paths = Gem.path.map{ |path|
|
|
34
|
+
File.join(path, 'gems', plruby_dir, plruby_bin)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
spec.post_install_message = <<-EOF
|
|
38
|
+
|
|
39
|
+
Now run the following commands from within a postgresql shell in order
|
|
40
|
+
to create the plruby language on in database server:
|
|
41
|
+
|
|
42
|
+
create function plruby_call_handler() returns language_handler
|
|
43
|
+
as '#{path_to_binary}'
|
|
44
|
+
language 'C';
|
|
45
|
+
|
|
46
|
+
create trusted language 'plruby'
|
|
47
|
+
handler plruby_call_handler
|
|
48
|
+
lancompiler 'PL/Ruby';
|
|
49
|
+
|
|
50
|
+
NOTE: Your actual path to #{plruby_bin} may be different. Possible
|
|
51
|
+
paths to the plruby binary are:
|
|
52
|
+
|
|
53
|
+
#{possible_paths.join("\n ")}
|
|
54
|
+
|
|
55
|
+
EOF
|
|
56
|
+
end
|
data/src/conversions.h
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
extern void plruby_require(char *);
|
|
3
|
+
|
|
4
|
+
plruby_require("plruby/plruby_basic");
|
|
5
|
+
rb_hash_aset(plruby_classes, INT2NUM(OIDOID), rb_cFixnum);
|
|
6
|
+
rb_hash_aset(plruby_classes, INT2NUM(INT2OID), rb_cFixnum);
|
|
7
|
+
rb_hash_aset(plruby_classes, INT2NUM(INT4OID), rb_cFixnum);
|
|
8
|
+
rb_hash_aset(plruby_classes, INT2NUM(INT8OID), rb_cFixnum);
|
|
9
|
+
|
|
10
|
+
rb_hash_aset(plruby_classes, INT2NUM(FLOAT4OID), rb_cFloat);
|
|
11
|
+
rb_hash_aset(plruby_classes, INT2NUM(FLOAT8OID), rb_cFloat);
|
|
12
|
+
rb_hash_aset(plruby_classes, INT2NUM(CASHOID), rb_cFloat);
|
|
13
|
+
rb_hash_aset(plruby_classes, INT2NUM(NUMERICOID), rb_cFloat);
|
|
14
|
+
|
|
15
|
+
rb_hash_aset(plruby_classes, INT2NUM(TIMESTAMPOID), rb_cTime);
|
|
16
|
+
rb_hash_aset(plruby_classes, INT2NUM(TIMESTAMPTZOID), rb_cTime);
|
|
17
|
+
rb_hash_aset(plruby_classes, INT2NUM(ABSTIMEOID), rb_cTime);
|
|
18
|
+
rb_hash_aset(plruby_classes, INT2NUM(DATEOID), rb_cTime);
|
|
19
|
+
rb_hash_aset(plruby_classes, INT2NUM(RELTIMEOID), rb_cTime);
|
|
20
|
+
rb_hash_aset(plruby_classes, INT2NUM(INTERVALOID), rb_cTime);
|
|
21
|
+
rb_hash_aset(plruby_classes, INT2NUM(TIMETZOID), rb_cTime);
|
|
22
|
+
rb_hash_aset(plruby_classes, INT2NUM(TIMEOID), rb_cTime);
|
|
23
|
+
|
|
24
|
+
rb_hash_aset(plruby_classes, ULONG2NUM(BYTEAOID), rb_cString);
|
|
25
|
+
}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
#include "convcommon.h"
|
|
2
|
+
|
|
3
|
+
#include <utils/cash.h>
|
|
4
|
+
#include <utils/date.h>
|
|
5
|
+
#include <utils/nabstime.h>
|
|
6
|
+
#include <utils/pg_locale.h>
|
|
7
|
+
#include <utils/timestamp.h>
|
|
8
|
+
#include <math.h>
|
|
9
|
+
|
|
10
|
+
static double cash_divisor;
|
|
11
|
+
static Timestamp epoch;
|
|
12
|
+
static ID id_at, id_to_f, id_to_i, id_usec;
|
|
13
|
+
|
|
14
|
+
static VALUE
|
|
15
|
+
pl_fixnum_s_datum(VALUE obj, VALUE a)
|
|
16
|
+
{
|
|
17
|
+
Oid typoid;
|
|
18
|
+
Datum value;
|
|
19
|
+
|
|
20
|
+
value = plruby_datum_get(a, &typoid);
|
|
21
|
+
switch (typoid) {
|
|
22
|
+
case OIDOID:
|
|
23
|
+
return UINT2NUM(DatumGetObjectId(value));
|
|
24
|
+
|
|
25
|
+
case INT2OID:
|
|
26
|
+
return INT2NUM(DatumGetInt16(value));
|
|
27
|
+
|
|
28
|
+
case INT4OID:
|
|
29
|
+
return INT2NUM(DatumGetInt32(value));
|
|
30
|
+
|
|
31
|
+
case INT8OID:
|
|
32
|
+
return LL2NUM(DatumGetInt64(value));
|
|
33
|
+
|
|
34
|
+
default:
|
|
35
|
+
rb_raise(rb_eArgError, "unknown OID type %d", typoid);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static VALUE
|
|
40
|
+
pl_fixnum_to_datum(VALUE obj, VALUE a)
|
|
41
|
+
{
|
|
42
|
+
Datum d;
|
|
43
|
+
|
|
44
|
+
switch (plruby_datum_oid(a, NULL)) {
|
|
45
|
+
case OIDOID:
|
|
46
|
+
d = ObjectIdGetDatum(NUM2UINT(obj));
|
|
47
|
+
break;
|
|
48
|
+
|
|
49
|
+
case INT2OID:
|
|
50
|
+
d = Int16GetDatum(NUM2INT(obj));
|
|
51
|
+
break;
|
|
52
|
+
|
|
53
|
+
case INT4OID:
|
|
54
|
+
d = Int32GetDatum(NUM2INT(obj));
|
|
55
|
+
break;
|
|
56
|
+
|
|
57
|
+
case INT8OID:
|
|
58
|
+
d = Int64GetDatum(NUM2LL(obj));
|
|
59
|
+
break;
|
|
60
|
+
|
|
61
|
+
default:
|
|
62
|
+
return Qnil;
|
|
63
|
+
}
|
|
64
|
+
return plruby_datum_set(a, d);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static VALUE
|
|
68
|
+
pl_float_s_datum(VALUE obj, VALUE a)
|
|
69
|
+
{
|
|
70
|
+
Oid typoid;
|
|
71
|
+
Datum value;
|
|
72
|
+
double result;
|
|
73
|
+
|
|
74
|
+
value = plruby_datum_get(a, &typoid);
|
|
75
|
+
switch (typoid) {
|
|
76
|
+
case FLOAT4OID:
|
|
77
|
+
result = DatumGetFloat4(value);
|
|
78
|
+
break;
|
|
79
|
+
|
|
80
|
+
case FLOAT8OID:
|
|
81
|
+
result = DatumGetFloat8(value);
|
|
82
|
+
break;
|
|
83
|
+
|
|
84
|
+
case CASHOID:
|
|
85
|
+
result = (double) *(Cash *) DatumGetPointer(value) / cash_divisor;
|
|
86
|
+
break;
|
|
87
|
+
|
|
88
|
+
case NUMERICOID:
|
|
89
|
+
result = DatumGetFloat8(plruby_dfc1(numeric_float8, value));
|
|
90
|
+
break;
|
|
91
|
+
|
|
92
|
+
default:
|
|
93
|
+
rb_raise(rb_eArgError, "unknown OID type %d", typoid);
|
|
94
|
+
}
|
|
95
|
+
return rb_float_new(result);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
extern double round();
|
|
99
|
+
|
|
100
|
+
static VALUE
|
|
101
|
+
pl_float_to_datum(VALUE obj, VALUE a)
|
|
102
|
+
{
|
|
103
|
+
double value;
|
|
104
|
+
Datum d;
|
|
105
|
+
|
|
106
|
+
value = RFLOAT_VALUE(obj);
|
|
107
|
+
switch (plruby_datum_oid(a, NULL)) {
|
|
108
|
+
case FLOAT4OID:
|
|
109
|
+
d = Float4GetDatum((float4)value);
|
|
110
|
+
break;
|
|
111
|
+
|
|
112
|
+
case FLOAT8OID:
|
|
113
|
+
d = Float8GetDatum((float8)value);
|
|
114
|
+
break;
|
|
115
|
+
|
|
116
|
+
case CASHOID:
|
|
117
|
+
{
|
|
118
|
+
Cash *cash = (Cash *) palloc(sizeof(Cash));
|
|
119
|
+
*cash = (Cash) round(value * cash_divisor);
|
|
120
|
+
d = PointerGetDatum(cash);
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
case NUMERICOID:
|
|
125
|
+
d = plruby_dfc1(float8_numeric, Float8GetDatum((float8)value));
|
|
126
|
+
break;
|
|
127
|
+
|
|
128
|
+
default:
|
|
129
|
+
return Qnil;
|
|
130
|
+
}
|
|
131
|
+
return plruby_datum_set(a, d);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static VALUE
|
|
135
|
+
pl_str_s_datum(VALUE klass, VALUE a)
|
|
136
|
+
{
|
|
137
|
+
bytea *data;
|
|
138
|
+
Oid typoid;
|
|
139
|
+
Datum value;
|
|
140
|
+
|
|
141
|
+
value = plruby_datum_get(a, &typoid);
|
|
142
|
+
if (typoid != BYTEAOID) {
|
|
143
|
+
return Qnil;
|
|
144
|
+
}
|
|
145
|
+
data = DatumGetByteaP(value);
|
|
146
|
+
return rb_str_new(VARDATA(data), VARSIZE(data) - VARHDRSZ);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
static VALUE
|
|
150
|
+
pl_str_to_datum(VALUE obj, VALUE a)
|
|
151
|
+
{
|
|
152
|
+
bytea *data;
|
|
153
|
+
size_t len;
|
|
154
|
+
|
|
155
|
+
/* Converts BYTEA only. */
|
|
156
|
+
if (plruby_datum_oid(a, NULL) != BYTEAOID)
|
|
157
|
+
return Qnil;
|
|
158
|
+
|
|
159
|
+
len = RSTRING_LEN(obj);
|
|
160
|
+
data = palloc(VARHDRSZ + len);
|
|
161
|
+
memcpy(VARDATA(data), RSTRING_PTR(obj), len);
|
|
162
|
+
#ifdef SET_VARSIZE
|
|
163
|
+
SET_VARSIZE(data, VARHDRSZ + len);
|
|
164
|
+
#else
|
|
165
|
+
VARATT_SIZEP(data) = VARHDRSZ + len;
|
|
166
|
+
#endif
|
|
167
|
+
return plruby_datum_set(a, PointerGetDatum(data));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
static VALUE
|
|
171
|
+
pl_time_s_datum(VALUE klass, VALUE a)
|
|
172
|
+
{
|
|
173
|
+
Timestamp ts;
|
|
174
|
+
Oid typoid;
|
|
175
|
+
Datum value;
|
|
176
|
+
|
|
177
|
+
/*
|
|
178
|
+
* INTERVAL and RELTIME are converted to Float (number of seconds).
|
|
179
|
+
* For INTERVALs containing nonzero month/year component, duration of one
|
|
180
|
+
* month is assumed to be 30*24*60*60 seconds. A special type has to be
|
|
181
|
+
* created for this, because of the months/year components and also because
|
|
182
|
+
* long or short enough numbers do not convert back right (exponential
|
|
183
|
+
* notation of INTERVALs is not accepted by Postgres).
|
|
184
|
+
*
|
|
185
|
+
* TIMESTAMP, TIMESTAMP WITH TIME ZONE, ABSTIME, DATE are converted to klass
|
|
186
|
+
* (Time), naturally.
|
|
187
|
+
*
|
|
188
|
+
* TIME and TIME WITH TIME ZONE are also converted to klass (Time), as in
|
|
189
|
+
* the (totally broken anyway) 0.4.3 implementation. The result is that
|
|
190
|
+
* specific time since Unix epoch. That makes little sense (the reverse
|
|
191
|
+
* conversion of the result breaks anyway), but some at least. A special
|
|
192
|
+
* type has to be created for this.
|
|
193
|
+
*/
|
|
194
|
+
value = plruby_datum_get(a, &typoid);
|
|
195
|
+
switch (typoid) {
|
|
196
|
+
/* Time interval types. */
|
|
197
|
+
|
|
198
|
+
case RELTIMEOID:
|
|
199
|
+
value = plruby_dfc1(reltime_interval, value);
|
|
200
|
+
/* ... */
|
|
201
|
+
case INTERVALOID:
|
|
202
|
+
{
|
|
203
|
+
Interval *iv = DatumGetIntervalP(value);
|
|
204
|
+
|
|
205
|
+
return rb_float_new((double) iv->month * 30*24*60*60 +
|
|
206
|
+
iv->time
|
|
207
|
+
#ifdef HAVE_INT64_TIMESTAMP
|
|
208
|
+
/ 1E6
|
|
209
|
+
#endif
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/*
|
|
214
|
+
* Time of day types.
|
|
215
|
+
*
|
|
216
|
+
* No separate conversion code is written, abusing the coincidence of C
|
|
217
|
+
* types used for TimeADT and Timestamp (int64 or double, depending on
|
|
218
|
+
* HAVE_INT64_TIMESTAMP). The proper implementation would use a special
|
|
219
|
+
* type anyway, see above.
|
|
220
|
+
*/
|
|
221
|
+
|
|
222
|
+
case TIMETZOID:
|
|
223
|
+
{
|
|
224
|
+
TimeTzADT *timetz = DatumGetTimeTzADTP(value);
|
|
225
|
+
|
|
226
|
+
/* Shift according to the timezone. */
|
|
227
|
+
ts = timetz->time + (Timestamp) timetz->zone
|
|
228
|
+
#ifdef HAVE_INT64_TIMESTAMP
|
|
229
|
+
* 1000000
|
|
230
|
+
#endif
|
|
231
|
+
;
|
|
232
|
+
}
|
|
233
|
+
goto convert;
|
|
234
|
+
|
|
235
|
+
case TIMEOID:
|
|
236
|
+
ts = (Timestamp) DatumGetTimeADT(value);
|
|
237
|
+
goto convert;
|
|
238
|
+
|
|
239
|
+
/* The rest of types end up as a Timestamp in `value'. */
|
|
240
|
+
|
|
241
|
+
case ABSTIMEOID:
|
|
242
|
+
value = plruby_dfc1(abstime_timestamptz, value);
|
|
243
|
+
break;
|
|
244
|
+
|
|
245
|
+
case DATEOID:
|
|
246
|
+
value = plruby_dfc1(date_timestamptz, value);
|
|
247
|
+
break;
|
|
248
|
+
|
|
249
|
+
case TIMESTAMPOID:
|
|
250
|
+
case TIMESTAMPTZOID:
|
|
251
|
+
break;
|
|
252
|
+
|
|
253
|
+
default:
|
|
254
|
+
rb_raise(rb_eTypeError, "%s: incompatible type OID %u",
|
|
255
|
+
rb_class2name(klass), typoid);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
ts = DatumGetTimestamp(value) - epoch;
|
|
259
|
+
|
|
260
|
+
convert:
|
|
261
|
+
return rb_funcall(klass, id_at,
|
|
262
|
+
#ifndef HAVE_INT64_TIMESTAMP
|
|
263
|
+
1, rb_float_new(ts)
|
|
264
|
+
#else
|
|
265
|
+
2, LONG2NUM(ts / 1000000), ULONG2NUM(ts % 1000000)
|
|
266
|
+
#endif
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
static VALUE
|
|
271
|
+
pl_time_to_datum(VALUE obj, VALUE a)
|
|
272
|
+
{
|
|
273
|
+
PGFunction conv;
|
|
274
|
+
Datum d;
|
|
275
|
+
int typoid;
|
|
276
|
+
|
|
277
|
+
typoid = plruby_datum_oid(a, NULL);
|
|
278
|
+
switch (typoid) {
|
|
279
|
+
case ABSTIMEOID:
|
|
280
|
+
case DATEOID:
|
|
281
|
+
case TIMEOID:
|
|
282
|
+
case TIMESTAMPOID:
|
|
283
|
+
case TIMESTAMPTZOID:
|
|
284
|
+
case TIMETZOID:
|
|
285
|
+
break;
|
|
286
|
+
|
|
287
|
+
default:
|
|
288
|
+
return Qnil;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/* Convert Time to TimestampTz first. */
|
|
292
|
+
#ifndef HAVE_INT64_TIMESTAMP
|
|
293
|
+
d = TimestampTzGetDatum(epoch + NUM2DBL(rb_funcall(obj, id_to_f, 0)));
|
|
294
|
+
#else
|
|
295
|
+
d = TimestampTzGetDatum(epoch + (TimestampTz)
|
|
296
|
+
NUM2LONG(rb_funcall(obj, id_to_i, 0)) * 1000000 +
|
|
297
|
+
NUM2ULONG(rb_funcall(obj, id_usec, 0)));
|
|
298
|
+
#endif
|
|
299
|
+
|
|
300
|
+
conv = NULL;
|
|
301
|
+
switch (typoid) {
|
|
302
|
+
case ABSTIMEOID:
|
|
303
|
+
conv = timestamptz_abstime;
|
|
304
|
+
break;
|
|
305
|
+
|
|
306
|
+
case DATEOID:
|
|
307
|
+
conv = timestamptz_date;
|
|
308
|
+
break;
|
|
309
|
+
|
|
310
|
+
case TIMEOID:
|
|
311
|
+
conv = timestamptz_time;
|
|
312
|
+
break;
|
|
313
|
+
|
|
314
|
+
case TIMESTAMPOID:
|
|
315
|
+
conv = timestamptz_timestamp;
|
|
316
|
+
break;
|
|
317
|
+
|
|
318
|
+
case TIMESTAMPTZOID:
|
|
319
|
+
break;
|
|
320
|
+
|
|
321
|
+
case TIMETZOID:
|
|
322
|
+
conv = timestamptz_timetz;
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (conv == NULL) {
|
|
327
|
+
return Qnil;
|
|
328
|
+
}
|
|
329
|
+
d = plruby_dfc1(conv, d);
|
|
330
|
+
return plruby_datum_set(a, d);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
void Init_plruby_basic()
|
|
334
|
+
{
|
|
335
|
+
int fpoint;
|
|
336
|
+
struct lconv *lconvert = PGLC_localeconv();
|
|
337
|
+
|
|
338
|
+
fpoint = lconvert->frac_digits;
|
|
339
|
+
if (fpoint < 0 || fpoint > 10) {
|
|
340
|
+
fpoint = 2;
|
|
341
|
+
}
|
|
342
|
+
cash_divisor = pow(10.0, fpoint);
|
|
343
|
+
epoch = SetEpochTimestamp();
|
|
344
|
+
id_at = rb_intern("at");
|
|
345
|
+
id_to_f = rb_intern("to_f");
|
|
346
|
+
id_to_i = rb_intern("to_i");
|
|
347
|
+
id_usec = rb_intern("usec");
|
|
348
|
+
|
|
349
|
+
rb_define_singleton_method(rb_cFixnum, "from_datum", pl_fixnum_s_datum, 1);
|
|
350
|
+
rb_define_method(rb_cFixnum, "to_datum", pl_fixnum_to_datum, 1);
|
|
351
|
+
rb_define_singleton_method(rb_cFloat, "from_datum", pl_float_s_datum, 1);
|
|
352
|
+
rb_define_method(rb_cFloat, "to_datum", pl_float_to_datum, 1);
|
|
353
|
+
rb_define_singleton_method(rb_cString, "from_datum", pl_str_s_datum, 1);
|
|
354
|
+
rb_define_method(rb_cString, "to_datum", pl_str_to_datum, 1);
|
|
355
|
+
rb_define_singleton_method(rb_cTime, "from_datum", pl_time_s_datum, 1);
|
|
356
|
+
rb_define_method(rb_cTime, "to_datum", pl_time_to_datum, 1);
|
|
357
|
+
}
|