upsert 0.1.2 → 0.2.0
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/.gitignore +1 -0
- data/README.md +14 -10
- data/Rakefile +1 -1
- data/lib/upsert.rb +95 -10
- data/lib/upsert/active_record_upsert.rb +12 -0
- data/lib/upsert/mysql2_client.rb +160 -0
- data/lib/upsert/pg_connection.rb +84 -0
- data/lib/upsert/pg_connection/column_definition.rb +60 -0
- data/lib/upsert/row.rb +8 -8
- data/lib/upsert/sqlite3_database.rb +39 -0
- data/lib/upsert/version.rb +1 -1
- data/test/misc/get_postgres_reserved_words.rb +12 -0
- data/test/misc/mysql_reserved.txt +226 -0
- data/test/misc/pg_reserved.txt +742 -0
- data/test/shared/multibyte.rb +2 -2
- data/test/shared/reserved_words.rb +41 -0
- data/test/test_active_record_upsert.rb +23 -0
- data/test/test_mysql2.rb +2 -0
- data/test/test_pg.rb +2 -0
- data/test/test_sqlite.rb +14 -11
- metadata +17 -8
- data/lib/upsert/buffer.rb +0 -58
- data/lib/upsert/buffer/mysql2_client.rb +0 -164
- data/lib/upsert/buffer/pg_connection.rb +0 -87
- data/lib/upsert/buffer/pg_connection/column_definition.rb +0 -60
- data/lib/upsert/buffer/sqlite3_database.rb +0 -43
- data/lib/upsert/quoter.rb +0 -43
@@ -1,60 +0,0 @@
|
|
1
|
-
class Upsert
|
2
|
-
class Buffer
|
3
|
-
class PG_Connection < Buffer
|
4
|
-
# @private
|
5
|
-
# activerecord-3.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb#column_definitions
|
6
|
-
class ColumnDefinition
|
7
|
-
class << self
|
8
|
-
def auto_increment_primary_key(connection, table_name)
|
9
|
-
res = connection.exec <<-EOS
|
10
|
-
SELECT attr.attname, seq.relname
|
11
|
-
FROM pg_class seq,
|
12
|
-
pg_attribute attr,
|
13
|
-
pg_depend dep,
|
14
|
-
pg_namespace name,
|
15
|
-
pg_constraint cons
|
16
|
-
WHERE seq.oid = dep.objid
|
17
|
-
AND seq.relkind = 'S'
|
18
|
-
AND attr.attrelid = dep.refobjid
|
19
|
-
AND attr.attnum = dep.refobjsubid
|
20
|
-
AND attr.attrelid = cons.conrelid
|
21
|
-
AND attr.attnum = cons.conkey[1]
|
22
|
-
AND cons.contype = 'p'
|
23
|
-
AND dep.refobjid = '#{connection.quote_ident(table_name.to_s)}'::regclass
|
24
|
-
EOS
|
25
|
-
if hit = res.first
|
26
|
-
hit['attname']
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def all(connection, table_name)
|
31
|
-
auto_increment_primary_key = auto_increment_primary_key(connection, table_name)
|
32
|
-
res = connection.exec <<-EOS
|
33
|
-
SELECT a.attname AS name, format_type(a.atttypid, a.atttypmod) AS sql_type, d.adsrc AS default
|
34
|
-
FROM pg_attribute a LEFT JOIN pg_attrdef d
|
35
|
-
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
|
36
|
-
WHERE a.attrelid = '#{connection.quote_ident(table_name.to_s)}'::regclass
|
37
|
-
AND a.attnum > 0 AND NOT a.attisdropped
|
38
|
-
ORDER BY a.attnum
|
39
|
-
EOS
|
40
|
-
res.reject do |row|
|
41
|
-
row['name'] == auto_increment_primary_key
|
42
|
-
end.map do |row|
|
43
|
-
new row['name'], row['sql_type'], row['default']
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
attr_reader :name
|
49
|
-
attr_reader :sql_type
|
50
|
-
attr_reader :default
|
51
|
-
|
52
|
-
def initialize(name, sql_type, default)
|
53
|
-
@name = name
|
54
|
-
@sql_type = sql_type
|
55
|
-
@default = default
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
class Upsert
|
2
|
-
class Buffer
|
3
|
-
# @private
|
4
|
-
class SQLite3_Database < Buffer
|
5
|
-
include Quoter
|
6
|
-
|
7
|
-
def chunk
|
8
|
-
return if rows.empty?
|
9
|
-
row = rows.shift
|
10
|
-
%{INSERT OR IGNORE INTO "#{table_name}" (#{row.columns_sql}) VALUES (#{row.values_sql});UPDATE "#{table_name}" SET #{row.set_sql} WHERE #{row.where_sql}}
|
11
|
-
end
|
12
|
-
|
13
|
-
def execute(sql)
|
14
|
-
connection.execute_batch sql
|
15
|
-
end
|
16
|
-
|
17
|
-
def quote_string(v)
|
18
|
-
SINGLE_QUOTE + SQLite3::Database.quote(v) + SINGLE_QUOTE
|
19
|
-
end
|
20
|
-
|
21
|
-
def quote_binary(v)
|
22
|
-
X_AND_SINGLE_QUOTE + v.unpack("H*")[0] + SINGLE_QUOTE
|
23
|
-
end
|
24
|
-
|
25
|
-
def quote_time(v)
|
26
|
-
quote_string [v.strftime(ISO8601_DATETIME), sprintf(USEC_SPRINTF, v.usec)].join('.')
|
27
|
-
end
|
28
|
-
|
29
|
-
def quote_ident(k)
|
30
|
-
DOUBLE_QUOTE + SQLite3::Database.quote(k.to_s) + DOUBLE_QUOTE
|
31
|
-
end
|
32
|
-
|
33
|
-
def quote_boolean(v)
|
34
|
-
s = v ? 't' : 'f'
|
35
|
-
quote_string s
|
36
|
-
end
|
37
|
-
|
38
|
-
def quote_big_decimal(v)
|
39
|
-
v.to_f
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
data/lib/upsert/quoter.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
class Upsert
|
2
|
-
# @private
|
3
|
-
module Quoter
|
4
|
-
ISO8601_DATE = '%F'
|
5
|
-
|
6
|
-
def quote_value(v)
|
7
|
-
case v
|
8
|
-
when NilClass
|
9
|
-
'NULL'
|
10
|
-
when Upsert::Binary
|
11
|
-
quote_binary v # must be defined by base
|
12
|
-
when String
|
13
|
-
quote_string v # must be defined by base
|
14
|
-
when TrueClass, FalseClass
|
15
|
-
quote_boolean v
|
16
|
-
when BigDecimal
|
17
|
-
quote_big_decimal v
|
18
|
-
when Numeric
|
19
|
-
v
|
20
|
-
when Symbol
|
21
|
-
quote_string v.to_s
|
22
|
-
when Time, DateTime
|
23
|
-
quote_time v # must be defined by base
|
24
|
-
when Date
|
25
|
-
quote_string v.strftime(ISO8601_DATE)
|
26
|
-
else
|
27
|
-
raise "not sure how to quote #{v.class}: #{v.inspect}"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def quote_idents(idents)
|
32
|
-
idents.map { |k| quote_ident(k) }.join(',') # must be defined by base
|
33
|
-
end
|
34
|
-
|
35
|
-
def quote_values(values)
|
36
|
-
values.map { |v| quote_value(v) }.join(',')
|
37
|
-
end
|
38
|
-
|
39
|
-
def quote_pairs(pairs)
|
40
|
-
pairs.map { |k, v| [quote_ident(k),quote_value(v)].join('=') }.join(',')
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|