activerecord-jdbcvertica-adapter 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/activerecord-jdbcvertica-adapter/version.rb +1 -1
- data/lib/arjdbc/vertica/adapter.rb +81 -1
- data/spec/bulk_insert_spec.rb +65 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2411f766a5415371744b5ae088f649a194bca87d
|
4
|
+
data.tar.gz: 75538ba4703aa40da5ce94bda56da15da8adc8b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9eeefd2cacc1262b89b2ea25d71bc5b28fd5501ef9410ec9742a025bb8f4b7e405ee6bfb83db397aa8c850b073f945deee2ae6b2b15f6f8bdd5f5b4f321f31df
|
7
|
+
data.tar.gz: ddb252641d5a599d17ba58209a0106316b9d90da5d8e77c3caaf04a07d415bc4ca1cea58feaff12b954beb3614abd219433dfd712651343bed0d8bb8add7e0ee
|
@@ -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 => "
|
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.
|
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-
|
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
|