flydata 0.1.12 → 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -31,17 +31,19 @@ class RedshiftTableDef
31
31
  }
32
32
  def self.from_flydata_tabledef(flydata_tabledef, options = {})
33
33
  options[:flydata_ctl_table] = true unless options.has_key?(:flydata_ctl_table)
34
+ schema_name = options[:schema_name]
34
35
 
35
36
  tabledef = ""
36
- tabledef += create_flydata_ctl_table_sql if options[:flydata_ctl_table]
37
- tabledef += create_table_sql(flydata_tabledef)
38
- tabledef += comment_sql(flydata_tabledef)
39
- tabledef += flydata_ctl_sql(flydata_tabledef)
37
+ tabledef += create_flydata_ctl_table_sql(schema_name) if options[:flydata_ctl_table]
38
+ tabledef += create_table_sql(flydata_tabledef, schema_name)
39
+ tabledef += comment_sql(flydata_tabledef, schema_name)
40
+ tabledef += flydata_ctl_sql(flydata_tabledef, schema_name)
40
41
  end
41
42
 
43
+ FLYDATA_CTL_COLUMNS_TABLE = "flydata_ctl_columns"
42
44
  CREATE_FLYDATA_CTL_TABLE_SQL = <<EOS
43
- DROP TABLE flydata_ctl_columns;
44
- CREATE TABLE flydata_ctl_columns (
45
+ DROP TABLE %s;
46
+ CREATE TABLE %s(
45
47
  id integer NOT NULL IDENTITY(1,1),
46
48
  table_name varchar(128) NOT NULL,
47
49
  column_name varchar(128) NOT NULL,
@@ -51,9 +53,19 @@ CREATE TABLE flydata_ctl_columns (
51
53
  PRIMARY KEY(id)
52
54
  ) DISTKEY(table_name) SORTKEY(table_name);
53
55
  EOS
54
- def self.create_flydata_ctl_table_sql
56
+
57
+ def self.table_name_for_ddl(table_name, schema_name)
58
+ schema_name.to_s.empty? ? "\"#{table_name}\"" : "\"#{schema_name}\".\"#{table_name}\""
59
+ end
60
+
61
+ def self.flydata_ctl_table_for_ddl(schema_name)
62
+ table_name_for_ddl(FLYDATA_CTL_COLUMNS_TABLE, schema_name)
63
+ end
64
+
65
+ def self.create_flydata_ctl_table_sql(schema_name)
55
66
  # No drop table here intentionally because losing the data is fatal.
56
- CREATE_FLYDATA_CTL_TABLE_SQL
67
+ tbl = flydata_ctl_table_for_ddl(schema_name)
68
+ CREATE_FLYDATA_CTL_TABLE_SQL % [tbl, tbl]
57
69
  end
58
70
 
59
71
  CREATE_TABLE_SQL = <<EOS
@@ -63,7 +75,7 @@ CREATE TABLE %s (
63
75
  );
64
76
  EOS
65
77
 
66
- def self.create_table_sql(flydata_tabledef)
78
+ def self.create_table_sql(flydata_tabledef, schema_name)
67
79
  lines = flydata_tabledef[:columns].collect{|column| column_def_sql(column) }
68
80
  pk_def = primary_key_sql(flydata_tabledef)
69
81
  lines << pk_def if pk_def
@@ -71,7 +83,8 @@ EOS
71
83
  contents = lines.join(",\n")
72
84
 
73
85
  table_name = flydata_tabledef[:table_name]
74
- CREATE_TABLE_SQL % [table_name, table_name, contents]
86
+ redshift_tbl = table_name_for_ddl(table_name, schema_name)
87
+ CREATE_TABLE_SQL % [redshift_tbl, redshift_tbl, contents]
75
88
  end
76
89
 
77
90
  def self.column_def_sql(column)
@@ -118,13 +131,13 @@ EOS
118
131
  pks.empty? ? nil : " PRIMARY KEY (#{pks.join(',')})"
119
132
  end
120
133
 
121
- def self.comment_sql(flydata_tabledef)
134
+ def self.comment_sql(flydata_tabledef, schema_name)
122
135
  sql = ""
123
136
  flydata_tabledef[:columns].each do |col|
124
137
  next unless col[:comment]
125
138
 
126
139
  sql += <<EOS
127
- COMMENT ON COLUMN #{flydata_tabledef[:table_name]}."#{col[:name]}"
140
+ COMMENT ON COLUMN #{table_name_for_ddl(flydata_tabledef[:table_name], schema_name)}."#{col[:name]}"
128
141
  IS '#{col[:comment]}';
129
142
  EOS
130
143
  end
@@ -132,11 +145,12 @@ EOS
132
145
  end
133
146
 
134
147
  FLYDATA_CTL_COLUMNS_SQL = <<EOS
135
- DELETE FROM flydata_ctl_columns WHERE table_name = '%s';
136
- INSERT INTO flydata_ctl_columns (table_name, column_name, src_data_type, ordinal_position) VALUES
148
+ DELETE FROM %s WHERE table_name = '%s';
149
+ INSERT INTO %s (table_name, column_name, src_data_type, ordinal_position) VALUES
137
150
  EOS
138
- def self.flydata_ctl_sql(flydata_tabledef)
139
- sql = FLYDATA_CTL_COLUMNS_SQL % [ flydata_tabledef[:table_name] ]
151
+ def self.flydata_ctl_sql(flydata_tabledef, schema_name)
152
+ flydata_ctl_tbl = flydata_ctl_table_for_ddl(schema_name)
153
+ sql = FLYDATA_CTL_COLUMNS_SQL % [ flydata_ctl_tbl, flydata_tabledef[:table_name], flydata_ctl_tbl ]
140
154
  values = []
141
155
  flydata_tabledef[:columns].each.with_index(1) do |col, i|
142
156
  values << "('#{flydata_tabledef[:table_name]}', '#{col[:name]}', '#{escape(col[:type])}', #{i})"
@@ -280,16 +280,11 @@ EOT
280
280
  end
281
281
  end
282
282
 
283
- context 'when received alter table event' do
284
- it do
285
- expect_no_emitted_record(alter_table_add_column_event)
286
- end
287
- end
288
-
289
- #TODO: Uncomment the following test and delete the above one after supporting alter table
290
283
  context 'when received alter table add column event' do
291
284
  it do
292
- skip "Now alter table add column is not supported"
285
+ # TODO Replace the expectation when enabling alter table
286
+ expect_no_emitted_record(alter_table_add_column_event)
287
+ =begin
293
288
  expect_emitted_records(alter_table_add_column_event, {
294
289
  type: :alter_table,
295
290
  table_name: "test_table",
@@ -300,12 +295,15 @@ EOT
300
295
  actions: [{
301
296
  action: :add_column, column: "sum", :type=>'int4'}],
302
297
  })
298
+ =end
303
299
  end
304
300
  end
305
301
 
306
302
  context 'when received alter table drop column event' do
307
303
  it do
308
- skip "Now alter table drop column is not supported"
304
+ # TODO Replace the expectation when enabling alter table
305
+ expect_no_emitted_record(alter_table_drop_column_event)
306
+ =begin
309
307
  expect_emitted_records(alter_table_drop_column_event, {
310
308
  type: :alter_table,
311
309
  table_name: "test_table",
@@ -316,6 +314,7 @@ EOT
316
314
  actions: [{
317
315
  action: :drop_column, column: "sum"}],
318
316
  })
317
+ =end
319
318
  end
320
319
  end
321
320
 
@@ -234,6 +234,60 @@ describe 'MysqlAlterTableParser' do
234
234
  end
235
235
  end
236
236
 
237
+ context 'when table_name is wrapped with backquote' do
238
+ let(:query) { "alter table `test_table` drop value" }
239
+ it do
240
+ expect(subject).to eq(
241
+ type: :alter_table,
242
+ table_name: "test_table",
243
+ actions: [{
244
+ action: :drop_column,
245
+ column: "value"
246
+ }])
247
+ end
248
+ end
249
+
250
+ context 'when keywords are capitalized' do
251
+ let(:query) { "ALTER TABLE `test_table` DROP value" }
252
+ it do
253
+ expect(subject).to eq(
254
+ type: :alter_table,
255
+ table_name: "test_table",
256
+ actions: [{
257
+ action: :drop_column,
258
+ column: "value"
259
+ }])
260
+ end
261
+ end
262
+
263
+ context 'when table_name includes schema' do
264
+ let(:query) { "alter table test_schema.test_table drop value" }
265
+ it do
266
+ expect(subject).to eq(
267
+ type: :alter_table,
268
+ schema_name: "test_schema",
269
+ table_name: "test_table",
270
+ actions: [{
271
+ action: :drop_column,
272
+ column: "value"
273
+ }])
274
+ end
275
+ end
276
+
277
+ context 'when table_name includes schema with quotes' do
278
+ let(:query) { "alter table `test_schema`.`test_table` drop `value`" }
279
+ it do
280
+ expect(subject).to eq(
281
+ type: :alter_table,
282
+ schema_name: "test_schema",
283
+ table_name: "test_table",
284
+ actions: [{
285
+ action: :drop_column,
286
+ column: "value"
287
+ }])
288
+ end
289
+ end
290
+
237
291
  context 'when query has unsupported drop dextension' do
238
292
  subject { parser.parse(query) }
239
293
 
@@ -6,6 +6,136 @@ module TableDef
6
6
 
7
7
  describe RedshiftTableDef do
8
8
 
9
+ describe '.from_flydata_tabledef' do
10
+ let(:flydata_tabledef) { {
11
+ table_name: "test_table",
12
+ columns: [
13
+ { name: "id", type: "int4(11)", not_null: true, primary_key: true },
14
+ { name: "value", type: "text" },
15
+ ],
16
+ default_charset: "utf8;"} }
17
+ let(:option) { { flydata_ctl_table: false } }
18
+
19
+ subject { described_class.from_flydata_tabledef(flydata_tabledef, option) }
20
+
21
+ context 'with simple flydatadef' do
22
+ it 'should return ddl' do
23
+ expect(subject).to eq( <<EOT.strip )
24
+ DROP TABLE "test_table";
25
+ CREATE TABLE "test_table" (
26
+ "id" int4 NOT NULL,
27
+ "value" varchar(max),
28
+ PRIMARY KEY (id)
29
+ );
30
+ DELETE FROM "flydata_ctl_columns" WHERE table_name = 'test_table';
31
+ INSERT INTO "flydata_ctl_columns" (table_name, column_name, src_data_type, ordinal_position) VALUES
32
+ ('test_table', 'id', 'int4(11)', 1),
33
+ ('test_table', 'value', 'text', 2);
34
+ EOT
35
+ end
36
+ end
37
+
38
+ context 'with flydata_ctl_columns option true' do
39
+ let(:option) { { flydata_ctl_columns: true } }
40
+
41
+ it 'should return ddl including flydata_ctl_columns creation' do
42
+ expect(subject).to eq( <<EOT.strip )
43
+ DROP TABLE "flydata_ctl_columns";
44
+ CREATE TABLE "flydata_ctl_columns"(
45
+ id integer NOT NULL IDENTITY(1,1),
46
+ table_name varchar(128) NOT NULL,
47
+ column_name varchar(128) NOT NULL,
48
+ src_data_type varchar(1024) NOT NULL,
49
+ revision int NOT NULL DEFAULT 1,
50
+ ordinal_position int NOT NULL,
51
+ PRIMARY KEY(id)
52
+ ) DISTKEY(table_name) SORTKEY(table_name);
53
+ DROP TABLE "test_table";
54
+ CREATE TABLE "test_table" (
55
+ "id" int4 NOT NULL,
56
+ "value" varchar(max),
57
+ PRIMARY KEY (id)
58
+ );
59
+ DELETE FROM "flydata_ctl_columns" WHERE table_name = 'test_table';
60
+ INSERT INTO "flydata_ctl_columns" (table_name, column_name, src_data_type, ordinal_position) VALUES
61
+ ('test_table', 'id', 'int4(11)', 1),
62
+ ('test_table', 'value', 'text', 2);
63
+ EOT
64
+ end
65
+ end
66
+
67
+ context 'with flydatadef with comment' do
68
+ let(:flydata_tabledef) { {
69
+ table_name: "test_table",
70
+ columns: [
71
+ { name: "id", type: "int4(11)", not_null: true, primary_key: true },
72
+ { name: "value", type: "text" },
73
+ { name: "cmnt", type: "text", comment: "helloworld" },
74
+ ],
75
+ default_charset: "utf8;"} }
76
+
77
+ it 'should add comment creation ddl' do
78
+ expect(subject).to eq( <<EOT.strip )
79
+ DROP TABLE "test_table";
80
+ CREATE TABLE "test_table" (
81
+ "id" int4 NOT NULL,
82
+ "value" varchar(max),
83
+ "cmnt" varchar(max),
84
+ PRIMARY KEY (id)
85
+ );
86
+ COMMENT ON COLUMN "test_table"."cmnt"
87
+ IS 'helloworld';
88
+ DELETE FROM "flydata_ctl_columns" WHERE table_name = 'test_table';
89
+ INSERT INTO "flydata_ctl_columns" (table_name, column_name, src_data_type, ordinal_position) VALUES
90
+ ('test_table', 'id', 'int4(11)', 1),
91
+ ('test_table', 'value', 'text', 2),
92
+ ('test_table', 'cmnt', 'text', 3);
93
+ EOT
94
+ end
95
+ end
96
+
97
+ context 'with schema_name' do
98
+ let(:flydata_tabledef) { {
99
+ table_name: "test_table",
100
+ columns: [
101
+ { name: "id", type: "int4(11)", not_null: true, primary_key: true },
102
+ { name: "value", type: "text" },
103
+ { name: "cmnt", type: "text", comment: "helloworld" },
104
+ ],
105
+ default_charset: "utf8;"} }
106
+ let(:option) { { flydata_ctl_table: true, schema_name: 'test_schema' } }
107
+
108
+ it 'should preappend schema name to table name' do
109
+ expect(subject).to eq( <<EOT.strip )
110
+ DROP TABLE "test_schema"."flydata_ctl_columns";
111
+ CREATE TABLE "test_schema"."flydata_ctl_columns"(
112
+ id integer NOT NULL IDENTITY(1,1),
113
+ table_name varchar(128) NOT NULL,
114
+ column_name varchar(128) NOT NULL,
115
+ src_data_type varchar(1024) NOT NULL,
116
+ revision int NOT NULL DEFAULT 1,
117
+ ordinal_position int NOT NULL,
118
+ PRIMARY KEY(id)
119
+ ) DISTKEY(table_name) SORTKEY(table_name);
120
+ DROP TABLE "test_schema"."test_table";
121
+ CREATE TABLE "test_schema"."test_table" (
122
+ "id" int4 NOT NULL,
123
+ "value" varchar(max),
124
+ "cmnt" varchar(max),
125
+ PRIMARY KEY (id)
126
+ );
127
+ COMMENT ON COLUMN "test_schema"."test_table"."cmnt"
128
+ IS 'helloworld';
129
+ DELETE FROM "test_schema"."flydata_ctl_columns" WHERE table_name = 'test_table';
130
+ INSERT INTO "test_schema"."flydata_ctl_columns" (table_name, column_name, src_data_type, ordinal_position) VALUES
131
+ ('test_table', 'id', 'int4(11)', 1),
132
+ ('test_table', 'value', 'text', 2),
133
+ ('test_table', 'cmnt', 'text', 3);
134
+ EOT
135
+ end
136
+ end
137
+ end
138
+
9
139
  describe '.column_def_sql' do
10
140
  let(:column) { {} }
11
141
  subject { described_class.column_def_sql(column) }