rdo-postgres 0.0.6 → 0.0.7
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/README.md +33 -11
- data/ext/rdo_postgres/arrays.c +48 -0
- data/ext/rdo_postgres/arrays.h +9 -0
- data/ext/rdo_postgres/casts.c +68 -25
- data/ext/rdo_postgres/casts.h +3 -0
- data/ext/rdo_postgres/driver.c +4 -8
- data/ext/rdo_postgres/extconf.rb +1 -2
- data/ext/rdo_postgres/rdo_postgres.c +2 -0
- data/ext/rdo_postgres/statements.c +25 -20
- data/ext/rdo_postgres/types.h +74 -0
- data/lib/rdo/postgres.rb +12 -0
- data/lib/rdo/postgres/array.rb +84 -0
- data/lib/rdo/postgres/array/boolean.rb +21 -0
- data/lib/rdo/postgres/array/bytea.rb +22 -0
- data/lib/rdo/postgres/array/date.rb +17 -0
- data/lib/rdo/postgres/array/float.rb +30 -0
- data/lib/rdo/postgres/array/integer.rb +21 -0
- data/lib/rdo/postgres/array/numeric.rb +23 -0
- data/lib/rdo/postgres/array/text.rb +15 -0
- data/lib/rdo/postgres/array/timestamp.rb +17 -0
- data/lib/rdo/postgres/array/timestamp_tz.rb +17 -0
- data/lib/rdo/postgres/version.rb +1 -1
- data/spec/postgres/array/boolean_spec.rb +74 -0
- data/spec/postgres/array/bytea_spec.rb +82 -0
- data/spec/postgres/array/date_spec.rb +74 -0
- data/spec/postgres/array/float_spec.rb +98 -0
- data/spec/postgres/array/integer_spec.rb +74 -0
- data/spec/postgres/array/numeric_spec.rb +83 -0
- data/spec/postgres/array/timestamp_spec.rb +80 -0
- data/spec/postgres/array/timestamp_tz_spec.rb +80 -0
- data/spec/postgres/array_spec.rb +122 -0
- data/spec/postgres/bind_params_spec.rb +191 -1
- data/spec/postgres/type_cast_spec.rb +223 -0
- metadata +33 -2
@@ -0,0 +1,74 @@
|
|
1
|
+
/*
|
2
|
+
* RDO Postgres Driver.
|
3
|
+
* Copyright © 2012 Chris Corbyn.
|
4
|
+
*
|
5
|
+
* See LICENSE file for details.
|
6
|
+
*/
|
7
|
+
|
8
|
+
/*
|
9
|
+
* Definitions for types taken from postgres/catalog/pg_type.h.
|
10
|
+
*
|
11
|
+
* Since not all the types we care about have named defines, they exist here.
|
12
|
+
*/
|
13
|
+
|
14
|
+
// integers
|
15
|
+
#define RDO_PG_INT2OID 21
|
16
|
+
#define RDO_PG_INT4OID 23
|
17
|
+
#define RDO_PG_INT8OID 20
|
18
|
+
|
19
|
+
// floats
|
20
|
+
#define RDO_PG_FLOAT4OID 700
|
21
|
+
#define RDO_PG_FLOAT8OID 701
|
22
|
+
|
23
|
+
// precision decimals
|
24
|
+
#define RDO_PG_NUMERICOID 1700
|
25
|
+
|
26
|
+
// boolean
|
27
|
+
#define RDO_PG_BOOLOID 16
|
28
|
+
|
29
|
+
// bytea
|
30
|
+
#define RDO_PG_BYTEAOID 17
|
31
|
+
|
32
|
+
// dates
|
33
|
+
#define RDO_PG_DATEOID 1082
|
34
|
+
|
35
|
+
// timestamps
|
36
|
+
#define RDO_PG_TIMESTAMPOID 1114
|
37
|
+
#define RDO_PG_TIMESTAMPTZOID 1184
|
38
|
+
|
39
|
+
// text/char
|
40
|
+
#define RDO_PG_TEXTOID 25
|
41
|
+
#define RDO_PG_CHAROID 18
|
42
|
+
#define RDO_PG_VARCHAROID 1043
|
43
|
+
#define RDO_PG_BPCHAROID 1042
|
44
|
+
|
45
|
+
// text[]/char[]
|
46
|
+
#define RDO_PG_TEXTARRAYOID 1009
|
47
|
+
#define RDO_PG_CHARARRAYOID 1002
|
48
|
+
#define RDO_PG_BPCHARARRAYOID 1014
|
49
|
+
#define RDO_PG_VARCHARARRAYOID 1015
|
50
|
+
|
51
|
+
// integer[]
|
52
|
+
#define RDO_PG_INT2ARRAYOID 1005
|
53
|
+
#define RDO_PG_INT4ARRAYOID 1007
|
54
|
+
#define RDO_PG_INT8ARRAYOID 1016
|
55
|
+
|
56
|
+
// float[]
|
57
|
+
#define RDO_PG_FLOAT4ARRAYOID 1021
|
58
|
+
#define RDO_PG_FLOAT8ARRAYOID 1022
|
59
|
+
|
60
|
+
// numeric[]/decimal[]
|
61
|
+
#define RDO_PG_NUMERICARRAYOID 1231
|
62
|
+
|
63
|
+
// boolean[]
|
64
|
+
#define RDO_PG_BOOLARRAYOID 1000
|
65
|
+
|
66
|
+
// bytea[]
|
67
|
+
#define RDO_PG_BYTEAARRAYOID 1001
|
68
|
+
|
69
|
+
// date[]
|
70
|
+
#define RDO_PG_DATEARRAYOID 1182
|
71
|
+
|
72
|
+
// timestamp[]/timestamptz[]
|
73
|
+
#define RDO_PG_TIMESTAMPARRAYOID 1115
|
74
|
+
#define RDO_PG_TIMESTAMPTZARRAYOID 1185
|
data/lib/rdo/postgres.rb
CHANGED
@@ -6,9 +6,21 @@
|
|
6
6
|
##
|
7
7
|
|
8
8
|
require "rdo"
|
9
|
+
|
9
10
|
require "rdo/postgres/version"
|
10
11
|
require "rdo/postgres/driver"
|
11
12
|
|
13
|
+
require "rdo/postgres/array"
|
14
|
+
require "rdo/postgres/array/text"
|
15
|
+
require "rdo/postgres/array/integer"
|
16
|
+
require "rdo/postgres/array/float"
|
17
|
+
require "rdo/postgres/array/numeric"
|
18
|
+
require "rdo/postgres/array/boolean"
|
19
|
+
require "rdo/postgres/array/bytea"
|
20
|
+
require "rdo/postgres/array/date"
|
21
|
+
require "rdo/postgres/array/timestamp"
|
22
|
+
require "rdo/postgres/array/timestamp_tz"
|
23
|
+
|
12
24
|
# c extension
|
13
25
|
require "rdo_postgres/rdo_postgres"
|
14
26
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
##
|
2
|
+
# RDO PostgreSQL driver.
|
3
|
+
# Copyright © 2012 Chris Corbyn.
|
4
|
+
#
|
5
|
+
# See LICENSE file for details.
|
6
|
+
##
|
7
|
+
|
8
|
+
module RDO
|
9
|
+
module Postgres
|
10
|
+
# Utility class used to handle PostgreSQL arrays.
|
11
|
+
#
|
12
|
+
# The default implementation assumes only String support.
|
13
|
+
# Subclasses override #parse_value and #format_value for typed-arrays.
|
14
|
+
#
|
15
|
+
# @example Turn a Ruby Array into a PostgreSQL array String
|
16
|
+
# RDO::Postgres::Array.new(original).to_s
|
17
|
+
# # => {"John Smith","Sarah Doe"}
|
18
|
+
#
|
19
|
+
# @example Turn a PostgreSQL array String into a Ruby Array
|
20
|
+
# RDO::Postgres::Array.parse('{"John Smith","Sarah Doe"}').to_a
|
21
|
+
# # => ["John Smith", "Sarah Doe"]
|
22
|
+
class Array < ::Array
|
23
|
+
class << self
|
24
|
+
# Read a PostgreSQL array in its string form.
|
25
|
+
#
|
26
|
+
# @param [String] str
|
27
|
+
# an array string from postgresql
|
28
|
+
#
|
29
|
+
# @return [Array]
|
30
|
+
# a Ruby Array for this string
|
31
|
+
def parse(str)
|
32
|
+
new.tap do |a|
|
33
|
+
a.replace(str[1...-1].split(",").map(&a.method(:parse_value_or_null)))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Convert the Array to the format used by PostgreSQL.
|
39
|
+
#
|
40
|
+
# @return [String]
|
41
|
+
# a postgresql array string
|
42
|
+
def to_s
|
43
|
+
"{#{map(&method(:format_value_or_null)).join(",")}}"
|
44
|
+
end
|
45
|
+
|
46
|
+
# Format an individual element in the Array for building into a String.
|
47
|
+
#
|
48
|
+
# The default implementation wraps quotes around the element.
|
49
|
+
#
|
50
|
+
# @param [Object] v
|
51
|
+
# the Ruby type in the Array
|
52
|
+
#
|
53
|
+
# @return [String]
|
54
|
+
# a String used to build the formatted array
|
55
|
+
def format_value(v)
|
56
|
+
%Q{"#{v.to_s.gsub('\\', '\\\\\\\\').gsub('"', '\\\\"')}"}
|
57
|
+
end
|
58
|
+
|
59
|
+
# Parse an individual element from the array.
|
60
|
+
#
|
61
|
+
# The default implementation parses as if it were text.
|
62
|
+
# Subclasses should override this.
|
63
|
+
#
|
64
|
+
# @param [String] s
|
65
|
+
# the string form of the array element
|
66
|
+
#
|
67
|
+
# @return [Object]
|
68
|
+
# the Ruby value
|
69
|
+
def parse_value(s)
|
70
|
+
s[0] == '"' ? s[1...-1].gsub(/\\(.)/, "\\1") : s
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def format_value_or_null(v)
|
76
|
+
v.nil? ? "NULL" : format_value(v)
|
77
|
+
end
|
78
|
+
|
79
|
+
def parse_value_or_null(s)
|
80
|
+
s == "NULL" ? nil : parse_value(s)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
##
|
2
|
+
# RDO PostgreSQL driver.
|
3
|
+
# Copyright © 2012 Chris Corbyn.
|
4
|
+
#
|
5
|
+
# See LICENSE file for details.
|
6
|
+
##
|
7
|
+
|
8
|
+
module RDO
|
9
|
+
module Postgres
|
10
|
+
# Ruby handling for boolean[] type in PostgreSQL.
|
11
|
+
class Array::Boolean < Array
|
12
|
+
def parse_value(s)
|
13
|
+
s[0] == "t"
|
14
|
+
end
|
15
|
+
|
16
|
+
def format_value(v)
|
17
|
+
(!!v).to_s
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
##
|
2
|
+
# RDO PostgreSQL driver.
|
3
|
+
# Copyright © 2012 Chris Corbyn.
|
4
|
+
#
|
5
|
+
# See LICENSE file for details.
|
6
|
+
##
|
7
|
+
|
8
|
+
module RDO
|
9
|
+
module Postgres
|
10
|
+
# Ruby handling for bytea[] type in PostgreSQL.
|
11
|
+
class Array::Bytea < Array
|
12
|
+
def parse_value(s)
|
13
|
+
# defined in ext/rdo_postgres/arrays.c
|
14
|
+
end
|
15
|
+
|
16
|
+
def format_value(v)
|
17
|
+
# defined in ext/rdo_postgres/arrays.c
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
##
|
2
|
+
# RDO PostgreSQL driver.
|
3
|
+
# Copyright © 2012 Chris Corbyn.
|
4
|
+
#
|
5
|
+
# See LICENSE file for details.
|
6
|
+
##
|
7
|
+
|
8
|
+
module RDO
|
9
|
+
module Postgres
|
10
|
+
# Ruby handling for date[] type in PostgreSQL.
|
11
|
+
class Array::Date < Array
|
12
|
+
def parse_value(s)
|
13
|
+
RDO::Util.date(s)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
##
|
2
|
+
# RDO PostgreSQL driver.
|
3
|
+
# Copyright © 2012 Chris Corbyn.
|
4
|
+
#
|
5
|
+
# See LICENSE file for details.
|
6
|
+
##
|
7
|
+
|
8
|
+
module RDO
|
9
|
+
module Postgres
|
10
|
+
# Ruby handling for float[] type in PostgreSQL.
|
11
|
+
class Array::Float < Array
|
12
|
+
def parse_value(s)
|
13
|
+
case s
|
14
|
+
when "Infinity"
|
15
|
+
::Float::INFINITY
|
16
|
+
when "-Infinity"
|
17
|
+
-::Float::INFINITY
|
18
|
+
when "NaN"
|
19
|
+
::Float::NAN
|
20
|
+
else
|
21
|
+
s.to_f
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def format_value(v)
|
26
|
+
v.to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
##
|
2
|
+
# RDO PostgreSQL driver.
|
3
|
+
# Copyright © 2012 Chris Corbyn.
|
4
|
+
#
|
5
|
+
# See LICENSE file for details.
|
6
|
+
##
|
7
|
+
|
8
|
+
module RDO
|
9
|
+
module Postgres
|
10
|
+
# Ruby handling for integer[] type in PostgreSQL.
|
11
|
+
class Array::Integer < Array
|
12
|
+
def parse_value(s)
|
13
|
+
s.to_i
|
14
|
+
end
|
15
|
+
|
16
|
+
def format_value(v)
|
17
|
+
v.to_s
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
##
|
2
|
+
# RDO PostgreSQL driver.
|
3
|
+
# Copyright © 2012 Chris Corbyn.
|
4
|
+
#
|
5
|
+
# See LICENSE file for details.
|
6
|
+
##
|
7
|
+
|
8
|
+
require "bigdecimal"
|
9
|
+
|
10
|
+
module RDO
|
11
|
+
module Postgres
|
12
|
+
# Ruby handling for numeric[] type in PostgreSQL.
|
13
|
+
class Array::Numeric < Array
|
14
|
+
def parse_value(s)
|
15
|
+
BigDecimal.new(s)
|
16
|
+
end
|
17
|
+
|
18
|
+
def format_value(v)
|
19
|
+
v.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
##
|
2
|
+
# RDO PostgreSQL driver.
|
3
|
+
# Copyright © 2012 Chris Corbyn.
|
4
|
+
#
|
5
|
+
# See LICENSE file for details.
|
6
|
+
##
|
7
|
+
|
8
|
+
module RDO
|
9
|
+
module Postgres
|
10
|
+
# Ruby handling for text[] type in PostgreSQL.
|
11
|
+
class Array::Text < Array
|
12
|
+
# abstract class behaves as text anyway
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
##
|
2
|
+
# RDO PostgreSQL driver.
|
3
|
+
# Copyright © 2012 Chris Corbyn.
|
4
|
+
#
|
5
|
+
# See LICENSE file for details.
|
6
|
+
##
|
7
|
+
|
8
|
+
module RDO
|
9
|
+
module Postgres
|
10
|
+
# Ruby handling for timestamp[] type in PostgreSQL.
|
11
|
+
class Array::Timestamp < Array
|
12
|
+
def parse_value(s)
|
13
|
+
RDO::Util.date_time_without_zone(s)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
##
|
2
|
+
# RDO PostgreSQL driver.
|
3
|
+
# Copyright © 2012 Chris Corbyn.
|
4
|
+
#
|
5
|
+
# See LICENSE file for details.
|
6
|
+
##
|
7
|
+
|
8
|
+
module RDO
|
9
|
+
module Postgres
|
10
|
+
# Ruby handling for timestamptz[] type in PostgreSQL.
|
11
|
+
class Array::TimestampTZ < Array
|
12
|
+
def parse_value(s)
|
13
|
+
RDO::Util.date_time_with_zone(s)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/rdo/postgres/version.rb
CHANGED
@@ -0,0 +1,74 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe RDO::Postgres::Array::Boolean do
|
4
|
+
it "is a kind of ::Array" do
|
5
|
+
RDO::Postgres::Array::Boolean.new.should be_a_kind_of(::Array)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#to_s" do
|
9
|
+
context "with an empty array" do
|
10
|
+
let(:arr) { RDO::Postgres::Array::Boolean[] }
|
11
|
+
|
12
|
+
it "returns {}" do
|
13
|
+
arr.to_s.should == '{}'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "with an array of Booleans" do
|
18
|
+
let(:arr) { RDO::Postgres::Array::Boolean[true, false, false] }
|
19
|
+
|
20
|
+
it "uses truth literals" do
|
21
|
+
arr.to_s.should == '{true,false,false}'
|
22
|
+
end
|
23
|
+
|
24
|
+
context "containing nil" do
|
25
|
+
let(:arr) { RDO::Postgres::Array::Boolean[true, nil] }
|
26
|
+
|
27
|
+
it "uses NULL" do
|
28
|
+
arr.to_s.should == '{true,NULL}'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#to_a" do
|
35
|
+
let(:arr) { RDO::Postgres::Array::Bytea["\x00\x11", "\x22\x33", "\x44\x55"] }
|
36
|
+
|
37
|
+
it "returns a Ruby ::Array" do
|
38
|
+
arr.to_a.should == ["\x00\x11", "\x22\x33", "\x44\x55"]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe ".parse" do
|
43
|
+
let(:str) { '{}' }
|
44
|
+
let(:arr) { RDO::Postgres::Array::Bytea.parse(str) }
|
45
|
+
|
46
|
+
it "returns a RDO::Postgres::Array::Bytea" do
|
47
|
+
arr.should be_a_kind_of(RDO::Postgres::Array::Bytea)
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with an empty array string" do
|
51
|
+
let(:str) { '{}' }
|
52
|
+
|
53
|
+
it "returns an empty Array" do
|
54
|
+
arr.should be_empty
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "with an array of byteas" do
|
59
|
+
let(:str) { '{"\\\\x0011","\\\\x2233"}' }
|
60
|
+
|
61
|
+
it "returns an Array of Strings" do
|
62
|
+
arr.to_a.should == ["\x00\x11", "\x22\x33"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with an array containing NULL" do
|
67
|
+
let(:str) { '{NULL,NULL,"\\\\x0011"}' }
|
68
|
+
|
69
|
+
it "uses nil as the value" do
|
70
|
+
arr.to_a.should == [nil, nil, "\x00\x11"]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|