Created
August 20, 2010 19:50
-
-
Save metaskills/540999 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
require 'odbc' | |
require 'odbc_utf8' | |
GC.disable | |
module ODBC | |
class Statement | |
def finished? | |
begin | |
connected? | |
false | |
rescue ODBC::Error | |
true | |
end | |
end | |
end | |
end | |
module ODBC_UTF8 | |
class Statement | |
def finished? | |
begin | |
connected? | |
false | |
rescue ODBC_UTF8::Error | |
true | |
end | |
end | |
end | |
end | |
def select_value(con,sql) | |
h = con.run(sql) | |
v = h.fetch.first | |
h.drop | |
v | |
end | |
con1 = ODBC.connect 'mc2008', 'rails', '' | |
con2 = ODBC_UTF8.connect 'mc2008', 'rails', '' | |
select_value(con1, "SELECT N'v' AS N'n'").encoding # => #<Encoding:ASCII-8BIT> | |
select_value(con2, "SELECT N'v' AS N'n'").encoding # => #<Encoding:UTF-8> | |
con1.odbc_version # => 2 | |
con2.odbc_version # => 3 | |
sth_runprc1 = con1.run "EXEC sp_helpconstraint 'people', 'nomsg'" | |
sth_runprc1.columns(true).map{|c|c.name} # => ["constraint_type", "constraint_name", "delete_action", "update_action", "status_enabled", "status_for_replication", "constraint_keys"] | |
sth_runprc1.fetch_all # => [["DEFAULT on column lock_version", "DF__people__lock_ver__22D86D16", "(n/a)", "(n/a)", "(n/a)", "(n/a)", "((0))"], ["PRIMARY KEY (clustered)", "PK__people__3213E83F20F024A4", "(n/a)", "(n/a)", "(n/a)", "(n/a)", "id"]] | |
sth_runprc1.more_results # => false | |
sth_runprc1.drop | |
sth_runprc2 = con2.run "EXEC sp_helpconstraint 'people', 'nomsg'" | |
sth_runprc2.columns(true).map{|c|c.name} # => ["constraint_type", "constraint_name", "delete_action", "update_action", "status_enabled", "status_for_replication", "constraint_keys"] | |
sth_runprc2.fetch_all # => [["DEFAULT on column lock_version", "DF__people__lock_ver__22D86D16", "(n/a)", "(n/a)", "(n/a)", "(n/a)", "((0))"], ["PRIMARY KEY (clustered)", "PK__people__3213E83F20F024A4", "(n/a)", "(n/a)", "(n/a)", "(n/a)", "id"]] | |
sth_runprc2.more_results # => true | |
sth_runprc2.drop | |
sth_runsel1 = con1.run "SELECT N'v' AS N'n'" | |
sth_runsel1.columns(true).map{|c|c.name} # => ["n"] | |
sth_runsel1.columns(true).map{|c|c.name}[0].encoding # => #<Encoding:ASCII-8BIT> | |
sth_runsel1.fetch_all # => [["v"]] | |
sth_runsel1.more_results # => false | |
sth_runsel1.drop | |
sth_runsel2 = con2.run "SELECT N'v' AS N'n'" | |
sth_runsel2.columns(true).map{|c|c.name} # => ["n"] | |
sth_runsel2.columns(true).map{|c|c.name}[0].encoding # => #<Encoding:UTF-8> | |
sth_runsel2.fetch_all # => [["v"]] | |
sth_runsel2.more_results # => false | |
sth_runsel2.drop | |
sth = con2.run "SELECT N'v' AS N'n'" | |
sth.columns(true)[0].name # => "n" | |
sth.columns(true)[0].name.encoding # => # => #<Encoding:UTF-8> | |
sth.drop | |
con1.do "DELETE FROM [sql_server_unicodes]" | |
con1.do "INSERT INTO [sql_server_unicodes] ([nvarchar]) VALUES (N'一二34五六')" # => 1 | |
select_value(con1, "SELECT TOP 1 [nvarchar] FROM [sql_server_unicodes]") # => 一二34五六 | |
select_value(con1, "SELECT TOP 1 [nvarchar] FROM [sql_server_unicodes]").encoding # => #<Encoding:ASCII-8BIT> | |
con2.do "DELETE FROM [sql_server_unicodes]" | |
con2.do "INSERT INTO [sql_server_unicodes] ([nvarchar]) VALUES (N'一二34五六')" # => [FreeTDS][SQL Server]Incorrect syntax near ''. (ODBC_UTF8::Error) | |
select_value(con2, "SELECT TOP 1 [nvarchar] FROM [sql_server_unicodes]") # => | |
select_value(con2, "SELECT TOP 1 [nvarchar] FROM [sql_server_unicodes]").encoding # => | |
=begin | |
Example Adapter Fails with UTF8 variant. | |
1) Error: | |
test: Testing unicode data should insert into nvarchar field. (UnicodeTestSqlserver): | |
ActiveRecord::StatementInvalid: ODBC::Error: 42000 (102) [FreeTDS][SQL Server]Incorrect syntax near ''.: INSERT INTO [sql_server_unicodes] ([nchar], [nchar_10], [ntext], [ntext_10], [nvarchar], [nvarchar_100], [nvarchar_max], [nvarchar_max_10]) VALUES (NULL, NULL, NULL, NULL, N'一二34五六', NULL, NULL, NULL) | |
2) Error: | |
test: Testing unicode data should re-encode data on DB reads. (UnicodeTestSqlserver): | |
ActiveRecord::StatementInvalid: ODBC::Error: 42000 (102) [FreeTDS][SQL Server]Incorrect syntax near ''.: INSERT INTO [sql_server_unicodes] ([nchar], [nchar_10], [ntext], [ntext_10], [nvarchar], [nvarchar_100], [nvarchar_max], [nvarchar_max_10]) VALUES (NULL, NULL, NULL, NULL, N'一二34五六', NULL, NULL, NULL) | |
3) Error: | |
test_coerced_validate_uniqueness_with_limit_and_utf8(UniquenessValidationTest): | |
ActiveRecord::StatementInvalid: ODBC::Error: 42000 (102) [FreeTDS][SQL Server]Incorrect syntax near ''.: SELECT TOP (1) [events].[id] FROM [events] WHERE ([events].[title] COLLATE Latin1_General_CS_AS_WS = N'一二三四五') | |
=end | |
# [written_on] # => datetime | |
# [bonus_time] # => time | |
# [last_read] # => date | |
con1.use_time # => false | |
sth = con1.run "SELECT [topics].* FROM [topics]" #<ODBC::Statement:0x00000100a48868> | |
row = sth.fetch_hash # => {"id"=>1, "title"=>"The First Topic", "author_name"=>"David", "author_email_address"=>"[email protected]", "written_on"=>#<ODBC::TimeStamp: "2003-07-16 10:28:11 223000000">, "bonus_time"=>"09:28:00.0000000", "last_read"=>"2004-04-15", "content"=>"Have a nice day", "approved"=>0, "replies_count"=>1, "parent_id"=>nil, "parent_title"=>nil, "type"=>nil, "group"=>nil} | |
row['written_on'].class # => ODBC::TimeStamp | |
row['bonus_time'].class # => String | |
row['last_read'].class # => String | |
con1.use_time = true | |
sth = con1.run "SELECT [topics].* FROM [topics]" | |
row = sth.fetch_hash # => {"id"=>1, "title"=>"The First Topic", "author_name"=>"David", "author_email_address"=>"[email protected]", "written_on"=>2003-07-16 10:28:11 -0400, "bonus_time"=>"09:28:00.0000000", "last_read"=>"2004-04-15", "content"=>"Have a nice day", "approved"=>0, "replies_count"=>1, "parent_id"=>nil, "parent_title"=>nil, "type"=>nil, "group"=>nil} | |
row['written_on'].class # => Time | |
row['bonus_time'].class # => String | |
row['last_read'].class # => String | |
con1.use_time # => false | |
sth = con1.run "SELECT [topics].* FROM [topics]" | |
sth.fetch_all # => [[1, "The First Topic", "David", "[email protected]", #<ODBC::TimeStamp: "2003-07-16 10:28:11 223000000">, "09:28:00.0000000", "2004-04-15", "Have a nice day", 0, 1, nil, nil, nil, nil], [2, "The Second Topic of the day", "Mary", nil, #<ODBC::TimeStamp: "2004-07-15 10:28:00 10000000">, nil, nil, "Have a nice day", 1, 0, 1, nil, "Reply", nil], [3, "The Third Topic of the day", "Carl", nil, #<ODBC::TimeStamp: "2005-07-15 10:28:00 10000000">, nil, nil, "I'm a troll", 1, 1, nil, nil, nil, nil], [4, "The Fourth Topic of the day", "Carl", nil, #<ODBC::TimeStamp: "2006-07-15 10:28:00 10000000">, nil, nil, "Why not?", 1, 0, 3, nil, "Reply", nil]] | |
con1.use_time = true | |
sth = con1.run "SELECT [topics].* FROM [topics]" | |
sth.fetch_all # ArgumentError: wrong number of arguments (7 for 0) | |
sth1 = con1.run "SELECT [topics].* FROM [topics]" | |
r1 = sth1.fetch_hash # => {"id"=>1, "title"=>"The First Topic", "author_name"=>"David", "author_email_address"=>"[email protected]", "written_on"=>#<ODBC::TimeStamp: "2003-07-16 10:28:11 223000000">, "bonus_time"=>"09:28:00.0000000", "last_read"=>"2004-04-15", "content"=>"Have a nice day", "approved"=>0, "replies_count"=>1, "parent_id"=>nil, "parent_title"=>nil, "type"=>nil, "group"=>nil} | |
r2 = sth1.fetch_hash # => {"id"=>2, "title"=>"The Second Topic of the day", "author_name"=>"Mary", "author_email_address"=>nil, "written_on"=>#<ODBC::TimeStamp: "2004-07-15 10:28:00 10000000">, "bonus_time"=>nil, "last_read"=>nil, "content"=>"Have a nice day", "approved"=>1, "replies_count"=>0, "parent_id"=>1, "parent_title"=>nil, "type"=>"Reply", "group"=>nil} | |
r3 = sth1.fetch_hash # => {"id"=>3, "title"=>"The Third Topic of the day", "author_name"=>"Carl", "author_email_address"=>nil, "written_on"=>#<ODBC::TimeStamp: "2005-07-15 10:28:00 10000000">, "bonus_time"=>nil, "last_read"=>nil, "content"=>"I'm a troll", "approved"=>1, "replies_count"=>1, "parent_id"=>nil, "parent_title"=>nil, "type"=>nil, "group"=>nil} | |
r4 = sth1.fetch_hash # => {"id"=>4, "title"=>"The Fourth Topic of the day", "author_name"=>"Carl", "author_email_address"=>nil, "written_on"=>#<ODBC::TimeStamp: "2006-07-15 10:28:00 10000000">, "bonus_time"=>nil, "last_read"=>nil, "content"=>"Why not?", "approved"=>1, "replies_count"=>0, "parent_id"=>3, "parent_title"=>nil, "type"=>"Reply", "group"=>nil} | |
r1.keys.map { |k| k.object_id } # => [2156581320, 2156581300, 2156581280, 2156581260, 2156581240, 2156581220, 2156581200, 2156581180, 2156581160, 2156581140, 2156581120, 2156581100, 2156581080, 2156581060] | |
r2.keys.map { |k| k.object_id } # => [2156581320, 2156581300, 2156581280, 2156581260, 2156581240, 2156581220, 2156581200, 2156581180, 2156581160, 2156581140, 2156581120, 2156581100, 2156581080, 2156581060] | |
r3.keys.map { |k| k.object_id } # => [2156581320, 2156581300, 2156581280, 2156581260, 2156581240, 2156581220, 2156581200, 2156581180, 2156581160, 2156581140, 2156581120, 2156581100, 2156581080, 2156581060] | |
r4.keys.map { |k| k.object_id } # => [2156581320, 2156581300, 2156581280, 2156581260, 2156581240, 2156581220, 2156581200, 2156581180, 2156581160, 2156581140, 2156581120, 2156581100, 2156581080, 2156581060] | |
sth1.drop | |
sth1 = con1.run "SELECT [topics].* FROM [topics]" | |
data = sth1.each_hash | |
data[0].keys.map { |k| k.object_id } # => [2168558420, 2168558400, 2168558380, 2168558360, 2168558340, 2168558320, 2168558300, 2168558280, 2168558260, 2168558240, 2168558220, 2168558200, 2168558180, 2168558160] | |
data[1].keys.map { |k| k.object_id } # => [2168558420, 2168558400, 2168558380, 2168558360, 2168558340, 2168558320, 2168558300, 2168558280, 2168558260, 2168558240, 2168558220, 2168558200, 2168558180, 2168558160] | |
data[2].keys.map { |k| k.object_id } # => [2168558420, 2168558400, 2168558380, 2168558360, 2168558340, 2168558320, 2168558300, 2168558280, 2168558260, 2168558240, 2168558220, 2168558200, 2168558180, 2168558160] | |
data[3].keys.map { |k| k.object_id } # => [2168558420, 2168558400, 2168558380, 2168558360, 2168558340, 2168558320, 2168558300, 2168558280, 2168558260, 2168558240, 2168558220, 2168558200, 2168558180, 2168558160] | |
sth1.drop | |
sth2 = con2.run "SELECT [topics].* FROM [topics]" | |
# Same as above!!!! | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
String keys work great!
I could not test ODBC::Database#timezone=. What is the format?
Still getting syntax error when quoting UTF8 data. Included some sample test fails from adapter.
No matter which way #use_time is set, time/date data types come back as strings. I'm somewhat OK with that. They were previously ODBC::TimeStamps too. I know that ActiveRecord will convert these higher up for me to correct ruby objects. But I think ideally when #use_time is false, they maintain backward compatibility as ODBC::TimeStamp objects and when set to true, become full blown Date object, the #time data type should just be like #datetime. Lemme double check what mysql2 gem does. Yea, here is a report that I think we should shoot for too. http://gist.github.com/562465
Bad bug in #fetch_all. Raises argument error.