flydata 0.3.9 → 0.3.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/flydata-core/lib/flydata-core/errors.rb +23 -3
- data/flydata-core/lib/flydata-core/fluent-plugins/multi_buffer.rb +8 -0
- data/flydata-core/lib/flydata-core/logger.rb +39 -7
- data/flydata-core/lib/flydata-core/table_def/mysql_table_def.rb +1 -0
- data/flydata-core/lib/flydata-core/table_def/redshift_table_def.rb +31 -14
- data/flydata-core/spec/table_def/mysql_table_def_spec.rb +8 -1
- data/flydata-core/spec/table_def/mysql_to_redshift_table_def_spec.rb +27 -21
- data/flydata-core/spec/table_def/mysqldump_test_table_all.dump +3 -0
- data/flydata-core/spec/table_def/redshift_table_def_spec.rb +107 -6
- data/flydata.gemspec +5 -4
- data/lib/flydata/command/sync.rb +6 -3
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 478d29c0767a534808dea15674528d5b5442bbed
|
4
|
+
data.tar.gz: c6536fb66fedffbdcc52069cb28f32f74fe3465d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b97f3acc0e763fcff4f2d4a18dcc4d9625d736db229b00554aee36da0ff8e68a189324a46abb3d985dfd1e2d4964ec6963a9299d475170e759485cb1e07faec
|
7
|
+
data.tar.gz: fdee03e1c1bf32699f8c5157aa51f48ecf6f1c023d2160a63b996ca7ac0599fa952de02b55045715b4a66283083b204860201a31a157b9cbf92d2413aebc77d5
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.10
|
@@ -51,6 +51,7 @@ end
|
|
51
51
|
# RetryableError
|
52
52
|
|
53
53
|
class RetryableError < StandardError
|
54
|
+
NO_RETRY_LIMIT = :no_retry_limit
|
54
55
|
def initialize(original_exception, retry_alert_limit = nil)
|
55
56
|
@original_exception = original_exception
|
56
57
|
@retry_alert_limit = retry_alert_limit
|
@@ -59,10 +60,20 @@ class RetryableError < StandardError
|
|
59
60
|
attr_reader :retry_alert_limit
|
60
61
|
end
|
61
62
|
|
62
|
-
#
|
63
|
+
# UserMaintenanceError
|
64
|
+
|
65
|
+
class UserMaintenanceError < StandardError
|
66
|
+
end
|
67
|
+
|
68
|
+
# An error that indicates that sync record was received for a table whose sync is broken
|
69
|
+
# These records cannot be retried, should be ignored
|
70
|
+
class BrokenTableSyncError < StandardError
|
71
|
+
end
|
72
|
+
|
73
|
+
# FlyDataError
|
63
74
|
# data_node_id, data_entry_id, chunk_identifier, table_name, err_code, err_reason, err_level
|
64
75
|
|
65
|
-
class
|
76
|
+
class FlydataError < StandardError
|
66
77
|
def initialize(error_reason, error_content = {})
|
67
78
|
error_content = if error_reason.kind_of?(String)
|
68
79
|
{ err_reason: error_reason}.merge(error_content)
|
@@ -125,6 +136,14 @@ class DataDeliveryError < StandardError
|
|
125
136
|
end
|
126
137
|
end
|
127
138
|
|
139
|
+
# DataDeliveryError
|
140
|
+
# An error which results in data clog or loss of information.
|
141
|
+
# This type of error gets reported to customer as data delivery error.
|
142
|
+
# data_node_id, data_entry_id, chunk_identifier, table_name, err_code, err_reason, err_level
|
143
|
+
|
144
|
+
class DataDeliveryError < FlydataError
|
145
|
+
end
|
146
|
+
|
128
147
|
# + RecordDeliveryError
|
129
148
|
# data_node_id, data_entry_id, chunk_identifier, table_name, err_code, err_reason, err_level, record_no, raw_record
|
130
149
|
|
@@ -174,7 +193,8 @@ class TableRevisionError < RecordDeliveryError
|
|
174
193
|
end
|
175
194
|
|
176
195
|
# Table's revision is lower than the record's revision. Should catch up soon.
|
177
|
-
class StaleTableRevisionError <
|
196
|
+
class StaleTableRevisionError < FlydataError
|
197
|
+
def err_code; ErrorCode::TABLE_REVISION_ERROR; end
|
178
198
|
end
|
179
199
|
|
180
200
|
# Unsupported ALTER TABLE which breaks the tables sync consistency.
|
@@ -108,33 +108,63 @@ module FlydataCore
|
|
108
108
|
def log_common(level, message, log_params, options)
|
109
109
|
msg = build_log_message(level, message, log_params, options)
|
110
110
|
before_logging(level, message, msg, log_params, options)
|
111
|
-
get_logger(options)
|
111
|
+
logger = get_logger(options)
|
112
|
+
set_mutex(logger)
|
113
|
+
logger.mutex.synchronize do
|
114
|
+
original_depth_offset = nil
|
115
|
+
if logger.instance_variable_defined? :@depth_offset
|
116
|
+
original_depth_offset = logger.instance_variable_get(:@depth_offset)
|
117
|
+
depth_offset = 3 # log_common + synchronize + synchronized block
|
118
|
+
depth_offset += options[:depth_offset] if options.has_key?(:depth_offset)
|
119
|
+
logger.instance_variable_set(:@depth_offset, original_depth_offset + depth_offset)
|
120
|
+
end
|
121
|
+
logger.send(level, msg)
|
122
|
+
if original_depth_offset
|
123
|
+
logger.instance_variable_set(:@depth_offset, original_depth_offset)
|
124
|
+
end
|
125
|
+
end
|
112
126
|
end
|
113
127
|
|
114
128
|
def log_debug(message, log_params = {}, options = {})
|
115
|
-
|
129
|
+
opt = { depth_offset: 1}.merge(options)
|
130
|
+
log_common(:debug, message, log_params, opt)
|
116
131
|
end
|
117
132
|
|
118
133
|
def log_info(message, log_params = {}, options = {})
|
119
|
-
|
134
|
+
opt = { depth_offset: 1}.merge(options)
|
135
|
+
log_common(:info, message, log_params, opt)
|
120
136
|
end
|
121
137
|
|
122
138
|
def log_warn(message, log_params = {}, options = {})
|
123
|
-
|
139
|
+
opt = { depth_offset: 1}.merge(options)
|
140
|
+
log_common(:warn, message, log_params, opt)
|
124
141
|
end
|
125
142
|
|
126
143
|
def log_error(message, log_params = {}, options = {})
|
127
|
-
|
144
|
+
opt = { depth_offset: 1}.merge(options)
|
145
|
+
log_common(:error, message, log_params, opt)
|
128
146
|
end
|
129
147
|
|
130
148
|
def log_error_with_backtrace(message, log_params = {}, options = {})
|
131
|
-
|
149
|
+
opt = { depth_offset: 1}.merge(options)
|
150
|
+
log_common(:error, message, log_params, opt.merge(backtrace: true))
|
132
151
|
end
|
133
152
|
|
134
153
|
def get_logger(options = {})
|
135
154
|
options[:logger] || logger || log_context_logger || $log
|
136
155
|
end
|
137
156
|
|
157
|
+
# set mutex if logger doesn't have one
|
158
|
+
def set_mutex(logger)
|
159
|
+
return if logger.respond_to?(:mutex)
|
160
|
+
|
161
|
+
mtx = Mutex.new
|
162
|
+
logger.instance_variable_set(:@mutex, mtx)
|
163
|
+
class << logger
|
164
|
+
attr_reader :mutex
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
138
168
|
def build_log_message(level, raw_message, log_params = {}, options = {})
|
139
169
|
message = raw_message.dup
|
140
170
|
# check keys
|
@@ -209,7 +239,9 @@ module FlydataCore
|
|
209
239
|
exception = exception.original_exception unless exception.original_exception.nil?
|
210
240
|
end
|
211
241
|
|
212
|
-
unless is_retryable_error &&
|
242
|
+
unless is_retryable_error &&
|
243
|
+
(retry_alert_limit == FlydataCore::RetryableError::NO_RETRY_LIMIT ||
|
244
|
+
retry_count < retry_alert_limit)
|
213
245
|
if exception.kind_of?(FlydataCore::DataDeliveryError)
|
214
246
|
# Do not log a DataDeliveryError as ERROR. It's a user error which
|
215
247
|
# should not cause a system alert
|
@@ -62,6 +62,7 @@ class MysqlTableDef
|
|
62
62
|
'tinytext' => {type: 'text'},
|
63
63
|
'varbinary' => {type: 'varbinary', override: PROC_override_varbinary},
|
64
64
|
'varchar' => {type: 'varchar', override: PROC_override_varchar},
|
65
|
+
'year' => {type: 'year'},
|
65
66
|
}
|
66
67
|
|
67
68
|
def self.convert_to_flydata_type(type)
|
@@ -33,6 +33,7 @@ class RedshiftTableDef
|
|
33
33
|
'time' => {type: 'timestamp', default_value: '0000-01-01'},
|
34
34
|
'varbinary' => {type: 'varchar', use_params: true, max_size: 65535, default_value: ''},
|
35
35
|
'varchar' => {type: 'varchar', use_params: true, max_size: 65535, default_value: ''},
|
36
|
+
'year' => {type: 'date', default_value: '0001-01-01'},
|
36
37
|
}
|
37
38
|
def self.from_flydata_tabledef(flydata_tabledef, options = {})
|
38
39
|
options[:flydata_ctl_table] = true unless options.has_key?(:flydata_ctl_table)
|
@@ -56,7 +57,7 @@ class RedshiftTableDef
|
|
56
57
|
CREATE SCHEMA "%s";
|
57
58
|
EOS
|
58
59
|
CREATE_FLYDATA_CTL_TABLE_SQL = <<EOS
|
59
|
-
CREATE TABLE %s(
|
60
|
+
CREATE TABLE IF NOT EXISTS %s(
|
60
61
|
id integer NOT NULL IDENTITY(1,1),
|
61
62
|
table_name varchar(128) NOT NULL,
|
62
63
|
column_name varchar(128) NOT NULL,
|
@@ -86,7 +87,7 @@ EOS
|
|
86
87
|
end
|
87
88
|
|
88
89
|
CREATE_TABLE_SQL = <<EOS
|
89
|
-
DROP TABLE %s;
|
90
|
+
DROP TABLE IF EXISTS %s;
|
90
91
|
CREATE TABLE %s (
|
91
92
|
%s
|
92
93
|
)%s;
|
@@ -141,9 +142,10 @@ EOS
|
|
141
142
|
|
142
143
|
NULL_STR = "NULL"
|
143
144
|
|
144
|
-
def self.replace_default_value(
|
145
|
+
def self.replace_default_value(redshift_type, default_value)
|
145
146
|
return NULL_STR if default_value.nil?
|
146
|
-
|
147
|
+
|
148
|
+
case redshift_type
|
147
149
|
when 'timestamp'
|
148
150
|
if default_value.upcase == "CURRENT_TIMESTAMP"
|
149
151
|
'SYSDATE'
|
@@ -224,7 +226,7 @@ EOS
|
|
224
226
|
def self.check_and_replace_max(params, max_size_a)
|
225
227
|
final_params = []
|
226
228
|
params.split(",").each_with_index do |param, i|
|
227
|
-
final_params << (/\d+/.match(param) && max_size_a[i] && param.to_i > max_size_a[i].to_i ?
|
229
|
+
final_params << (/\d+/.match(param) && max_size_a[i] && param.to_i > max_size_a[i].to_i ?
|
228
230
|
max_size_a[i] : param)
|
229
231
|
end
|
230
232
|
final_params.join(",")
|
@@ -234,23 +236,24 @@ EOS
|
|
234
236
|
TIME_REGEXP = Regexp.new('^(?<sign>-)?(?<hour>\d{2,3}):(?<minute>[0-5][0-9]):(?<second>[0-5][0-9](\.\d+)?)$')
|
235
237
|
|
236
238
|
def self.parse_timestamp(value)
|
237
|
-
|
238
|
-
if
|
239
|
+
value_str = value.to_s
|
240
|
+
return nil if value_str.empty?
|
241
|
+
if value.kind_of?(Integer) or /^\d+$/ === value_str
|
239
242
|
# Unix epoch in UTC
|
240
|
-
t = DateTime.strptime(
|
241
|
-
elsif APACHE_TIMESTAMP_REGEXP.match(
|
243
|
+
t = DateTime.strptime(value_str, '%s')
|
244
|
+
elsif APACHE_TIMESTAMP_REGEXP.match(value_str)
|
242
245
|
# apache time format
|
243
246
|
t = DateTime.strptime(value, "[%d/%b/%Y:%H:%M:%S %Z]")
|
244
|
-
elsif time_match = TIME_REGEXP.match(
|
247
|
+
elsif time_match = TIME_REGEXP.match(value_str)
|
245
248
|
t = convert_time_into_timestamp(time_match)
|
246
249
|
else
|
247
|
-
t = DateTime.parse(
|
250
|
+
t = DateTime.parse(value_str)
|
248
251
|
end
|
249
252
|
t = t.new_offset(0) # Redshift Plug-in uses UTC
|
250
253
|
t.strftime('%Y-%m-%d %H:%M:%S.%6N')
|
251
254
|
rescue ArgumentError => ae
|
252
255
|
# '0000-00-00 00:00:00' is valid for mysql datetime column
|
253
|
-
if
|
256
|
+
if value_str.start_with?('0000-00-00 00:00:00')
|
254
257
|
return '0001-01-01 00:00:00.000000'
|
255
258
|
else
|
256
259
|
raise ae
|
@@ -268,15 +271,29 @@ EOS
|
|
268
271
|
end
|
269
272
|
|
270
273
|
def self.parse_date(value)
|
271
|
-
dt = Date.parse(value)
|
274
|
+
dt = Date.parse(convert_year_into_date(value))
|
272
275
|
dt.strftime('%Y-%m-%d')
|
273
276
|
rescue ArgumentError => ae
|
274
277
|
# '0000-00-00' is valid for mysql date column
|
275
278
|
return '0001-01-01' if value == '0000-00-00'
|
276
279
|
raise ae
|
277
280
|
end
|
281
|
+
|
282
|
+
def self.convert_year_into_date(value)
|
283
|
+
if value == '0' || value == '0000'
|
284
|
+
converted_value = '0001-01-01' # '0001-01-01' is the "base" date
|
285
|
+
else
|
286
|
+
case value
|
287
|
+
when /^\d{4}$/
|
288
|
+
converted_value = "#{value}-01-01"
|
289
|
+
when /^\d{2}$/
|
290
|
+
converted_value = "#{value.to_i >= 70 ? "19" : "20"}#{value}-01-01"
|
291
|
+
else
|
292
|
+
converted_value = value # Return the value as is
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
278
296
|
end
|
279
297
|
|
280
298
|
end
|
281
299
|
end
|
282
|
-
|
@@ -56,7 +56,10 @@ describe MysqlTableDef do
|
|
56
56
|
{:column=>"col_tinyint", :type=>"int1(4)", :default=>nil},
|
57
57
|
{:column=>"col_tinytext", :type=>"text"},
|
58
58
|
{:column=>"col_varbinary", :type=>"varbinary(512)", :default=>nil},
|
59
|
-
{:column=>"col_varchar", :type=>"varchar(372)", :default=>nil}
|
59
|
+
{:column=>"col_varchar", :type=>"varchar(372)", :default=>nil},
|
60
|
+
{:column=>"col_year", :type=>"year", :default=>nil},
|
61
|
+
{:column=>"col_year_4", :type=>"year(4)", :default=>nil},
|
62
|
+
{:column=>"col_year_2", :type=>"year(2)", :default=>nil},
|
60
63
|
]
|
61
64
|
)
|
62
65
|
end
|
@@ -329,6 +332,10 @@ describe MysqlTableDef do
|
|
329
332
|
let(:flydata_type) { 'text' }
|
330
333
|
it_behaves_like "converting the mysql data type to the expected flydata type"
|
331
334
|
end
|
335
|
+
context "year" do
|
336
|
+
let(:flydata_type) { 'year' }
|
337
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
338
|
+
end
|
332
339
|
end
|
333
340
|
end
|
334
341
|
end
|
@@ -27,7 +27,7 @@ module FlydataCore
|
|
27
27
|
|
28
28
|
it 'should return ddl' do
|
29
29
|
expect(subject).to eq( <<EOT.strip )
|
30
|
-
CREATE TABLE "flydata_ctl_columns"(
|
30
|
+
CREATE TABLE IF NOT EXISTS "flydata_ctl_columns"(
|
31
31
|
id integer NOT NULL IDENTITY(1,1),
|
32
32
|
table_name varchar(128) NOT NULL,
|
33
33
|
column_name varchar(128) NOT NULL,
|
@@ -36,7 +36,7 @@ CREATE TABLE "flydata_ctl_columns"(
|
|
36
36
|
ordinal_position int NOT NULL,
|
37
37
|
PRIMARY KEY(id)
|
38
38
|
) DISTKEY(table_name) SORTKEY(table_name);
|
39
|
-
DROP TABLE "test_table_all";
|
39
|
+
DROP TABLE IF EXISTS "test_table_all";
|
40
40
|
CREATE TABLE "test_table_all" (
|
41
41
|
"id" int8 NOT NULL,
|
42
42
|
"col_binary" varchar(202) DEFAULT NULL,
|
@@ -65,6 +65,9 @@ CREATE TABLE "test_table_all" (
|
|
65
65
|
"col_tinytext" varchar(max),
|
66
66
|
"col_varbinary" varchar(512) DEFAULT NULL,
|
67
67
|
"col_varchar" varchar(372) DEFAULT NULL,
|
68
|
+
"col_year" date DEFAULT NULL,
|
69
|
+
"col_year_4" date DEFAULT NULL,
|
70
|
+
"col_year_2" date DEFAULT NULL,
|
68
71
|
PRIMARY KEY (id)
|
69
72
|
) DISTKEY(id) SORTKEY(id);
|
70
73
|
DELETE FROM "flydata_ctl_columns" WHERE table_name = 'test_table_all';
|
@@ -95,7 +98,10 @@ INSERT INTO "flydata_ctl_columns" (table_name, column_name, src_data_type, ordin
|
|
95
98
|
('test_table_all', 'col_tinyint', 'int1(4)', 24),
|
96
99
|
('test_table_all', 'col_tinytext', 'text', 25),
|
97
100
|
('test_table_all', 'col_varbinary', 'varbinary(512)', 26),
|
98
|
-
('test_table_all', 'col_varchar', 'varchar(372)', 27)
|
101
|
+
('test_table_all', 'col_varchar', 'varchar(372)', 27),
|
102
|
+
('test_table_all', 'col_year', 'year', 28),
|
103
|
+
('test_table_all', 'col_year_4', 'year(4)', 29),
|
104
|
+
('test_table_all', 'col_year_2', 'year(2)', 30);
|
99
105
|
EOT
|
100
106
|
end
|
101
107
|
end
|
@@ -105,7 +111,7 @@ EOT
|
|
105
111
|
|
106
112
|
it 'should return ddl' do
|
107
113
|
expect(subject).to eq( <<EOT.strip )
|
108
|
-
CREATE TABLE "flydata_ctl_columns"(
|
114
|
+
CREATE TABLE IF NOT EXISTS "flydata_ctl_columns"(
|
109
115
|
id integer NOT NULL IDENTITY(1,1),
|
110
116
|
table_name varchar(128) NOT NULL,
|
111
117
|
column_name varchar(128) NOT NULL,
|
@@ -114,7 +120,7 @@ CREATE TABLE "flydata_ctl_columns"(
|
|
114
120
|
ordinal_position int NOT NULL,
|
115
121
|
PRIMARY KEY(id)
|
116
122
|
) DISTKEY(table_name) SORTKEY(table_name);
|
117
|
-
DROP TABLE "bit_test_def_1";
|
123
|
+
DROP TABLE IF EXISTS "bit_test_def_1";
|
118
124
|
CREATE TABLE "bit_test_def_1" (
|
119
125
|
"id" int4 NOT NULL,
|
120
126
|
"bit_value" bigint DEFAULT 1,
|
@@ -135,7 +141,7 @@ EOT
|
|
135
141
|
|
136
142
|
it 'should return ddl' do
|
137
143
|
expect(subject).to eq( <<EOT.strip )
|
138
|
-
CREATE TABLE "flydata_ctl_columns"(
|
144
|
+
CREATE TABLE IF NOT EXISTS "flydata_ctl_columns"(
|
139
145
|
id integer NOT NULL IDENTITY(1,1),
|
140
146
|
table_name varchar(128) NOT NULL,
|
141
147
|
column_name varchar(128) NOT NULL,
|
@@ -144,7 +150,7 @@ CREATE TABLE "flydata_ctl_columns"(
|
|
144
150
|
ordinal_position int NOT NULL,
|
145
151
|
PRIMARY KEY(id)
|
146
152
|
) DISTKEY(table_name) SORTKEY(table_name);
|
147
|
-
DROP TABLE "product_order";
|
153
|
+
DROP TABLE IF EXISTS "product_order";
|
148
154
|
CREATE TABLE "product_order" (
|
149
155
|
"no" int4 NOT NULL,
|
150
156
|
"product_category" int4 NOT NULL,
|
@@ -167,7 +173,7 @@ EOT
|
|
167
173
|
|
168
174
|
it 'should return ddl' do
|
169
175
|
expect(subject).to eq( <<EOT.strip )
|
170
|
-
CREATE TABLE "flydata_ctl_columns"(
|
176
|
+
CREATE TABLE IF NOT EXISTS "flydata_ctl_columns"(
|
171
177
|
id integer NOT NULL IDENTITY(1,1),
|
172
178
|
table_name varchar(128) NOT NULL,
|
173
179
|
column_name varchar(128) NOT NULL,
|
@@ -176,7 +182,7 @@ CREATE TABLE "flydata_ctl_columns"(
|
|
176
182
|
ordinal_position int NOT NULL,
|
177
183
|
PRIMARY KEY(id)
|
178
184
|
) DISTKEY(table_name) SORTKEY(table_name);
|
179
|
-
DROP TABLE "test_table_column_comment";
|
185
|
+
DROP TABLE IF EXISTS "test_table_column_comment";
|
180
186
|
CREATE TABLE "test_table_column_comment" (
|
181
187
|
"id" int4 NOT NULL DEFAULT '0',
|
182
188
|
"value" varchar(max),
|
@@ -197,7 +203,7 @@ EOT
|
|
197
203
|
|
198
204
|
it 'should return ddl' do
|
199
205
|
expect(subject).to eq( <<EOT.strip )
|
200
|
-
CREATE TABLE "flydata_ctl_columns"(
|
206
|
+
CREATE TABLE IF NOT EXISTS "flydata_ctl_columns"(
|
201
207
|
id integer NOT NULL IDENTITY(1,1),
|
202
208
|
table_name varchar(128) NOT NULL,
|
203
209
|
column_name varchar(128) NOT NULL,
|
@@ -206,7 +212,7 @@ CREATE TABLE "flydata_ctl_columns"(
|
|
206
212
|
ordinal_position int NOT NULL,
|
207
213
|
PRIMARY KEY(id)
|
208
214
|
) DISTKEY(table_name) SORTKEY(table_name);
|
209
|
-
DROP TABLE "test_table_enum";
|
215
|
+
DROP TABLE IF EXISTS "test_table_enum";
|
210
216
|
CREATE TABLE "test_table_enum" (
|
211
217
|
"id" int4 NOT NULL,
|
212
218
|
"enum_1" varchar encode bytedict DEFAULT NULL,
|
@@ -229,7 +235,7 @@ EOT
|
|
229
235
|
|
230
236
|
it 'should return ddl' do
|
231
237
|
expect(subject).to eq( <<EOT.strip )
|
232
|
-
CREATE TABLE "flydata_ctl_columns"(
|
238
|
+
CREATE TABLE IF NOT EXISTS "flydata_ctl_columns"(
|
233
239
|
id integer NOT NULL IDENTITY(1,1),
|
234
240
|
table_name varchar(128) NOT NULL,
|
235
241
|
column_name varchar(128) NOT NULL,
|
@@ -238,7 +244,7 @@ CREATE TABLE "flydata_ctl_columns"(
|
|
238
244
|
ordinal_position int NOT NULL,
|
239
245
|
PRIMARY KEY(id)
|
240
246
|
) DISTKEY(table_name) SORTKEY(table_name);
|
241
|
-
DROP TABLE "test_table_multi_pk";
|
247
|
+
DROP TABLE IF EXISTS "test_table_multi_pk";
|
242
248
|
CREATE TABLE "test_table_multi_pk" (
|
243
249
|
"id1" int4 NOT NULL DEFAULT '0',
|
244
250
|
"id2" int4 NOT NULL DEFAULT '0',
|
@@ -267,7 +273,7 @@ EOT
|
|
267
273
|
|
268
274
|
it 'should return ddl' do
|
269
275
|
expect(subject).to eq( <<EOT.strip )
|
270
|
-
CREATE TABLE "flydata_ctl_columns"(
|
276
|
+
CREATE TABLE IF NOT EXISTS "flydata_ctl_columns"(
|
271
277
|
id integer NOT NULL IDENTITY(1,1),
|
272
278
|
table_name varchar(128) NOT NULL,
|
273
279
|
column_name varchar(128) NOT NULL,
|
@@ -276,7 +282,7 @@ CREATE TABLE "flydata_ctl_columns"(
|
|
276
282
|
ordinal_position int NOT NULL,
|
277
283
|
PRIMARY KEY(id)
|
278
284
|
) DISTKEY(table_name) SORTKEY(table_name);
|
279
|
-
DROP TABLE "sample1";
|
285
|
+
DROP TABLE IF EXISTS "sample1";
|
280
286
|
CREATE TABLE "sample1" (
|
281
287
|
"id" int4 NOT NULL,
|
282
288
|
"title" varchar(768) DEFAULT NULL,
|
@@ -299,7 +305,7 @@ EOT
|
|
299
305
|
|
300
306
|
it 'should return ddl' do
|
301
307
|
expect(subject).to eq( <<EOT.strip )
|
302
|
-
CREATE TABLE "flydata_ctl_columns"(
|
308
|
+
CREATE TABLE IF NOT EXISTS "flydata_ctl_columns"(
|
303
309
|
id integer NOT NULL IDENTITY(1,1),
|
304
310
|
table_name varchar(128) NOT NULL,
|
305
311
|
column_name varchar(128) NOT NULL,
|
@@ -308,7 +314,7 @@ CREATE TABLE "flydata_ctl_columns"(
|
|
308
314
|
ordinal_position int NOT NULL,
|
309
315
|
PRIMARY KEY(id)
|
310
316
|
) DISTKEY(table_name) SORTKEY(table_name);
|
311
|
-
DROP TABLE "sample1";
|
317
|
+
DROP TABLE IF EXISTS "sample1";
|
312
318
|
CREATE TABLE "sample1" (
|
313
319
|
"id" int4 NOT NULL,
|
314
320
|
"title" varchar(768) DEFAULT NULL,
|
@@ -331,7 +337,7 @@ EOT
|
|
331
337
|
|
332
338
|
it 'should return ddl' do
|
333
339
|
expect(subject).to eq( <<EOT.strip )
|
334
|
-
CREATE TABLE "flydata_ctl_columns"(
|
340
|
+
CREATE TABLE IF NOT EXISTS "flydata_ctl_columns"(
|
335
341
|
id integer NOT NULL IDENTITY(1,1),
|
336
342
|
table_name varchar(128) NOT NULL,
|
337
343
|
column_name varchar(128) NOT NULL,
|
@@ -340,7 +346,7 @@ CREATE TABLE "flydata_ctl_columns"(
|
|
340
346
|
ordinal_position int NOT NULL,
|
341
347
|
PRIMARY KEY(id)
|
342
348
|
) DISTKEY(table_name) SORTKEY(table_name);
|
343
|
-
DROP TABLE "invoice_items";
|
349
|
+
DROP TABLE IF EXISTS "invoice_items";
|
344
350
|
CREATE TABLE "invoice_items" (
|
345
351
|
"id" int4 NOT NULL,
|
346
352
|
"app_id" int4 NOT NULL,
|
@@ -391,7 +397,7 @@ EOT
|
|
391
397
|
|
392
398
|
it 'should return ddl' do
|
393
399
|
expect(subject).to eq( <<EOT.strip )
|
394
|
-
CREATE TABLE "flydata_ctl_columns"(
|
400
|
+
CREATE TABLE IF NOT EXISTS "flydata_ctl_columns"(
|
395
401
|
id integer NOT NULL IDENTITY(1,1),
|
396
402
|
table_name varchar(128) NOT NULL,
|
397
403
|
column_name varchar(128) NOT NULL,
|
@@ -400,7 +406,7 @@ CREATE TABLE "flydata_ctl_columns"(
|
|
400
406
|
ordinal_position int NOT NULL,
|
401
407
|
PRIMARY KEY(id)
|
402
408
|
) DISTKEY(table_name) SORTKEY(table_name);
|
403
|
-
DROP TABLE "zerofill_table";
|
409
|
+
DROP TABLE IF EXISTS "zerofill_table";
|
404
410
|
CREATE TABLE "zerofill_table" (
|
405
411
|
"id" int4 NOT NULL,
|
406
412
|
"value_int" int8 DEFAULT NULL,
|
@@ -50,6 +50,9 @@ CREATE TABLE `test_table_all` (
|
|
50
50
|
`col_tinytext` tinytext,
|
51
51
|
`col_varbinary` varbinary(255) DEFAULT NULL,
|
52
52
|
`col_varchar` varchar(124) DEFAULT NULL,
|
53
|
+
`col_year` year DEFAULT NULL,
|
54
|
+
`col_year_4` year(4) DEFAULT NULL,
|
55
|
+
`col_year_2` year(2) DEFAULT NULL,
|
53
56
|
PRIMARY KEY (`id`)
|
54
57
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='test table includes all kind of format type';
|
55
58
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
@@ -22,7 +22,7 @@ describe RedshiftTableDef do
|
|
22
22
|
context 'with simple flydatadef' do
|
23
23
|
it 'should return ddl' do
|
24
24
|
expect(subject).to eq( <<EOT.strip )
|
25
|
-
DROP TABLE "test_table";
|
25
|
+
DROP TABLE IF EXISTS "test_table";
|
26
26
|
CREATE TABLE "test_table" (
|
27
27
|
"id" int4 NOT NULL,
|
28
28
|
"age" int8,
|
@@ -43,7 +43,7 @@ EOT
|
|
43
43
|
|
44
44
|
it 'should return ddl including flydata_ctl_columns creation' do
|
45
45
|
expect(subject).to eq( <<EOT.strip )
|
46
|
-
CREATE TABLE "flydata_ctl_columns"(
|
46
|
+
CREATE TABLE IF NOT EXISTS "flydata_ctl_columns"(
|
47
47
|
id integer NOT NULL IDENTITY(1,1),
|
48
48
|
table_name varchar(128) NOT NULL,
|
49
49
|
column_name varchar(128) NOT NULL,
|
@@ -52,7 +52,7 @@ CREATE TABLE "flydata_ctl_columns"(
|
|
52
52
|
ordinal_position int NOT NULL,
|
53
53
|
PRIMARY KEY(id)
|
54
54
|
) DISTKEY(table_name) SORTKEY(table_name);
|
55
|
-
DROP TABLE "test_table";
|
55
|
+
DROP TABLE IF EXISTS "test_table";
|
56
56
|
CREATE TABLE "test_table" (
|
57
57
|
"id" int4 NOT NULL,
|
58
58
|
"age" int8,
|
@@ -80,7 +80,7 @@ EOT
|
|
80
80
|
|
81
81
|
it 'should add comment creation ddl' do
|
82
82
|
expect(subject).to eq( <<EOT.strip )
|
83
|
-
DROP TABLE "test_table";
|
83
|
+
DROP TABLE IF EXISTS "test_table";
|
84
84
|
CREATE TABLE "test_table" (
|
85
85
|
"id" int4 NOT NULL,
|
86
86
|
"value" varchar(max),
|
@@ -112,7 +112,7 @@ EOT
|
|
112
112
|
it 'should preappend schema name to table name' do
|
113
113
|
expect(subject).to eq( <<EOT.strip )
|
114
114
|
CREATE SCHEMA "test_schema";
|
115
|
-
CREATE TABLE "test_schema"."flydata_ctl_columns"(
|
115
|
+
CREATE TABLE IF NOT EXISTS "test_schema"."flydata_ctl_columns"(
|
116
116
|
id integer NOT NULL IDENTITY(1,1),
|
117
117
|
table_name varchar(128) NOT NULL,
|
118
118
|
column_name varchar(128) NOT NULL,
|
@@ -121,7 +121,7 @@ CREATE TABLE "test_schema"."flydata_ctl_columns"(
|
|
121
121
|
ordinal_position int NOT NULL,
|
122
122
|
PRIMARY KEY(id)
|
123
123
|
) DISTKEY(table_name) SORTKEY(table_name);
|
124
|
-
DROP TABLE "test_schema"."test_table";
|
124
|
+
DROP TABLE IF EXISTS "test_schema"."test_table";
|
125
125
|
CREATE TABLE "test_schema"."test_table" (
|
126
126
|
"id" int4 NOT NULL,
|
127
127
|
"value" varchar(max),
|
@@ -409,6 +409,50 @@ EOT
|
|
409
409
|
it_behaves_like *examples
|
410
410
|
end
|
411
411
|
end
|
412
|
+
|
413
|
+
context 'with year column def' do
|
414
|
+
before do
|
415
|
+
column[:column] = "value_year"
|
416
|
+
column[:type] = "year(4)"
|
417
|
+
end
|
418
|
+
let(:type_sql) { %Q|"value_year" date| }
|
419
|
+
let(:not_null_default_sql) { " DEFAULT '0001-01-01'" }
|
420
|
+
|
421
|
+
context 'when default_value is normal' do
|
422
|
+
let(:default_value) { "'2014'" }
|
423
|
+
let(:default_value_sql) { "'2014-01-01'" }
|
424
|
+
it_behaves_like *examples
|
425
|
+
end
|
426
|
+
|
427
|
+
context 'when default_value is 69' do
|
428
|
+
let(:default_value) { "'69'" }
|
429
|
+
let(:default_value_sql) { "'2069-01-01'" }
|
430
|
+
it_behaves_like *examples
|
431
|
+
end
|
432
|
+
|
433
|
+
context 'when default_value is 70' do
|
434
|
+
let(:default_value) { "'70'" }
|
435
|
+
let(:default_value_sql) { "'1970-01-01'" }
|
436
|
+
it_behaves_like *examples
|
437
|
+
end
|
438
|
+
|
439
|
+
context 'when default_value is 0' do
|
440
|
+
let(:default_value) { "'0'" }
|
441
|
+
let(:default_value_sql) { "'0001-01-01'" }
|
442
|
+
it_behaves_like *examples
|
443
|
+
end
|
444
|
+
|
445
|
+
context 'when the type has no width' do
|
446
|
+
before do
|
447
|
+
column[:type] = "year"
|
448
|
+
end
|
449
|
+
context 'when default_value is normal' do
|
450
|
+
let(:default_value) { "'2014'" }
|
451
|
+
let(:default_value_sql) { "'2014-01-01'" }
|
452
|
+
it_behaves_like *examples
|
453
|
+
end
|
454
|
+
end
|
455
|
+
end
|
412
456
|
end
|
413
457
|
|
414
458
|
context 'for create table' do
|
@@ -592,6 +636,63 @@ EOT
|
|
592
636
|
let(:value) { 'abcd' }
|
593
637
|
it { expect{subject}.to raise_error(ArgumentError) }
|
594
638
|
end
|
639
|
+
|
640
|
+
context 'with boolean value' do
|
641
|
+
let(:value){ false }
|
642
|
+
it { expect{subject}.to raise_error(ArgumentError) }
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
describe '.convert_year_into_date' do
|
647
|
+
let(:value) { nil }
|
648
|
+
subject { described_class.convert_year_into_date(value) }
|
649
|
+
|
650
|
+
context 'with year values' do
|
651
|
+
context 'with value 0' do
|
652
|
+
let(:value){ '0' }
|
653
|
+
it { is_expected.to eq('0001-01-01') }
|
654
|
+
end
|
655
|
+
|
656
|
+
context 'with value 0000' do
|
657
|
+
let(:value){ '0000' }
|
658
|
+
it { is_expected.to eq('0001-01-01') }
|
659
|
+
end
|
660
|
+
|
661
|
+
context 'with year(4) >= 1970' do
|
662
|
+
let(:value){ '2000' }
|
663
|
+
it { is_expected.to eq('2000-01-01') }
|
664
|
+
end
|
665
|
+
|
666
|
+
context 'with year(4) < 1970' do
|
667
|
+
let(:value){ '1969' }
|
668
|
+
it { is_expected.to eq('1969-01-01') }
|
669
|
+
end
|
670
|
+
|
671
|
+
context 'with year(2) >= 70' do
|
672
|
+
let(:value){ '07' }
|
673
|
+
it { is_expected.to eq('2007-01-01') }
|
674
|
+
end
|
675
|
+
|
676
|
+
context 'with year(2) < 70' do
|
677
|
+
let(:value){ '69' }
|
678
|
+
it { is_expected.to eq('2069-01-01') }
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
context 'with date values' do
|
683
|
+
shared_examples "returning the input value as is" do
|
684
|
+
it { is_expected.to eq(value) }
|
685
|
+
end
|
686
|
+
context 'with valid date' do
|
687
|
+
let(:value){ '1920-01-01' }
|
688
|
+
it_behaves_like "returning the input value as is"
|
689
|
+
end
|
690
|
+
|
691
|
+
context 'with zero date' do
|
692
|
+
let(:value){ '0000-00-00' }
|
693
|
+
it_behaves_like "returning the input value as is"
|
694
|
+
end
|
695
|
+
end
|
595
696
|
end
|
596
697
|
end
|
597
698
|
|
data/flydata.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: flydata 0.3.
|
5
|
+
# stub: flydata 0.3.10 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "flydata"
|
9
|
-
s.version = "0.3.
|
9
|
+
s.version = "0.3.10"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Koichi Fujikawa", "Masashi Miyazaki", "Matthew Luu", "Mak Inada", "Sriram NS"]
|
14
|
-
s.date = "2015-03-
|
14
|
+
s.date = "2015-03-31"
|
15
15
|
s.description = "FlyData Agent"
|
16
16
|
s.email = "sysadmin@flydata.com"
|
17
17
|
s.executables = ["fdmysqldump", "flydata", "serverinfo"]
|
@@ -44,6 +44,7 @@ Gem::Specification.new do |s|
|
|
44
44
|
"flydata-core/lib/flydata-core/core_ext/object.rb",
|
45
45
|
"flydata-core/lib/flydata-core/core_ext/object/prepend.rb",
|
46
46
|
"flydata-core/lib/flydata-core/errors.rb",
|
47
|
+
"flydata-core/lib/flydata-core/fluent-plugins/multi_buffer.rb",
|
47
48
|
"flydata-core/lib/flydata-core/logger.rb",
|
48
49
|
"flydata-core/lib/flydata-core/table_def.rb",
|
49
50
|
"flydata-core/lib/flydata-core/table_def/mysql_table_def.rb",
|
@@ -167,7 +168,7 @@ Gem::Specification.new do |s|
|
|
167
168
|
]
|
168
169
|
s.homepage = "http://flydata.com/"
|
169
170
|
s.licenses = ["All right reserved."]
|
170
|
-
s.rubygems_version = "2.
|
171
|
+
s.rubygems_version = "2.4.3"
|
171
172
|
s.summary = "FlyData Agent"
|
172
173
|
|
173
174
|
if s.respond_to? :specification_version then
|
data/lib/flydata/command/sync.rb
CHANGED
@@ -24,7 +24,7 @@ module Flydata
|
|
24
24
|
class Sync < Base
|
25
25
|
include Helpers
|
26
26
|
INSERT_PROGRESS_INTERVAL = 1000
|
27
|
-
SERVER_DATA_PROCESSING_TIMEOUT =
|
27
|
+
SERVER_DATA_PROCESSING_TIMEOUT = 3600 # seconds
|
28
28
|
|
29
29
|
# for dump.pos file
|
30
30
|
STATUS_PARSING = 'PARSING'
|
@@ -179,7 +179,10 @@ EOS
|
|
179
179
|
sync_fm.table_rev_file_paths(*@input_tables),
|
180
180
|
sync_fm.table_ddl_file_paths(*@input_tables)
|
181
181
|
]
|
182
|
-
|
182
|
+
new_tables_after_reset = @new_tables + @input_tables
|
183
|
+
if @input_tables.empty? or @full_tables.empty? or @full_tables.all?{|ft| new_tables_after_reset.include?(ft)}
|
184
|
+
delete_files << sync_fm.binlog_path
|
185
|
+
end
|
183
186
|
delete_files.flatten.each do |path|
|
184
187
|
FileUtils.rm(path) if File.exists?(path)
|
185
188
|
end
|
@@ -737,13 +740,13 @@ Thank you for using FlyData!
|
|
737
740
|
def flush_buffer_and_stop(tables = [])
|
738
741
|
sender = Flydata::Command::Sender.new
|
739
742
|
sender.flush_client_buffer
|
743
|
+
sender.stop(quiet: true)
|
740
744
|
if opts.skip_flush?
|
741
745
|
log_info_stdout("Skip waiting for server data processing.")
|
742
746
|
else
|
743
747
|
wait_for_server_data_processing(
|
744
748
|
timeout: SERVER_DATA_PROCESSING_TIMEOUT, tables: tables)
|
745
749
|
end
|
746
|
-
sender.stop(quiet: true)
|
747
750
|
end
|
748
751
|
|
749
752
|
# Utility methods
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flydata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Koichi Fujikawa
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2015-03-
|
15
|
+
date: 2015-03-31 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rest-client
|
@@ -467,6 +467,7 @@ files:
|
|
467
467
|
- flydata-core/lib/flydata-core/core_ext/object.rb
|
468
468
|
- flydata-core/lib/flydata-core/core_ext/object/prepend.rb
|
469
469
|
- flydata-core/lib/flydata-core/errors.rb
|
470
|
+
- flydata-core/lib/flydata-core/fluent-plugins/multi_buffer.rb
|
470
471
|
- flydata-core/lib/flydata-core/logger.rb
|
471
472
|
- flydata-core/lib/flydata-core/table_def.rb
|
472
473
|
- flydata-core/lib/flydata-core/table_def/mysql_table_def.rb
|
@@ -607,7 +608,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
607
608
|
version: '0'
|
608
609
|
requirements: []
|
609
610
|
rubyforge_project:
|
610
|
-
rubygems_version: 2.
|
611
|
+
rubygems_version: 2.4.3
|
611
612
|
signing_key:
|
612
613
|
specification_version: 4
|
613
614
|
summary: FlyData Agent
|