rails-sqlserver-2000-2005-adapter 1.0.1 → 2.2.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/README.rdoc +91 -10
- data/Rakefile +0 -51
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +69 -69
- data/test/cases/adapter_test_sqlserver.rb +0 -27
- data/test/cases/column_test_sqlserver.rb +200 -20
- data/test/cases/schema_dumper_test_sqlserver.rb +40 -19
- data/test/cases/sqlserver_helper.rb +8 -0
- data/test/cases/table_name_test_sqlserver.rb +23 -0
- data/test/cases/unicode_test_sqlserver.rb +44 -0
- data/test/schema/sqlserver_specific_schema.rb +26 -0
- metadata +5 -2
data/README.rdoc
CHANGED
@@ -1,36 +1,117 @@
|
|
1
1
|
|
2
2
|
== Rails SQL Server 2000 & 2005 Adapter
|
3
3
|
|
4
|
-
|
4
|
+
The SQL Server adapter for rails is back for ActiveRecord 2.2 and up! We are currently passing all tests and hope to continue to do so moving forward.
|
5
|
+
|
6
|
+
|
7
|
+
== What's New
|
8
|
+
|
9
|
+
* Enabled support for DDL transactions.
|
10
|
+
* Micro second support. Time#usec is automatically converted to SQL Server's 3.33 millisecond limitation.
|
11
|
+
* Datetime data types before type casting are represented correctly. For example: 1998-01-01 23:59:59.997
|
12
|
+
* Implementation for #disable_referential_integrity used by ActiveRecord's Fixtures class.
|
13
|
+
* Pessimistic locking suppot. See the #add_lock! method for details.
|
14
|
+
* Enabled #case_sensitive_equality_operator used by unique validations.
|
15
|
+
* Unicode character support for nchar, nvarchar and ntext data types.
|
16
|
+
|
17
|
+
==== Date/Time Data Type Hinting
|
18
|
+
|
19
|
+
Both SQL Server 2000 and 2005 do not have native data types for just 'date' or 'time', it only has 'datetime'. To pass the ActiveRecord tests we implemented two simple class methods that can teach your models to coerce column information to be cast correctly. Simply past a list of symbols to either the <tt>coerce_sqlserver_date</tt> or <tt>coerce_sqlserver_time</tt> methods that correspond to 'datetime' columns that need to be cast correctly.
|
20
|
+
|
21
|
+
class Topic < ActiveRecord::Base
|
22
|
+
coerce_sqlserver_date :last_read
|
23
|
+
coerce_sqlserver_time :bonus_time
|
24
|
+
end
|
25
|
+
|
26
|
+
This implementation has some limitations. To date we can only coerce date/time types for models that conform to the expected ActiveRecord class to table naming convention. So a table of 'foo_bar_widgets' will look for coerced types in the FooBarWidget class if it exists.
|
27
|
+
|
28
|
+
==== Native Data Type Support
|
29
|
+
|
30
|
+
Currently the following custom data types have been tested for schema definitions.
|
31
|
+
|
32
|
+
* char
|
33
|
+
* nchar
|
34
|
+
* nvarchar
|
35
|
+
* ntext
|
36
|
+
* varchar(max) for SQL Server 2005 only.
|
37
|
+
* nvarchar(max) for SQL Server 2005 only.
|
38
|
+
|
39
|
+
For example:
|
40
|
+
|
41
|
+
create_table :sql_server_custom_types, :force => true do |t|
|
42
|
+
t.column :ten_code, :char, :limit => 10
|
43
|
+
t.column :ten_code_utf8, :nchar, :limit => 10
|
44
|
+
t.column :title_utf8, :nvarchar
|
45
|
+
t.column :body, :varchar_max # Creates varchar(max)
|
46
|
+
t.column :body_utf8, :ntext
|
47
|
+
t.column :body2_utf8, :nvarchar_max # Creates nvarchar(max)
|
48
|
+
end
|
49
|
+
|
50
|
+
Manually creating a varchar(max) on SQL Server 2005 is not necessary since this is the default type created when specifying a :text field. As time goes on we will be testing other SQL Server specific data types are handled correctly when created in a migration.
|
51
|
+
|
52
|
+
|
53
|
+
==== Native Text/Binary Data Type Accessor
|
54
|
+
|
55
|
+
To pass the ActiveRecord tests we had to implement an class accessor for the native type created for :text columns. By default any :text column created by migrations will create these native types.
|
56
|
+
|
57
|
+
* SQL Server 2000 is 'text'
|
58
|
+
* SQL Server 2005 is 'varchar(max)'
|
59
|
+
|
60
|
+
During testing this type is set to 'varchar(8000)' for both versions. The reason is that rails expects to be able to use SQL = operators on text data types and this is not possible with a native 'text' data type in SQL Server. The default 'varchar(max)' for SQL Server 2005 can be queried using the SQL = operator and has plenty of storage space which is why we made it the default for 2005. If for some reason you want to change the data type created during migrations for any SQL Server version, you can include this line in your environment.rb file.
|
61
|
+
|
62
|
+
ActiveRecord::ConnectionAdapters::SQLServerAdapter.native_text_database_type = 'varchar(8000)'
|
63
|
+
|
64
|
+
By default any :binary column created by migrations will create these native types
|
65
|
+
|
66
|
+
* SQL Server 2000 is 'image'
|
67
|
+
* SQL Server 2005 is 'varbinary(max)'
|
68
|
+
|
69
|
+
|
70
|
+
== Versions
|
71
|
+
|
72
|
+
It is our goal to match the adapter version with each version of rails. However we will track our own tiny version independent of ActiveRecord. For example, an adapter version of 2.2.x will work on any 2.2.x version of ActiveRecord. This convention will be used in both the Git tags as well as the Rubygems versioning.
|
5
73
|
|
6
74
|
|
7
75
|
== Installation
|
8
|
-
|
9
|
-
This method is unconfirmed. You can install the adapter as a gem using the following command. Once I confirm this I can give you an example of a config.gem command too. For now I know that rails and/or ActiveRecord expects to find the SQL Server adapter in the vendor/plugins/adapters/sqlserver folder of your rails project.
|
10
76
|
|
11
|
-
|
77
|
+
First, you will need Ruby DBI and Ruby ODBC. To my knowledge the ADO DBD for DBI is no longer supported. The installation below is not a comprehensive walk thru on how to get all the required moving parts like FreeTDS installed and/or configured. It will also assume gem installations of both the dependent libraries and the adapter itself.
|
12
78
|
|
13
|
-
|
79
|
+
It should be noted that this version of the adapter was developed using both the ancient 0.0.23 version of DBI up to the current stable release of 0.4.0. Because later versions of DBI will be changing many things, IT IS HIGHLY RECOMMENDED that you max your install to version 0.4.0 which the examples below show. For the time being we are not supporting DBI versions higher than 0.4.0. The good news is that if you were using a very old DBI with ADO, technically this adapter will still work for you, but be warned your path is getting old and may not be supported for long.
|
14
80
|
|
15
|
-
$
|
16
|
-
$
|
81
|
+
$ gem install dbi --version 0.4.0
|
82
|
+
$ gem install dbd-odbc --version 0.2.4
|
83
|
+
$ gem install rails-sqlserver-2000-2005-adapter
|
17
84
|
|
18
85
|
Optionally configure your gem dependencies in your rails environment.rb file.
|
19
86
|
|
20
87
|
config.gem 'dbi', :version => '0.4.0'
|
21
88
|
config.gem 'dbd-odbc', :version => '0.2.4', :lib => 'dbd/ODBC'
|
89
|
+
config.gem 'rails-sqlserver-2000-2005-adapter', :lib => 'active_record/connection_adapters/sqlserver_adapter'
|
90
|
+
|
91
|
+
Here are some external links for libraries and/or tutorials on how to install any other additional components to use this adapter. If you know of a good one that we can include here, just let us know.
|
92
|
+
|
93
|
+
* http://ruby-dbi.sourceforge.net/
|
94
|
+
* http://www.ch-werner.de/rubyodbc/
|
22
95
|
|
23
96
|
|
24
97
|
== Contributing
|
25
98
|
|
26
|
-
Please read the RUNNING_UNIT_TESTS file for the details of how to run the unit tests.
|
99
|
+
If you’d like to contribute a feature or bugfix, thanks! To make sure your fix/feature has a high chance of being added, please read the following guidelines. First, ask on the Google list, IRC, or post a ticket in Lighthouse. Second, make sure there are tests! We will not accept any patch that is not tested. Please read the RUNNING_UNIT_TESTS file for the details of how to run the unit tests.
|
27
100
|
|
28
|
-
|
101
|
+
* Lighthouse: http://rails-sqlserver.lighthouseapp.com/projects/20277-sql-server-05-adapter/overview
|
102
|
+
* Google Group: http://groups.google.com/group/rails-sqlserver-adapter
|
103
|
+
* IRC Room: #rails-sqlserver on irc.freenode.net
|
29
104
|
|
30
105
|
|
31
106
|
== Credits
|
32
107
|
|
33
|
-
Many many people have contributed
|
108
|
+
Many many people have contributed. If you do not see your name here and it should be let us know.
|
109
|
+
|
110
|
+
* Ken Collins
|
111
|
+
* Murray Steele
|
112
|
+
* Shawn Balestracci
|
113
|
+
* Joe Rafaniello
|
114
|
+
* Tom Ward
|
34
115
|
|
35
116
|
|
36
117
|
== License
|
data/Rakefile
CHANGED
@@ -1,52 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
3
|
require 'rake/testtask'
|
4
|
-
require 'rake/packagetask'
|
5
|
-
require 'rake/gempackagetask'
|
6
|
-
require 'rake/contrib/rubyforgepublisher'
|
7
4
|
|
8
|
-
PKG_NAME = 'activerecord-sqlserver-adapter'
|
9
|
-
PKG_BUILD = (".#{ENV['PKG_BUILD']}" if ENV['PKG_BUILD'])
|
10
|
-
PKG_VERSION = "1.0.0.314#{PKG_BUILD}"
|
11
|
-
|
12
|
-
spec = Gem::Specification.new do |s|
|
13
|
-
s.name = PKG_NAME
|
14
|
-
s.summary = 'SQL Server adapter for Active Record - ABR'
|
15
|
-
s.version = PKG_VERSION
|
16
|
-
|
17
|
-
s.add_dependency 'activerecord', '>= 1.15.5.7843'
|
18
|
-
s.require_path = 'lib'
|
19
|
-
|
20
|
-
s.files = %w(lib/active_record/connection_adapters/sqlserver_adapter.rb)
|
21
|
-
|
22
|
-
s.author = 'Tom Ward'
|
23
|
-
s.email = 'tom@popdog.net'
|
24
|
-
s.homepage = 'http://wiki.rubyonrails.org/rails/pages/SQL+Server'
|
25
|
-
s.rubyforge_project = 'activerecord'
|
26
|
-
end
|
27
|
-
|
28
|
-
Rake::GemPackageTask.new(spec) do |p|
|
29
|
-
p.gem_spec = spec
|
30
|
-
p.need_tar = true
|
31
|
-
p.need_zip = true
|
32
|
-
end
|
33
|
-
|
34
|
-
desc "Publish the beta gem"
|
35
|
-
task :pgem => :package do
|
36
|
-
Rake::SshFilePublisher.new("davidhh@wrath.rubyonrails.org", "public_html/gems/gems", "pkg", "#{PKG_NAME}-#{PKG_VERSION}.gem").upload
|
37
|
-
`ssh davidhh@wrath.rubyonrails.org './gemupdate.sh'`
|
38
|
-
end
|
39
|
-
|
40
|
-
desc "Publish the release files to RubyForge."
|
41
|
-
task :release => :package do
|
42
|
-
require 'rubyforge'
|
43
|
-
|
44
|
-
packages = %w(gem tgz zip).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" }
|
45
|
-
|
46
|
-
rubyforge = RubyForge.new
|
47
|
-
rubyforge.login
|
48
|
-
rubyforge.add_release(PKG_NAME, PKG_NAME, "REL #{PKG_VERSION}", *packages)
|
49
|
-
end
|
50
5
|
|
51
6
|
desc 'Create the SQL Server test databases'
|
52
7
|
task :create_databases do
|
@@ -87,9 +42,3 @@ for adapter in %w( sqlserver sqlserver_odbc )
|
|
87
42
|
end
|
88
43
|
end
|
89
44
|
|
90
|
-
|
91
|
-
desc 'Clean existing gems out'
|
92
|
-
task :clean do
|
93
|
-
packages = %w(gem tgz zip).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" }
|
94
|
-
FileUtils.rm(packages, :force => true)
|
95
|
-
end
|
@@ -61,7 +61,7 @@ module ActiveRecord
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def is_utf8?
|
64
|
-
sql_type =~ /nvarchar|ntext|nchar
|
64
|
+
sql_type =~ /nvarchar|ntext|nchar/i
|
65
65
|
end
|
66
66
|
|
67
67
|
def table_name
|
@@ -77,10 +77,16 @@ module ActiveRecord
|
|
77
77
|
|
78
78
|
def extract_limit(sql_type)
|
79
79
|
case sql_type
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
80
|
+
when /^smallint/i
|
81
|
+
2
|
82
|
+
when /^int/i
|
83
|
+
4
|
84
|
+
when /^bigint/i
|
85
|
+
8
|
86
|
+
when /\(max\)/, /decimal/, /numeric/
|
87
|
+
nil
|
88
|
+
else
|
89
|
+
super
|
84
90
|
end
|
85
91
|
end
|
86
92
|
|
@@ -146,14 +152,14 @@ module ActiveRecord
|
|
146
152
|
ADAPTER_NAME = 'SQLServer'.freeze
|
147
153
|
DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s+(\d{4})/
|
148
154
|
SUPPORTED_VERSIONS = [2000,2005].freeze
|
149
|
-
LIMITABLE_TYPES = [
|
155
|
+
LIMITABLE_TYPES = ['string','integer','float','char','nchar','varchar','nvarchar'].freeze
|
150
156
|
|
151
|
-
cattr_accessor :native_text_database_type
|
157
|
+
cattr_accessor :native_text_database_type, :native_binary_database_type
|
152
158
|
|
153
159
|
class << self
|
154
160
|
|
155
161
|
def type_limitable?(type)
|
156
|
-
LIMITABLE_TYPES.include?(type.
|
162
|
+
LIMITABLE_TYPES.include?(type.to_s)
|
157
163
|
end
|
158
164
|
|
159
165
|
end
|
@@ -205,11 +211,22 @@ module ActiveRecord
|
|
205
211
|
self.class.native_text_database_type || (sqlserver_2005? ? 'varchar(max)' : 'text')
|
206
212
|
end
|
207
213
|
|
214
|
+
def native_binary_database_type
|
215
|
+
self.class.native_binary_database_type || (sqlserver_2005? ? 'varbinary(max)' : 'image')
|
216
|
+
end
|
217
|
+
|
208
218
|
# QUOTING ==================================================#
|
209
219
|
|
210
220
|
def quote(value, column = nil)
|
211
|
-
|
212
|
-
|
221
|
+
case value
|
222
|
+
when String, ActiveSupport::Multibyte::Chars
|
223
|
+
if column && column.type == :binary
|
224
|
+
column.class.string_to_binary(value)
|
225
|
+
elsif column && column.respond_to?(:is_utf8?) && column.is_utf8?
|
226
|
+
quoted_utf8_value(value)
|
227
|
+
else
|
228
|
+
super
|
229
|
+
end
|
213
230
|
else
|
214
231
|
super
|
215
232
|
end
|
@@ -223,6 +240,11 @@ module ActiveRecord
|
|
223
240
|
column_name.to_s.split('.').map{ |name| "[#{name}]" }.join('.')
|
224
241
|
end
|
225
242
|
|
243
|
+
def quote_table_name(table_name)
|
244
|
+
return table_name if table_name =~ /^\[.*\]$/
|
245
|
+
quote_column_name(table_name)
|
246
|
+
end
|
247
|
+
|
226
248
|
def quoted_true
|
227
249
|
'1'
|
228
250
|
end
|
@@ -239,6 +261,10 @@ module ActiveRecord
|
|
239
261
|
end
|
240
262
|
end
|
241
263
|
|
264
|
+
def quoted_utf8_value(value)
|
265
|
+
"N'#{quote_string(value)}'"
|
266
|
+
end
|
267
|
+
|
242
268
|
# REFERENTIAL INTEGRITY ====================================#
|
243
269
|
|
244
270
|
def disable_referential_integrity(&block)
|
@@ -389,20 +415,26 @@ module ActiveRecord
|
|
389
415
|
# SCHEMA STATEMENTS ========================================#
|
390
416
|
|
391
417
|
def native_database_types
|
392
|
-
binary = sqlserver_2005? ? "varbinary(max)" : "image"
|
393
418
|
{
|
394
|
-
:primary_key
|
395
|
-
:string
|
396
|
-
:text
|
397
|
-
:integer
|
398
|
-
:float
|
399
|
-
:decimal
|
400
|
-
:datetime
|
401
|
-
:timestamp
|
402
|
-
:time
|
403
|
-
:date
|
404
|
-
:binary
|
405
|
-
:boolean
|
419
|
+
:primary_key => "int NOT NULL IDENTITY(1, 1) PRIMARY KEY",
|
420
|
+
:string => { :name => "varchar", :limit => 255 },
|
421
|
+
:text => { :name => native_text_database_type },
|
422
|
+
:integer => { :name => "int", :limit => 4 },
|
423
|
+
:float => { :name => "float", :limit => 8 },
|
424
|
+
:decimal => { :name => "decimal" },
|
425
|
+
:datetime => { :name => "datetime" },
|
426
|
+
:timestamp => { :name => "datetime" },
|
427
|
+
:time => { :name => "datetime" },
|
428
|
+
:date => { :name => "datetime" },
|
429
|
+
:binary => { :name => native_binary_database_type },
|
430
|
+
:boolean => { :name => "bit"},
|
431
|
+
# These are custom types that may move somewhere else for good schema_dumper.rb hacking to output them.
|
432
|
+
:char => { :name => 'char' },
|
433
|
+
:varchar_max => { :name => 'varchar(max)' },
|
434
|
+
:nchar => { :name => "nchar" },
|
435
|
+
:nvarchar => { :name => "nvarchar", :limit => 255 },
|
436
|
+
:nvarchar_max => { :name => "nvarchar(max)" },
|
437
|
+
:ntext => { :name => "ntext" }
|
406
438
|
}
|
407
439
|
end
|
408
440
|
|
@@ -500,7 +532,8 @@ module ActiveRecord
|
|
500
532
|
|
501
533
|
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
502
534
|
limit = nil unless self.class.type_limitable?(type)
|
503
|
-
|
535
|
+
case type.to_s
|
536
|
+
when 'integer'
|
504
537
|
case limit
|
505
538
|
when 1..2 then 'smallint'
|
506
539
|
when 3..4, nil then 'integer'
|
@@ -601,12 +634,10 @@ module ActiveRecord
|
|
601
634
|
end
|
602
635
|
|
603
636
|
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
604
|
-
set_utf8_values!(sql)
|
605
637
|
super || select_value("SELECT SCOPE_IDENTITY() AS Ident")
|
606
638
|
end
|
607
639
|
|
608
640
|
def update_sql(sql, name = nil)
|
609
|
-
set_utf8_values!(sql)
|
610
641
|
execute(sql, name)
|
611
642
|
select_value('SELECT @@ROWCOUNT AS AffectedRows')
|
612
643
|
end
|
@@ -789,11 +820,9 @@ module ActiveRecord
|
|
789
820
|
def column_definitions(table_name)
|
790
821
|
db_name = unqualify_db_name(table_name)
|
791
822
|
table_name = unqualify_table_name(table_name)
|
792
|
-
# COL_LENGTH returns values that do not reflect how much data can be stored in certain data types.
|
793
|
-
# COL_LENGTH returns -1 for varchar(max), nvarchar(max), and varbinary(max)
|
794
|
-
# COL_LENGTH returns 16 for ntext, text, image types
|
795
823
|
sql = %{
|
796
824
|
SELECT
|
825
|
+
columns.TABLE_NAME as table_name,
|
797
826
|
columns.COLUMN_NAME as name,
|
798
827
|
columns.DATA_TYPE as type,
|
799
828
|
CASE
|
@@ -803,10 +832,7 @@ module ActiveRecord
|
|
803
832
|
columns.NUMERIC_SCALE as numeric_scale,
|
804
833
|
columns.NUMERIC_PRECISION as numeric_precision,
|
805
834
|
CASE
|
806
|
-
WHEN columns.DATA_TYPE IN ('nvarchar')
|
807
|
-
WHEN columns.DATA_TYPE IN ('varchar', 'varbinary') AND COL_LENGTH(columns.TABLE_NAME, columns.COLUMN_NAME) = -1 THEN 2147483647
|
808
|
-
WHEN columns.DATA_TYPE IN ('ntext') AND COL_LENGTH(columns.TABLE_NAME, columns.COLUMN_NAME) = 16 THEN 1073741823
|
809
|
-
WHEN columns.DATA_TYPE IN ('text', 'image') AND COL_LENGTH(columns.TABLE_NAME, columns.COLUMN_NAME) = 16 THEN 2147483647
|
835
|
+
WHEN columns.DATA_TYPE IN ('nchar','nvarchar') THEN columns.CHARACTER_MAXIMUM_LENGTH
|
810
836
|
ELSE COL_LENGTH(columns.TABLE_NAME, columns.COLUMN_NAME)
|
811
837
|
END as length,
|
812
838
|
CASE
|
@@ -824,12 +850,16 @@ module ActiveRecord
|
|
824
850
|
results = without_type_conversion { select(sql,nil,true) }
|
825
851
|
results.collect do |ci|
|
826
852
|
ci.symbolize_keys!
|
827
|
-
ci[:type] =
|
853
|
+
ci[:type] = case ci[:type]
|
854
|
+
when /^bit|image|text|ntext|datetime$/
|
855
|
+
ci[:type]
|
856
|
+
when /^numeric|decimal$/i
|
828
857
|
"#{ci[:type]}(#{ci[:numeric_precision]},#{ci[:numeric_scale]})"
|
858
|
+
when /^char|nchar|varchar|nvarchar|varbinary|bigint|int|smallint$/
|
859
|
+
ci[:length].to_i == -1 ? "#{ci[:type]}(max)" : "#{ci[:type]}(#{ci[:length]})"
|
829
860
|
else
|
830
|
-
|
861
|
+
ci[:type]
|
831
862
|
end
|
832
|
-
ci[:table_name] = table_name
|
833
863
|
ci[:default_value] = ci[:default_value].match(/\A\(+N?'?(.*?)'?\)+\Z/)[1] if ci[:default_value]
|
834
864
|
ci[:null] = ci[:is_nullable].to_i == 1 ; ci.delete(:is_nullable)
|
835
865
|
ci
|
@@ -843,8 +873,6 @@ module ActiveRecord
|
|
843
873
|
column
|
844
874
|
end
|
845
875
|
|
846
|
-
|
847
|
-
|
848
876
|
def change_order_direction(order)
|
849
877
|
order.split(",").collect {|fragment|
|
850
878
|
case fragment
|
@@ -854,11 +882,11 @@ module ActiveRecord
|
|
854
882
|
end
|
855
883
|
}.join(",")
|
856
884
|
end
|
857
|
-
|
885
|
+
|
858
886
|
def special_columns(table_name)
|
859
887
|
columns(table_name).select(&:is_special?).map(&:name)
|
860
888
|
end
|
861
|
-
|
889
|
+
|
862
890
|
def repair_special_columns(sql)
|
863
891
|
special_cols = special_columns(get_table_name(sql))
|
864
892
|
for col in special_cols.to_a
|
@@ -867,35 +895,7 @@ module ActiveRecord
|
|
867
895
|
end
|
868
896
|
sql
|
869
897
|
end
|
870
|
-
|
871
|
-
def utf8_columns(table_name)
|
872
|
-
columns(table_name).select(&:is_utf8?).map(&:name)
|
873
|
-
end
|
874
|
-
|
875
|
-
def set_utf8_values!(sql)
|
876
|
-
utf8_cols = utf8_columns(get_table_name(sql))
|
877
|
-
if sql =~ /^\s*UPDATE/i
|
878
|
-
utf8_cols.each do |col|
|
879
|
-
sql.gsub!("[#{col.to_s}] = '", "[#{col.to_s}] = N'")
|
880
|
-
end
|
881
|
-
elsif sql =~ /^\s*INSERT(?!.*DEFAULT VALUES\s*$)/i
|
882
|
-
# TODO This code should be simplified
|
883
|
-
# Get columns and values, split them into arrays, and store the original_values for when we need to replace them
|
884
|
-
columns_and_values = sql.scan(/\((.*?)\)/m).flatten
|
885
|
-
columns = columns_and_values.first.split(',')
|
886
|
-
values = columns_and_values[1].split(',')
|
887
|
-
original_values = values.dup
|
888
|
-
# Iterate columns that should be UTF8, and append an N to the value, if the value is not NULL
|
889
|
-
utf8_cols.each do |col|
|
890
|
-
columns.each_with_index do |column, idx|
|
891
|
-
values[idx] = " N#{values[idx].gsub(/^ /, '')}" if column =~ /\[#{col}\]/ and values[idx] !~ /^NULL$/
|
892
|
-
end
|
893
|
-
end
|
894
|
-
# Replace (in place) the SQL
|
895
|
-
sql.gsub!(original_values.join(','), values.join(','))
|
896
|
-
end
|
897
|
-
end
|
898
|
-
|
898
|
+
|
899
899
|
end #class SQLServerAdapter < AbstractAdapter
|
900
900
|
|
901
901
|
end #module ConnectionAdapters
|
@@ -215,33 +215,6 @@ class AdapterTestSqlserver < ActiveRecord::TestCase
|
|
215
215
|
|
216
216
|
end
|
217
217
|
|
218
|
-
context 'which have coerced types' do
|
219
|
-
|
220
|
-
setup do
|
221
|
-
christmas_08 = "2008-12-25".to_time
|
222
|
-
christmas_08_afternoon = "2008-12-25 12:00".to_time
|
223
|
-
@chronic_date = SqlServerChronic.create!(:date => christmas_08).reload
|
224
|
-
@chronic_time = SqlServerChronic.create!(:time => christmas_08_afternoon).reload
|
225
|
-
end
|
226
|
-
|
227
|
-
should 'have an inheritable attribute ' do
|
228
|
-
assert SqlServerChronic.coerced_sqlserver_date_columns.include?('date')
|
229
|
-
end
|
230
|
-
|
231
|
-
should 'have column and objects cast to date' do
|
232
|
-
date_column = SqlServerChronic.columns_hash['date']
|
233
|
-
assert_equal :date, date_column.type, "This column: \n#{date_column.inspect}"
|
234
|
-
assert_instance_of Date, @chronic_date.date
|
235
|
-
end
|
236
|
-
|
237
|
-
should 'have column objects cast to time' do
|
238
|
-
time_column = SqlServerChronic.columns_hash['time']
|
239
|
-
assert_equal :time, time_column.type, "This column: \n#{time_column.inspect}"
|
240
|
-
assert_instance_of Time, @chronic_time.time
|
241
|
-
end
|
242
|
-
|
243
|
-
end
|
244
|
-
|
245
218
|
end
|
246
219
|
|
247
220
|
context 'For identity inserts' do
|
@@ -4,6 +4,7 @@ require 'models/binary'
|
|
4
4
|
class ColumnTestSqlserver < ActiveRecord::TestCase
|
5
5
|
|
6
6
|
def setup
|
7
|
+
@connection = ActiveRecord::Base.connection
|
7
8
|
@column_klass = ActiveRecord::ConnectionAdapters::SQLServerColumn
|
8
9
|
end
|
9
10
|
|
@@ -18,7 +19,16 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
|
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
|
-
|
22
|
+
should 'return correct null, limit, and default for Topic' do
|
23
|
+
tch = Topic.columns_hash
|
24
|
+
assert_equal false, tch['id'].null
|
25
|
+
assert_equal true, tch['title'].null
|
26
|
+
assert_equal 255, tch['author_name'].limit
|
27
|
+
assert_equal true, tch['approved'].default
|
28
|
+
assert_equal 0, tch['replies_count'].default
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'For binary columns' do
|
22
32
|
|
23
33
|
setup do
|
24
34
|
@binary_string = "GIF89a\001\000\001\000\200\000\000\377\377\377\000\000\000!\371\004\000\000\000\000\000,\000\000\000\000\001\000\001\000\000\002\002D\001\000;"
|
@@ -29,6 +39,13 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
|
|
29
39
|
assert_equal @binary_string, Binary.find(@saved_bdata).data
|
30
40
|
end
|
31
41
|
|
42
|
+
should 'have correct attributes' do
|
43
|
+
column = Binary.columns_hash['data']
|
44
|
+
assert_equal :binary, column.type
|
45
|
+
assert_equal @connection.native_binary_database_type, column.sql_type
|
46
|
+
assert_equal nil, column.limit
|
47
|
+
end
|
48
|
+
|
32
49
|
should 'quote data for sqlserver with literal 0x prefix' do
|
33
50
|
# See the output of the stored procedure: 'exec sp_datatype_info'
|
34
51
|
sqlserver_encoded_bdata = "0x47494638396101000100800000ffffff00000021f90400000000002c00000000010001000002024401003b"
|
@@ -37,30 +54,193 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
|
|
37
54
|
|
38
55
|
end
|
39
56
|
|
40
|
-
context 'For
|
57
|
+
context 'For string columns' do
|
58
|
+
|
59
|
+
setup do
|
60
|
+
@char = SqlServerString.columns_hash['char']
|
61
|
+
@char10 = SqlServerString.columns_hash['char_10']
|
62
|
+
@varcharmax = SqlServerString.columns_hash['varchar_max']
|
63
|
+
@varcharmax10 = SqlServerString.columns_hash['varchar_max_10']
|
64
|
+
end
|
41
65
|
|
42
|
-
should '
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
66
|
+
should 'have correct simplified types' do
|
67
|
+
assert_equal :string, @char.type
|
68
|
+
assert_equal :string, @char10.type
|
69
|
+
if sqlserver_2005?
|
70
|
+
assert_equal :string, @varcharmax.type
|
71
|
+
assert_equal :string, @varcharmax10.type
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
should 'have correct #sql_type per schema definition' do
|
76
|
+
assert_equal 'char(1)', @char.sql_type, 'Specifing a char type with no limit is 1 by SQL Server standards.'
|
77
|
+
assert_equal 'char(10)', @char10.sql_type, @char10.inspect
|
78
|
+
if sqlserver_2005?
|
79
|
+
assert_equal 'varchar(max)', @varcharmax.sql_type, 'A -1 limit should be converted to max (max) type.'
|
80
|
+
assert_equal 'varchar(max)', @varcharmax10.sql_type, 'A -1 limit should be converted to max (max) type.'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
should 'have correct #limit per schema definition' do
|
85
|
+
assert_equal 1, @char.limit
|
86
|
+
assert_equal 10, @char10.limit
|
87
|
+
if sqlserver_2005?
|
88
|
+
assert_equal nil, @varcharmax.limit, 'Limits on max types are moot and we should let rails know that.'
|
89
|
+
assert_equal nil, @varcharmax10.limit, 'Limits on max types are moot and we should let rails know that.'
|
90
|
+
end
|
60
91
|
end
|
61
92
|
|
62
93
|
end
|
63
94
|
|
64
95
|
|
96
|
+
context 'For all national/unicode columns' do
|
97
|
+
|
98
|
+
setup do
|
99
|
+
@nchar = SqlServerUnicode.columns_hash['nchar']
|
100
|
+
@nvarchar = SqlServerUnicode.columns_hash['nvarchar']
|
101
|
+
@ntext = SqlServerUnicode.columns_hash['ntext']
|
102
|
+
@ntext10 = SqlServerUnicode.columns_hash['ntext_10']
|
103
|
+
@nchar10 = SqlServerUnicode.columns_hash['nchar_10']
|
104
|
+
@nvarchar100 = SqlServerUnicode.columns_hash['nvarchar_100']
|
105
|
+
@nvarcharmax = SqlServerUnicode.columns_hash['nvarchar_max']
|
106
|
+
@nvarcharmax10 = SqlServerUnicode.columns_hash['nvarchar_max_10']
|
107
|
+
end
|
108
|
+
|
109
|
+
should 'all respond true to #is_utf8?' do
|
110
|
+
SqlServerUnicode.columns_hash.except('id').values.each do |column|
|
111
|
+
assert column.is_utf8?, "This column #{column.inspect} should have been a unicode column."
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
should 'have correct simplified types' do
|
116
|
+
assert_equal :string, @nchar.type
|
117
|
+
assert_equal :string, @nvarchar.type
|
118
|
+
assert_equal :text, @ntext.type
|
119
|
+
assert_equal :text, @ntext10.type
|
120
|
+
assert_equal :string, @nchar10.type
|
121
|
+
assert_equal :string, @nvarchar100.type
|
122
|
+
if sqlserver_2005?
|
123
|
+
assert_equal :string, @nvarcharmax.type
|
124
|
+
assert_equal :string, @nvarcharmax10.type
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
should 'have correct #sql_type per schema definition' do
|
129
|
+
assert_equal 'nchar(1)', @nchar.sql_type, 'Specifing a nchar type with no limit is 1 by SQL Server standards.'
|
130
|
+
assert_equal 'nvarchar(255)', @nvarchar.sql_type, 'Default nvarchar limit is 255.'
|
131
|
+
assert_equal 'ntext', @ntext.sql_type, 'Nice and clean ntext, limit means nothing here.'
|
132
|
+
assert_equal 'ntext', @ntext10.sql_type, 'Even a next with a limit of 10 specified will mean nothing.'
|
133
|
+
assert_equal 'nchar(10)', @nchar10.sql_type, 'An nchar with a limit of 10 needs to have it show up here.'
|
134
|
+
assert_equal 'nvarchar(100)', @nvarchar100.sql_type, 'An nvarchar with a specified limit of 100 needs to show it.'
|
135
|
+
if sqlserver_2005?
|
136
|
+
assert_equal 'nvarchar(max)', @nvarcharmax.sql_type, 'A -1 limit should be converted to max (max) type.'
|
137
|
+
assert_equal 'nvarchar(max)', @nvarcharmax10.sql_type, 'A -1 limit should be converted to max (max) type.'
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
should 'have correct #limit per schema definition' do
|
142
|
+
assert_equal 1, @nchar.limit
|
143
|
+
assert_equal 255, @nvarchar.limit
|
144
|
+
assert_equal nil, @ntext.limit, 'An ntext column limit is moot, it is a fixed variable length'
|
145
|
+
assert_equal 10, @nchar10.limit
|
146
|
+
assert_equal 100, @nvarchar100.limit
|
147
|
+
if sqlserver_2005?
|
148
|
+
assert_equal nil, @nvarcharmax.limit, 'Limits on max types are moot and we should let rails know that.'
|
149
|
+
assert_equal nil, @nvarcharmax10.limit, 'Limits on max types are moot and we should let rails know that.'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'For datetime columns' do
|
156
|
+
|
157
|
+
setup do
|
158
|
+
@date = SqlServerChronic.columns_hash['date']
|
159
|
+
@time = SqlServerChronic.columns_hash['time']
|
160
|
+
@datetime = SqlServerChronic.columns_hash['datetime']
|
161
|
+
end
|
162
|
+
|
163
|
+
should 'have correct simplified type for uncast datetime' do
|
164
|
+
assert_equal :datetime, @datetime.type
|
165
|
+
end
|
166
|
+
|
167
|
+
should 'all be a datetime #sql_type' do
|
168
|
+
assert_equal 'datetime', @date.sql_type
|
169
|
+
assert_equal 'datetime', @time.sql_type
|
170
|
+
assert_equal 'datetime', @datetime.sql_type
|
171
|
+
end
|
172
|
+
|
173
|
+
should 'all be have nil #limit' do
|
174
|
+
assert_equal nil, @date.limit
|
175
|
+
assert_equal nil, @time.limit
|
176
|
+
assert_equal nil, @datetime.limit
|
177
|
+
end
|
178
|
+
|
179
|
+
context 'which have coerced types' do
|
180
|
+
|
181
|
+
setup do
|
182
|
+
christmas_08 = "2008-12-25".to_time
|
183
|
+
christmas_08_afternoon = "2008-12-25 12:00".to_time
|
184
|
+
@chronic_date = SqlServerChronic.create!(:date => christmas_08).reload
|
185
|
+
@chronic_time = SqlServerChronic.create!(:time => christmas_08_afternoon).reload
|
186
|
+
end
|
187
|
+
|
188
|
+
should 'have an inheritable attribute ' do
|
189
|
+
assert SqlServerChronic.coerced_sqlserver_date_columns.include?('date')
|
190
|
+
end
|
191
|
+
|
192
|
+
should 'have column and objects cast to date' do
|
193
|
+
assert_equal :date, @date.type, "This column: \n#{@date.inspect}"
|
194
|
+
assert_instance_of Date, @chronic_date.date
|
195
|
+
end
|
196
|
+
|
197
|
+
should 'have column objects cast to time' do
|
198
|
+
assert_equal :time, @time.type, "This column: \n#{@time.inspect}"
|
199
|
+
assert_instance_of Time, @chronic_time.time
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
context 'For decimal and numeric columns' do
|
207
|
+
|
208
|
+
setup do
|
209
|
+
@bank_balance = NumericData.columns_hash['bank_balance']
|
210
|
+
@big_bank_balance = NumericData.columns_hash['big_bank_balance']
|
211
|
+
@world_population = NumericData.columns_hash['world_population']
|
212
|
+
@my_house_population = NumericData.columns_hash['my_house_population']
|
213
|
+
end
|
214
|
+
|
215
|
+
should 'have correct simplified types' do
|
216
|
+
assert_equal :decimal, @bank_balance.type
|
217
|
+
assert_equal :decimal, @big_bank_balance.type
|
218
|
+
assert_equal :integer, @world_population.type, 'Since #extract_scale == 0'
|
219
|
+
assert_equal :integer, @my_house_population.type, 'Since #extract_scale == 0'
|
220
|
+
end
|
221
|
+
|
222
|
+
should 'have correct #sql_type' do
|
223
|
+
assert_equal 'decimal(10,2)', @bank_balance.sql_type
|
224
|
+
assert_equal 'decimal(15,2)', @big_bank_balance.sql_type
|
225
|
+
assert_equal 'decimal(10,0)', @world_population.sql_type
|
226
|
+
assert_equal 'decimal(2,0)', @my_house_population.sql_type
|
227
|
+
end
|
228
|
+
|
229
|
+
should 'have correct #limit' do
|
230
|
+
assert_equal nil, @bank_balance.limit
|
231
|
+
assert_equal nil, @big_bank_balance.limit
|
232
|
+
assert_equal nil, @world_population.limit
|
233
|
+
assert_equal nil, @my_house_population.limit
|
234
|
+
end
|
235
|
+
|
236
|
+
should 'return correct precisions and scales' do
|
237
|
+
assert_equal [10,2], [@bank_balance.precision, @bank_balance.scale]
|
238
|
+
assert_equal [15,2], [@big_bank_balance.precision, @big_bank_balance.scale]
|
239
|
+
assert_equal [10,0], [@world_population.precision, @world_population.scale]
|
240
|
+
assert_equal [2,0], [@my_house_population.precision, @my_house_population.scale]
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
244
|
+
|
65
245
|
|
66
246
|
end
|
@@ -2,34 +2,47 @@ require 'cases/sqlserver_helper'
|
|
2
2
|
|
3
3
|
class SchemaDumperTestSqlserver < ActiveRecord::TestCase
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
assert_match %r{c_int_5.*:limit => 8}, output
|
16
|
-
assert_match %r{c_int_6.*:limit => 8}, output
|
17
|
-
assert_match %r{c_int_7.*:limit => 8}, output
|
18
|
-
assert_match %r{c_int_8.*:limit => 8}, output
|
5
|
+
setup :find_all_tables
|
6
|
+
|
7
|
+
context 'For primary keys' do
|
8
|
+
|
9
|
+
should 'honor nonstandards' do
|
10
|
+
table_dump('movies') do |output|
|
11
|
+
match = output.match(%r{create_table "movies"(.*)do})
|
12
|
+
assert_not_nil(match, "nonstandardpk table not found")
|
13
|
+
assert_match %r(:primary_key => "movieid"), match[1], "non-standard primary key not preserved"
|
14
|
+
end
|
19
15
|
end
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'For integers' do
|
20
|
+
|
21
|
+
should 'include limit constraint that match logic for smallint and bigint in #extract_limit' do
|
22
|
+
table_dump('integer_limits') do |output|
|
23
|
+
assert_match %r{c_int_1.*:limit => 2}, output
|
24
|
+
assert_match %r{c_int_2.*:limit => 2}, output
|
25
|
+
assert_match %r{c_int_3.*}, output
|
26
|
+
assert_match %r{c_int_4.*}, output
|
27
|
+
assert_no_match %r{c_int_3.*:limit}, output
|
28
|
+
assert_no_match %r{c_int_4.*:limit}, output
|
29
|
+
assert_match %r{c_int_5.*:limit => 8}, output
|
30
|
+
assert_match %r{c_int_6.*:limit => 8}, output
|
31
|
+
assert_match %r{c_int_7.*:limit => 8}, output
|
32
|
+
assert_match %r{c_int_8.*:limit => 8}, output
|
33
|
+
end
|
26
34
|
end
|
27
35
|
|
28
36
|
end
|
29
37
|
|
30
38
|
|
39
|
+
|
31
40
|
private
|
32
41
|
|
42
|
+
def find_all_tables
|
43
|
+
@all_tables ||= ActiveRecord::Base.connection.tables
|
44
|
+
end
|
45
|
+
|
33
46
|
def standard_dump(ignore_tables = [])
|
34
47
|
stream = StringIO.new
|
35
48
|
ActiveRecord::SchemaDumper.ignore_tables = [*ignore_tables]
|
@@ -37,4 +50,12 @@ class SchemaDumperTestSqlserver < ActiveRecord::TestCase
|
|
37
50
|
stream.string
|
38
51
|
end
|
39
52
|
|
53
|
+
def table_dump(*table_names)
|
54
|
+
stream = StringIO.new
|
55
|
+
ActiveRecord::SchemaDumper.ignore_tables = @all_tables-table_names
|
56
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
57
|
+
yield stream.string
|
58
|
+
stream.string
|
59
|
+
end
|
60
|
+
|
40
61
|
end
|
@@ -19,6 +19,8 @@ class TableWithRealColumn < ActiveRecord::Base; end
|
|
19
19
|
class FkTestHasFk < ActiveRecord::Base ; end
|
20
20
|
class FkTestHasPk < ActiveRecord::Base ; end
|
21
21
|
class NumericData < ActiveRecord::Base ; self.table_name = 'numeric_data' ; end
|
22
|
+
class SqlServerUnicode < ActiveRecord::Base ; end
|
23
|
+
class SqlServerString < ActiveRecord::Base ; end
|
22
24
|
class SqlServerChronic < ActiveRecord::Base
|
23
25
|
coerce_sqlserver_date :date
|
24
26
|
coerce_sqlserver_time :time
|
@@ -72,6 +74,10 @@ end
|
|
72
74
|
|
73
75
|
module ActiveRecord
|
74
76
|
class TestCase < ActiveSupport::TestCase
|
77
|
+
class << self
|
78
|
+
def sqlserver_2000? ; ActiveRecord::Base.connection.sqlserver_2000? ; end
|
79
|
+
def sqlserver_2005? ; ActiveRecord::Base.connection.sqlserver_2005? ; end
|
80
|
+
end
|
75
81
|
def assert_sql(*patterns_to_match)
|
76
82
|
$queries_executed = []
|
77
83
|
yield
|
@@ -82,6 +88,8 @@ module ActiveRecord
|
|
82
88
|
end
|
83
89
|
assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found in:\n#{$queries_executed.inspect}"
|
84
90
|
end
|
91
|
+
def sqlserver_2000? ; self.class.sqlserver_2000? ; end
|
92
|
+
def sqlserver_2005? ; self.class.sqlserver_2005? ; end
|
85
93
|
end
|
86
94
|
end
|
87
95
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'cases/sqlserver_helper'
|
2
|
+
require 'models/order'
|
3
|
+
|
4
|
+
class TableNameTestSqlserver < ActiveRecord::TestCase
|
5
|
+
|
6
|
+
self.use_transactional_fixtures = false
|
7
|
+
|
8
|
+
def setup
|
9
|
+
Order.table_name = '[orders]'
|
10
|
+
Order.reset_column_information
|
11
|
+
end
|
12
|
+
|
13
|
+
should 'load columns with escaped table name for model' do
|
14
|
+
assert_equal 4, Order.columns.length
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
should 'not re-escape table name if it is escaped already for SQL queries' do
|
19
|
+
assert_sql(/SELECT \* FROM \[orders\]/) { Order.all }
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'cases/sqlserver_helper'
|
2
|
+
|
3
|
+
class UnicodeTestSqlserver < ActiveRecord::TestCase
|
4
|
+
|
5
|
+
|
6
|
+
context 'Testing basic saves and unicode limits' do
|
7
|
+
|
8
|
+
should 'save and reload simple nchar string' do
|
9
|
+
assert nchar_data = SqlServerUnicode.create!(:nchar => 'A')
|
10
|
+
assert_equal 'A', SqlServerUnicode.find(nchar_data.id).nchar
|
11
|
+
end
|
12
|
+
|
13
|
+
should 'save and reload simple nvarchar(max) string' do
|
14
|
+
test_string = 'Ken Collins'
|
15
|
+
assert nvarcharmax_data = SqlServerUnicode.create!(:nvarchar_max => test_string)
|
16
|
+
assert_equal test_string, SqlServerUnicode.find(nvarcharmax_data.id).nvarchar_max
|
17
|
+
end if sqlserver_2005?
|
18
|
+
|
19
|
+
should 'enforce default nchar_10 limit of 10' do
|
20
|
+
assert_raise(ActiveRecord::StatementInvalid) { SqlServerUnicode.create!(:nchar => '01234567891') }
|
21
|
+
end
|
22
|
+
|
23
|
+
should 'enforce default nvarchar_100 limit of 100' do
|
24
|
+
assert_raise(ActiveRecord::StatementInvalid) { SqlServerUnicode.create!(:nvarchar_100 => '0123456789'*10+'1') }
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'Testing unicode data' do
|
30
|
+
|
31
|
+
setup do
|
32
|
+
@unicode_data = "一二34五六"
|
33
|
+
end
|
34
|
+
|
35
|
+
should 'insert into nvarchar field' do
|
36
|
+
assert data = SqlServerUnicode.create!(:nvarchar => @unicode_data)
|
37
|
+
assert_equal @unicode_data, data.reload.nvarchar
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
end
|
@@ -2,6 +2,7 @@ ActiveRecord::Schema.define do
|
|
2
2
|
|
3
3
|
create_table :table_with_real_columns, :force => true do |t|
|
4
4
|
t.column :real_number, :real
|
5
|
+
# t.column :varchar_max, :varchar_max if ActiveRecord::Base.connection.sqlserver_2005?
|
5
6
|
end
|
6
7
|
|
7
8
|
create_table :defaults, :force => true do |t|
|
@@ -34,5 +35,30 @@ ActiveRecord::Schema.define do
|
|
34
35
|
REFERENCES #{quote_table_name('fk_test_has_pks')} (#{quote_column_name('id')})
|
35
36
|
ADDFKSQL
|
36
37
|
|
38
|
+
create_table :sql_server_unicodes, :force => true do |t|
|
39
|
+
t.column :nchar, :nchar
|
40
|
+
t.column :nvarchar, :nvarchar
|
41
|
+
t.column :ntext, :ntext
|
42
|
+
t.column :ntext_10, :ntext, :limit => 10
|
43
|
+
t.column :nchar_10, :nchar, :limit => 10
|
44
|
+
t.column :nvarchar_100, :nvarchar, :limit => 100
|
45
|
+
if ActiveRecord::Base.connection.sqlserver_2005?
|
46
|
+
t.column :nvarchar_max, :nvarchar_max
|
47
|
+
t.column :nvarchar_max_10, :nvarchar_max, :limit => 10
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
create_table :sql_server_strings, :force => true do |t|
|
52
|
+
t.column :char, :char
|
53
|
+
t.column :char_10, :char, :limit => 10
|
54
|
+
if ActiveRecord::Base.connection.sqlserver_2005?
|
55
|
+
t.column :varchar_max, :varchar_max
|
56
|
+
t.column :varchar_max_10, :varchar_max, :limit => 10
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
create_table :sql_server_binary_types, :force => true do |t|
|
61
|
+
# TODO: Add some different native binary types and test.
|
62
|
+
end
|
37
63
|
|
38
64
|
end
|
metadata
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-sqlserver-2000-2005-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ken Collins
|
8
8
|
- Murray Steele
|
9
9
|
- Shawn Balestracci
|
10
|
+
- Joe Rafaniello
|
10
11
|
- Tom Ward
|
11
12
|
autorequire:
|
12
13
|
bindir: bin
|
13
14
|
cert_chain: []
|
14
15
|
|
15
|
-
date: 2008-11-
|
16
|
+
date: 2008-11-21 00:00:00 -08:00
|
16
17
|
default_executable:
|
17
18
|
dependencies: []
|
18
19
|
|
@@ -82,6 +83,8 @@ test_files:
|
|
82
83
|
- test/cases/schema_dumper_test_sqlserver.rb
|
83
84
|
- test/cases/specific_schema_test_sqlserver.rb
|
84
85
|
- test/cases/sqlserver_helper.rb
|
86
|
+
- test/cases/table_name_test_sqlserver.rb
|
87
|
+
- test/cases/unicode_test_sqlserver.rb
|
85
88
|
- test/connections/native_sqlserver/connection.rb
|
86
89
|
- test/connections/native_sqlserver_odbc/connection.rb
|
87
90
|
- test/migrations/transaction_table/1_table_will_never_be_created.rb
|