activerecord-jdbcvertica-adapter 0.0.7 → 0.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d8318f964be5c0fda875c96fe3c5136e02d0ff73
4
- data.tar.gz: a9ab0afc7b2d5b5e67d6f9a80362949128c21994
3
+ metadata.gz: 2411f766a5415371744b5ae088f649a194bca87d
4
+ data.tar.gz: 75538ba4703aa40da5ce94bda56da15da8adc8b2
5
5
  SHA512:
6
- metadata.gz: 190ff0e13bbb386942cac0d7d1f20ab723c6554de401da9f8f7677a12195a8f5b05446de9973a222aa002ab571e464e1389e410e1f01da0d61fecff010300c73
7
- data.tar.gz: cf0b1dacef7b49c9894c51ca33e7237df99c8cbcac3ad9c3ab7e88f74d00f0f032530c9d8d8a25042d449469d5ebf668327e50c774e6a9949045b31b217d11d7
6
+ metadata.gz: 9eeefd2cacc1262b89b2ea25d71bc5b28fd5501ef9410ec9742a025bb8f4b7e405ee6bfb83db397aa8c850b073f945deee2ae6b2b15f6f8bdd5f5b4f321f31df
7
+ data.tar.gz: ddb252641d5a599d17ba58209a0106316b9d90da5d8e77c3caaf04a07d415bc4ca1cea58feaff12b954beb3614abd219433dfd712651343bed0d8bb8add7e0ee
@@ -1,7 +1,7 @@
1
1
  module Activerecord
2
2
  module Jdbcvertica
3
3
  module Adapter
4
- VERSION = "0.0.7"
4
+ VERSION = "0.0.8"
5
5
  end
6
6
  end
7
7
  end
@@ -1,4 +1,5 @@
1
1
  require 'arjdbc/vertica/column'
2
+ require 'securerandom'
2
3
 
3
4
  # Load a mapping for the "text" type that will actually work
4
5
  ::ActiveRecord::ConnectionAdapters::JdbcTypeConverter::AR_TO_JDBC_TYPES[:text] << lambda { |r| r['type_name'] =~ /varchar$/i }
@@ -9,6 +10,26 @@ module ::ActiveRecord
9
10
  def self.sequence_name
10
11
  "#{self.table_name}_#{self.primary_key || 'id'}_seq"
11
12
  end
13
+
14
+ def self.bulk_insert(columns, data)
15
+ connection.bulk_insert(self.table_name, self.primary_key, self.sequence_name, columns, data)
16
+ end
17
+
18
+ def self.bulk_insert_records(*records)
19
+ records.flatten!
20
+ data = []
21
+ column_names_without_id = column_names.reject { |name| name == self.primary_key }
22
+
23
+ records.each do |record|
24
+ values = []
25
+ column_names_without_id.each do |column_name|
26
+ values << record.__send__("#{column_name}")
27
+ end
28
+ data << values
29
+ end
30
+
31
+ bulk_insert(column_names_without_id, data)
32
+ end
12
33
  end
13
34
  end
14
35
 
@@ -21,7 +42,7 @@ module ::ArJdbc
21
42
  INSERT_TABLE_EXTRACTION = /into\s+(?<table_name>[^\(]*).*values\s*\(/im
22
43
 
23
44
  NATIVE_DATABASE_TYPES = {
24
- :primary_key => "integer primary key",
45
+ :primary_key => "INTEGER NOT NULL PRIMARY KEY",
25
46
  :string => { :name => "varchar", :limit => 255 },
26
47
  :text => { :name => "varchar", :limit => 15000 },
27
48
  :integer => { :name => "integer" },
@@ -44,9 +65,30 @@ module ::ArJdbc
44
65
  # no op
45
66
  end
46
67
 
68
+ def bulk_insert(table_name, primary_key, sequence_name, column_names, data)
69
+ sql = "INSERT INTO #{table_name} (#{column_names.join(',')},#{primary_key || 'id'}) #{$/}"
70
+ row_count = data.size
71
+ last_index = row_count - 1
72
+ temp_table_name = vertica_random_temp_table_name
73
+ column_types = vertica_column_types_for(table_name, column_names)
74
+
75
+ sql << "SELECT #{temp_table_name}.*, #{sequence_name}.nextval FROM ("
76
+ data.each_with_index do |data_row, index|
77
+ sql << "SELECT #{vertica_bulk_insert_select_for(column_types, data_row)} "
78
+
79
+ unless index == last_index
80
+ sql << "#{$/} UNION ALL #{$/}"
81
+ end
82
+ end
83
+ sql << ") #{temp_table_name};"
84
+
85
+ execute(sql)
86
+ end
87
+
47
88
  def columns(table_name, name = nil)
48
89
  sql = "SELECT * from V_CATALOG.COLUMNS WHERE table_name = '#{table_name}';"
49
90
  raw_columns = execute(sql, name || "SCHEMA")
91
+
50
92
  columns = raw_columns.map do |raw_column|
51
93
  ::ActiveRecord::ConnectionAdapters::VerticaColumn.new(
52
94
  raw_column['column_name'],
@@ -174,6 +216,44 @@ module ::ArJdbc
174
216
  "#{table_name}_#{primary_key_name || 'id'}_seq"
175
217
  end
176
218
 
219
+ ##
220
+ # Custom Vertica methods to allow
221
+ # bulk insert operations on a db engine
222
+ # that does not support multi-insert
223
+ def vertica_bulk_insert_select_for(column_types, data_row)
224
+ insert_values = data_row.each_with_index.map do |value, index|
225
+ "#{quote(value)}::#{column_types[index]}"
226
+ end
227
+
228
+ return insert_values.join(",")
229
+ end
230
+
231
+ def vertica_column_types_for(table_name, column_names)
232
+ column_names.map { |column_name| vertica_column_type_for(table_name, column_name) }
233
+ end
234
+
235
+ def vertica_column_type_for(table_name, column_name)
236
+ column = vertica_memoized_columns(table_name).find { |column| column.name == "#{column_name}" }
237
+ return column.sql_type if column
238
+ return nil
239
+ end
240
+
241
+ def vertica_memoized_columns(table_name, name = nil)
242
+ @vertica_memoized_columns ||= {}
243
+ normalized_table_name = "#{table_name}"
244
+
245
+ unless @vertica_memoized_columns.has_key?(normalized_table_name)
246
+ @vertica_memoized_columns[normalized_table_name] = columns(table_name, name)
247
+ end
248
+
249
+ return @vertica_memoized_columns[normalized_table_name]
250
+ end
251
+
252
+ def vertica_random_temp_table_name
253
+ # Generate a Random "table_name" to prevent collisions (not sure if needed)
254
+ "temporary_table_#{::SecureRandom.hex}"
255
+ end
256
+
177
257
  end
178
258
  end
179
259
 
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ class CreateFullObject < ::ActiveRecord::Migration
4
+ def self.up
5
+ create_table :full_objects do |t|
6
+ t.string :string
7
+ t.text :text
8
+ t.integer :integer
9
+ t.float :float
10
+ t.decimal :decimal
11
+ t.datetime :datetime
12
+ t.time :time
13
+ t.date :date
14
+ t.boolean :boolean
15
+ end
16
+ end
17
+
18
+ def self.down
19
+ if table_exists?(:full_objects)
20
+ drop_table :full_objects
21
+ end
22
+ end
23
+ end
24
+
25
+ class FullObject < ::ActiveRecord::Base
26
+ end
27
+
28
+ describe ::FullObject do
29
+ before do
30
+ CreateFullObject.down
31
+ CreateFullObject.up
32
+ end
33
+
34
+ it "bulk inserts" do
35
+ ::FullObject.count.must_equal(0)
36
+ a = []
37
+ 100.times { a << ["derp"] }
38
+ ::FullObject.bulk_insert([:string], a)
39
+ ::FullObject.count.must_equal(100)
40
+ end
41
+
42
+ it "records with string" do
43
+ ::FullObject.count.must_equal(0)
44
+ a = []
45
+ 100.times { a << FullObject.new(:string => "derp") }
46
+ ::FullObject.bulk_insert_records(a)
47
+ ::FullObject.count.must_equal(100)
48
+ end
49
+
50
+ it "records with integer" do
51
+ ::FullObject.count.must_equal(0)
52
+ a = []
53
+ 100.times { a << FullObject.new(:integer => 1) }
54
+ ::FullObject.bulk_insert_records(a)
55
+ ::FullObject.count.must_equal(100)
56
+ end
57
+
58
+ it "records with DateTime" do
59
+ ::FullObject.count.must_equal(0)
60
+ a = []
61
+ 100.times { a << FullObject.new(:datetime => Time.current) }
62
+ ::FullObject.bulk_insert_records(a)
63
+ ::FullObject.count.must_equal(100)
64
+ end
65
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-jdbcvertica-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Dewitt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-10 00:00:00.000000000 Z
11
+ date: 2014-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -120,6 +120,7 @@ files:
120
120
  - lib/arjdbc/vertica/column.rb
121
121
  - lib/arjdbc/vertica/connection_methods.rb
122
122
  - lib/tasks/vertica_database_tasks.rake
123
+ - spec/bulk_insert_spec.rb
123
124
  - spec/full_object_spec.rb
124
125
  - spec/migrations/column_spec.rb
125
126
  - spec/migrations/index_spec.rb
@@ -150,6 +151,7 @@ signing_key:
150
151
  specification_version: 4
151
152
  summary: An ActiveRecord adapter JDBC
152
153
  test_files:
154
+ - spec/bulk_insert_spec.rb
153
155
  - spec/full_object_spec.rb
154
156
  - spec/migrations/column_spec.rb
155
157
  - spec/migrations/index_spec.rb