db_suit_rails 0.4.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ec869f044990a140af694c70bef1002b5e3e8e9cde39af3dde4a889f57a4706a
4
+ data.tar.gz: cce91a8c112295d0993a063f2b1dbc5f9927d02b0cd87ab65fa946df8feaca1c
5
+ SHA512:
6
+ metadata.gz: 75a00ce98daf73a16f248f90703de44976796c694a86ef24227661da06cb6a8c5849b07291fdd310c048e571a7cef7b14e18376fae700a89d27a05612232d7a2
7
+ data.tar.gz: e5e11f5f1bb6a03a36a566487c38ab988145ec8712a93bdee491150685e2e1edcccc1182663d95ad670f54592131a23071480c08c6bd088b3b4ed9f410f9eb6e
@@ -0,0 +1,11 @@
1
+ *.[oa]
2
+ *.so
3
+ *~
4
+ *.nogem
5
+ *nogem.*
6
+ *.bak
7
+ *.org
8
+ *.orig
9
+ *.gem
10
+ *.pyc
11
+ *.yardoc
@@ -0,0 +1,41 @@
1
+ -----
2
+ (Version: 0.4.1)
3
+ 2018-03-31 Masa Sakano
4
+ * Updated the document.
5
+
6
+ -----
7
+ (Version: 0.4.1)
8
+ 2018-03-31 Masa Sakano
9
+ * Updated the document.
10
+
11
+ -----
12
+ (Version: 0.4)
13
+ 2018-03-26 Masa Sakano
14
+ * Added new command-line options (--[no-]withsql --mappingsql=FILE.SQL --mapping-tbl-prefix=PREFIX --mapping-tbl-suffix-from=SUFFIX --mapping-tbl-suffix-to=SUFFIX) so a normalised SQL-mapping file is output.
15
+ * Now it can deal with the table names in the form of "public.talbe_name"
16
+ * lib/db_suit_rails/sql_skelton.rb
17
+ * SqlSkelton::DefMappingFilename changed into DefMappingCsvname .
18
+ * New constant DefMappingSql is defined.
19
+ * new() and run() accept an additional option "mappingsql".
20
+ * new class method: self.colname4id()
21
+ * lib/db_suit_rails/sql_skelton/fkey.rb
22
+ * now requires "active_support/all" and "db_suit_rails/sql_skelton/utils" and includes the latter.
23
+ * lib/db_suit_rails/sql_skelton/utils.rb
24
+ * New private method: remove_sqlprefix()
25
+ * test/test_sql_skelton.rb : updated with a few new tests.
26
+
27
+ -----
28
+ (Version: 0.3)
29
+ 2018-03-13 Masa Sakano
30
+ * Fixed a serious bug in bin/copy_nline where some lines after a small number of data are omitted. Added --version option in bin/copy_nline and bin/mk_sqlskelton .
31
+
32
+ -----
33
+ (Version: 0.2)
34
+ 2018-03-13 Masa Sakano
35
+ * Added an executable bin/copy_nline . Added a new module SqlSkelton::Utils (lib/db_suit_rails/sql_skelton/utils.rb). Added routines to check reserved words for table/column names in col_index.rb and tbl_index.rb and implemented related tests.
36
+
37
+ -----
38
+ (Version: 0.1)
39
+ 2018-03-10 Masa Sakano
40
+
41
+ * Initial preliminary commit.
@@ -0,0 +1,22 @@
1
+ ALL =
2
+
3
+ objs =
4
+
5
+ .SUFFIXES: .so .o .c .f
6
+
7
+ #.o.so:
8
+ # ${LD} ${LFLAGS} -o $@ $< ${LINK_LIB}
9
+
10
+ all: ${ALL}
11
+
12
+
13
+ .PHONY: clean test doc
14
+ clean:
15
+ $(RM) bin/*~
16
+
17
+ test:
18
+ rake test
19
+
20
+ doc:
21
+ yard doc
22
+
@@ -0,0 +1,118 @@
1
+
2
+ = db_suit_rails - Database conversion to suit Ruby-on-Rails
3
+
4
+ == Summary
5
+
6
+ Script to create a SQL file to inject a table that follows the
7
+ convention of Rails.
8
+
9
+ == Install
10
+
11
+ This script requires {Ruby}[http://www.ruby-lang.org] Version 2.0
12
+ or above, and Rails library (called gem) of version 5.0 or above.
13
+ The standard way to install Rails gem is from the command-line
14
+ Prompt% gem install rails
15
+
16
+ Put the main-script file +mk_sqlskelton+ in any of your command-line search
17
+ paths and give it the executable permission.
18
+
19
+ You may need to modify the first line (Shebang line) of the script to suit your
20
+ environment (it should be unnecessary for Linux and MacOS), or run it
21
+ explicitly with your Ruby command as
22
+ Prompt% /YOUR/ENV/ruby /YOUR/INSTALLED/mk_sqlskelton
23
+
24
+ Prior to it, make sure the RUBYLIB environment
25
+ variable contains the library directory to this gem, which is
26
+ /THIS/GEM/LIBRARY/PATH/db_suit_rails/lib
27
+
28
+ == Simple Examples
29
+
30
+ All you need to do is to run
31
+ mk_sqlskelton [OPTIONS] OriginalSQL.sql
32
+
33
+ You may start with
34
+ mk_sqlskelton --help
35
+ to see the available options, which are described below in detail.
36
+
37
+ == Description
38
+
39
+ This script
40
+
41
+ * pluralizes all the table names,
42
+ * changes table names containing `*_[0-9]*` into `*_n[0-9]*` ,
43
+ * changes table names `id` into `id_cli` ,
44
+ * changes table names containing `*_id` into `*_id_cli` ,
45
+ * removes all the PRIMARY KEY constraints (n.b., those individual columns are not UNIQUE, either, any more),
46
+ * creates the new PRIMARY KEY named 'id' in each table,
47
+ * sets sets of composite PRIMARY KEY as equivalent UNIQUE keys,
48
+ * changes the reference settings, reflecting all these changes,
49
+ * removes all the triggers.
50
+
51
+ The script is far from perfect, but is useful enough for practical uses.
52
+
53
+ For example, the script assumes a certain format for the input SQL
54
+ file. Crucially, CREATE TABLE statements should have newlines at
55
+ usual locations, and other statements should not have newlines inside
56
+ a single sentence.
57
+
58
+ It tries to handle references. However, there are many forms to
59
+ specify references in PostgreSQL, and this script handles not all of them.
60
+
61
+ Also, its support for composite unique keys and their references are
62
+ also limited. If you encounter an error like
63
+
64
+ there is no unique constraint matching given keys for referenced table "...."
65
+
66
+ then chances are, unique constrants are not set appropriately.
67
+
68
+ SEQUENCEs are preserved, though probably they should not be.
69
+
70
+ Essentially, not all the unique keys in the current table may be
71
+ applicable in the generated table for Rails, depending on the
72
+ specification of the table! For example, if a column references the
73
+ primary key in another table, would it be still valid,
74
+ after the primary key is changed into a normal column, that is the
75
+ ex-primary-key should really be unique after the migration? If a
76
+ new table combines entries from multiple tables, the column that used
77
+ to be unique in a single table man not be unique any more. It
78
+ entirely depends on what you wnat in the newly generated database and tables.
79
+
80
+ == Command-line options
81
+
82
+ USAGE: mk_sqlskelton [options] OriginalSQL.sql
83
+
84
+ -e:: Regular expression for the tables to convert
85
+ -o, --output:: Output SQL file. In default, OriginalSQL_ror.sql
86
+ -i, --index:: Index SQL file to list old and new. In default, ./index.sql
87
+ -n, --[no-]dryrun:: Dryrun (Def: false). It still attempts to access the files, and then you can tell which files exist and which do not.
88
+
89
+
90
+ == Examples
91
+
92
+
93
+ == Developer's note
94
+
95
+
96
+ === Algorithm
97
+
98
+ * The components for the output SQL filename and components (table and
99
+ column names) are represented by a hash in the current
100
+ imprementation as in Ver.0.3, but it had better be by a class.
101
+
102
+ === Tests
103
+
104
+ Ruby codes under the directory <tt>test/</tt> are the test scripts.
105
+ You can run them from the top directory as <tt>ruby test/test_****.rb</tt>
106
+ or simply run <tt>make test</tt>.
107
+
108
+
109
+ == Known bugs
110
+
111
+ None.
112
+
113
+
114
+ == Copyright
115
+
116
+ Author:: Masa Sakano < info a_t wisebabel dot com >
117
+ Versions:: The versions of this package follow Semantic Versioning (2.0.0) http://semver.org/
118
+
@@ -0,0 +1,9 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
9
+
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require 'optparse'
5
+ require 'open3'
6
+
7
+ BANNER = <<"__EOF__"
8
+ USAGE: #{File.basename($0)} [--nlines=N] [--pg-dump-command=COM] -- [options] [DBNAME] > STDOUT
9
+ __EOF__
10
+
11
+
12
+ # Initialising the hash for the command-line options.
13
+ OPTS = {
14
+ :nlines => 5,
15
+ :pg_dump_command => 'pg_dump',
16
+ :read_file => nil,
17
+ :version => nil,
18
+ # :debug => false,
19
+ }
20
+
21
+ # Print the version number and exit
22
+ #
23
+ # If the global constant VERSION is defiend, it is returned.
24
+ # Else, this assumes the library to load follows the proper Ruby/Gem style,
25
+ # where the library is found in the path /.../gems/GEM_NAME-1.2.3/lib/
26
+ #
27
+ # @param libfile [String] the library file, e.g., 'my_gem_name/lib_to_load', where the file is used as in require 'my_gem_name/lib_to_load'
28
+ # @return [String,NilClass] eg., '(Gem) did_you_mean-1.2.0'
29
+ def get_version_in_gem(libfile)
30
+ defined?(VERSION) && (return VERSION)
31
+
32
+ libfile_base = libfile.sub(/^(\/)?(.+)(\.rb)?$/, '\2')
33
+ $LOAD_PATH.each do |dir|
34
+ if Dir.glob(dir+"/#{libfile_base}{,.rb}").size > 1
35
+ retstr = dir.sub(/\/lib\/?$/, '').sub(/.*\//, '')
36
+ if (%r@/gems/$@ =~ $&)
37
+ retstr.sub!(/^/, '(Gem) ')
38
+ else
39
+ retstr = sprintf("(Library under directory): %s", dir)
40
+ end
41
+ return retstr
42
+ end
43
+ end
44
+
45
+ ## Perhaps not in Gem
46
+ nil
47
+ end
48
+
49
+
50
+ # Print the version number and exit
51
+ #
52
+ # @param see #get_version_in_gem
53
+ # @return [NilClass]
54
+ def print_version_and_exit(libfile)
55
+ version = get_version_in_gem(libfile)
56
+
57
+ if version
58
+ puts version
59
+ exit
60
+ end
61
+
62
+ warn "ERROR: No version is found. Perhaps the command is not in the properly installed Gem style (or currently in development)?"
63
+ exit 1
64
+ end
65
+
66
+
67
+ # VERSION = (get_version_in_gem('db_suit_rails/sql_skelton') || false)
68
+
69
+ # Function to handle the command-line arguments.
70
+ #
71
+ # ARGV will be modified, and the constant variable OPTS is set.
72
+ #
73
+ # @return [Hash] Optional-argument hash.
74
+ #
75
+ def handle_argv
76
+ # opt = OptionParser.new(BANNER, version: get_version_in_gem('db_suit_rails/sql_skelton'))
77
+ opt = OptionParser.new(BANNER)
78
+
79
+ opt.on( '--nlines=NUM', sprintf("Number of lines to be included (Def: %s)", OPTS[:nlines]), Integer) { |v| OPTS[:nlines]=v }
80
+ opt.on( '--pg-dump-command=COM', sprintf("pg_dump command name (Def: %s)", OPTS[:pg_dump_command])) { |v| OPTS[:pg_dump_command]=v }
81
+ opt.on( '--read-file=FILENAME', sprintf("Specify the filename for direct input from a file (Def: ''). If you specify this, you probablly do not want to specify any other options.", OPTS[:read_file])) { |v| OPTS[:read_file]=v }
82
+ # opt.on( '--[no-]debug', "Debug (Def: false)", TrueClass) {|v| OPTS[:debug] = v}
83
+ opt.on( '--version', "Display the version and exits.", TrueClass) {|v| OPTS[:version] = v} # Consider opts.on_tail
84
+ opt.separator "" # Way to control a help message.
85
+ opt.separator "Note:"
86
+ opt.separator " NUM lines (or rows) of data at most per table are included."
87
+ opt.separator ' Please make sure to include "--" always!'
88
+ opt.separator ' "[options]" above are any options for pg_dump'
89
+ opt.separator " Do not include --schema-only as it does not make sense!"
90
+ opt.separator " Do not include --(*-)inserts as this script would not handle it."
91
+ opt.separator " Useful options include '-t|-T table' '--disable-triggers', '--no-owner'"
92
+ opt.parse!(ARGV)
93
+
94
+ if OPTS[:version]
95
+ print_version_and_exit('db_suit_rails/sql_skelton')
96
+ # print_version_and_exit('did_you_mean') # for testing
97
+ end
98
+
99
+ OPTS
100
+ end
101
+
102
+
103
+ ################################################
104
+ # MAIN
105
+ ################################################
106
+
107
+ $stdout.sync=true
108
+ $stderr.sync=true
109
+
110
+ # Handle the command-line options => OPTS
111
+ handle_argv()
112
+
113
+ st_argv = ARGV.join(' ')
114
+ com = if OPTS[:read_file]
115
+ sprintf("cat %s %s", st_argv, OPTS[:read_file])
116
+ else
117
+ OPTS[:pg_dump_command]+' '+st_argv
118
+ end
119
+
120
+ counter = -1;
121
+ Open3.popen2(com){|ioIn,ioStdOut,wt|
122
+ ioStdOut.each_line do |ea_line|
123
+ next if counter >= OPTS[:nlines] && /^\\\./ !~ ea_line
124
+
125
+ print ea_line
126
+
127
+ if counter >= OPTS[:nlines] || (/^\\\./ !~ ea_line && counter >= 0)
128
+ counter = -1;
129
+ elsif counter >= 0
130
+ counter += 1;
131
+ elsif /^COPY / =~ ea_line
132
+ counter = 0
133
+ end
134
+ end
135
+ # p wt.value.exitstatus
136
+ }
137
+
138
+ exit
139
+
140
+ __END__
141
+
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require 'optparse'
5
+ require 'db_suit_rails/sql_skelton'
6
+
7
+ BANNER = <<"__EOF__"
8
+ USAGE: #{File.basename($0)} [options] [INFILE.sql] < STDIN
9
+ INFILE (or STDIN) is an output of pg_dump (-s, -t|-T)
10
+ __EOF__
11
+
12
+ # Initialising the hash for the command-line options.
13
+ OPTS = {
14
+ :outfile => 'rails_db.sql',
15
+ :mappingcsv => SqlSkelton::DefMappingCsvname, # 'mapping.csv'
16
+ :mappingsql => {:filename => nil},
17
+ :withsql => true,
18
+ :mapping_tbl_prefix => '',
19
+ :mapping_col_suffix_from => SqlSkelton::DefMappingSql[:colsuffix4from],
20
+ :mapping_col_suffix_to => SqlSkelton::DefMappingSql[:colsuffix4to],
21
+ :delete_primary => true,
22
+ :delete_sequence => false, ###### Investigate...
23
+ :delete_trigger => true,
24
+ # :clobber => true, # Default
25
+ # :chatter => 3, # Default
26
+ :dryrun => false,
27
+ :debug => false,
28
+ }
29
+
30
+ # Print the version number and exit
31
+ #
32
+ # If the global constant VERSION is defiend, it is returned.
33
+ # Else, this assumes the library to load follows the proper Ruby/Gem style,
34
+ # where the library is found in the path /.../gems/GEM_NAME-1.2.3/lib/
35
+ #
36
+ # @param libfile [String] the library file, e.g., 'my_gem_name/lib_to_load', where the file is used as in require 'my_gem_name/lib_to_load'
37
+ # @return [String,NilClass] eg., '(Gem) did_you_mean-1.2.0'
38
+ def get_version_in_gem(libfile)
39
+ defined?(VERSION) && (return VERSION)
40
+
41
+ libfile_base = libfile.sub(/^(\/)?(.+)(\.rb)?$/, '\2')
42
+ $LOAD_PATH.each do |dir|
43
+ if Dir.glob(dir+"/#{libfile_base}{,.rb}").size > 1
44
+ retstr = dir.sub(/\/lib\/?$/, '').sub(/.*\//, '')
45
+ if (%r@/gems/$@ =~ $&)
46
+ retstr.sub!(/^/, '(Gem) ')
47
+ else
48
+ retstr = sprintf("(Library under directory): %s", dir)
49
+ end
50
+ return retstr
51
+ end
52
+ end
53
+
54
+ ## Perhaps not in Gem
55
+ nil
56
+ end
57
+
58
+
59
+ # Print the version number and exit
60
+ #
61
+ # @param see #get_version_in_gem
62
+ # @return [NilClass]
63
+ def print_version_and_exit(libfile)
64
+ version = get_version_in_gem(libfile)
65
+
66
+ if version
67
+ puts version
68
+ exit
69
+ end
70
+
71
+ warn "ERROR: No version is found. Perhaps the command is not in the properly installed Gem style (or currently in development)?"
72
+ exit 1
73
+ end
74
+
75
+
76
+ # Function to handle the command-line arguments.
77
+ #
78
+ # ARGV will be modified, and the constant variable OPTS is set.
79
+ #
80
+ # @return [Hash] Optional-argument hash.
81
+ #
82
+ def handle_argv
83
+ opt = OptionParser.new(BANNER)
84
+ opt.on('-o OUTFILE', '--outfile=FILE.SQL', sprintf("Output SQL filename (Def: %s)", OPTS[:outfile]), String) { |v| OPTS[:outfile]=v }
85
+ opt.on('-m MAPPINGCSV', '--mappingfile=FILE.CSV', sprintf("Output mapping CSV filename (Def: %s)", OPTS[:mappingcsv])) { |v| OPTS[:mappingcsv]=v }
86
+ opt.on( '--[no-]withsql', sprintf("If the SQL file is created (Def: %s)", OPTS[:withsql].inspect), TrueClass) {|v| OPTS[:withsql] = v}
87
+ opt.on( '--mappingsql=FILE.SQL', sprintf("Output mapping SQL filename (Def: mapping.sql)")) { |v| OPTS[:mappingsql][:filename]=v }
88
+ opt.on( '--mapping-tbl-prefix=PREFIX', sprintf("Mapping SQL-tablename prefix (Def: %s)", OPTS[:mapping_tbl_prefix].inspect)) { |v| OPTS[:mapping_tbl_prefix]=v }
89
+ opt.on( '--mapping-tbl-suffix-from=SUFFIX', sprintf("Mapping SQL-column-name suffix for 'from' (Def: %s)", OPTS[:mapping_col_suffix_from].inspect)) { |v| OPTS[:mapping_col_suffix_from]=v }
90
+ opt.on( '--mapping-tbl-suffix-to=SUFFIX', sprintf("Mapping SQL-column-name suffix for 'to' (Def: %s)", OPTS[:mapping_col_suffix_to].inspect) ) { |v| OPTS[:mapping_col_suffix_to]=v }
91
+ opt.on( '--[no-]delete-primary', "Delete primary keys (Def: #{OPTS[:delete_primary]})", TrueClass) {|v| OPTS[:delete_primary] = v}
92
+ # opt.on( '--[no-]delete-sequence', "Delete sequences (Def: #{OPTS[:delete_sequence]})", TrueClass) {|v| OPTS[:delete_sequence] = v}
93
+ # opt.on( '--[no-]delete-trigger', "Delete triggers (Def: #{OPTS[:delete_trigger]})", TrueClass) {|v| OPTS[:delete_trigger] = v}
94
+ # opt.on( '--[no-]clobber', sprintf("Overwrites the existing files if true (Default: %s)", OPTS[:clobber].inspect.capitalize), TrueClass) { |v| OPTS[:clobber] = v}
95
+ # opt.on( '--chatter=INT', Integer, sprintf("Chatter level (0(silent) to 5(chatty), Default: %d)", OPTS[:chatter])) { |v| OPTS[:chatter] = v}
96
+ opt.on('-n', '--[no-]dryrun', "Dryrun (Def: #{OPTS[:dryrun]})", TrueClass) {|v| OPTS[:dryrun] = v}
97
+ opt.on( '--[no-]debug', "Debug (Def: false)", TrueClass) {|v| OPTS[:debug] = v}
98
+ opt.on( '--version', "Display the version and exits.", TrueClass) {|v| OPTS[:version] = v} # Consider opts.on_tail
99
+ opt.separator "" # Way to control a help message.
100
+ opt.separator "Note:"
101
+ opt.separator " Mapping-CSV-file has the columns of Old_Table, New_Table, Old_Column, New_Column."
102
+ opt.separator " Output files are overwritten."
103
+ opt.separator " In running psql after this script, --single-transaction option is highly recommended."
104
+
105
+ opt.parse!(ARGV)
106
+
107
+ if OPTS[:version]
108
+ print_version_and_exit('db_suit_rails/sql_skelton')
109
+ # print_version_and_exit('did_you_mean') # for testing
110
+ end
111
+
112
+ if OPTS[:withsql]
113
+ ## See {SqlSkelton#new} for the specification of the Hash
114
+
115
+ # Sets a default if --mappingsql is not specified explicitly.
116
+ OPTS[:mappingsql][:filename] ||= OPTS[:mappingcsv].sub(/\.csv$/i, '') + '.sql' # => (Default)"mapping.sql"
117
+
118
+ OPTS[:mappingsql][:tblname] = {
119
+ :tbl => OPTS[:mapping_tbl_prefix] + SqlSkelton::DefMappingSql[:tblname4tbl],
120
+ :col => OPTS[:mapping_tbl_prefix] + SqlSkelton::DefMappingSql[:tblname4col],
121
+ }
122
+ OPTS[:mappingsql][:colname] = {
123
+ :tbl => {
124
+ :from => SqlSkelton::DefMappingSql[:colprefix4tbl] + OPTS[:mapping_col_suffix_from],
125
+ :to => SqlSkelton::DefMappingSql[:colprefix4tbl] + OPTS[:mapping_col_suffix_to],
126
+ },
127
+ :col => {
128
+ :from => SqlSkelton::DefMappingSql[:colprefix4col] + OPTS[:mapping_col_suffix_from],
129
+ :to => SqlSkelton::DefMappingSql[:colprefix4col] + OPTS[:mapping_col_suffix_to],
130
+ },
131
+ }
132
+ end
133
+
134
+ if 'stdout' == OPTS[:outfile].downcase
135
+ OPTS[:outfile] = $stdout
136
+ end
137
+
138
+ OPTS
139
+ end
140
+
141
+
142
+ ################################################
143
+ # MAIN
144
+ ################################################
145
+
146
+ $stdout.sync=true
147
+ $stderr.sync=true
148
+
149
+ # Handle the command-line options => OPTS
150
+ handle_argv()
151
+
152
+ ss = SqlSkelton.new(ARGF, OPTS[:outfile], mappingcsv: OPTS[:mappingcsv], mappingsql: OPTS[:mappingsql])
153
+ ss.run(dryrun: OPTS[:dryrun], delete_primary: OPTS[:delete_primary], delete_sequence: OPTS[:delete_sequence], delete_trigger: OPTS[:delete_trigger])
154
+
155
+ exit
156
+
157
+ __END__
158
+