sqlserver-schema-reflector 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|