mkxms-mssql 1.0.0 → 1.1.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.
- checksums.yaml +4 -4
- data/README.md +4 -10
- data/lib/mkxms/mssql.rb +18 -0
- data/lib/mkxms/mssql/adoption_script_writer.rb +759 -91
- data/lib/mkxms/mssql/clr_aggregate_handler.rb +98 -0
- data/lib/mkxms/mssql/clr_assembly_handler.rb +92 -0
- data/lib/mkxms/mssql/clr_function_handler.rb +172 -0
- data/lib/mkxms/mssql/clr_impl.rb +58 -0
- data/lib/mkxms/mssql/clr_stored_procedure_handler.rb +88 -0
- data/lib/mkxms/mssql/clr_type_handler.rb +92 -0
- data/lib/mkxms/mssql/database_handler.rb +124 -3
- data/lib/mkxms/mssql/declaratives_creator.rb +206 -0
- data/lib/mkxms/mssql/dml_trigger_handler.rb +107 -0
- data/lib/mkxms/mssql/filegroup_handler.rb +1 -4
- data/lib/mkxms/mssql/function_handler.rb +1 -4
- data/lib/mkxms/mssql/indented_string_builder.rb +8 -2
- data/lib/mkxms/mssql/index_handler.rb +1 -4
- data/lib/mkxms/mssql/keywords.rb +492 -0
- data/lib/mkxms/mssql/primary_key_handler.rb +1 -4
- data/lib/mkxms/mssql/property_handler.rb +8 -0
- data/lib/mkxms/mssql/query_cursor.rb +12 -4
- data/lib/mkxms/mssql/references_handler.rb +24 -0
- data/lib/mkxms/mssql/role_handler.rb +1 -4
- data/lib/mkxms/mssql/scalar_type_handler.rb +108 -0
- data/lib/mkxms/mssql/schema_handler.rb +1 -4
- data/lib/mkxms/mssql/sql_string_manipulators.rb +4 -4
- data/lib/mkxms/mssql/statistics_handler.rb +1 -4
- data/lib/mkxms/mssql/stored_procedure_handler.rb +1 -4
- data/lib/mkxms/mssql/synonym_handler.rb +40 -0
- data/lib/mkxms/mssql/table_handler.rb +2 -8
- data/lib/mkxms/mssql/table_type_handler.rb +254 -0
- data/lib/mkxms/mssql/utils.rb +96 -0
- data/lib/mkxms/mssql/version.rb +1 -1
- data/lib/mkxms/mssql/view_handler.rb +1 -4
- data/spec/utils/indented_string_builder_spec.rb +21 -0
- data/spec/utils/query_cursor_spec.rb +2 -2
- data/spec/utils/sql_string_manipulators_spec.rb +59 -0
- metadata +18 -3
data/lib/mkxms/mssql/utils.rb
CHANGED
@@ -50,6 +50,92 @@ module Mkxms::Mssql::Utils
|
|
50
50
|
item.send(@children_message).each(&blk)
|
51
51
|
end
|
52
52
|
end
|
53
|
+
|
54
|
+
module StringHelpers
|
55
|
+
def expand_tabs(tabstops_every = 8)
|
56
|
+
self.lines.map do |l|
|
57
|
+
if l.include?("\t")
|
58
|
+
segs = l.split("\t")
|
59
|
+
segs[0...-1].map do |seg|
|
60
|
+
# seg length must _increase_ to a multiple of 8
|
61
|
+
spaces_needed = tabstops_every - (seg.length + 1) % tabstops_every + 1
|
62
|
+
seg + ' ' * spaces_needed
|
63
|
+
end.join('') + segs[-1]
|
64
|
+
else
|
65
|
+
l
|
66
|
+
end
|
67
|
+
end.join('')
|
68
|
+
end
|
69
|
+
|
70
|
+
def sql_quoted
|
71
|
+
%Q{N'#{gsub("'", "''")}'}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Primes in the interval [100, 255]. This enumerator can be queried by
|
76
|
+
# classes that generate RAISERROR statements to provide unique-ish context
|
77
|
+
# by passing the next multiple of one of the values taken from this
|
78
|
+
# enumerator for each RAISERROR statement output (as a literal number in
|
79
|
+
# the generated SQL). This will assist
|
80
|
+
RAISERROR_STATE_BASE = [
|
81
|
+
101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163 ,167, 173,
|
82
|
+
179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251
|
83
|
+
].each unless defined? RAISERROR_STATE_BASE
|
84
|
+
|
85
|
+
# Create one instance of this class to write a sequence of similar
|
86
|
+
# RAISERROR messages. The state of each message will be unique within the
|
87
|
+
# sequence until the 256th message. The particular order is unique to
|
88
|
+
# all other instances of this class.
|
89
|
+
class RaiserrorWriter
|
90
|
+
# Severity:
|
91
|
+
# 11 is the minimum to transfer into a CATCH
|
92
|
+
# 19 or higher can only be raised by sysadmin
|
93
|
+
# 20 or higher is fatal to the connection
|
94
|
+
|
95
|
+
SYMBOLIC_SEVERITIES = {
|
96
|
+
:warning => 1,
|
97
|
+
:error => 11,
|
98
|
+
}
|
99
|
+
|
100
|
+
def initialize(message, severity: 11)
|
101
|
+
# Get a unique prime to use as an ideal to generate the 0-255 state-value
|
102
|
+
# space. With luck, the number is fairly unique to the message.
|
103
|
+
severity = map_severity(severity)
|
104
|
+
@state_base = RAISERROR_STATE_BASE.next
|
105
|
+
@index = 1 # Start at 1 because 0 is the kernel -- every @state_base * 0 == 0
|
106
|
+
@message = message
|
107
|
+
@severity = severity
|
108
|
+
end
|
109
|
+
|
110
|
+
attr_reader :state_base
|
111
|
+
attr_accessor :message, :severity
|
112
|
+
|
113
|
+
def map_severity(value)
|
114
|
+
SYMBOLIC_SEVERITIES.fetch(value, value)
|
115
|
+
end
|
116
|
+
|
117
|
+
def current_statement(*args, severity: nil)
|
118
|
+
severity = map_severity(severity || self.severity)
|
119
|
+
state_str = current_error_marker
|
120
|
+
full_message = %Q{N'#{message.gsub("'", "''")} (search for "#{state_str}")'}
|
121
|
+
trailing_args = ([state_str] + args.map(&:to_s)).join(', ')
|
122
|
+
%Q{RAISERROR (#{full_message}, #{severity}, #{trailing_args})}.tap do |stmt|
|
123
|
+
stmt.define_singleton_method(:error_marker) {state_str}
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def current_error_marker
|
128
|
+
"/*ERR*/ #{current_state} /*ERR*/"
|
129
|
+
end
|
130
|
+
|
131
|
+
def current_state
|
132
|
+
(state_base * @index) % 256
|
133
|
+
end
|
134
|
+
|
135
|
+
def next_statement(*args, **kwargs)
|
136
|
+
current_statement(*args, **kwargs).tap {@index += 1}
|
137
|
+
end
|
138
|
+
end
|
53
139
|
end
|
54
140
|
|
55
141
|
class << Mkxms::Mssql::Utils
|
@@ -80,4 +166,14 @@ class << Mkxms::Mssql::Utils
|
|
80
166
|
l
|
81
167
|
end.join('')
|
82
168
|
end
|
169
|
+
|
170
|
+
def dry_run?
|
171
|
+
@dry_run.tap do |v|
|
172
|
+
(break @dry_run = !!(ENV.fetch('DRY_RUN', '') =~ /^(y(es)?|t(rue)?|1)$/i)) if v.nil?
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class String
|
178
|
+
include Mkxms::Mssql::Utils::StringHelpers
|
83
179
|
end
|
data/lib/mkxms/mssql/version.rb
CHANGED
@@ -34,14 +34,11 @@ module Mkxms::Mssql
|
|
34
34
|
a = node.attributes
|
35
35
|
|
36
36
|
@view = View.new(a).tap do |v|
|
37
|
+
store_properties_on v
|
37
38
|
views << v
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
41
|
-
def extended_properties
|
42
|
-
@view.extended_properties
|
43
|
-
end
|
44
|
-
|
45
42
|
def handle_definition_element(parse); end
|
46
43
|
|
47
44
|
def handle_references_element(parse)
|
@@ -213,6 +213,27 @@ describe Mkxms::Mssql::IndentedStringBuilder do
|
|
213
213
|
test_instance = test_class.new
|
214
214
|
expect(test_instance.to_s).to eql("BEGIN\n command\nEND\n")
|
215
215
|
end
|
216
|
+
|
217
|
+
it "handles blank lines properly" do
|
218
|
+
test_class = Class.new(described_class) do
|
219
|
+
def initialize
|
220
|
+
super
|
221
|
+
|
222
|
+
add_level_one
|
223
|
+
end
|
224
|
+
|
225
|
+
def add_level_one
|
226
|
+
dsl {
|
227
|
+
puts "foo"
|
228
|
+
puts
|
229
|
+
}
|
230
|
+
puts "bar"
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
test_instance = test_class.new
|
235
|
+
expect(test_instance.to_s).to eql("foo\n\nbar\n")
|
236
|
+
end
|
216
237
|
end
|
217
238
|
end
|
218
239
|
end
|
@@ -16,7 +16,7 @@ describe Mkxms::Mssql::QueryCursor do
|
|
16
16
|
sql.puts " -- Handle a row"
|
17
17
|
end
|
18
18
|
|
19
|
-
expect(sql.string).to eql("DECLARE @schema_id INT, @schema_name SYSNAME;\nDECLARE test_cursor CURSOR LOCAL FOR\nSELECT schema_id, name FROM sys.schemas;\nFETCH NEXT FROM test_cursor INTO @schema_id, @schema_name;\nWHILE @@FETCH_STATUS = 0\nBEGIN\n -- Handle a row\n FETCH NEXT FROM test_cursor INTO @schema_id, @schema_name;\nEND;\n")
|
19
|
+
expect(sql.string).to eql("DECLARE @schema_id INT, @schema_name SYSNAME;\nDECLARE test_cursor CURSOR LOCAL FOR\nSELECT schema_id, name FROM sys.schemas;\nOPEN test_cursor;\nFETCH NEXT FROM test_cursor INTO @schema_id, @schema_name;\nWHILE @@FETCH_STATUS = 0\nBEGIN\n -- Handle a row\n FETCH NEXT FROM test_cursor INTO @schema_id, @schema_name;\nEND;\n")
|
20
20
|
end
|
21
21
|
|
22
22
|
it "provides a expectation loop" do
|
@@ -52,6 +52,6 @@ describe Mkxms::Mssql::QueryCursor do
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
expect(sql.string).to eql("DECLARE @column_name SYSNAME, @is_sorted_descending BIT;\nDECLARE test_cursor CURSOR LOCAL FOR\nSELECT c.name, ic.is_descending_key FROM sys.index_columns ic JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id WHERE ic.object_id = @relation_id AND ic.index_id = @index_id AND ic.key_ordinal >= 1 ORDER BY ic.key_ordinal;\nFETCH NEXT FROM test_cursor INTO @column_name, @is_sorted_descending;\nIF @@FETCH_STATUS <> 0\nBEGIN\n-- Handle missing entry\nEND ELSE BEGIN\n-- Test column name is foo.\n-- Test is ascending.\nEND;\nFETCH NEXT FROM test_cursor INTO @column_name, @is_sorted_descending;\nIF @@FETCH_STATUS <> 0\nBEGIN\n-- Handle missing entry\nEND ELSE BEGIN\n-- Test column name is bar.\n-- Test is ascending.\nEND;\nFETCH NEXT FROM test_cursor INTO @column_name, @is_sorted_descending;\nIF @@FETCH_STATUS <> 0\nBEGIN\n-- Handle missing entry\nEND ELSE BEGIN\n-- Test column name is baz.\n-- Test is descending.\nEND;\nFETCH NEXT FROM test_cursor INTO @column_name, @is_sorted_descending;\nIF @@FETCH_STATUS = 0\nBEGIN\n-- Handle extra entry/ies\nEND;\nCLOSE test_cursor; DEALLOCATE test_cursor;\n")
|
55
|
+
expect(sql.string).to eql("DECLARE @column_name SYSNAME, @is_sorted_descending BIT;\nDECLARE test_cursor CURSOR LOCAL FOR\nSELECT c.name, ic.is_descending_key FROM sys.index_columns ic JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id WHERE ic.object_id = @relation_id AND ic.index_id = @index_id AND ic.key_ordinal >= 1 ORDER BY ic.key_ordinal;\nOPEN test_cursor;\n\nFETCH NEXT FROM test_cursor INTO @column_name, @is_sorted_descending;\nIF @@FETCH_STATUS <> 0\nBEGIN\n-- Handle missing entry\nEND ELSE BEGIN\n-- Test column name is foo.\n-- Test is ascending.\nEND;\n\nFETCH NEXT FROM test_cursor INTO @column_name, @is_sorted_descending;\nIF @@FETCH_STATUS <> 0\nBEGIN\n-- Handle missing entry\nEND ELSE BEGIN\n-- Test column name is bar.\n-- Test is ascending.\nEND;\n\nFETCH NEXT FROM test_cursor INTO @column_name, @is_sorted_descending;\nIF @@FETCH_STATUS <> 0\nBEGIN\n-- Handle missing entry\nEND ELSE BEGIN\n-- Test column name is baz.\n-- Test is descending.\nEND;\nFETCH NEXT FROM test_cursor INTO @column_name, @is_sorted_descending;\nIF @@FETCH_STATUS = 0\nBEGIN\n-- Handle extra entry/ies\nEND;\nCLOSE test_cursor; DEALLOCATE test_cursor;\n")
|
56
56
|
end
|
57
57
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'mkxms/mssql/sql_string_manipulators'
|
2
|
+
|
3
|
+
describe Mkxms::Mssql::SqlStringManipulators do
|
4
|
+
module T
|
5
|
+
extend Mkxms::Mssql::SqlStringManipulators
|
6
|
+
end
|
7
|
+
|
8
|
+
context "dedenting" do
|
9
|
+
it "handles a string with no newlines" do
|
10
|
+
expect(T.dedent("foo")).to eq("foo")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "handles a string with a all lines at a constant indent" do
|
14
|
+
s = T.dedent %Q{
|
15
|
+
Jack and Jill went up the hill
|
16
|
+
to fetch a pail of water
|
17
|
+
}
|
18
|
+
expect(s.lines.size).to eq(2)
|
19
|
+
expect(s.lines[0]).not_to start_with(' ')
|
20
|
+
end
|
21
|
+
|
22
|
+
it "handles nested indentation" do
|
23
|
+
s = T.dedent %Q{
|
24
|
+
one
|
25
|
+
two
|
26
|
+
one
|
27
|
+
two
|
28
|
+
}
|
29
|
+
expect(s.lines.size).to eq(4)
|
30
|
+
expect(s.lines[0]).not_to start_with(' ')
|
31
|
+
expect(s.lines[1]).to start_with(' t')
|
32
|
+
end
|
33
|
+
|
34
|
+
it "allows leading blank lines" do
|
35
|
+
s = T.dedent %Q{
|
36
|
+
|
37
|
+
after the break
|
38
|
+
}
|
39
|
+
expect(s.lines[0]).to match(/^\s*$/)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "allows trailing blank lines" do
|
43
|
+
s = T.dedent %Q{
|
44
|
+
before the break
|
45
|
+
|
46
|
+
}
|
47
|
+
expect(s.lines[1]).to match(/^\s*$/)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "allows internal blank lines" do
|
51
|
+
s = T.dedent %Q{
|
52
|
+
before
|
53
|
+
|
54
|
+
after
|
55
|
+
}
|
56
|
+
expect(s.lines[1]).to eq("\n")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mkxms-mssql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Weeks
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: xmigra
|
@@ -85,8 +85,16 @@ files:
|
|
85
85
|
- lib/mkxms/mssql/access_object_definition.rb
|
86
86
|
- lib/mkxms/mssql/adoption_script_writer.rb
|
87
87
|
- lib/mkxms/mssql/check_constraint_handler.rb
|
88
|
+
- lib/mkxms/mssql/clr_aggregate_handler.rb
|
89
|
+
- lib/mkxms/mssql/clr_assembly_handler.rb
|
90
|
+
- lib/mkxms/mssql/clr_function_handler.rb
|
91
|
+
- lib/mkxms/mssql/clr_impl.rb
|
92
|
+
- lib/mkxms/mssql/clr_stored_procedure_handler.rb
|
93
|
+
- lib/mkxms/mssql/clr_type_handler.rb
|
88
94
|
- lib/mkxms/mssql/database_handler.rb
|
95
|
+
- lib/mkxms/mssql/declaratives_creator.rb
|
89
96
|
- lib/mkxms/mssql/default_constraint_handler.rb
|
97
|
+
- lib/mkxms/mssql/dml_trigger_handler.rb
|
90
98
|
- lib/mkxms/mssql/engine.rb
|
91
99
|
- lib/mkxms/mssql/exceptions.rb
|
92
100
|
- lib/mkxms/mssql/filegroup_handler.rb
|
@@ -96,16 +104,21 @@ files:
|
|
96
104
|
- lib/mkxms/mssql/index_column.rb
|
97
105
|
- lib/mkxms/mssql/index_handler.rb
|
98
106
|
- lib/mkxms/mssql/keylike_constraint_helper.rb
|
107
|
+
- lib/mkxms/mssql/keywords.rb
|
99
108
|
- lib/mkxms/mssql/permission_handler.rb
|
100
109
|
- lib/mkxms/mssql/primary_key_handler.rb
|
101
110
|
- lib/mkxms/mssql/property_handler.rb
|
102
111
|
- lib/mkxms/mssql/query_cursor.rb
|
112
|
+
- lib/mkxms/mssql/references_handler.rb
|
103
113
|
- lib/mkxms/mssql/role_handler.rb
|
114
|
+
- lib/mkxms/mssql/scalar_type_handler.rb
|
104
115
|
- lib/mkxms/mssql/schema_handler.rb
|
105
116
|
- lib/mkxms/mssql/sql_string_manipulators.rb
|
106
117
|
- lib/mkxms/mssql/statistics_handler.rb
|
107
118
|
- lib/mkxms/mssql/stored_procedure_handler.rb
|
119
|
+
- lib/mkxms/mssql/synonym_handler.rb
|
108
120
|
- lib/mkxms/mssql/table_handler.rb
|
121
|
+
- lib/mkxms/mssql/table_type_handler.rb
|
109
122
|
- lib/mkxms/mssql/unique_constraint_handler.rb
|
110
123
|
- lib/mkxms/mssql/utils.rb
|
111
124
|
- lib/mkxms/mssql/version.rb
|
@@ -113,6 +126,7 @@ files:
|
|
113
126
|
- mkxms-mssql.gemspec
|
114
127
|
- spec/utils/indented_string_builder_spec.rb
|
115
128
|
- spec/utils/query_cursor_spec.rb
|
129
|
+
- spec/utils/sql_string_manipulators_spec.rb
|
116
130
|
homepage: ''
|
117
131
|
licenses:
|
118
132
|
- MIT
|
@@ -133,10 +147,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
147
|
version: '0'
|
134
148
|
requirements: []
|
135
149
|
rubyforge_project:
|
136
|
-
rubygems_version: 2.
|
150
|
+
rubygems_version: 2.4.8
|
137
151
|
signing_key:
|
138
152
|
specification_version: 4
|
139
153
|
summary: XMigra source files from MS-SQL database description.
|
140
154
|
test_files:
|
141
155
|
- spec/utils/indented_string_builder_spec.rb
|
142
156
|
- spec/utils/query_cursor_spec.rb
|
157
|
+
- spec/utils/sql_string_manipulators_spec.rb
|