activerecord-redshift-adapter 0.9.1 → 0.9.3

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 CHANGED
@@ -33,6 +33,7 @@ redshift_development:
33
33
  ```
34
34
 
35
35
  ## options
36
+ ```html
36
37
  <table>
37
38
  <tr>
38
39
  <th>option</th>
@@ -47,3 +48,54 @@ redshift_development:
47
48
  <td>force timezone for datetime when select values. ActiveRecord default timezone will set if not given.</td>
48
49
  </tr>
49
50
  </table>
51
+ ```
52
+
53
+ ## TableManager
54
+
55
+ Helpful code to clone redshift tables
56
+
57
+ ```sql
58
+ create table foos
59
+ (
60
+ id int not null primary key distkey,
61
+ name varchar(255) unique sortkey
62
+ );
63
+ ```
64
+
65
+ ```ruby
66
+ class Foo < ActiveRecord::Base
67
+ end
68
+
69
+ require 'activerecord_redshift_adapter'
70
+
71
+ table_manager = ActiverecordRedshift::TableManager.new(Foo.connection, :exemplar_table_name => Foo.table_name)
72
+ table_manager.duplicate_table
73
+ ```
74
+
75
+ yields:
76
+
77
+ ```sql
78
+ select oid from pg_namespace where nspname = 'public' limit 1;
79
+
80
+ select oid,reldiststyle from pg_class where relnamespace = 2200 and relname = 'foos' limit 1;
81
+
82
+ select contype,conkey from pg_constraint where connamespace = 2200 and conrelid = 212591;
83
+
84
+ select attname,attnum from pg_attribute where attrelid = 212591 and attnum in (2,1);
85
+
86
+ show search_path;
87
+
88
+ set search_path = 'public';
89
+
90
+ select * from pg_table_def where tablename = 'foos' and schemaname = 'public';
91
+
92
+ create temporary table temporary_events_25343
93
+ (
94
+ id integer not null distkey,
95
+ name character varying(255),
96
+ primary key (id),
97
+ unique (name)
98
+ ) sortkey (name);
99
+
100
+ set search_path = '$user','public';
101
+ ```
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
7
7
  s.name = 'activerecord-redshift-adapter'
8
8
  s.version = ActiverecordRedshiftAdapter::VERSION
9
9
  s.license = 'New BSD License'
10
- s.date = '2013-03-23'
10
+ s.date = '2013-09-17'
11
11
  s.summary = "Rails 3 database adapter support for AWS RedShift."
12
12
  s.description = "This gem provides the Rails 3 with database adapter for AWS RedShift."
13
13
  s.authors = ["Keith Gabryelski"]
@@ -249,7 +249,7 @@ module ActiveRecord
249
249
  ADAPTER_NAME = 'Redshift'
250
250
 
251
251
  NATIVE_DATABASE_TYPES = {
252
- :primary_key => "serial primary key",
252
+ :primary_key => "bigint primary key",
253
253
  :string => { :name => "character varying", :limit => 255 },
254
254
  :text => { :name => "text" },
255
255
  :integer => { :name => "integer" },
@@ -413,7 +413,7 @@ module ActiveRecord
413
413
  end
414
414
 
415
415
  def supports_insert_with_returning?
416
- true
416
+ false
417
417
  end
418
418
 
419
419
  def supports_ddl_transactions?
@@ -538,7 +538,7 @@ module ActiveRecord
538
538
  # REFERENTIAL INTEGRITY ====================================
539
539
 
540
540
  def supports_disable_referential_integrity? #:nodoc:
541
- true
541
+ false
542
542
  end
543
543
 
544
544
  def disable_referential_integrity #:nodoc:
@@ -609,9 +609,12 @@ module ActiveRecord
609
609
  table_ref = extract_table_ref_from_insert_sql(sql)
610
610
  pk = primary_key(table_ref) if table_ref
611
611
  end
612
-
613
- if pk
612
+
613
+ if pk && use_insert_returning?
614
614
  select_value("#{sql} RETURNING #{quote_column_name(pk)}")
615
+ elsif pk
616
+ super
617
+ last_insert_id_value(sequence_name || default_sequence_name(table_ref, pk))
615
618
  else
616
619
  super
617
620
  end
@@ -709,7 +712,7 @@ module ActiveRecord
709
712
  pk = primary_key(table_ref) if table_ref
710
713
  end
711
714
 
712
- sql = "#{sql} RETURNING #{quote_column_name(pk)}" if pk
715
+ sql = "#{sql} RETURNING #{quote_column_name(pk)}" if pk && use_insert_returning?
713
716
 
714
717
  [sql, binds]
715
718
  end
@@ -0,0 +1,218 @@
1
+ module ActiverecordRedshift
2
+ class TableManager
3
+ attr_reader :default_options
4
+
5
+ DEFAULT_OPTIONS = { :exemplar_table_name => nil, :add_identity => false, :temporary => true}
6
+
7
+ def initialize(connection, default_options = {})
8
+ @connection = connection
9
+ table_name_options = {}
10
+ if default_options[:partitioned_model]
11
+ model = default_options[:partitioned_model]
12
+ default_options[:exemplar_table_name] = model.table_name
13
+ default_options[:schema_name] = model.configurator.schema_name
14
+ end
15
+
16
+ if default_options[:table_name].blank?
17
+ connection_pid = @connection.execute("select pg_backend_pid() as pid").first['pid'].to_i
18
+ table_name_options[:table_name] = "temporary_events_#{connection_pid}"
19
+ end
20
+ @default_options = DEFAULT_OPTIONS.merge(table_name_options).merge(default_options)
21
+ end
22
+
23
+ def partitioned_model
24
+ return @default_options[:partitioned_model]
25
+ end
26
+
27
+ def schema_name
28
+ return @default_options[:schema_name]
29
+ end
30
+
31
+ def exemplar_table_name
32
+ return @default_options[:exemplar_table_name]
33
+ end
34
+
35
+ def add_identity
36
+ return @default_options[:add_identity]
37
+ end
38
+
39
+ def temporary
40
+ return @default_options[:temporary]
41
+ end
42
+
43
+ def base_table_name
44
+ return @default_options[:table_name]
45
+ end
46
+
47
+ def table_name
48
+ if schema_name.blank?
49
+ return base_table_name
50
+ end
51
+ return "#{schema_name}.#{base_table_name}"
52
+ end
53
+
54
+ def drop_table
55
+ @connection.execute("drop table #{table_name}")
56
+ end
57
+
58
+ def duplicate_table(options = {})
59
+ current_options = @default_options.merge(options)
60
+ target_table_name = current_options[:table_name]
61
+ raise "target_table_name not set" if target_table_name.blank?
62
+ exemplar_table_name = current_options[:exemplar_table_name]
63
+ raise "exemplar_table_name not set" if exemplar_table_name.blank?
64
+ table_name_elements = exemplar_table_name.split('.');
65
+ if table_name_elements.length == 1
66
+ table_name_elements.unshift("public")
67
+ end
68
+ schema_name = table_name_elements[0]
69
+ parent_table_name = table_name_elements[1]
70
+
71
+ # first find the diststyle
72
+ ## namespace first
73
+ sql = "select oid from pg_namespace where nspname = '#{schema_name}' limit 1"
74
+ schema_oid = @connection.execute(sql).first['oid'].to_i
75
+
76
+ ## now the diststyle 0 = even, 1 = some column
77
+ sql = "select oid,reldiststyle from pg_class where relnamespace = #{schema_oid} and relname = '#{parent_table_name}' limit 1"
78
+ pg_class_row = @connection.execute(sql).first
79
+ reldiststyle = pg_class_row['reldiststyle'].to_i
80
+ even_diststyle = (reldiststyle == 0)
81
+ table_oid = pg_class_row['oid'].to_i
82
+
83
+ ## get unique and primary key constraints (pg_constraints)
84
+ sql = "select contype,conkey from pg_constraint where connamespace = #{schema_oid} and conrelid = #{table_oid}"
85
+ primary_key = nil
86
+ uniques = []
87
+ @connection.execute(sql).each do |row|
88
+ if row['contype'] == 'p'
89
+ # primary key
90
+ primary_key = row['conkey'][1..-2].split(',')
91
+ elsif row['contype'] == 'u'
92
+ # unique
93
+ uniques << row['conkey'][1..-2].split(',')
94
+ end
95
+ end
96
+
97
+ attnums = uniques.clone
98
+ unless primary_key.blank?
99
+ attnums << primary_key
100
+ end
101
+ attnums = attnums.flatten.uniq
102
+
103
+ sql = "select attname,attnum from pg_attribute where attrelid = #{table_oid} and attnum in (#{attnums.join(',')})"
104
+ column_names = {}
105
+ @connection.execute(sql).each do |row|
106
+ column_names[row['attnum']] = row['attname']
107
+ end
108
+
109
+ with_search_path([schema_name]) do
110
+ # select * from pg_table_def where tablename = 'bids' and schemaname = 'public';
111
+ ## column, type, encoding, distkey, sortkey, not null
112
+ sortkeys = []
113
+ sql_columns = []
114
+
115
+ if current_options[:add_identity]
116
+ sql_columns << "_identity bigint identity"
117
+ end
118
+
119
+ sql = "select * from pg_table_def where tablename = '#{parent_table_name}' and schemaname = '#{schema_name}'"
120
+ sql_column_rows = @connection.execute(sql)
121
+ sql_column_rows.each do |row|
122
+ column_info = []
123
+ column_name = row['column']
124
+ column_info << column_name
125
+ column_info << row['type']
126
+ if row['notnull'] == "t"
127
+ column_info << "not null"
128
+ end
129
+ if row['distkey'] == "t"
130
+ column_info << "distkey"
131
+ end
132
+ if row['encoding'] != 'none'
133
+ column_info << "encode #{row['encoding']}"
134
+ end
135
+ if row['sortkey'] != "0"
136
+ sortkeys[row['sortkey'].to_i - 1] = column_name
137
+ end
138
+ sql_columns << column_info.join(" ")
139
+ end
140
+
141
+ unless primary_key.blank?
142
+ sql_columns << "primary key (#{primary_key.map{|pk| column_names[pk]}.join(',')})"
143
+ end
144
+
145
+ uniques.each do |unique|
146
+ sql_columns << "unique (#{unique.map{|uk| column_names[uk]}.join(',')})"
147
+ end
148
+
149
+ if sortkeys.blank?
150
+ sql_sortkeys = ""
151
+ else
152
+ sql_sortkeys = " sortkey (#{sortkeys.join(',')})"
153
+ end
154
+ sql = <<-SQL
155
+ create #{"temporary " if current_options[:temporary]}table #{table_name}
156
+ (
157
+ #{sql_columns.join(', ')}
158
+ ) #{"diststyle even " if even_diststyle}#{sql_sortkeys}
159
+ SQL
160
+ @connection.execute(sql)
161
+ end
162
+ end
163
+
164
+ def table_def(table_name)
165
+ table_parts = table_name.split('.')
166
+ if table_parts.length == 1
167
+ name = table_parts.first
168
+ search_path = ["public"]
169
+ else
170
+ name = table_parts.last
171
+ search_path = [table_parts.first]
172
+ end
173
+
174
+ with_search_path(search_path) do
175
+ return @connection.execute("select * from pg_table_def where tablename = '#{name}'").to_a
176
+ end
177
+ end
178
+
179
+ # search_path = array
180
+ # modes: :prefix, :suffix, :replace
181
+ def with_search_path(search_path, mode = :replace, &block)
182
+ unless search_path.is_a? Array
183
+ raise "search_path must be an Array"
184
+ end
185
+
186
+ old_search_path = get_search_path
187
+ if mode == :prefix
188
+ new_search_path = search_path + old_search_path
189
+ elsif mode == :suffix
190
+ new_search_path = old_search_path + search_path
191
+ elsif mode == :replace
192
+ new_search_path = search_path
193
+ else
194
+ raise "mode must be :prefix, :suffix, :replace"
195
+ end
196
+
197
+ set_search_path(new_search_path)
198
+ begin
199
+ yield
200
+ ensure
201
+ set_search_path(old_search_path)
202
+ end
203
+ end
204
+
205
+ def get_search_path
206
+ return @connection.execute("show search_path").to_a.first["search_path"].split(',').map{|p| p.delete('" ')}
207
+ end
208
+
209
+ def set_search_path(search_path)
210
+ unless search_path.is_a? Array
211
+ raise "search_path must be an Array"
212
+ end
213
+ quoted_search_path = search_path.map{|sp| "'#{sp}'"}.join(',')
214
+ @connection.execute("set search_path = #{quoted_search_path}")
215
+ end
216
+
217
+ end
218
+ end
@@ -1 +1,4 @@
1
1
  require 'activerecord_redshift_adapter/version'
2
+ require 'activerecord_redshift/table_manager'
3
+ require 'monkeypatch_activerecord'
4
+ require 'monkeypatch_arel'
@@ -1,4 +1,4 @@
1
1
  module ActiverecordRedshiftAdapter
2
2
  # the current version of this gem
3
- VERSION = "0.9.1"
3
+ VERSION = "0.9.3"
4
4
  end
@@ -0,0 +1,195 @@
1
+ module ActiveRecord
2
+ module Querying
3
+ delegate :unload, :copy, :to => :scoped
4
+ end
5
+ end
6
+
7
+ module ActiveRecord::QueryMethods
8
+ module CopyUnloadParser
9
+ def self.parse_options(options, options_hash, valid_switches, valid_options, valid_unquoted_options, valid_special_options)
10
+ # credentials first
11
+ credentials = nil
12
+ if options_hash.has_key?(:credentials)
13
+ credentials = options_hash[:credentials]
14
+ else
15
+ creds = {}
16
+ creds[:aws_access_key_id] = options_hash[:aws_access_key_id] if options_hash.has_key?(:aws_access_key_id)
17
+ creds[:aws_secret_access_key] = options_hash[:aws_secret_access_key] if options_hash.has_key?(:aws_secret_access_key)
18
+ creds[:token] = options_hash[:token] if options_hash.has_key?(:token)
19
+ creds[:master_symmetric_key] = options_hash[:master_symmetric_key] if options_hash.has_key?(:master_symmetric_key)
20
+ credentials = creds.map{|k,v| "#{k}=#{v}"}.join(';')
21
+ end
22
+
23
+ option_list = []
24
+ option_list << "WITH CREDENTIALS AS #{connection.quote_value(credentials)}" unless credentials.blank?
25
+
26
+ valid_switches.each do |switch_name|
27
+ if options.include? switch_name
28
+ option_list << switch_name.to_s.upcase
29
+ end
30
+ end
31
+
32
+ valid_options.each do |option_name|
33
+ if options_hash.has_key? option_name
34
+ option_list << "#{option_name.to_s.upcase} AS #{connection.quote_value(options_hash[option_name])}"
35
+ end
36
+ end
37
+
38
+ valid_unquoted_options.each do |option_name|
39
+ if options_hash.has_key? option_name
40
+ option_list << "#{option_name.to_s.upcase} #{options_hash[option_name]}"
41
+ end
42
+ end
43
+
44
+ return credentials, option_list
45
+ end
46
+ end
47
+ end
48
+
49
+ module ActiveRecord
50
+ module QueryMethods
51
+ # UNLOAD ('select_statement')
52
+ # TO 's3_path'
53
+ # [ WITH ] CREDENTIALS [AS] 'aws_access_credentials'
54
+ # [ option [ ... ] ]
55
+ #
56
+ # where option is
57
+ #
58
+ # { DELIMITER [ AS ] 'delimiter_char'
59
+ # | FIXEDWIDTH [ AS ] 'fixedwidth_spec' }
60
+ # | ENCRYPTED
61
+ # | GZIP
62
+ # | ADDQUOTES
63
+ # | NULL [ AS ] 'null_string'
64
+ # | ESCAPE
65
+ # | ALLOWOVERWRITE
66
+ VALID_UNLOAD_SWITCHES = [
67
+ :gzip,
68
+ :addquotes,
69
+ :escape,
70
+ :allowoverwrite
71
+ ]
72
+ VALID_UNLOAD_OPTIONS = [
73
+ :delimiter,
74
+ :fixedwidth,
75
+ :null
76
+ ]
77
+ VALID_UNQUOTED_UNLOAD_OPTIONS = [ ]
78
+ VALID_SPECIAL_UNLOAD_OPTIONS = [
79
+ :credentials,
80
+ :aws_access_key_id,
81
+ :aws_secret_access_key,
82
+ :master_symmetric_key,
83
+ :token
84
+ ]
85
+
86
+ def unload(to_s3_filename, *options)
87
+ if options.last.is_a? Hash
88
+ options_hash = options.last
89
+ else
90
+ options_hash = {}
91
+ end
92
+
93
+ credentials, unload_options =
94
+ ActiveRecord::QueryMethods::CopyUnloadParser.parse_options(options, options_hash,
95
+ VALID_UNLOAD_SWITCHES, VALID_UNLOAD_OPTIONS, VALID_UNQUOTED_UNLOAD_OPTIONS, VALID_SPECIAL_UNLOAD_OPTIONS)
96
+
97
+
98
+ relation = Arel::Nodes::UnloadStatement.new(Arel::Nodes::Unload.new(Arel::Nodes::Relation.new(clone), to_s3_filename), unload_options.join(" "))
99
+ relation
100
+ end
101
+
102
+ VALID_COPY_SWITCHES = [
103
+ :encrypted,
104
+ :gzip,
105
+ :removequotes,
106
+ :explicit_ids,
107
+ :escape,
108
+ :acceptanydate,
109
+ :ignoreblanklines,
110
+ :truncatecolumns,
111
+ :fillrecord,
112
+ :trimblanks,
113
+ :noload,
114
+ :emptyasnull,
115
+ :blanksasnull,
116
+ :escape,
117
+ :roundec
118
+ ]
119
+ VALID_COPY_OPTIONS = [
120
+ :delimiter,
121
+ :fixedwidth,
122
+ :csv,
123
+ :acceptinvchars,
124
+ :dateformat,
125
+ :timeformat,
126
+ :null
127
+ ]
128
+
129
+ VALID_UNQUOTED_COPY_OPTIONS = [
130
+ :maxerror,
131
+ :ignoreheader,
132
+ :comprows,
133
+ :compupdate,
134
+ :statupdate
135
+ ]
136
+
137
+ VALID_SPECIAL_COPY_OPTIONS = [
138
+ :credentials,
139
+ :aws_access_key_id,
140
+ :aws_secret_access_key,
141
+ :master_symmetric_key,
142
+ :token
143
+ ]
144
+
145
+ # COPY table_name [ (column1 [,column2, ...]) ]
146
+ # FROM 's3://objectpath'
147
+ # [ WITH ] CREDENTIALS [AS] 'aws_access_credentials'
148
+ # [ option [ ... ] ]
149
+
150
+ # where option is
151
+
152
+ # { FIXEDWIDTH 'fixedwidth_spec'
153
+ # | [DELIMITER [ AS ] 'delimiter_char']
154
+ # [CSV [QUOTE [ AS ] 'quote_character']}
155
+
156
+ # | ENCRYPTED
157
+ # | GZIP
158
+ # | REMOVEQUOTES
159
+ # | EXPLICIT_IDS
160
+
161
+ # | ACCEPTINVCHARS [ AS ] ['replacement_char']
162
+ # | MAXERROR [ AS ] error_count
163
+ # | DATEFORMAT [ AS ] { 'dateformat_string' | 'auto' }
164
+ # | TIMEFORMAT [ AS ] { 'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
165
+ # | IGNOREHEADER [ AS ] number_rows
166
+ # | ACCEPTANYDATE
167
+ # | IGNOREBLANKLINES
168
+ # | TRUNCATECOLUMNS
169
+ # | FILLRECORD
170
+ # | TRIMBLANKS
171
+ # | NOLOAD
172
+ # | NULL [ AS ] 'null_string'
173
+ # | EMPTYASNULL
174
+ # | BLANKSASNULL
175
+ # | COMPROWS numrows
176
+ # | COMPUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
177
+ # | STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
178
+ # | ESCAPE
179
+ # | ROUNDEC
180
+ def copy(to_s3_filename, *options)
181
+ if options.last.is_a? Hash
182
+ options_hash = options.last
183
+ else
184
+ options_hash = {}
185
+ end
186
+
187
+ credentials, copy_options =
188
+ ::ActiveRecord::QueryMethods::CopyUnloadParser.parse_options(options, options_hash,
189
+ VALID_COPY_SWITCHES, VALID_COPY_OPTIONS, VALID_UNQUOTED_COPY_OPTIONS, VALID_SPECIAL_COPY_OPTIONS)
190
+
191
+
192
+ conncection.execute(Arel::Nodes::CopyStatement.new(Arel::Nodes::Copy.new(table_name, to_s3_filename), copy_options.join(" ")).to_sql)
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,96 @@
1
+ module Arel
2
+ module Nodes
3
+ class Relation < Arel::Nodes::Unary
4
+ end
5
+
6
+ class Unload < Arel::Nodes::Binary
7
+ alias :statement :left
8
+ alias :statement= :left=
9
+ alias :to :right
10
+ alias :to= :right=
11
+ def initialize statement = nil, to = nil
12
+ super
13
+ end
14
+
15
+ def initialize_copy other
16
+ super
17
+ @right = @right.clone
18
+ end
19
+ end
20
+
21
+ class UnloadStatement < Arel::Nodes::Binary
22
+ alias :relation :left
23
+ alias :relation= :left=
24
+ alias :options :right
25
+ alias :options= :right=
26
+
27
+ def initialize relation = nil, options = []
28
+ super
29
+ end
30
+
31
+ def initialize_copy other
32
+ super
33
+ @right = @right.clone
34
+ end
35
+ end
36
+
37
+ class Copy < Arel::Nodes::Binary
38
+ alias :statement :left
39
+ alias :statement= :left=
40
+ alias :from :right
41
+ alias :from= :right=
42
+ def initialize statement = nil, from = nil
43
+ super
44
+ end
45
+
46
+ def initialize_copy other
47
+ super
48
+ @right = @right.clone
49
+ end
50
+ end
51
+
52
+ class CopyStatement < Arel::Nodes::Binary
53
+ alias :relation :left
54
+ alias :relation= :left=
55
+ alias :options :right
56
+ alias :options= :right=
57
+
58
+ def initialize relation = nil, options = []
59
+ super
60
+ end
61
+
62
+ def initialize_copy other
63
+ super
64
+ @right = @right.clone
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+
71
+ module Arel
72
+ module Visitors
73
+ class ToSql < Arel::Visitors::Visitor
74
+
75
+ def visit_Arel_Nodes_UnloadStatement o
76
+ "#{visit o.relation} #{o.options}"
77
+ end
78
+
79
+ def visit_Arel_Nodes_Unload o
80
+ "UNLOAD (#{visit o.statement}) TO #{visit o.to}"
81
+ end
82
+
83
+ def visit_Arel_Nodes_CopyStatement o
84
+ "#{visit o.relation} #{o.options}"
85
+ end
86
+
87
+ def visit_Arel_Nodes_Copy o
88
+ "COPY #{o.statement} FROM #{visit o.from}"
89
+ end
90
+
91
+ def visit_Arel_Nodes_Relation o
92
+ visit o.expr.to_sql
93
+ end
94
+ end
95
+ end
96
+ end
@@ -5,6 +5,8 @@ port: 5432
5
5
  username: test_user
6
6
  password: test_password
7
7
  database: dev
8
+ #As RedShift does not support RETURNING keyword yet
9
+ use_insert_returning: false
8
10
  # ssl: true
9
11
  # search_path:
10
12
  # role:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-redshift-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-23 00:00:00.000000000 Z
12
+ date: 2013-09-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pg
@@ -72,8 +72,11 @@ files:
72
72
  - Rakefile
73
73
  - activerecord-redshift-adapter.gemspec
74
74
  - lib/active_record/connection_adapters/redshift_adapter.rb
75
+ - lib/activerecord_redshift/table_manager.rb
75
76
  - lib/activerecord_redshift_adapter.rb
76
77
  - lib/activerecord_redshift_adapter/version.rb
78
+ - lib/monkeypatch_activerecord.rb
79
+ - lib/monkeypatch_arel.rb
77
80
  - spec/active_record/base_spec.rb
78
81
  - spec/active_record/connection_adapters/redshift_adapter_spec.rb
79
82
  - spec/dummy/config/database.example.yml
@@ -99,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
102
  version: '0'
100
103
  requirements: []
101
104
  rubyforge_project:
102
- rubygems_version: 1.8.25
105
+ rubygems_version: 1.8.24
103
106
  signing_key:
104
107
  specification_version: 3
105
108
  summary: Rails 3 database adapter support for AWS RedShift.