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 +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
|