activerecord-redshift-adapter-ng 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +0 -33
  3. data/README.md +12 -16
  4. data/lib/active_record/connection_adapters/redshift/column.rb +11 -1
  5. data/lib/active_record/connection_adapters/redshift/oid.rb +15 -0
  6. data/lib/active_record/connection_adapters/redshift/oid/array.rb +96 -0
  7. data/lib/active_record/connection_adapters/redshift/oid/bit.rb +52 -0
  8. data/lib/active_record/connection_adapters/redshift/oid/bit_varying.rb +13 -0
  9. data/lib/active_record/connection_adapters/redshift/oid/bytea.rb +14 -0
  10. data/lib/active_record/connection_adapters/redshift/oid/cidr.rb +46 -0
  11. data/lib/active_record/connection_adapters/redshift/oid/date_time.rb +0 -9
  12. data/lib/active_record/connection_adapters/redshift/oid/enum.rb +17 -0
  13. data/lib/active_record/connection_adapters/redshift/oid/hstore.rb +59 -0
  14. data/lib/active_record/connection_adapters/redshift/oid/inet.rb +13 -0
  15. data/lib/active_record/connection_adapters/redshift/oid/json.rb +1 -1
  16. data/lib/active_record/connection_adapters/redshift/oid/money.rb +43 -0
  17. data/lib/active_record/connection_adapters/redshift/oid/point.rb +43 -0
  18. data/lib/active_record/connection_adapters/redshift/oid/range.rb +76 -0
  19. data/lib/active_record/connection_adapters/redshift/oid/specialized_string.rb +15 -0
  20. data/lib/active_record/connection_adapters/redshift/oid/type_map_initializer.rb +42 -20
  21. data/lib/active_record/connection_adapters/redshift/oid/uuid.rb +28 -0
  22. data/lib/active_record/connection_adapters/redshift/oid/vector.rb +26 -0
  23. data/lib/active_record/connection_adapters/redshift/oid/xml.rb +28 -0
  24. data/lib/active_record/connection_adapters/redshift/quoting.rb +10 -0
  25. data/lib/active_record/connection_adapters/redshift/referential_integrity.rb +15 -0
  26. data/lib/active_record/connection_adapters/redshift/schema_definitions.rb +85 -0
  27. data/lib/active_record/connection_adapters/redshift/schema_statements.rb +171 -8
  28. data/lib/active_record/connection_adapters/redshift/utils.rb +4 -15
  29. data/lib/active_record/connection_adapters/redshift_adapter.rb +119 -38
  30. metadata +26 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de733c7700e8cdcabfb21c0f586ebdf5f982586b
4
- data.tar.gz: 74dad27ced8d0ff64e8638fb6c464112eb55c083
3
+ metadata.gz: ffdccdc8440d8d53be78f296fd2c137eab0481e1
4
+ data.tar.gz: f8402a7779848906a456ed6be8ec81210224d164
5
5
  SHA512:
6
- metadata.gz: f07eb341fdbc4b144b86760bb662483a015747c0d70479b6f4bf1a90018d01dab69aa53af883db67c5afac8e0b65f303eb2df4f602c841dcdad9420a6fda8643
7
- data.tar.gz: cf00590cf283dfbad15e0936d1f1d87c44b3d1b4668d9dfa8a7cbf3e5ef638f146adb0515154845fe74f81d32d9b3555f9abeee4e6ba127a29e304dde22df016
6
+ metadata.gz: e9cb7ba3125df8eb048c44e0425ff49397a9c23df14385952b390fff3759b83e54b928adb7e93d396247291fd1dbf1073678528303a733cf51453fe7fa930a91
7
+ data.tar.gz: 6c10e072ad442a23d4b3b4c2acf2f65450bd2060bab15ee8c8c568204b812885d7f77bb783c604d7fdd6d6bb09f876a33163b2e2450f8c2c92bac9243bb1052d
data/LICENSE CHANGED
@@ -1,4 +1,3 @@
1
- -----------------------------------------------------------------------------------
2
1
  The MIT License (MIT)
3
2
 
4
3
  Copyright (c) 2004-2013 David Heinemeier Hansson (original code author)
@@ -20,35 +19,3 @@ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20
19
  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21
20
  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
21
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
-
24
- -----------------------------------------------------------------------------------
25
- Copyright (c) 2010-2013, Fiksu, Inc.
26
- All rights reserved.
27
-
28
- Redistribution and use in source and binary forms, with or without
29
- modification, are permitted provided that the following conditions are
30
- met:
31
-
32
- o Redistributions of source code must retain the above copyright
33
- notice, this list of conditions and the following disclaimer.
34
-
35
- o Redistributions in binary form must reproduce the above copyright
36
- notice, this list of conditions and the following disclaimer in the
37
- documentation and/or other materials provided with the
38
- distribution.
39
-
40
- o Fiksu, Inc. nor the names of its contributors may be used to
41
- endorse or promote products derived from this software without
42
- specific prior written permission.
43
-
44
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
45
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
46
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
47
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
48
- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
50
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
51
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
52
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
53
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
54
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md CHANGED
@@ -1,34 +1,30 @@
1
- # activerecord-redshift-adapter-ng
1
+ activerecord4-redshift-adapter
2
+ ==============================
2
3
 
3
- Amazon Redshift adapter for ActiveRecord.
4
- I copied PostgreSQL driver from ActiveRecord and modified for Redshift.
5
- "Barely works" patch was borrowed from fiksu/activerecord-redshift-adapter.
4
+ Amazon Redshift adapter for ActiveRecord 4 (Rails 4).
5
+ Almost all code are copied from ActiveRecord 4.2.0 PostgreSQL
6
+ driver and modified for Redshift.
6
7
 
7
- I know Redshift driver already exists (https://github.com/fiksu/activerecord-redshift-adapter),
8
- but it currently supports only ActiveRecord 3. Also, AR4 code is magnifically
9
- different from AR3 code because of file separation, patching does not work well.
10
- I want to use Rails 4 with Redshift NOW, so I wrote this driver.
11
- If anybody write better Redshift driver which works with ActiveRecord 4,
12
- I abandon this driver.
8
+ Forked and heavily modified from (https://github.com/aamine/activerecord4-redshift-adapter).
13
9
 
14
- Usage
10
+ How to Use
15
11
  -------------------
16
12
 
17
- Write following in Gemfile:
13
+ In Gemfile
18
14
  ```
19
- gem 'activerecord-redshift-adapter-ng'
15
+ gem 'activerecord4-redshift-adapter', github: 'khwangster/activerecord4-redshift-adapter'
20
16
  ```
21
17
 
22
18
  In database.yml
23
19
  ```
24
20
  development:
25
21
  adapter: redshift
26
- host: your_cluster_name.hashhash.ap-northeast-1.redshift.amazonaws.com
27
- port: 5439
22
+ host: your_cluster_name.ident.ap-east-1.redshift.amazonaws.com
28
23
  database: dev
24
+ port: 5439
29
25
  username: your_user
30
26
  password: your_password
31
- encoding: utf8
27
+ encoding: utf-8
32
28
  pool: 3
33
29
  timeout: 5000
34
30
  ```
@@ -1,8 +1,18 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters
3
+ # PostgreSQL-specific extensions to column definitions in a table.
3
4
  class RedshiftColumn < Column #:nodoc:
5
+ attr_accessor :array
6
+
4
7
  def initialize(name, default, cast_type, sql_type = nil, null = true, default_function = nil)
5
- super name, default, cast_type, sql_type, null
8
+ if sql_type =~ /\[\]$/
9
+ @array = true
10
+ super(name, default, cast_type, sql_type[0..sql_type.length - 3], null)
11
+ else
12
+ @array = false
13
+ super(name, default, cast_type, sql_type, null)
14
+ end
15
+
6
16
  @default_function = default_function
7
17
  end
8
18
  end
@@ -1,13 +1,28 @@
1
1
  require 'active_record/connection_adapters/redshift/oid/infinity'
2
2
 
3
+ require 'active_record/connection_adapters/redshift/oid/array'
4
+ require 'active_record/connection_adapters/redshift/oid/bit'
5
+ require 'active_record/connection_adapters/redshift/oid/bit_varying'
6
+ require 'active_record/connection_adapters/redshift/oid/bytea'
7
+ require 'active_record/connection_adapters/redshift/oid/cidr'
3
8
  require 'active_record/connection_adapters/redshift/oid/date'
4
9
  require 'active_record/connection_adapters/redshift/oid/date_time'
5
10
  require 'active_record/connection_adapters/redshift/oid/decimal'
11
+ require 'active_record/connection_adapters/redshift/oid/enum'
6
12
  require 'active_record/connection_adapters/redshift/oid/float'
13
+ require 'active_record/connection_adapters/redshift/oid/hstore'
14
+ require 'active_record/connection_adapters/redshift/oid/inet'
7
15
  require 'active_record/connection_adapters/redshift/oid/integer'
8
16
  require 'active_record/connection_adapters/redshift/oid/json'
9
17
  require 'active_record/connection_adapters/redshift/oid/jsonb'
18
+ require 'active_record/connection_adapters/redshift/oid/money'
19
+ require 'active_record/connection_adapters/redshift/oid/point'
20
+ require 'active_record/connection_adapters/redshift/oid/range'
21
+ require 'active_record/connection_adapters/redshift/oid/specialized_string'
10
22
  require 'active_record/connection_adapters/redshift/oid/time'
23
+ require 'active_record/connection_adapters/redshift/oid/uuid'
24
+ require 'active_record/connection_adapters/redshift/oid/vector'
25
+ require 'active_record/connection_adapters/redshift/oid/xml'
11
26
 
12
27
  require 'active_record/connection_adapters/redshift/oid/type_map_initializer'
13
28
 
@@ -0,0 +1,96 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Redshift
4
+ module OID # :nodoc:
5
+ class Array < Type::Value # :nodoc:
6
+ include Type::Mutable
7
+
8
+ # Loads pg_array_parser if available. String parsing can be
9
+ # performed quicker by a native extension, which will not create
10
+ # a large amount of Ruby objects that will need to be garbage
11
+ # collected. pg_array_parser has a C and Java extension
12
+ begin
13
+ require 'pg_array_parser'
14
+ include PgArrayParser
15
+ rescue LoadError
16
+ require 'active_record/connection_adapters/redshift/array_parser'
17
+ include Redshift::ArrayParser
18
+ end
19
+
20
+ attr_reader :subtype, :delimiter
21
+ delegate :type, to: :subtype
22
+
23
+ def initialize(subtype, delimiter = ',')
24
+ @subtype = subtype
25
+ @delimiter = delimiter
26
+ end
27
+
28
+ def type_cast_from_database(value)
29
+ if value.is_a?(::String)
30
+ type_cast_array(parse_pg_array(value), :type_cast_from_database)
31
+ else
32
+ super
33
+ end
34
+ end
35
+
36
+ def type_cast_from_user(value)
37
+ type_cast_array(value, :type_cast_from_user)
38
+ end
39
+
40
+ def type_cast_for_database(value)
41
+ if value.is_a?(::Array)
42
+ cast_value_for_database(value)
43
+ else
44
+ super
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def type_cast_array(value, method)
51
+ if value.is_a?(::Array)
52
+ value.map { |item| type_cast_array(item, method) }
53
+ else
54
+ @subtype.public_send(method, value)
55
+ end
56
+ end
57
+
58
+ def cast_value_for_database(value)
59
+ if value.is_a?(::Array)
60
+ casted_values = value.map { |item| cast_value_for_database(item) }
61
+ "{#{casted_values.join(delimiter)}}"
62
+ else
63
+ quote_and_escape(subtype.type_cast_for_database(value))
64
+ end
65
+ end
66
+
67
+ ARRAY_ESCAPE = "\\" * 2 * 2 # escape the backslash twice for PG arrays
68
+
69
+ def quote_and_escape(value)
70
+ case value
71
+ when ::String
72
+ if string_requires_quoting?(value)
73
+ value = value.gsub(/\\/, ARRAY_ESCAPE)
74
+ value.gsub!(/"/,"\\\"")
75
+ %("#{value}")
76
+ else
77
+ value
78
+ end
79
+ when nil then "NULL"
80
+ else value
81
+ end
82
+ end
83
+
84
+ # See http://www.postgresql.org/docs/9.2/static/arrays.html#ARRAYS-IO
85
+ # for a list of all cases in which strings will be quoted.
86
+ def string_requires_quoting?(string)
87
+ string.empty? ||
88
+ string == "NULL" ||
89
+ string =~ /[\{\}"\\\s]/ ||
90
+ string.include?(delimiter)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,52 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Redshift
4
+ module OID # :nodoc:
5
+ class Bit < Type::Value # :nodoc:
6
+ def type
7
+ :bit
8
+ end
9
+
10
+ def type_cast(value)
11
+ if ::String === value
12
+ case value
13
+ when /^0x/i
14
+ value[2..-1].hex.to_s(2) # Hexadecimal notation
15
+ else
16
+ value # Bit-string notation
17
+ end
18
+ else
19
+ value
20
+ end
21
+ end
22
+
23
+ def type_cast_for_database(value)
24
+ Data.new(super) if value
25
+ end
26
+
27
+ class Data
28
+ def initialize(value)
29
+ @value = value
30
+ end
31
+
32
+ def to_s
33
+ value
34
+ end
35
+
36
+ def binary?
37
+ /\A[01]*\Z/ === value
38
+ end
39
+
40
+ def hex?
41
+ /\A[0-9A-F]*\Z/i === value
42
+ end
43
+
44
+ protected
45
+
46
+ attr_reader :value
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,13 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Redshift
4
+ module OID # :nodoc:
5
+ class BitVarying < OID::Bit # :nodoc:
6
+ def type
7
+ :bit_varying
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Redshift
4
+ module OID # :nodoc:
5
+ class Bytea < Type::Binary # :nodoc:
6
+ def type_cast_from_database(value)
7
+ return if value.nil?
8
+ PGconn.unescape_bytea(super)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,46 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Redshift
4
+ module OID # :nodoc:
5
+ class Cidr < Type::Value # :nodoc:
6
+ def type
7
+ :cidr
8
+ end
9
+
10
+ def type_cast_for_schema(value)
11
+ subnet_mask = value.instance_variable_get(:@mask_addr)
12
+
13
+ # If the subnet mask is equal to /32, don't output it
14
+ if subnet_mask == (2**32 - 1)
15
+ "\"#{value.to_s}\""
16
+ else
17
+ "\"#{value.to_s}/#{subnet_mask.to_s(2).count('1')}\""
18
+ end
19
+ end
20
+
21
+ def type_cast_for_database(value)
22
+ if IPAddr === value
23
+ "#{value.to_s}/#{value.instance_variable_get(:@mask_addr).to_s(2).count('1')}"
24
+ else
25
+ value
26
+ end
27
+ end
28
+
29
+ def cast_value(value)
30
+ if value.nil?
31
+ nil
32
+ elsif String === value
33
+ begin
34
+ IPAddr.new(value)
35
+ rescue ArgumentError
36
+ nil
37
+ end
38
+ else
39
+ value
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -5,15 +5,6 @@ module ActiveRecord
5
5
  class DateTime < Type::DateTime # :nodoc:
6
6
  include Infinity
7
7
 
8
- def type_cast_for_database(value)
9
- if has_precision? && value.acts_like?(:time) && value.year <= 0
10
- bce_year = format("%04d", -value.year + 1)
11
- super.sub(/^-?\d+/, bce_year) + " BC"
12
- else
13
- super
14
- end
15
- end
16
-
17
8
  def cast_value(value)
18
9
  if value.is_a?(::String)
19
10
  case value
@@ -0,0 +1,17 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Redshift
4
+ module OID # :nodoc:
5
+ class Enum < Type::Value # :nodoc:
6
+ def type
7
+ :enum
8
+ end
9
+
10
+ def type_cast(value)
11
+ value.to_s
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,59 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module Redshift
4
+ module OID # :nodoc:
5
+ class Hstore < Type::Value # :nodoc:
6
+ include Type::Mutable
7
+
8
+ def type
9
+ :hstore
10
+ end
11
+
12
+ def type_cast_from_database(value)
13
+ if value.is_a?(::String)
14
+ ::Hash[value.scan(HstorePair).map { |k, v|
15
+ v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
16
+ k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
17
+ [k, v]
18
+ }]
19
+ else
20
+ value
21
+ end
22
+ end
23
+
24
+ def type_cast_for_database(value)
25
+ if value.is_a?(::Hash)
26
+ value.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(', ')
27
+ else
28
+ value
29
+ end
30
+ end
31
+
32
+ def accessor
33
+ ActiveRecord::Store::StringKeyedHashAccessor
34
+ end
35
+
36
+ private
37
+
38
+ HstorePair = begin
39
+ quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
40
+ unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
41
+ /(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/
42
+ end
43
+
44
+ def escape_hstore(value)
45
+ if value.nil?
46
+ 'NULL'
47
+ else
48
+ if value == ""
49
+ '""'
50
+ else
51
+ '"%s"' % value.to_s.gsub(/(["\\])/, '\\\\\1')
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end