sqlserver-schema-reflector 0.0.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.
- data/.gitignore +6 -0
- data/Gemfile +7 -0
- data/Rakefile +14 -0
- data/lib/sqlserver_schema_reflector.rb +11 -0
- data/lib/sqlserver_schema_reflector/array.rb +15 -0
- data/lib/sqlserver_schema_reflector/column_reflection.rb +30 -0
- data/lib/sqlserver_schema_reflector/hash.rb +15 -0
- data/lib/sqlserver_schema_reflector/reflector.rb +21 -0
- data/lib/sqlserver_schema_reflector/string.rb +10 -0
- data/lib/sqlserver_schema_reflector/table_reflection.rb +48 -0
- data/lib/sqlserver_schema_reflector/version.rb +3 -0
- data/spec/fixtures/object_definitions.json +91 -0
- data/spec/sqlserver_schema_reflector_test.rb +80 -0
- data/sqlserver_schema_reflector.gemspec +24 -0
- metadata +96 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
task :run do
|
3
|
+
require './lib/sqlserver_schema_reflector.rb'
|
4
|
+
SqlServerSchemaReflector::Reflector.run(
|
5
|
+
File.open('./schema.sql', 'w'),
|
6
|
+
:username => 'user',
|
7
|
+
:password => 'user',
|
8
|
+
:host => '16.88.192.55',
|
9
|
+
:database => 'todNMCIAOM'
|
10
|
+
)
|
11
|
+
end
|
12
|
+
task :test do
|
13
|
+
system 'bundle exec rspec spec/sqlserver_schema_reflector_test.rb'
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module SqlServerSchemaReflector
|
2
|
+
end
|
3
|
+
require "sqlserver_schema_reflector/version"
|
4
|
+
require 'json'
|
5
|
+
require 'tiny_tds'
|
6
|
+
require 'sqlserver_schema_reflector/string'
|
7
|
+
require 'sqlserver_schema_reflector/hash'
|
8
|
+
require 'sqlserver_schema_reflector/array'
|
9
|
+
require 'sqlserver_schema_reflector/column_reflection.rb'
|
10
|
+
require "sqlserver_schema_reflector/table_reflection.rb"
|
11
|
+
require "sqlserver_schema_reflector/reflector.rb"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Array
|
2
|
+
def find_hashes(keys)
|
3
|
+
results = []
|
4
|
+
each do |item|
|
5
|
+
hash = item.find_hashes(keys)
|
6
|
+
if !hash.nil?
|
7
|
+
results.push(hash)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
return nil if results.length == 0
|
11
|
+
return results[0] if results.length == 1
|
12
|
+
return results
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class SqlServerSchemaReflector::ColumnReflection
|
2
|
+
attr_reader :identity
|
3
|
+
def initialize(properties, identity = nil)
|
4
|
+
@properties = properties
|
5
|
+
if identity[:identity] === properties[:column_name]
|
6
|
+
@identity = identity unless identity.nil?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
def name
|
10
|
+
@properties[:column_name]
|
11
|
+
end
|
12
|
+
def type
|
13
|
+
@properties[:type]
|
14
|
+
end
|
15
|
+
def length
|
16
|
+
"(#{@properties[:length]})" unless @properties[:length].nil? || type === 'int'
|
17
|
+
end
|
18
|
+
def nullable
|
19
|
+
_nullable = "NOT NULL"
|
20
|
+
_nullable = "NULL" if @properties[:nullable] === 'yes'
|
21
|
+
_nullable
|
22
|
+
end
|
23
|
+
def id_statement
|
24
|
+
"IDENTITY(#{@identity[:seed]},#{@identity[:increment]})" unless @identity.nil?
|
25
|
+
end
|
26
|
+
def sql
|
27
|
+
"[#{name}] [#{type}]#{length} #{id_statement} #{nullable}"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Hash
|
2
|
+
def symbolize_keys
|
3
|
+
inject({}) do |options, (key, value)|
|
4
|
+
options[(key.underscore.downcase.to_sym rescue key) || key] = value
|
5
|
+
options
|
6
|
+
end
|
7
|
+
end
|
8
|
+
def find_hashes(keys)
|
9
|
+
h = symbolize_keys
|
10
|
+
keys.each do |k|
|
11
|
+
return nil unless h.keys.include? k
|
12
|
+
end
|
13
|
+
return h
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class SqlServerSchemaReflector::Reflector
|
2
|
+
def self.run(out, options)
|
3
|
+
client = TinyTds::Client.new(options)
|
4
|
+
names = client.execute("SELECT ([TABLE_SCHEMA] + '.' + [TABLE_NAME]) AS name FROM information_schema.tables").map {|r| r['name']}
|
5
|
+
names.each do |name|
|
6
|
+
begin
|
7
|
+
table_hash = client.execute("sp_help '#{name}'").map { |result| result }
|
8
|
+
table = SqlServerSchemaReflector::TableReflection.new(table_hash)
|
9
|
+
out.write table.create_sql + "\n"
|
10
|
+
puts "Successfully generated create statement for #{name}"
|
11
|
+
rescue
|
12
|
+
e = "/*\n"
|
13
|
+
e << "Unable to generate create statement for table: #{name}\n"
|
14
|
+
e << $!
|
15
|
+
e << "*/\n"
|
16
|
+
out.write e
|
17
|
+
$stderr.print e
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class SqlServerSchemaReflector::TableReflection
|
2
|
+
def initialize(properties)
|
3
|
+
@properties = properties
|
4
|
+
end
|
5
|
+
def meta
|
6
|
+
@meta ||= @properties.find_hashes [:name, :owner, :type]
|
7
|
+
end
|
8
|
+
def columns
|
9
|
+
if @columns.nil?
|
10
|
+
@columns = []
|
11
|
+
column_hashes = @properties.find_hashes [:column_name, :type]
|
12
|
+
column_hashes = [column_hashes] if column_hashes.class.name == 'Hash'
|
13
|
+
column_hashes.each do |column|
|
14
|
+
@columns.push(SqlServerSchemaReflector::ColumnReflection.new(column, identity))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
@columns
|
18
|
+
end
|
19
|
+
def identity
|
20
|
+
if @identity.nil?
|
21
|
+
@identity = @properties.find_hashes [:identity, :seed, :increment]
|
22
|
+
@identity[:seed] = @identity[:seed].to_f.to_i
|
23
|
+
@identity[:increment] = @identity[:increment].to_f.to_i
|
24
|
+
end
|
25
|
+
@identity
|
26
|
+
end
|
27
|
+
def indexes
|
28
|
+
if @indexes.nil?
|
29
|
+
@indexes = @properties.find_hashes [:index_name, :index_description, :index_keys]
|
30
|
+
@indexes = [@indexes] if @indexes.class.name === 'Hash'
|
31
|
+
end
|
32
|
+
@indexes
|
33
|
+
end
|
34
|
+
def constraints
|
35
|
+
if @constraints.nil?
|
36
|
+
@constraints = @properties.find_hashes [:constraint_name, :constraint_type]
|
37
|
+
@constraints = [@constraints] if @constraints.class.name === 'Hash'
|
38
|
+
end
|
39
|
+
@constraints
|
40
|
+
end
|
41
|
+
def create_sql
|
42
|
+
sql = "CREATE TABLE [#{meta[:owner]}].[#{meta[:name]}]("
|
43
|
+
columns.each do |c|
|
44
|
+
sql << "\n\t#{c.sql},"
|
45
|
+
end
|
46
|
+
sql << "\n)"
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
[
|
2
|
+
[
|
3
|
+
[{"Name":"employees","Owner":"dbo","Type":"user table","Created_datetime":"2011-07-19 14:08:32 -0600"}],
|
4
|
+
[
|
5
|
+
{
|
6
|
+
"Column_name":"id",
|
7
|
+
"Type":"int",
|
8
|
+
"Computed":"no",
|
9
|
+
"Length":4,
|
10
|
+
"Prec":"10",
|
11
|
+
"Scale":"0",
|
12
|
+
"Nullable":"no",
|
13
|
+
"TrimTrailingBlanks":"(n/a)",
|
14
|
+
"FixedLenNullInSource":"(n/a)",
|
15
|
+
"Collation":null
|
16
|
+
},
|
17
|
+
{
|
18
|
+
"Column_name":"first_name",
|
19
|
+
"Type":"varchar",
|
20
|
+
"Computed":"no",
|
21
|
+
"Length":255,
|
22
|
+
"Prec":"",
|
23
|
+
"Scale":"",
|
24
|
+
"Nullable":"yes",
|
25
|
+
"TrimTrailingBlanks":"no",
|
26
|
+
"FixedLenNullInSource":"yes",
|
27
|
+
"Collation":"SQL_Latin1_General_CP1_CI_AS"
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"Column_name":"last_name",
|
31
|
+
"Type":"varchar",
|
32
|
+
"Computed":"no",
|
33
|
+
"Length":255,
|
34
|
+
"Prec":"",
|
35
|
+
"Scale":"",
|
36
|
+
"Nullable":"yes",
|
37
|
+
"TrimTrailingBlanks":"no",
|
38
|
+
"FixedLenNullInSource":"yes",
|
39
|
+
"Collation":"SQL_Latin1_General_CP1_CI_AS"
|
40
|
+
},
|
41
|
+
{
|
42
|
+
"Column_name":"suffix",
|
43
|
+
"Type":"varchar",
|
44
|
+
"Computed":"no",
|
45
|
+
"Length":255,
|
46
|
+
"Prec":" ",
|
47
|
+
"Scale":" ",
|
48
|
+
"Nullable":"yes",
|
49
|
+
"TrimTrailingBlanks":"no",
|
50
|
+
"FixedLenNullInSource":"yes",
|
51
|
+
"Collation":"SQL_Latin1_General_CP1_CI_AS"
|
52
|
+
}
|
53
|
+
],
|
54
|
+
[
|
55
|
+
{
|
56
|
+
"Identity":"id",
|
57
|
+
"Seed":"0.1E1",
|
58
|
+
"Increment":"0.1E1",
|
59
|
+
"Not For Replication":0
|
60
|
+
}
|
61
|
+
],
|
62
|
+
[
|
63
|
+
{
|
64
|
+
"RowGuidCol":"No rowguidcol column defined."
|
65
|
+
}
|
66
|
+
],
|
67
|
+
[
|
68
|
+
{
|
69
|
+
"Data_located_on_filegroup":"PRIMARY"
|
70
|
+
}
|
71
|
+
],
|
72
|
+
[
|
73
|
+
{
|
74
|
+
"index_name":"PK__employee__3213E83F023D5A04",
|
75
|
+
"index_description":"clustered, unique, primary key located on PRIMARY",
|
76
|
+
"index_keys":"id"
|
77
|
+
}
|
78
|
+
],
|
79
|
+
[
|
80
|
+
{
|
81
|
+
"constraint_type":"PRIMARY KEY (clustered)",
|
82
|
+
"constraint_name":"PK__employee__3213E83F023D5A04",
|
83
|
+
"delete_action":"(n/a)",
|
84
|
+
"update_action":"(n/a)",
|
85
|
+
"status_enabled":"(n/a)",
|
86
|
+
"status_for_replication":"(n/a)",
|
87
|
+
"constraint_keys":"id"
|
88
|
+
}
|
89
|
+
]
|
90
|
+
]
|
91
|
+
]
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'sqlserver_schema_reflector'
|
2
|
+
|
3
|
+
def employees_table_def
|
4
|
+
@employees_table ||= JSON.parse(File.read('./spec/fixtures/object_definitions.json'))[0]
|
5
|
+
end
|
6
|
+
|
7
|
+
def table_reflection
|
8
|
+
SqlServerSchemaReflector::TableReflection.new(employees_table_def)
|
9
|
+
end
|
10
|
+
|
11
|
+
def column_reflection
|
12
|
+
SqlServerSchemaReflector::ColumnReflection.new(
|
13
|
+
employees_table_def.find_hashes([:column_name])[0],
|
14
|
+
table_reflection.identity
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe SqlServerSchemaReflector do
|
19
|
+
describe SqlServerSchemaReflector::TableReflection do
|
20
|
+
|
21
|
+
describe "#new" do
|
22
|
+
it "creates an object with correct meta data" do
|
23
|
+
table_reflection.meta.should be_a(Hash)
|
24
|
+
table_reflection.meta[:name].should == "employees"
|
25
|
+
table_reflection.meta[:owner].should == "dbo"
|
26
|
+
table_reflection.meta[:type].should == "user table"
|
27
|
+
end
|
28
|
+
it "creates an array of column reflection objects" do
|
29
|
+
table_reflection.columns.should be_an(Array)
|
30
|
+
table_reflection.columns.length.should == 4
|
31
|
+
table_reflection.columns[0].should be_a(SqlServerSchemaReflector::ColumnReflection)
|
32
|
+
table_reflection.columns[0].name.should == "id"
|
33
|
+
table_reflection.columns[0].type.should == 'int'
|
34
|
+
end
|
35
|
+
it "creates an object with correct identity data" do
|
36
|
+
table_reflection.identity[:identity].should === 'id'
|
37
|
+
table_reflection.identity[:seed].should === 1
|
38
|
+
table_reflection.identity[:increment].should === 1
|
39
|
+
table_reflection.identity[:not_for_replication].should == 0
|
40
|
+
end
|
41
|
+
it "creates an object with correct index data" do
|
42
|
+
table_reflection.indexes.length.should === 1
|
43
|
+
table_reflection.indexes[0][:index_name].should === 'PK__employee__3213E83F023D5A04'
|
44
|
+
table_reflection.indexes[0][:index_description].should === 'clustered, unique, primary key located on PRIMARY'
|
45
|
+
table_reflection.indexes[0][:index_keys].should === 'id'
|
46
|
+
end
|
47
|
+
it "creates an object with correct constraints" do
|
48
|
+
table_reflection.constraints.length.should === 1
|
49
|
+
table_reflection.constraints[0][:constraint_name].should === "PK__employee__3213E83F023D5A04"
|
50
|
+
table_reflection.constraints[0][:constraint_type].should === "PRIMARY KEY (clustered)"
|
51
|
+
end
|
52
|
+
it "generates proper sql create table statement" do
|
53
|
+
table_reflection.create_sql.should === "" <<
|
54
|
+
"CREATE TABLE [dbo].[employees](\n" <<
|
55
|
+
"\t[id] [int] IDENTITY(1,1) NOT NULL,\n" <<
|
56
|
+
"\t[first_name] [varchar](255) NULL,\n" <<
|
57
|
+
"\t[last_name] [varchar](255) NULL,\n" <<
|
58
|
+
"\t[suffix] [varchar](255) NULL,\n" <<
|
59
|
+
")"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
describe SqlServerSchemaReflector::ColumnReflection do
|
64
|
+
it "creates an object with correct properties" do
|
65
|
+
column_reflection.name.should == 'id'
|
66
|
+
column_reflection.type.should == 'int'
|
67
|
+
end
|
68
|
+
it "creates an object with proper identity data" do
|
69
|
+
column_reflection.identity.should be_a(Hash)
|
70
|
+
column_reflection.identity[:seed].should === 1
|
71
|
+
column_reflection.identity[:increment].should === 1
|
72
|
+
end
|
73
|
+
it "creates the proper sql column declaration" do
|
74
|
+
table_reflection.columns[0].sql.should === "[id] [int] IDENTITY(1,1) NOT NULL"
|
75
|
+
table_reflection.columns[1].sql.should === "[first_name] [varchar](255) NULL"
|
76
|
+
table_reflection.columns[2].sql.should === "[last_name] [varchar](255) NULL"
|
77
|
+
table_reflection.columns[3].sql.should === '[suffix] [varchar](255) NULL'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "sqlserver_schema_reflector/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "sqlserver-schema-reflector"
|
7
|
+
s.version = SqlserverSchemaReflector::VERSION
|
8
|
+
s.authors = ["Jacob Morris"]
|
9
|
+
s.email = ["jacob.s.morris@gmail.com"]
|
10
|
+
s.homepage = "http://www.thewhitespace.co"
|
11
|
+
s.summary = %q{Analyze any SqlServer database and produce a sql script for replicating the database}
|
12
|
+
s.description = %q{Analyzing any SqlServer database and produce a sql script for replicating the database}
|
13
|
+
|
14
|
+
s.add_dependency 'json'
|
15
|
+
s.add_dependency 'json_pure'
|
16
|
+
s.add_dependency 'tiny_tds'
|
17
|
+
|
18
|
+
s.rubyforge_project = "sqlserver_schema_reflector"
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sqlserver-schema-reflector
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jacob Morris
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-07-21 00:00:00.000000000 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json
|
17
|
+
requirement: &29136084 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *29136084
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: json_pure
|
28
|
+
requirement: &29135832 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *29135832
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: tiny_tds
|
39
|
+
requirement: &29135580 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :runtime
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *29135580
|
48
|
+
description: Analyzing any SqlServer database and produce a sql script for replicating
|
49
|
+
the database
|
50
|
+
email:
|
51
|
+
- jacob.s.morris@gmail.com
|
52
|
+
executables: []
|
53
|
+
extensions: []
|
54
|
+
extra_rdoc_files: []
|
55
|
+
files:
|
56
|
+
- .gitignore
|
57
|
+
- Gemfile
|
58
|
+
- Rakefile
|
59
|
+
- lib/sqlserver_schema_reflector.rb
|
60
|
+
- lib/sqlserver_schema_reflector/array.rb
|
61
|
+
- lib/sqlserver_schema_reflector/column_reflection.rb
|
62
|
+
- lib/sqlserver_schema_reflector/hash.rb
|
63
|
+
- lib/sqlserver_schema_reflector/reflector.rb
|
64
|
+
- lib/sqlserver_schema_reflector/string.rb
|
65
|
+
- lib/sqlserver_schema_reflector/table_reflection.rb
|
66
|
+
- lib/sqlserver_schema_reflector/version.rb
|
67
|
+
- spec/fixtures/object_definitions.json
|
68
|
+
- spec/sqlserver_schema_reflector_test.rb
|
69
|
+
- sqlserver_schema_reflector.gemspec
|
70
|
+
has_rdoc: true
|
71
|
+
homepage: http://www.thewhitespace.co
|
72
|
+
licenses: []
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project: sqlserver_schema_reflector
|
91
|
+
rubygems_version: 1.5.2
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: Analyze any SqlServer database and produce a sql script for replicating the
|
95
|
+
database
|
96
|
+
test_files: []
|