activerecord4-redshift-adapter 0.1.1 → 0.2.0
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.
- checksums.yaml +4 -4
- data/lib/active_record/connection_adapters/redshift/array_parser.rb +35 -39
- data/lib/active_record/connection_adapters/redshift/column.rb +10 -0
- data/lib/active_record/connection_adapters/redshift/database_statements.rb +37 -47
- data/lib/active_record/connection_adapters/redshift/oid.rb +14 -359
- data/lib/active_record/connection_adapters/redshift/oid/date.rb +11 -0
- data/lib/active_record/connection_adapters/redshift/oid/date_time.rb +36 -0
- data/lib/active_record/connection_adapters/redshift/oid/decimal.rb +13 -0
- data/lib/active_record/connection_adapters/redshift/oid/float.rb +21 -0
- data/lib/active_record/connection_adapters/redshift/oid/infinity.rb +13 -0
- data/lib/active_record/connection_adapters/redshift/oid/integer.rb +11 -0
- data/lib/active_record/connection_adapters/redshift/oid/json.rb +35 -0
- data/lib/active_record/connection_adapters/redshift/oid/jsonb.rb +23 -0
- data/lib/active_record/connection_adapters/redshift/oid/time.rb +11 -0
- data/lib/active_record/connection_adapters/redshift/oid/type_map_initializer.rb +63 -0
- data/lib/active_record/connection_adapters/redshift/quoting.rb +45 -119
- data/lib/active_record/connection_adapters/redshift/referential_integrity.rb +4 -19
- data/lib/active_record/connection_adapters/redshift/schema_definitions.rb +73 -0
- data/lib/active_record/connection_adapters/redshift/schema_statements.rb +141 -76
- data/lib/active_record/connection_adapters/redshift/utils.rb +77 -0
- data/lib/active_record/connection_adapters/redshift_adapter.rb +252 -496
- metadata +17 -11
- data/lib/active_record/connection_adapters/redshift/cast.rb +0 -156
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34f882890a917a408523cf0d811fec93c61f662b
|
4
|
+
data.tar.gz: b946f1a2a36571c0ddfb1e4fa8087396b590d5b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a11030528067cd95e0e19f046db194214642be0bfe93d42394d9160e4aa6627ea420e4ee1684273aaaa56e782e587bdb1a67df18a0d52011ac04763d27daa2f0
|
7
|
+
data.tar.gz: 8638c106814e78f348adeccb9e0b896a53287da248993be0e546cd4c9a4e0da0f06769c6330dc6bfbfd641b41c9c3e565d0bb2e24b46233e4360e6c67c523b87
|
@@ -1,41 +1,36 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
|
-
|
4
|
-
module ArrayParser
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
3
|
+
module Redshift
|
4
|
+
module ArrayParser # :nodoc:
|
5
|
+
|
6
|
+
DOUBLE_QUOTE = '"'
|
7
|
+
BACKSLASH = "\\"
|
8
|
+
COMMA = ','
|
9
|
+
BRACKET_OPEN = '{'
|
10
|
+
BRACKET_CLOSE = '}'
|
11
|
+
|
12
|
+
def parse_pg_array(string) # :nodoc:
|
13
|
+
local_index = 0
|
14
|
+
array = []
|
15
|
+
while(local_index < string.length)
|
16
|
+
case string[local_index]
|
17
|
+
when BRACKET_OPEN
|
18
|
+
local_index,array = parse_array_contents(array, string, local_index + 1)
|
19
|
+
when BRACKET_CLOSE
|
20
|
+
return array
|
16
21
|
end
|
22
|
+
local_index += 1
|
17
23
|
end
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
array = []
|
22
|
-
while(local_index < string.length)
|
23
|
-
case string[local_index]
|
24
|
-
when '{'
|
25
|
-
local_index,array = parse_array_contents(array, string, local_index + 1)
|
26
|
-
when '}'
|
27
|
-
return array
|
28
|
-
end
|
29
|
-
local_index += 1
|
30
|
-
end
|
25
|
+
array
|
26
|
+
end
|
31
27
|
|
32
|
-
|
33
|
-
end
|
28
|
+
private
|
34
29
|
|
35
30
|
def parse_array_contents(array, string, index)
|
36
|
-
is_escaping
|
37
|
-
is_quoted
|
38
|
-
was_quoted
|
31
|
+
is_escaping = false
|
32
|
+
is_quoted = false
|
33
|
+
was_quoted = false
|
39
34
|
current_item = ''
|
40
35
|
|
41
36
|
local_index = index
|
@@ -47,29 +42,29 @@ module ActiveRecord
|
|
47
42
|
else
|
48
43
|
if is_quoted
|
49
44
|
case token
|
50
|
-
when
|
45
|
+
when DOUBLE_QUOTE
|
51
46
|
is_quoted = false
|
52
47
|
was_quoted = true
|
53
|
-
when
|
48
|
+
when BACKSLASH
|
54
49
|
is_escaping = true
|
55
50
|
else
|
56
51
|
current_item << token
|
57
52
|
end
|
58
53
|
else
|
59
54
|
case token
|
60
|
-
when
|
55
|
+
when BACKSLASH
|
61
56
|
is_escaping = true
|
62
|
-
when
|
57
|
+
when COMMA
|
63
58
|
add_item_to_array(array, current_item, was_quoted)
|
64
59
|
current_item = ''
|
65
60
|
was_quoted = false
|
66
|
-
when
|
61
|
+
when DOUBLE_QUOTE
|
67
62
|
is_quoted = true
|
68
|
-
when
|
63
|
+
when BRACKET_OPEN
|
69
64
|
internal_items = []
|
70
65
|
local_index,internal_items = parse_array_contents(internal_items, string, local_index + 1)
|
71
66
|
array.push(internal_items)
|
72
|
-
when
|
67
|
+
when BRACKET_CLOSE
|
73
68
|
add_item_to_array(array, current_item, was_quoted)
|
74
69
|
return local_index,array
|
75
70
|
else
|
@@ -84,8 +79,9 @@ module ActiveRecord
|
|
84
79
|
end
|
85
80
|
|
86
81
|
def add_item_to_array(array, current_item, quoted)
|
87
|
-
if current_item.length == 0
|
88
|
-
|
82
|
+
return if !quoted && current_item.length == 0
|
83
|
+
|
84
|
+
if !quoted && current_item == 'NULL'
|
89
85
|
array.push nil
|
90
86
|
else
|
91
87
|
array.push current_item
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class RedshiftColumn < Column #:nodoc:
|
4
|
+
def initialize(name, default, cast_type, sql_type = nil, null = true, default_function = nil)
|
5
|
+
super name, default, cast_type, sql_type, null
|
6
|
+
@default_function = default_function
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
|
-
|
3
|
+
module Redshift
|
4
4
|
module DatabaseStatements
|
5
5
|
def explain(arel, binds = [])
|
6
6
|
sql = "EXPLAIN #{to_sql(arel, binds)}"
|
@@ -44,10 +44,32 @@ module ActiveRecord
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
+
def select_value(arel, name = nil, binds = [])
|
48
|
+
arel, binds = binds_from_relation arel, binds
|
49
|
+
sql = to_sql(arel, binds)
|
50
|
+
execute_and_clear(sql, name, binds) do |result|
|
51
|
+
result.getvalue(0, 0) if result.ntuples > 0 && result.nfields > 0
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def select_values(arel, name = nil)
|
56
|
+
arel, binds = binds_from_relation arel, []
|
57
|
+
sql = to_sql(arel, binds)
|
58
|
+
execute_and_clear(sql, name, binds) do |result|
|
59
|
+
if result.nfields > 0
|
60
|
+
result.column_values(0)
|
61
|
+
else
|
62
|
+
[]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
47
67
|
# Executes a SELECT query and returns an array of rows. Each row is an
|
48
68
|
# array of field values.
|
49
|
-
def select_rows(sql, name = nil,
|
50
|
-
|
69
|
+
def select_rows(sql, name = nil, binds = [])
|
70
|
+
execute_and_clear(sql, name, binds) do |result|
|
71
|
+
result.values
|
72
|
+
end
|
51
73
|
end
|
52
74
|
|
53
75
|
# Executes an INSERT query and returns the new record's ID
|
@@ -72,6 +94,11 @@ module ActiveRecord
|
|
72
94
|
super.insert
|
73
95
|
end
|
74
96
|
|
97
|
+
# The internal PostgreSQL identifier of the money data type.
|
98
|
+
MONEY_COLUMN_TYPE_OID = 790 #:nodoc:
|
99
|
+
# The internal PostgreSQL identifier of the BYTEA data type.
|
100
|
+
BYTEA_COLUMN_TYPE_OID = 17 #:nodoc:
|
101
|
+
|
75
102
|
# create a 2D array representing the result set
|
76
103
|
def result_as_array(res) #:nodoc:
|
77
104
|
# check if we have any binary column and if they need escaping
|
@@ -129,39 +156,21 @@ module ActiveRecord
|
|
129
156
|
end
|
130
157
|
end
|
131
158
|
|
132
|
-
def substitute_at(column, index)
|
133
|
-
Arel::Nodes::BindParam.new "$#{index + 1}"
|
134
|
-
end
|
135
|
-
|
136
159
|
def exec_query(sql, name = 'SQL', binds = [])
|
137
|
-
|
138
|
-
result = binds.empty? ? exec_no_cache(sql, binds) :
|
139
|
-
exec_cache(sql, binds)
|
140
|
-
|
160
|
+
execute_and_clear(sql, name, binds) do |result|
|
141
161
|
types = {}
|
142
|
-
result.fields
|
162
|
+
fields = result.fields
|
163
|
+
fields.each_with_index do |fname, i|
|
143
164
|
ftype = result.ftype i
|
144
165
|
fmod = result.fmod i
|
145
|
-
types[fname] =
|
146
|
-
warn "unknown OID: #{fname}(#{oid}) (#{sql})"
|
147
|
-
OID::Identity.new
|
148
|
-
}
|
166
|
+
types[fname] = get_oid_type(ftype, fmod, fname)
|
149
167
|
end
|
150
|
-
|
151
|
-
ret = ActiveRecord::Result.new(result.fields, result.values, types)
|
152
|
-
result.clear
|
153
|
-
return ret
|
168
|
+
ActiveRecord::Result.new(fields, result.values, types)
|
154
169
|
end
|
155
170
|
end
|
156
171
|
|
157
172
|
def exec_delete(sql, name = 'SQL', binds = [])
|
158
|
-
|
159
|
-
result = binds.empty? ? exec_no_cache(sql, binds) :
|
160
|
-
exec_cache(sql, binds)
|
161
|
-
affected = result.cmd_tuples
|
162
|
-
result.clear
|
163
|
-
affected
|
164
|
-
end
|
173
|
+
execute_and_clear(sql, name, binds) {|result| result.cmd_tuples }
|
165
174
|
end
|
166
175
|
alias :exec_update :exec_delete
|
167
176
|
|
@@ -214,28 +223,9 @@ module ActiveRecord
|
|
214
223
|
end
|
215
224
|
|
216
225
|
# Aborts a transaction.
|
217
|
-
def
|
226
|
+
def exec_rollback_db_transaction
|
218
227
|
execute "ROLLBACK"
|
219
228
|
end
|
220
|
-
|
221
|
-
def outside_transaction?
|
222
|
-
message = "#outside_transaction? is deprecated. This method was only really used " \
|
223
|
-
"internally, but you can use #transaction_open? instead."
|
224
|
-
ActiveSupport::Deprecation.warn message
|
225
|
-
@connection.transaction_status == PGconn::PQTRANS_IDLE
|
226
|
-
end
|
227
|
-
|
228
|
-
def create_savepoint
|
229
|
-
execute("SAVEPOINT #{current_savepoint_name}")
|
230
|
-
end
|
231
|
-
|
232
|
-
def rollback_to_savepoint
|
233
|
-
execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}")
|
234
|
-
end
|
235
|
-
|
236
|
-
def release_savepoint
|
237
|
-
execute("RELEASE SAVEPOINT #{current_savepoint_name}")
|
238
|
-
end
|
239
229
|
end
|
240
230
|
end
|
241
231
|
end
|
@@ -1,365 +1,20 @@
|
|
1
|
-
require 'active_record/connection_adapters/
|
1
|
+
require 'active_record/connection_adapters/redshift/oid/infinity'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
value
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class Identity < Type
|
16
|
-
def type_cast(value)
|
17
|
-
value
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class Bit < Type
|
22
|
-
def type_cast(value)
|
23
|
-
if String === value
|
24
|
-
ConnectionAdapters::RedshiftColumn.string_to_bit value
|
25
|
-
else
|
26
|
-
value
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class Bytea < Type
|
32
|
-
def type_cast(value)
|
33
|
-
return if value.nil?
|
34
|
-
PGconn.unescape_bytea value
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
class Money < Type
|
39
|
-
def type_cast(value)
|
40
|
-
return if value.nil?
|
41
|
-
|
42
|
-
# Because money output is formatted according to the locale, there are two
|
43
|
-
# cases to consider (note the decimal separators):
|
44
|
-
# (1) $12,345,678.12
|
45
|
-
# (2) $12.345.678,12
|
46
|
-
|
47
|
-
case value
|
48
|
-
when /^-?\D+[\d,]+\.\d{2}$/ # (1)
|
49
|
-
value.gsub!(/[^-\d.]/, '')
|
50
|
-
when /^-?\D+[\d.]+,\d{2}$/ # (2)
|
51
|
-
value.gsub!(/[^-\d,]/, '').sub!(/,/, '.')
|
52
|
-
end
|
53
|
-
|
54
|
-
ConnectionAdapters::Column.value_to_decimal value
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
class Vector < Type
|
59
|
-
attr_reader :delim, :subtype
|
60
|
-
|
61
|
-
# +delim+ corresponds to the `typdelim` column in the pg_types
|
62
|
-
# table. +subtype+ is derived from the `typelem` column in the
|
63
|
-
# pg_types table.
|
64
|
-
def initialize(delim, subtype)
|
65
|
-
@delim = delim
|
66
|
-
@subtype = subtype
|
67
|
-
end
|
68
|
-
|
69
|
-
# FIXME: this should probably split on +delim+ and use +subtype+
|
70
|
-
# to cast the values. Unfortunately, the current Rails behavior
|
71
|
-
# is to just return the string.
|
72
|
-
def type_cast(value)
|
73
|
-
value
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
class Point < Type
|
78
|
-
def type_cast(value)
|
79
|
-
if String === value
|
80
|
-
ConnectionAdapters::RedshiftColumn.string_to_point value
|
81
|
-
else
|
82
|
-
value
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
class Array < Type
|
88
|
-
attr_reader :subtype
|
89
|
-
def initialize(subtype)
|
90
|
-
@subtype = subtype
|
91
|
-
end
|
92
|
-
|
93
|
-
def type_cast(value)
|
94
|
-
if String === value
|
95
|
-
ConnectionAdapters::RedshiftColumn.string_to_array value, @subtype
|
96
|
-
else
|
97
|
-
value
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
class Range < Type
|
103
|
-
attr_reader :subtype
|
104
|
-
def initialize(subtype)
|
105
|
-
@subtype = subtype
|
106
|
-
end
|
107
|
-
|
108
|
-
def extract_bounds(value)
|
109
|
-
from, to = value[1..-2].split(',')
|
110
|
-
{
|
111
|
-
from: (value[1] == ',' || from == '-infinity') ? infinity(:negative => true) : from,
|
112
|
-
to: (value[-2] == ',' || to == 'infinity') ? infinity : to,
|
113
|
-
exclude_start: (value[0] == '('),
|
114
|
-
exclude_end: (value[-1] == ')')
|
115
|
-
}
|
116
|
-
end
|
117
|
-
|
118
|
-
def infinity(options = {})
|
119
|
-
::Float::INFINITY * (options[:negative] ? -1 : 1)
|
120
|
-
end
|
121
|
-
|
122
|
-
def infinity?(value)
|
123
|
-
value.respond_to?(:infinite?) && value.infinite?
|
124
|
-
end
|
125
|
-
|
126
|
-
def to_integer(value)
|
127
|
-
infinity?(value) ? value : value.to_i
|
128
|
-
end
|
129
|
-
|
130
|
-
def type_cast(value)
|
131
|
-
return if value.nil? || value == 'empty'
|
132
|
-
return value if value.is_a?(::Range)
|
133
|
-
|
134
|
-
extracted = extract_bounds(value)
|
135
|
-
|
136
|
-
case @subtype
|
137
|
-
when :date
|
138
|
-
from = ConnectionAdapters::Column.value_to_date(extracted[:from])
|
139
|
-
from -= 1.day if extracted[:exclude_start]
|
140
|
-
to = ConnectionAdapters::Column.value_to_date(extracted[:to])
|
141
|
-
when :decimal
|
142
|
-
from = BigDecimal.new(extracted[:from].to_s)
|
143
|
-
# FIXME: add exclude start for ::Range, same for timestamp ranges
|
144
|
-
to = BigDecimal.new(extracted[:to].to_s)
|
145
|
-
when :time
|
146
|
-
from = ConnectionAdapters::Column.string_to_time(extracted[:from])
|
147
|
-
to = ConnectionAdapters::Column.string_to_time(extracted[:to])
|
148
|
-
when :integer
|
149
|
-
from = to_integer(extracted[:from]) rescue value ? 1 : 0
|
150
|
-
from -= 1 if extracted[:exclude_start]
|
151
|
-
to = to_integer(extracted[:to]) rescue value ? 1 : 0
|
152
|
-
else
|
153
|
-
return value
|
154
|
-
end
|
155
|
-
|
156
|
-
::Range.new(from, to, extracted[:exclude_end])
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
class Integer < Type
|
161
|
-
def type_cast(value)
|
162
|
-
return if value.nil?
|
163
|
-
|
164
|
-
ConnectionAdapters::Column.value_to_integer value
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
class Boolean < Type
|
169
|
-
def type_cast(value)
|
170
|
-
return if value.nil?
|
171
|
-
|
172
|
-
ConnectionAdapters::Column.value_to_boolean value
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
class Timestamp < Type
|
177
|
-
def type; :timestamp; end
|
178
|
-
|
179
|
-
def type_cast(value)
|
180
|
-
return if value.nil?
|
181
|
-
|
182
|
-
# FIXME: probably we can improve this since we know it is PG
|
183
|
-
# specific
|
184
|
-
ConnectionAdapters::RedshiftColumn.string_to_time value
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
class Date < Type
|
189
|
-
def type; :datetime; end
|
190
|
-
|
191
|
-
def type_cast(value)
|
192
|
-
return if value.nil?
|
3
|
+
require 'active_record/connection_adapters/redshift/oid/date'
|
4
|
+
require 'active_record/connection_adapters/redshift/oid/date_time'
|
5
|
+
require 'active_record/connection_adapters/redshift/oid/decimal'
|
6
|
+
require 'active_record/connection_adapters/redshift/oid/float'
|
7
|
+
require 'active_record/connection_adapters/redshift/oid/integer'
|
8
|
+
require 'active_record/connection_adapters/redshift/oid/json'
|
9
|
+
require 'active_record/connection_adapters/redshift/oid/jsonb'
|
10
|
+
require 'active_record/connection_adapters/redshift/oid/time'
|
193
11
|
|
194
|
-
|
195
|
-
# specific
|
196
|
-
ConnectionAdapters::Column.value_to_date value
|
197
|
-
end
|
198
|
-
end
|
12
|
+
require 'active_record/connection_adapters/redshift/oid/type_map_initializer'
|
199
13
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
# FIXME: probably we can improve this since we know it is PG
|
205
|
-
# specific
|
206
|
-
ConnectionAdapters::Column.string_to_dummy_time value
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
class Float < Type
|
211
|
-
def type_cast(value)
|
212
|
-
return if value.nil?
|
213
|
-
|
214
|
-
value.to_f
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
class Decimal < Type
|
219
|
-
def type_cast(value)
|
220
|
-
return if value.nil?
|
221
|
-
|
222
|
-
ConnectionAdapters::Column.value_to_decimal value
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
class Hstore < Type
|
227
|
-
def type_cast(value)
|
228
|
-
return if value.nil?
|
229
|
-
|
230
|
-
ConnectionAdapters::RedshiftColumn.string_to_hstore value
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
class Cidr < Type
|
235
|
-
def type_cast(value)
|
236
|
-
return if value.nil?
|
237
|
-
|
238
|
-
ConnectionAdapters::RedshiftColumn.string_to_cidr value
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
|
-
class Json < Type
|
243
|
-
def type_cast(value)
|
244
|
-
return if value.nil?
|
245
|
-
|
246
|
-
ConnectionAdapters::RedshiftColumn.string_to_json value
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
class TypeMap
|
251
|
-
def initialize
|
252
|
-
@mapping = {}
|
253
|
-
end
|
254
|
-
|
255
|
-
def []=(oid, type)
|
256
|
-
@mapping[oid] = type
|
257
|
-
end
|
258
|
-
|
259
|
-
def [](oid)
|
260
|
-
@mapping[oid]
|
261
|
-
end
|
262
|
-
|
263
|
-
def clear
|
264
|
-
@mapping.clear
|
265
|
-
end
|
266
|
-
|
267
|
-
def key?(oid)
|
268
|
-
@mapping.key? oid
|
269
|
-
end
|
270
|
-
|
271
|
-
def fetch(ftype, fmod)
|
272
|
-
# The type for the numeric depends on the width of the field,
|
273
|
-
# so we'll do something special here.
|
274
|
-
#
|
275
|
-
# When dealing with decimal columns:
|
276
|
-
#
|
277
|
-
# places after decimal = fmod - 4 & 0xffff
|
278
|
-
# places before decimal = (fmod - 4) >> 16 & 0xffff
|
279
|
-
if ftype == 1700 && (fmod - 4 & 0xffff).zero?
|
280
|
-
ftype = 23
|
281
|
-
end
|
282
|
-
|
283
|
-
@mapping.fetch(ftype) { |oid| yield oid, fmod }
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
TYPE_MAP = TypeMap.new # :nodoc:
|
288
|
-
|
289
|
-
# When the PG adapter connects, the pg_type table is queried. The
|
290
|
-
# key of this hash maps to the `typname` column from the table.
|
291
|
-
# TYPE_MAP is then dynamically built with oids as the key and type
|
292
|
-
# objects as values.
|
293
|
-
NAMES = Hash.new { |h,k| # :nodoc:
|
294
|
-
h[k] = OID::Identity.new
|
295
|
-
}
|
296
|
-
|
297
|
-
# Register an OID type named +name+ with a typcasting object in
|
298
|
-
# +type+. +name+ should correspond to the `typname` column in
|
299
|
-
# the `pg_type` table.
|
300
|
-
def self.register_type(name, type)
|
301
|
-
NAMES[name] = type
|
302
|
-
end
|
303
|
-
|
304
|
-
# Alias the +old+ type to the +new+ type.
|
305
|
-
def self.alias_type(new, old)
|
306
|
-
NAMES[new] = NAMES[old]
|
307
|
-
end
|
308
|
-
|
309
|
-
# Is +name+ a registered type?
|
310
|
-
def self.registered_type?(name)
|
311
|
-
NAMES.key? name
|
312
|
-
end
|
313
|
-
|
314
|
-
register_type 'int2', OID::Integer.new
|
315
|
-
alias_type 'int4', 'int2'
|
316
|
-
alias_type 'int8', 'int2'
|
317
|
-
alias_type 'oid', 'int2'
|
318
|
-
|
319
|
-
register_type 'daterange', OID::Range.new(:date)
|
320
|
-
register_type 'numrange', OID::Range.new(:decimal)
|
321
|
-
register_type 'tsrange', OID::Range.new(:time)
|
322
|
-
register_type 'int4range', OID::Range.new(:integer)
|
323
|
-
alias_type 'tstzrange', 'tsrange'
|
324
|
-
alias_type 'int8range', 'int4range'
|
325
|
-
|
326
|
-
register_type 'numeric', OID::Decimal.new
|
327
|
-
register_type 'text', OID::Identity.new
|
328
|
-
alias_type 'varchar', 'text'
|
329
|
-
alias_type 'char', 'text'
|
330
|
-
alias_type 'bpchar', 'text'
|
331
|
-
alias_type 'xml', 'text'
|
332
|
-
|
333
|
-
# FIXME: why are we keeping these types as strings?
|
334
|
-
alias_type 'tsvector', 'text'
|
335
|
-
alias_type 'interval', 'text'
|
336
|
-
alias_type 'macaddr', 'text'
|
337
|
-
alias_type 'uuid', 'text'
|
338
|
-
|
339
|
-
register_type 'money', OID::Money.new
|
340
|
-
register_type 'bytea', OID::Bytea.new
|
341
|
-
register_type 'bool', OID::Boolean.new
|
342
|
-
register_type 'bit', OID::Bit.new
|
343
|
-
register_type 'varbit', OID::Bit.new
|
344
|
-
|
345
|
-
register_type 'float4', OID::Float.new
|
346
|
-
alias_type 'float8', 'float4'
|
347
|
-
|
348
|
-
register_type 'timestamp', OID::Timestamp.new
|
349
|
-
register_type 'timestamptz', OID::Timestamp.new
|
350
|
-
register_type 'date', OID::Date.new
|
351
|
-
register_type 'time', OID::Time.new
|
352
|
-
|
353
|
-
register_type 'path', OID::Identity.new
|
354
|
-
register_type 'point', OID::Point.new
|
355
|
-
register_type 'polygon', OID::Identity.new
|
356
|
-
register_type 'circle', OID::Identity.new
|
357
|
-
register_type 'hstore', OID::Hstore.new
|
358
|
-
register_type 'json', OID::Json.new
|
359
|
-
register_type 'ltree', OID::Identity.new
|
360
|
-
|
361
|
-
register_type 'cidr', OID::Cidr.new
|
362
|
-
alias_type 'inet', 'cidr'
|
14
|
+
module ActiveRecord
|
15
|
+
module ConnectionAdapters
|
16
|
+
module Redshift
|
17
|
+
module OID # :nodoc:
|
363
18
|
end
|
364
19
|
end
|
365
20
|
end
|