scheman 0.0.3 → 0.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 13a488256dda03bd9e7c75477ab532b805ba3491
4
- data.tar.gz: c4f69982678f0427156d0d127f7fcdc0eaa9f5d6
3
+ metadata.gz: 456bdbc451ec84ddb6f377404e7654d2be2a9b8e
4
+ data.tar.gz: a3c758811636f4466abcc3fc82332931de0e8f69
5
5
  SHA512:
6
- metadata.gz: 7c2b41f51bf2f871e20e045c4f4828f292cdf288e4c5f2c8f4697b7a34950d16f05c9529d2f72ba8808f2afca3c3949c5b4b92fa254c4ddb3fb9da2d68d5f9cf
7
- data.tar.gz: 474496316452b1eb06fd78ff64cdd445dac31c75138d8beb9683c3b107cabfd4849d3a35052959575f51571e7138786c9b87d0ed228f62b24a29cd0c3b02e574
6
+ metadata.gz: 6da8d574d687da3d0394e4944032daecdc47eb15421412f1f26e798c7db22b6426a2cf3655549acf7ee8a21e712f6d0519349f5e8c0c337df6c2bb47d7d9e54d
7
+ data.tar.gz: 88bf79baf57946a03352ec156882243ed3cfb05753cce7660a70e60057ab3beb27d41c5503f2da1eb68512611a2a2bde26611fc6736370f96cd72826575143d9
data/CHANGELOG.md CHANGED
@@ -1,10 +1,14 @@
1
+ ## 0.0.4
2
+ * Add `schema diff` command
3
+ * Improve MySQL parser logic
4
+
1
5
  ## 0.0.3
2
- * Support DEFAULT field qualifier
6
+ * Support DEFAULT column qualifier
3
7
 
4
8
  ## 0.0.2
5
9
  * Support ADD INDEX
6
10
  * Support DROP INDEX
7
- * Detects altered column
11
+ * Detect altered column
8
12
 
9
13
  ## 0.0.1
10
14
  * 1st Release
data/bin/scheman ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
3
+ require "scheman"
4
+
5
+ Scheman::CommandBuilder.call(ARGV).call
data/lib/scheman.rb CHANGED
@@ -5,7 +5,11 @@ require "active_support/core_ext/object/blank"
5
5
  require "active_support/core_ext/object/try"
6
6
  require "active_support/core_ext/string/indent"
7
7
  require "parslet"
8
+ require "slop"
8
9
 
10
+ require "scheman/command_builder"
11
+ require "scheman/commands/base"
12
+ require "scheman/commands/diff"
9
13
  require "scheman/diff"
10
14
  require "scheman/errors"
11
15
  require "scheman/parser_builder"
@@ -0,0 +1,44 @@
1
+ module Scheman
2
+ class CommandBuilder
3
+ def self.call(*args)
4
+ new(*args).call
5
+ end
6
+
7
+ # @param argv [Array] ARGV
8
+ def initialize(argv)
9
+ @argv = argv
10
+ end
11
+
12
+ # @return [Scheman::Commands::Base]
13
+ def call
14
+ command_class.new(@argv)
15
+ rescue Errors::CommandNotFound
16
+ terminate
17
+ end
18
+
19
+ private
20
+
21
+ def command_class
22
+ case command_name
23
+ when "diff"
24
+ Commands::Diff
25
+ else
26
+ raise Errors::CommandNotFound
27
+ end
28
+ end
29
+
30
+ # @note You must pass a command name like "scheman diff"
31
+ def command_name
32
+ @argv[0]
33
+ end
34
+
35
+ def usage
36
+ "Usage: #{$0} <command> [options]"
37
+ end
38
+
39
+ def terminate
40
+ warn usage
41
+ exit(1)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,6 @@
1
+ module Scheman
2
+ module Commands
3
+ class Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,103 @@
1
+ module Scheman
2
+ module Commands
3
+ class Diff < Base
4
+ DEFAULT_AFTER_SCHEMA_PATH = "schema.sql"
5
+
6
+ DEFAULT_TYPE = "mysql"
7
+
8
+ # @param argv [Array] ARGV
9
+ def initialize(argv)
10
+ @argv = argv
11
+ end
12
+
13
+ # Outputs a schema diff
14
+ def call
15
+ print diff
16
+ end
17
+
18
+ private
19
+
20
+ def before
21
+ case
22
+ when has_input_from_stdin?
23
+ STDIN.read
24
+ when before_schema_path
25
+ File.read(before_schema_path)
26
+ else
27
+ raise Errors::NoBeforeSchema
28
+ end
29
+ end
30
+
31
+ def after
32
+ case
33
+ when after_schema_path
34
+ File.read(after_schema_path)
35
+ when has_default_schema_file?
36
+ default_schema
37
+ else
38
+ "CREATE DATABASE database_name;"
39
+ end
40
+ end
41
+
42
+ # @return [String]
43
+ # @example
44
+ # "mysql"
45
+ def type
46
+ options[:type] || DEFAULT_TYPE
47
+ end
48
+
49
+ # @return [Schema::Diff]
50
+ def diff
51
+ @diff ||= Scheman::Diff.new(
52
+ before: before,
53
+ after: after,
54
+ type: type,
55
+ )
56
+ end
57
+
58
+ # @return [true, false] True if any input given via STDIN
59
+ def has_input_from_stdin?
60
+ has_pipe_input? || has_redirect_input?
61
+ end
62
+
63
+ # @return [true, false] True if any input given from redirection
64
+ def has_pipe_input?
65
+ File.pipe?(STDIN)
66
+ end
67
+
68
+ # @return [true, false] True if any input given from redirection
69
+ def has_redirect_input?
70
+ File.select([STDIN], [], [], 0) != nil
71
+ end
72
+
73
+ # @return [String, nil] Path to a previous schema
74
+ def before_schema_path
75
+ options[:before]
76
+ end
77
+
78
+ # @return [String, nil] Path to a next schema
79
+ def after_schema_path
80
+ options[:after]
81
+ end
82
+
83
+ # @return [String, nil] True if a schema file exists in the default schema file path
84
+ def has_default_schema_file?
85
+ File.exist?(DEFAULT_AFTER_SCHEMA_PATH)
86
+ end
87
+
88
+ # @return [String, nil]
89
+ def default_schema
90
+ File.read(DEFAULT_AFTER_SCHEMA_PATH)
91
+ end
92
+
93
+ def options
94
+ @options ||= Slop.parse!(@argv, help: true) do
95
+ banner "Usage: #{$0} diff [options]"
96
+ on "type=", "SQL type (e.g. mysql)"
97
+ on "before=", "Path to the previous schema file"
98
+ on "after=", "Path to the next schema file"
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -8,5 +8,11 @@ module Scheman
8
8
 
9
9
  class ViewNotFound < Base
10
10
  end
11
+
12
+ class CommandNotFound < Base
13
+ end
14
+
15
+ class NoBeforeSchema < Base
16
+ end
11
17
  end
12
18
  end
@@ -67,7 +67,7 @@ module Scheman
67
67
  root(:statements)
68
68
 
69
69
  rule(:statements) do
70
- statement.repeat(1).as(:statements)
70
+ statement.repeat.as(:statements)
71
71
  end
72
72
 
73
73
  rule(:statement) do
@@ -80,7 +80,8 @@ module Scheman
80
80
  alter |
81
81
  insert |
82
82
  delimiter_statement |
83
- empty_statement
83
+ empty_statement |
84
+ spaces
84
85
  end
85
86
 
86
87
  rule(:newline) do
@@ -91,6 +92,10 @@ module Scheman
91
92
  match('\s')
92
93
  end
93
94
 
95
+ rule(:space?) do
96
+ space.maybe
97
+ end
98
+
94
99
  rule(:spaces) do
95
100
  space.repeat(1)
96
101
  end
@@ -138,8 +143,17 @@ module Scheman
138
143
  delimiter >> spaces?
139
144
  end
140
145
 
146
+ rule(:word) do
147
+ match('\w').repeat(1)
148
+ end
149
+
141
150
  rule(:comment) do
142
- (str("#") | str("--")) >> non(newline) >> newline >> spaces?
151
+ (
152
+ (str("#") | str("--")) >> non(newline) >> newline
153
+ ) | (
154
+ str("/") >> space? >> str("*") >>
155
+ ((str("*") >> space? >> str("/")).absent? >> any).repeat >> (str("*") >> space? >> str("/"))
156
+ )
143
157
  end
144
158
 
145
159
  rule(:use) do
@@ -172,7 +186,26 @@ module Scheman
172
186
 
173
187
  rule(:create_table) do
174
188
  create_table_beginning >> spaces >> table_name >>
175
- spaces? >> table_components >> eol
189
+ spaces? >> table_components >> (spaces? >> create_table_options >> spaces?).maybe >> eol
190
+ end
191
+
192
+ rule(:create_table_options) do
193
+ (comment_table_option | charset_table_option | other_table_option) >>
194
+ (spaces >> (comment_table_option | charset_table_option | other_table_option)).repeat
195
+ end
196
+
197
+ rule(:comment_table_option) do
198
+ case_insensitive_str("comment") >> spaces? >> str("=") >> spaces? >> single_quoted(match("[^']").repeat(1))
199
+ end
200
+
201
+ rule(:charset_table_option) do
202
+ case_insensitive_str("default ").maybe >>
203
+ (case_insensitive_str("charset") | case_insensitive_str("character set")) >>
204
+ spaces? >> str("=") >> spaces? >> word
205
+ end
206
+
207
+ rule(:other_table_option) do
208
+ word >> spaces? >> str("=") >> spaces? >> (word | single_quoted(word) | double_quoted(word))
176
209
  end
177
210
 
178
211
  rule(:table_components) do
@@ -336,11 +369,11 @@ module Scheman
336
369
  end
337
370
 
338
371
  rule(:auto_increment_qualifier) do
339
- case_insensitive_str("auto increment").as(:auto_increment_qualifier)
372
+ case_insensitive_str("auto_increment").as(:auto_increment_qualifier)
340
373
  end
341
374
 
342
375
  rule(:field_comment) do
343
- case_insensitive_str("comment") >> spaces >> single_quoted(match("[^']"))
376
+ case_insensitive_str("comment") >> spaces >> single_quoted(match("[^']").repeat(1))
344
377
  end
345
378
 
346
379
  rule(:on_update) do
@@ -45,7 +45,7 @@ module Scheman
45
45
  # @return [Array<Field>]
46
46
  def fields
47
47
  @table[:fields].map do |field|
48
- Field.new(field: field[:field], table: self)
48
+ Field.new(field[:field])
49
49
  end
50
50
  end
51
51
 
@@ -74,9 +74,8 @@ module Scheman
74
74
  end
75
75
 
76
76
  class Field
77
- def initialize(field: nil, table: nil)
77
+ def initialize(field)
78
78
  @field = field
79
- @table = table
80
79
  end
81
80
 
82
81
  # @note Overridden
@@ -1,3 +1,3 @@
1
1
  module Scheman
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -19,13 +19,17 @@ module Scheman
19
19
 
20
20
  class Transform < Parslet::Transform
21
21
  rule(root: subtree(:root)) do
22
- [
23
- "BEGIN;",
24
- "SET foreign_key_checks=0;",
25
- root,
26
- "SET foreign_key_checks=1;",
27
- "COMMIT;",
28
- ].join("\n\n") + "\n"
22
+ if root.to_s.present?
23
+ [
24
+ "BEGIN;",
25
+ "SET foreign_key_checks=0;",
26
+ root,
27
+ "SET foreign_key_checks=1;",
28
+ "COMMIT;",
29
+ ].join("\n\n") + "\n"
30
+ else
31
+ ""
32
+ end
29
33
  end
30
34
 
31
35
  rule(
@@ -296,7 +300,12 @@ module Scheman
296
300
  # @example
297
301
  # "NOT NULL"
298
302
  def type
299
- @element[:type].upcase.gsub("_", " ")
303
+ case @element[:type]
304
+ when "auto_increment"
305
+ @element[:type].upcase
306
+ else
307
+ @element[:type].upcase.gsub("_", " ")
308
+ end
300
309
  end
301
310
 
302
311
  # @example
data/scheman.gemspec CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.add_dependency "activesupport"
20
20
  spec.add_dependency "parslet"
21
+ spec.add_dependency "slop"
21
22
  spec.add_development_dependency "bundler", "~> 1.6"
22
23
  spec.add_development_dependency "pry"
23
24
  spec.add_development_dependency "rake"
@@ -0,0 +1,9 @@
1
+ CREATE TABLE `table1` (
2
+ `column1` INTEGER(11) PRIMARY KEY NOT NULL AUTO INCREMENT,
3
+ `column2` DATETIME DEFAULT NOW()
4
+ );
5
+
6
+ CREATE TABLE `table2` (
7
+ `column1` INTEGER(11) NOT NULL AUTO INCREMENT,
8
+ PRIMARY KEY (`column1`)
9
+ );
@@ -20,12 +20,12 @@ describe Scheman::Diff do
20
20
  let(:before_schema) do
21
21
  <<-EOS.strip_heredoc
22
22
  CREATE TABLE `table1` (
23
- `column1` INTEGER(11) PRIMARY KEY NOT NULL AUTO INCREMENT,
23
+ `column1` INTEGER(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
24
24
  `column2` DATETIME DEFAULT NOW()
25
25
  );
26
26
 
27
27
  CREATE TABLE `table2` (
28
- `column1` INTEGER(11) NOT NULL AUTO INCREMENT,
28
+ `column1` INTEGER(11) NOT NULL AUTO_INCREMENT,
29
29
  PRIMARY KEY (`column1`)
30
30
  );
31
31
  EOS
@@ -34,14 +34,14 @@ describe Scheman::Diff do
34
34
  let(:after_schema) do
35
35
  <<-EOS.strip_heredoc
36
36
  CREATE TABLE `table1` (
37
- `column1` CHAR(11) NOT NULL AUTO INCREMENT,
37
+ `column1` CHAR(11) NOT NULL AUTO_INCREMENT,
38
38
  `column2` DATETIME DEFAULT CURRENT_TIMESTAMP(),
39
39
  `column3` VARCHAR(255) NOT NULL DEFAULT "a",
40
40
  PRIMARY KEY (`column2`)
41
41
  );
42
42
 
43
43
  CREATE TABLE `table3` (
44
- `column1` INTEGER(11) NOT NULL AUTO INCREMENT,
44
+ `column1` INTEGER(11) NOT NULL AUTO_INCREMENT,
45
45
  PRIMARY KEY (`column1`)
46
46
  );
47
47
  EOS
@@ -59,12 +59,12 @@ describe Scheman::Diff do
59
59
  SET foreign_key_checks=0;
60
60
 
61
61
  CREATE TABLE `table3` (
62
- `column1` INTEGER(11) NOT NULL AUTO INCREMENT,
62
+ `column1` INTEGER(11) NOT NULL AUTO_INCREMENT,
63
63
  PRIMARY KEY (`column1`)
64
64
  );
65
65
 
66
66
  ALTER TABLE `table1` ADD COLUMN `column3` VARCHAR(255) NOT NULL DEFAULT "a",
67
- CHANGE COLUMN `column1` CHAR(11) NOT NULL AUTO INCREMENT,
67
+ CHANGE COLUMN `column1` CHAR(11) NOT NULL AUTO_INCREMENT,
68
68
  DROP PRIMARY KEY,
69
69
  ADD PRIMARY KEY `column2`;
70
70
 
@@ -29,7 +29,7 @@ describe Scheman::Parsers::Mysql do
29
29
  CREATE DATABASE database_name;
30
30
 
31
31
  CREATE TABLE `table1` (
32
- `column1` INTEGER(11) NOT NULL AUTO INCREMENT,
32
+ `column1` INTEGER(11) NOT NULL AUTO_INCREMENT,
33
33
  `column2` VARCHAR(255) NOT NULL,
34
34
  PRIMARY KEY (`column1`)
35
35
  );
@@ -141,9 +141,9 @@ describe Scheman::Parsers::Mysql do
141
141
  end
142
142
  end
143
143
 
144
- context "with AUTO INCREMENT field qualifier" do
144
+ context "with AUTO_INCREMENT field qualifier" do
145
145
  let(:str) do
146
- "CREATE TABLE `table1` (`column1` INTEGER AUTO INCREMENT);"
146
+ "CREATE TABLE `table1` (`column1` INTEGER AUTO_INCREMENT);"
147
147
  end
148
148
 
149
149
  it "succeeds in parse" do
@@ -494,5 +494,65 @@ describe Scheman::Parsers::Mysql do
494
494
  }
495
495
  end
496
496
  end
497
+
498
+ context "with empty string" do
499
+ let(:str) do
500
+ ""
501
+ end
502
+
503
+ it "succeeds in parse" do
504
+ should == []
505
+ end
506
+ end
507
+
508
+ context "with multi-line comment" do
509
+ let(:str) do
510
+ "/ * xy * /"
511
+ end
512
+
513
+ it "succeeds in parse" do
514
+ should == []
515
+ end
516
+ end
517
+
518
+ context "with comment table option" do
519
+ let(:str) do
520
+ "CREATE TABLE `table1` (`column1` INTEGER) COMMENT='test';"
521
+ end
522
+
523
+ it "succeeds in parse" do
524
+ expect { subject }.not_to raise_error
525
+ end
526
+ end
527
+
528
+ context "with charset table option" do
529
+ let(:str) do
530
+ "CREATE TABLE `table1` (`column1` INTEGER) DEFAULT CHARSET=latin1;"
531
+ end
532
+
533
+ it "succeeds in parse" do
534
+ expect { subject }.not_to raise_error
535
+ end
536
+ end
537
+
538
+ context "with another charset table option" do
539
+ let(:str) do
540
+ "CREATE TABLE `table1` (`column1` INTEGER) CHARACTER SET=latin1;"
541
+ end
542
+
543
+ it "succeeds in parse" do
544
+ expect { subject }.not_to raise_error
545
+ end
546
+ end
547
+
548
+ context "with engine table option" do
549
+ let(:str) do
550
+ "CREATE TABLE `table1` (`column1` INTEGER) ENGINE=MyISAM AUTO_INCREMENT=1;"
551
+ end
552
+
553
+ it "succeeds in parse" do
554
+ expect { subject }.not_to raise_error
555
+ end
556
+ end
497
557
  end
498
558
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scheman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryo Nakamura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-09 00:00:00.000000000 Z
11
+ date: 2014-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: slop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -97,7 +111,8 @@ dependencies:
97
111
  description:
98
112
  email:
99
113
  - r7kamura@gmail.com
100
- executables: []
114
+ executables:
115
+ - scheman
101
116
  extensions: []
102
117
  extra_rdoc_files: []
103
118
  files:
@@ -107,7 +122,11 @@ files:
107
122
  - LICENSE.txt
108
123
  - README.md
109
124
  - Rakefile
125
+ - bin/scheman
110
126
  - lib/scheman.rb
127
+ - lib/scheman/command_builder.rb
128
+ - lib/scheman/commands/base.rb
129
+ - lib/scheman/commands/diff.rb
111
130
  - lib/scheman/diff.rb
112
131
  - lib/scheman/errors.rb
113
132
  - lib/scheman/parser_builder.rb
@@ -118,6 +137,7 @@ files:
118
137
  - lib/scheman/views/base.rb
119
138
  - lib/scheman/views/mysql.rb
120
139
  - scheman.gemspec
140
+ - spec/fixtures/example1.sql
121
141
  - spec/scheman/diff_spec.rb
122
142
  - spec/scheman/parsers/mysql_spec.rb
123
143
  - spec/spec_helper.rb
@@ -146,6 +166,7 @@ signing_key:
146
166
  specification_version: 4
147
167
  summary: SQL schema parser.
148
168
  test_files:
169
+ - spec/fixtures/example1.sql
149
170
  - spec/scheman/diff_spec.rb
150
171
  - spec/scheman/parsers/mysql_spec.rb
151
172
  - spec/spec_helper.rb