activerecord-sqlserver-adapter-schemas 1.0.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.
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
== Schema support for Rails SQL Server 2000, 2005 and 2008 Adapter
|
3
|
+
|
4
|
+
Adds support for schemas to the activerecord-sqlserver-adapter gem
|
5
|
+
|
6
|
+
== Installation
|
7
|
+
|
8
|
+
$ gem install activerecord-sqlserver-adapter
|
9
|
+
$ gem install activerecord-sqlserver-adapter-schemas
|
10
|
+
|
11
|
+
Optionally configure your gem dependencies in your rails environment.rb file.
|
12
|
+
|
13
|
+
config.gem 'activerecord-sqlserver-adapter', :version => 'x.x.xx'
|
14
|
+
config.gem 'activerecord-sqlserver-adapter-schemas', :version => 'x.x.xx'
|
15
|
+
|
16
|
+
== Using Schemas with ActiveRecord
|
17
|
+
|
18
|
+
The simplest way to use schemas is to simply specify it as part of the table name
|
19
|
+
|
20
|
+
class FooBar < ActiveRecord::Base
|
21
|
+
set_table_name 'foo.bars'
|
22
|
+
end
|
23
|
+
|
24
|
+
To use any the following methods, you must first enable schema names:
|
25
|
+
|
26
|
+
ActiveRecord::Base.use_schema_names = true
|
27
|
+
|
28
|
+
With use_schema_names enabled, models in a module will use the module name as the schema name automatically. For example:
|
29
|
+
|
30
|
+
# the table name for this model would be assumed to be foo.bars
|
31
|
+
class Foo::Bar < ActiveRecord::Base
|
32
|
+
end
|
33
|
+
|
34
|
+
The schema name can also be set explicitly when use_schema_names is enabled:
|
35
|
+
|
36
|
+
class Bar < ActiveRecord::Base
|
37
|
+
set_schema_name 'foo'
|
38
|
+
end
|
39
|
+
|
40
|
+
== Migrations
|
41
|
+
|
42
|
+
It is possible to have separate schema_migrations tables in different schemas existing in the database at the same time. This is useful if you have multiple rails applications using the same database but different schemas.
|
43
|
+
|
44
|
+
To use this feature, use different users for each application with different default schemas set in the database. So if you have 2 rails applications, if they log in as different users with different default schemas, they each get their own schema_migrations table in that schema.
|
45
|
+
|
46
|
+
== License
|
47
|
+
|
48
|
+
Copyright 2010. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# This module is used to make it easier to deal with legacy char fields by trimming them automatically after a find.
|
2
|
+
module ActiveRecord
|
3
|
+
module Schemas
|
4
|
+
module Base
|
5
|
+
# returns true if schema names should be used. Default is false
|
6
|
+
def use_schema_names?
|
7
|
+
read_inheritable_attribute(:use_schema_names)
|
8
|
+
end
|
9
|
+
|
10
|
+
# sets if schema names should be used.
|
11
|
+
def use_schema_names=(value)
|
12
|
+
write_inheritable_attribute(:use_schema_names, value)
|
13
|
+
end
|
14
|
+
alias_method :set_use_schema_names, :use_schema_names=
|
15
|
+
|
16
|
+
# returns the schema name, either based on the module (via reset_schema_name) of an explicitly set value defined by the class
|
17
|
+
def schema_name
|
18
|
+
reset_schema_name
|
19
|
+
end
|
20
|
+
|
21
|
+
# calculates the schema name based on the class's module
|
22
|
+
def reset_schema_name
|
23
|
+
ar_descendant = class_of_active_record_descendant(self)
|
24
|
+
if ar_descendant == self
|
25
|
+
name = self.name.split('::').first.downcase
|
26
|
+
set_schema_name name
|
27
|
+
name
|
28
|
+
else
|
29
|
+
ar_descendant.schema_name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# overrides the default schema based on the module
|
34
|
+
def schema_name=(value = nil, &block)
|
35
|
+
define_attr_method :schema_name, value, &block
|
36
|
+
end
|
37
|
+
alias_method :set_schema_name, :schema_name=
|
38
|
+
|
39
|
+
# sets the table name with the schema
|
40
|
+
def reset_table_name_with_schema
|
41
|
+
ar_descendant = class_of_active_record_descendant(self)
|
42
|
+
if self == ar_descendant
|
43
|
+
name = reset_table_name
|
44
|
+
if use_schema_names? && schema_name
|
45
|
+
name = "#{"#{schema_name}." if schema_name}#{name}"
|
46
|
+
set_table_name name
|
47
|
+
end
|
48
|
+
name
|
49
|
+
else
|
50
|
+
name = ar_descendant.table_name
|
51
|
+
set_table_name name
|
52
|
+
name
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Schemas
|
3
|
+
module ConnectionAdapters
|
4
|
+
|
5
|
+
module SqlserverAdapter
|
6
|
+
|
7
|
+
# When this module is included, the following methods are chained in order
|
8
|
+
# to strip off the schema names if the schema is the default schema
|
9
|
+
def self.included(base)
|
10
|
+
base.alias_method_chain :columns, :default_schema_check
|
11
|
+
base.alias_method_chain :table_exists?, :default_schema_check
|
12
|
+
base.alias_method_chain :table_name_or_views_table_name, :default_schema_check
|
13
|
+
end
|
14
|
+
|
15
|
+
def default_schema
|
16
|
+
unless sqlserver_2000?
|
17
|
+
@default_schema ||= select_values("SELECT default_schema_name FROM sys.database_principals WHERE type = 'S' and name = '#{self.quote_string(@connection_options[:username])}'").first
|
18
|
+
end
|
19
|
+
@default_schema ||= 'dbo'
|
20
|
+
end
|
21
|
+
attr_writer :default_schema
|
22
|
+
|
23
|
+
def table_name_or_views_table_name_with_default_schema_check(table_name)
|
24
|
+
table_name = unqualify_table_name_if_default_schema(table_name)
|
25
|
+
table_name_or_views_table_name_without_default_schema_check(table_name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def table_exists_with_default_schema_check?(table_name)
|
29
|
+
table_name = unqualify_table_name_if_default_schema(table_name)
|
30
|
+
table_exists_without_default_schema_check?(table_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def columns_with_default_schema_check(table_name, column_name = nil)
|
34
|
+
table_name = unqualify_table_name_if_default_schema(table_name) if table_name
|
35
|
+
columns_without_default_schema_check(table_name, column_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def unqualify_schema_name(table_name)
|
39
|
+
parts = table_name.to_s.split('.')
|
40
|
+
parts.length == 1 ? default_schema : parts[parts.length - 2].gsub(/[\[\]]/,'')
|
41
|
+
end
|
42
|
+
|
43
|
+
def unqualify_table_name_if_default_schema(table_name)
|
44
|
+
schema = unqualify_schema_name(table_name)
|
45
|
+
schema == default_schema ? unqualify_table_name(table_name) : table_name
|
46
|
+
end
|
47
|
+
|
48
|
+
# override index name so that if there is a schema, rename it schema_table instead of schema.table
|
49
|
+
def index_name(table_name, options) #:nodoc:
|
50
|
+
super table_name.tr('.', '_'), options
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'active_record', 'schemas', 'base')
|
2
|
+
require File.join(File.dirname(__FILE__), 'active_record', 'schemas', 'connection_adapters', 'sqlserver_adapter')
|
3
|
+
|
4
|
+
class ActiveRecord::Base
|
5
|
+
extend ActiveRecord::Schemas::Base
|
6
|
+
|
7
|
+
def self.table_name
|
8
|
+
reset_table_name_with_schema
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class ActiveRecord::ConnectionAdapters::SQLServerAdapter
|
13
|
+
include ActiveRecord::Schemas::ConnectionAdapters::SqlserverAdapter
|
14
|
+
|
15
|
+
# This method is overridden to support linked servers
|
16
|
+
def unqualify_db_name(table_name)
|
17
|
+
table_names = table_name.to_s.split('.')
|
18
|
+
table_names.length >= 3 ? table_names[0...table_names.length - 2].join('.').tr('[]','') : nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# This method is overridden to support schema names
|
22
|
+
def tables(name = nil)
|
23
|
+
# return schema.table unless the schema is the default schema, in which case just return table
|
24
|
+
info_schema_query do
|
25
|
+
select_values("SELECT TABLE_SCHEMA + '.' + TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME <> 'dtproperties'").collect do |table|
|
26
|
+
default_schema && table.index("#{default_schema}.") == 0 ? table[default_schema.length + 1..table.length] : table
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# This method is overridden to support schema names
|
32
|
+
def views(name = nil)
|
33
|
+
# return schema.view unless the schema is the default schema, in which case just return view
|
34
|
+
@sqlserver_views_cache ||=
|
35
|
+
info_schema_query do
|
36
|
+
select_values("SELECT TABLE_SCHEMA + '.' + TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME NOT IN ('sysconstraints','syssegments')").collect do |view|
|
37
|
+
default_schema && view.index("#{default_schema}.") == 0 ? view[default_schema.length + 1..view.length] : view
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# This method is overridden to support references such as database..table
|
43
|
+
def quote_column_name(column_name)
|
44
|
+
column_name.to_s.split('..').collect do |part|
|
45
|
+
part.split('.').map{ |name| name =~ /^\[.*\]$/ ? name : "[#{name}]" }.join('.')
|
46
|
+
end.join('..')
|
47
|
+
end
|
48
|
+
|
49
|
+
# overridden to support schemas. sp_helpindex does not support linked servers
|
50
|
+
def indexes(table_name, name = nil)
|
51
|
+
db_name = unqualify_db_name(table_name)
|
52
|
+
db_name << '.' if db_name
|
53
|
+
schema_name = unqualify_schema_name(table_name) << '.'
|
54
|
+
table_name = unqualify_table_name(table_name)
|
55
|
+
|
56
|
+
select("EXEC sp_helpindex '#{quote_table_name("#{db_name}#{schema_name}#{table_name}")}'",name).inject([]) do |indexes,index|
|
57
|
+
if index['index_description'] =~ /primary key/
|
58
|
+
indexes
|
59
|
+
else
|
60
|
+
name = index['index_name']
|
61
|
+
unique = index['index_description'] =~ /unique/
|
62
|
+
columns = index['index_keys'].split(',').map do |column|
|
63
|
+
column.strip!
|
64
|
+
column.gsub! '(-)', '' if column.ends_with?('(-)')
|
65
|
+
column
|
66
|
+
end
|
67
|
+
indexes << ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, name, unique, columns)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def view_information(table_name)
|
73
|
+
db_name = unqualify_db_name(table_name)
|
74
|
+
schema_name = unqualify_schema_name(table_name)
|
75
|
+
table_name = unqualify_table_name(table_name)
|
76
|
+
|
77
|
+
@@sqlserver_view_information_cache ||= {}
|
78
|
+
@@sqlserver_view_information_cache[table_name.downcase] ||= begin
|
79
|
+
sql = "SELECT * FROM #{"#{db_name}." if db_name}INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = '#{table_name}'"
|
80
|
+
sql << " and TABLE_SCHEMA = '#{schema_name}'" if schema_name
|
81
|
+
view_info = info_schema_query { select_one(sql) }
|
82
|
+
if view_info
|
83
|
+
if view_info['VIEW_DEFINITION'].blank? || view_info['VIEW_DEFINITION'].length == 4000
|
84
|
+
view_info['VIEW_DEFINITION'] = info_schema_query { select_values("EXEC sp_helptext #{table_name}").join }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
view_info
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def column_definitions(table_name)
|
92
|
+
db_name = unqualify_db_name(table_name)
|
93
|
+
db_name << '.' if db_name
|
94
|
+
schema_name = unqualify_schema_name(table_name)
|
95
|
+
table_name = unqualify_table_name(table_name)
|
96
|
+
sql = %{
|
97
|
+
SELECT
|
98
|
+
columns.TABLE_NAME as table_name,
|
99
|
+
columns.COLUMN_NAME as name,
|
100
|
+
columns.DATA_TYPE as type,
|
101
|
+
columns.COLUMN_DEFAULT as default_value,
|
102
|
+
columns.NUMERIC_SCALE as numeric_scale,
|
103
|
+
columns.NUMERIC_PRECISION as numeric_precision,
|
104
|
+
CASE
|
105
|
+
WHEN columns.DATA_TYPE IN ('nchar','nvarchar') THEN columns.CHARACTER_MAXIMUM_LENGTH
|
106
|
+
ELSE COL_LENGTH(columns.TABLE_SCHEMA+'.'+columns.TABLE_NAME, columns.COLUMN_NAME)
|
107
|
+
END as length,
|
108
|
+
CASE
|
109
|
+
WHEN columns.IS_NULLABLE = 'YES' THEN 1
|
110
|
+
ELSE NULL
|
111
|
+
end as is_nullable,
|
112
|
+
CASE
|
113
|
+
WHEN COLUMNPROPERTY(OBJECT_ID(columns.TABLE_SCHEMA+'.'+columns.TABLE_NAME), columns.COLUMN_NAME, 'IsIdentity') = 0 THEN NULL
|
114
|
+
ELSE 1
|
115
|
+
END as is_identity
|
116
|
+
FROM #{db_name}INFORMATION_SCHEMA.COLUMNS columns
|
117
|
+
WHERE columns.TABLE_NAME = '#{table_name}'
|
118
|
+
#{"AND columns.TABLE_SCHEMA = '#{schema_name}'" if schema_name}
|
119
|
+
ORDER BY columns.ordinal_position
|
120
|
+
}.gsub(/[ \t\r\n]+/,' ')
|
121
|
+
results = info_schema_query { select(sql,nil,true) }
|
122
|
+
results.collect do |ci|
|
123
|
+
ci.symbolize_keys!
|
124
|
+
ci[:type] = case ci[:type]
|
125
|
+
when /^bit|image|text|ntext|datetime$/
|
126
|
+
ci[:type]
|
127
|
+
when /^numeric|decimal$/i
|
128
|
+
"#{ci[:type]}(#{ci[:numeric_precision]},#{ci[:numeric_scale]})"
|
129
|
+
when /^char|nchar|varchar|nvarchar|varbinary|bigint|int|smallint$/
|
130
|
+
ci[:length].to_i == -1 ? "#{ci[:type]}(max)" : "#{ci[:type]}(#{ci[:length]})"
|
131
|
+
else
|
132
|
+
ci[:type]
|
133
|
+
end
|
134
|
+
if ci[:default_value].nil? && views.include?(table_name)
|
135
|
+
real_table_name = table_name_or_views_table_name(table_name)
|
136
|
+
real_column_name = views_real_column_name(table_name,ci[:name])
|
137
|
+
col_default_sql = "SELECT c.COLUMN_DEFAULT FROM #{db_name}INFORMATION_SCHEMA.COLUMNS c WHERE c.TABLE_NAME = '#{real_table_name}' AND c.COLUMN_NAME = '#{real_column_name}'"
|
138
|
+
ci[:default_value] = info_schema_query { select_value(col_default_sql) }
|
139
|
+
end
|
140
|
+
ci[:default_value] = case ci[:default_value]
|
141
|
+
when nil, '(null)', '(NULL)'
|
142
|
+
nil
|
143
|
+
else
|
144
|
+
match_data = ci[:default_value].match(/\A\(+N?'?(.*?)'?\)+\Z/m)
|
145
|
+
match_data ? match_data[1] : nil
|
146
|
+
end
|
147
|
+
ci[:null] = ci[:is_nullable].to_i == 1 ; ci.delete(:is_nullable)
|
148
|
+
ci
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activerecord-sqlserver-adapter-schemas
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Airlite Plastics
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-06-25 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activerecord-sqlserver-adapter
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: Adds schema support to activerecord-sqlserver-adapter.
|
26
|
+
email: dtjablonski@airliteplastics.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.rdoc
|
33
|
+
files:
|
34
|
+
- MIT-LICENSE
|
35
|
+
- README.rdoc
|
36
|
+
- lib/activerecord-sqlserver-adapter-schemas.rb
|
37
|
+
- lib/active_record/schemas/base.rb
|
38
|
+
- lib/active_record/schemas/connection_adapters/sqlserver_adapter.rb
|
39
|
+
has_rdoc: true
|
40
|
+
homepage:
|
41
|
+
licenses: []
|
42
|
+
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options:
|
45
|
+
- --line-numbers
|
46
|
+
- --inline-source
|
47
|
+
- --main
|
48
|
+
- README.rdoc
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.8.6
|
56
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.3.5
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: Adds schema support to activerecord-sqlserver-adapter.
|
70
|
+
test_files: []
|
71
|
+
|