dbd-sqlanywhere 0.1.0 → 0.1.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/CHANGELOG +7 -1
- data/README +8 -2
- data/lib/dbd/SQLAnywhere.rb +5 -5
- data/test/DBD_TESTS +48 -0
- data/test/dbd/general/test_database.rb +157 -0
- data/test/dbd/general/test_statement.rb +249 -0
- data/test/dbd/general/test_types.rb +253 -0
- data/test/dbd/sqlanywhere/base.rb +26 -0
- data/test/dbd/sqlanywhere/down.sql +19 -0
- data/test/dbd/sqlanywhere/up.sql +28 -0
- data/test/ts_dbd.rb +118 -0
- metadata +16 -5
data/CHANGELOG
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
=CHANGE LOG
|
2
2
|
|
3
|
+
=====0.1.1 -- 2008/11/06
|
4
|
+
- Changed file permissions on archives
|
5
|
+
- Changed archives to be specific to platform (.zip on windows, .tar.gz
|
6
|
+
otherwise)
|
7
|
+
- Removed the default rake task
|
8
|
+
|
3
9
|
=====0.1.0 -- 2008/10/29
|
4
10
|
- Initial Release
|
5
|
-
- Wraps DBCAPI
|
11
|
+
- Wraps DBCAPI functionality
|
6
12
|
- Tested against DBI 0.4
|
data/README
CHANGED
@@ -29,7 +29,7 @@ The connection string takes the general form:
|
|
29
29
|
where,
|
30
30
|
[DB_NAME] is the name of the database you wish to connect to
|
31
31
|
[USER_NAME] is the username
|
32
|
-
[PASSWORD] is the
|
32
|
+
[PASSWORD] is the corresponding password for the username
|
33
33
|
|
34
34
|
[OPTIONS] is a hash of additional options for the connection.
|
35
35
|
|
@@ -37,6 +37,12 @@ For example, to start with named connection called 'ruby_dbi' you can use:
|
|
37
37
|
|
38
38
|
dbh = DBI.connect('DBI:SQLAnywhere:Test', 'dba', 'sql', {:CON => "ruby_dbi"})
|
39
39
|
|
40
|
+
==Running Test Suite
|
41
|
+
|
42
|
+
For information on running the Ruby/DBI DBD Tests, please see
|
43
|
+
|
44
|
+
test/DBD_TESTS
|
45
|
+
|
40
46
|
==Driver-Specific Features
|
41
47
|
|
42
48
|
At the time of this writing, there was no standard way to handle INOUT and OUT parameters
|
@@ -91,7 +97,7 @@ to retrieve the output value using the :name supplied at binding time.
|
|
91
97
|
buffer = "-some_string-"
|
92
98
|
prefix = "PREFIX"
|
93
99
|
|
94
|
-
# preparing the
|
100
|
+
# preparing the statement
|
95
101
|
sth = dbh.prepare("call foo( ?, ?, ?, ? )")
|
96
102
|
|
97
103
|
# Binding buffer column as :buf, and str_len column as :len
|
data/lib/dbd/SQLAnywhere.rb
CHANGED
@@ -37,7 +37,7 @@ module DBI
|
|
37
37
|
module DBD
|
38
38
|
module SQLAnywhere
|
39
39
|
|
40
|
-
VERSION = "0.1.
|
40
|
+
VERSION = "0.1.1"
|
41
41
|
|
42
42
|
def self.driver_name
|
43
43
|
"SQLAnywhere"
|
@@ -98,7 +98,7 @@ module SQLAnywhere
|
|
98
98
|
end
|
99
99
|
|
100
100
|
|
101
|
-
# This module provides
|
101
|
+
# This module provides functionality that is used by all the DBD classes
|
102
102
|
module Utility
|
103
103
|
|
104
104
|
NO_DIRECTION = 0
|
@@ -170,6 +170,6 @@ end # module SQLAnywhere
|
|
170
170
|
end # module DBD
|
171
171
|
end # module DBI
|
172
172
|
|
173
|
-
require 'dbd/
|
174
|
-
require 'dbd/
|
175
|
-
require 'dbd/
|
173
|
+
require 'dbd/sqlanywhere/driver'
|
174
|
+
require 'dbd/sqlanywhere/database'
|
175
|
+
require 'dbd/sqlanywhere/statement'
|
data/test/DBD_TESTS
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
================================================================================
|
2
|
+
Using DBD tests
|
3
|
+
================================================================================
|
4
|
+
|
5
|
+
Create a YAML file named .ruby-dbi.test-config.yaml in your home directory.
|
6
|
+
|
7
|
+
This file is a hash of keys that determine what you want to test and how you
|
8
|
+
access the databases related to those tests.
|
9
|
+
|
10
|
+
The key 'dbtypes' is an array which determines what tests you want to run. They
|
11
|
+
*do not* correspond to the driver names, they correspond to the test
|
12
|
+
directories that were made for them.
|
13
|
+
|
14
|
+
Each 'dbtype' has a key that contains a hash of values:
|
15
|
+
- username: the username of your account
|
16
|
+
- password: the password for your account
|
17
|
+
- dbname: the name of the database to connect to
|
18
|
+
|
19
|
+
NOTE that tests expect to connect to a database on localhost currently. This
|
20
|
+
may be fixed in the future, especially when we start writing Oracle and
|
21
|
+
SQLServer tests.
|
22
|
+
|
23
|
+
Each DBD test relies on database semantics which may not match up entirely with
|
24
|
+
this configuration. For instance, the postgresql tests expect you to be able to
|
25
|
+
work with the database directly via the `psql' client. This is something which
|
26
|
+
will eventually be remedied as time and ability allows.
|
27
|
+
|
28
|
+
Here is a sample configuration to get you started with the postgresql tests:
|
29
|
+
|
30
|
+
################################################################################
|
31
|
+
|
32
|
+
---
|
33
|
+
dbtypes:
|
34
|
+
- postgresql
|
35
|
+
postgresql:
|
36
|
+
username: erikh
|
37
|
+
password: monkeys
|
38
|
+
dbname: rubytest
|
39
|
+
|
40
|
+
################################################################################
|
41
|
+
|
42
|
+
NOTE the --- is part of the file and is not a separator.
|
43
|
+
|
44
|
+
================================================================================
|
45
|
+
Writing DBD tests
|
46
|
+
================================================================================
|
47
|
+
|
48
|
+
Coming soon.
|
@@ -0,0 +1,157 @@
|
|
1
|
+
@class = Class.new(DBDConfig.testbase(DBDConfig.current_dbtype)) do
|
2
|
+
def test_ping
|
3
|
+
assert @dbh.ping
|
4
|
+
# XXX if it isn't obvious, this should be tested better. Not sure what
|
5
|
+
# good behavior is yet.
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_columns
|
9
|
+
assert_nothing_raised do
|
10
|
+
cols = @dbh.columns("precision_test")
|
11
|
+
|
12
|
+
assert(cols)
|
13
|
+
assert_kind_of(Array, cols)
|
14
|
+
assert_equal(2, cols.length)
|
15
|
+
|
16
|
+
# the first column should always be "text_field" and have the following
|
17
|
+
# properties:
|
18
|
+
assert_equal("text_field", cols[0]["name"])
|
19
|
+
assert(!cols[0]["nullable"])
|
20
|
+
|
21
|
+
assert_equal(20, cols[0]["precision"])
|
22
|
+
# scale can be either nil or 0 for character types.
|
23
|
+
case cols[0]["scale"]
|
24
|
+
when nil
|
25
|
+
assert_equal(nil, cols[0]["scale"])
|
26
|
+
when 0
|
27
|
+
assert_equal(0, cols[0]["scale"])
|
28
|
+
else
|
29
|
+
flunk "scale can be either 0 or nil for character types"
|
30
|
+
end
|
31
|
+
|
32
|
+
assert_equal(
|
33
|
+
DBI::Type::Varchar,
|
34
|
+
DBI::TypeUtil.type_name_to_module(cols[0]["type_name"])
|
35
|
+
)
|
36
|
+
|
37
|
+
# the second column should always be "integer_field" and have the following
|
38
|
+
# properties:
|
39
|
+
assert_equal("integer_field", cols[1]["name"])
|
40
|
+
assert(cols[1]["nullable"])
|
41
|
+
assert_equal(1, cols[1]["scale"])
|
42
|
+
assert_equal(2, cols[1]["precision"])
|
43
|
+
assert_equal(
|
44
|
+
DBI::Type::Decimal,
|
45
|
+
DBI::TypeUtil.type_name_to_module(cols[1]["type_name"])
|
46
|
+
)
|
47
|
+
|
48
|
+
# finally, we ensure that every column in the array is a ColumnInfo
|
49
|
+
# object
|
50
|
+
cols.each { |col| assert_kind_of(DBI::ColumnInfo, col) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_prepare
|
55
|
+
@sth = @dbh.prepare('select * from names')
|
56
|
+
|
57
|
+
assert @sth
|
58
|
+
assert_kind_of DBI::StatementHandle, @sth
|
59
|
+
|
60
|
+
@sth.finish
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_do
|
64
|
+
assert_equal 1, @dbh.do("insert into names (name, age) values (?, ?)", "Billy", 21)
|
65
|
+
@sth = @dbh.prepare("select * from names where name = ?")
|
66
|
+
@sth.execute("Billy")
|
67
|
+
assert_equal ["Billy", 21], @sth.fetch
|
68
|
+
@sth.finish
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_tables
|
72
|
+
tables = @dbh.tables.sort
|
73
|
+
|
74
|
+
# since this is a general test, let's prune the system tables
|
75
|
+
# FIXME not so sure if this should be a general test anymore.
|
76
|
+
if dbtype == "odbc"
|
77
|
+
tables -= [
|
78
|
+
"administrable_role_authorizations",
|
79
|
+
"applicable_roles",
|
80
|
+
"attributes",
|
81
|
+
"check_constraint_routine_usage",
|
82
|
+
"check_constraints",
|
83
|
+
"column_domain_usage",
|
84
|
+
"column_privileges",
|
85
|
+
"column_udt_usage",
|
86
|
+
"columns",
|
87
|
+
"constraint_column_usage",
|
88
|
+
"constraint_table_usage",
|
89
|
+
"data_type_privileges",
|
90
|
+
"domain_constraints",
|
91
|
+
"domain_udt_usage",
|
92
|
+
"domains",
|
93
|
+
"element_types",
|
94
|
+
"enabled_roles",
|
95
|
+
"information_schema_catalog_name",
|
96
|
+
"key_column_usage",
|
97
|
+
"parameters",
|
98
|
+
"referential_constraints",
|
99
|
+
"role_column_grants",
|
100
|
+
"role_routine_grants",
|
101
|
+
"role_table_grants",
|
102
|
+
"role_usage_grants",
|
103
|
+
"routine_privileges",
|
104
|
+
"routines",
|
105
|
+
"schemata",
|
106
|
+
"sequences",
|
107
|
+
"sql_features",
|
108
|
+
"sql_implementation_info",
|
109
|
+
"sql_languages",
|
110
|
+
"sql_packages",
|
111
|
+
"sql_parts",
|
112
|
+
"sql_sizing",
|
113
|
+
"sql_sizing_profiles",
|
114
|
+
"table_constraints",
|
115
|
+
"table_privileges",
|
116
|
+
"tables",
|
117
|
+
"triggered_update_columns",
|
118
|
+
"triggers",
|
119
|
+
"usage_privileges",
|
120
|
+
"view_column_usage",
|
121
|
+
"view_routine_usage",
|
122
|
+
"view_table_usage",
|
123
|
+
"views"
|
124
|
+
]
|
125
|
+
end
|
126
|
+
|
127
|
+
case dbtype
|
128
|
+
when "postgresql"
|
129
|
+
tables.reject! { |x| x =~ /^pg_/ }
|
130
|
+
assert_equal %w(array_test bit_test blob_test boolean_test bytea_test db_specific_types_test field_types_test names precision_test time_test timestamp_test view_names), tables
|
131
|
+
else
|
132
|
+
assert_equal %w(bit_test blob_test boolean_test db_specific_types_test field_types_test names precision_test time_test timestamp_test view_names), tables
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_attrs
|
137
|
+
# test defaults
|
138
|
+
assert @dbh["AutoCommit"] # should be true
|
139
|
+
|
140
|
+
# test setting
|
141
|
+
assert !(@dbh["AutoCommit"] = false)
|
142
|
+
assert !@dbh["AutoCommit"]
|
143
|
+
|
144
|
+
# test committing an outstanding transaction
|
145
|
+
|
146
|
+
@sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
|
147
|
+
@sth.execute("Billy", 22)
|
148
|
+
@sth.finish
|
149
|
+
|
150
|
+
assert @dbh["AutoCommit"] = true # should commit at this point
|
151
|
+
|
152
|
+
@sth = @dbh.prepare("select * from names where name = ?")
|
153
|
+
@sth.execute("Billy")
|
154
|
+
assert_equal [ "Billy", 22 ], @sth.fetch
|
155
|
+
@sth.finish
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
@class = Class.new(DBDConfig.testbase(DBDConfig.current_dbtype)) do
|
2
|
+
|
3
|
+
def test_execute
|
4
|
+
assert_nothing_raised do
|
5
|
+
@dbh.execute("select * from names order by age") do |sth|
|
6
|
+
assert_equal([["Joe", 19], ["Bob", 21], ["Jim", 30]], sth.fetch_all)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_quoting # FIXME breaks sqlite-ruby to a segfault - research
|
12
|
+
@sth = nil
|
13
|
+
|
14
|
+
assert_nothing_raised do
|
15
|
+
if dbtype == "postgresql"
|
16
|
+
@sth = @dbh.prepare('select E\'\\\\\'')
|
17
|
+
else
|
18
|
+
@sth = @dbh.prepare('select \'\\\\\'')
|
19
|
+
end
|
20
|
+
@sth.execute
|
21
|
+
row = @sth.fetch
|
22
|
+
assert_equal ['\\'], row
|
23
|
+
@sth.finish
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_duplicate_columns
|
28
|
+
assert_nothing_raised do
|
29
|
+
@sth = @dbh.prepare("select name, name from names where name = ?")
|
30
|
+
@sth.execute("Bob")
|
31
|
+
assert_equal [["Bob", "Bob"]], @sth.fetch_all
|
32
|
+
@sth.finish
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_columninfo
|
37
|
+
@sth = nil
|
38
|
+
|
39
|
+
assert_nothing_raised do
|
40
|
+
@sth = @dbh.prepare("select * from precision_test")
|
41
|
+
@sth.execute
|
42
|
+
|
43
|
+
cols = @sth.column_info
|
44
|
+
|
45
|
+
assert(cols)
|
46
|
+
assert_kind_of(Array, cols)
|
47
|
+
assert_equal(2, cols.length)
|
48
|
+
|
49
|
+
# the first column should always be "text_field" and have the following
|
50
|
+
# properties:
|
51
|
+
assert_equal("text_field", cols[0]["name"])
|
52
|
+
assert_equal(20, cols[0]["precision"])
|
53
|
+
# scale can be either nil or 0 for character types.
|
54
|
+
case cols[0]["scale"]
|
55
|
+
when nil
|
56
|
+
assert_equal(nil, cols[0]["scale"])
|
57
|
+
when 0
|
58
|
+
assert_equal(0, cols[0]["scale"])
|
59
|
+
else
|
60
|
+
flunk "scale can be either 0 or nil for character types"
|
61
|
+
end
|
62
|
+
|
63
|
+
assert_equal(
|
64
|
+
DBI::Type::Varchar,
|
65
|
+
DBI::TypeUtil.type_name_to_module(cols[0]["type_name"])
|
66
|
+
)
|
67
|
+
|
68
|
+
# the second column should always be "integer_field" and have the following
|
69
|
+
# properties:
|
70
|
+
assert_equal("integer_field", cols[1]["name"])
|
71
|
+
assert_equal(1, cols[1]["scale"])
|
72
|
+
assert_equal(2, cols[1]["precision"])
|
73
|
+
assert_equal(
|
74
|
+
DBI::Type::Decimal,
|
75
|
+
DBI::TypeUtil.type_name_to_module(cols[1]["type_name"])
|
76
|
+
)
|
77
|
+
|
78
|
+
cols.each { |col| assert_kind_of(DBI::ColumnInfo, col) }
|
79
|
+
@sth.finish
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_duplicate_columns
|
84
|
+
assert_nothing_raised do
|
85
|
+
@sth = @dbh.prepare("select name, name from names where name = ?")
|
86
|
+
@sth.execute("Bob")
|
87
|
+
assert_equal [["Bob", "Bob"]], @sth.fetch_all
|
88
|
+
@sth.finish
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_rows
|
93
|
+
@sth = nil
|
94
|
+
|
95
|
+
assert_nothing_raised do
|
96
|
+
@sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
|
97
|
+
@sth.execute("Bill", 22);
|
98
|
+
end
|
99
|
+
|
100
|
+
assert 1, @sth.rows
|
101
|
+
|
102
|
+
@sth.finish
|
103
|
+
@sth = nil
|
104
|
+
|
105
|
+
assert_nothing_raised do
|
106
|
+
@sth = @dbh.prepare("delete from names where name = ?")
|
107
|
+
@sth.execute("Bill");
|
108
|
+
end
|
109
|
+
|
110
|
+
assert 1, @sth.rows
|
111
|
+
|
112
|
+
@sth.finish
|
113
|
+
|
114
|
+
assert_nothing_raised do
|
115
|
+
@sth = @dbh.prepare("select * from names")
|
116
|
+
@sth.execute
|
117
|
+
end
|
118
|
+
|
119
|
+
assert_equal 0, @sth.rows
|
120
|
+
assert @sth.fetchable?
|
121
|
+
assert @sth.any?
|
122
|
+
assert @sth.rows.zero?
|
123
|
+
@sth.finish
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_prepare_execute
|
127
|
+
assert_nothing_raised do
|
128
|
+
@sth = @dbh.prepare("select * from names")
|
129
|
+
@sth.execute
|
130
|
+
@sth.finish
|
131
|
+
end
|
132
|
+
|
133
|
+
assert_nothing_raised do
|
134
|
+
@sth = @dbh.prepare("select * from names where name = ?")
|
135
|
+
@sth.execute("Bob")
|
136
|
+
@sth.finish
|
137
|
+
end
|
138
|
+
|
139
|
+
assert_nothing_raised do
|
140
|
+
@sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
|
141
|
+
@sth.execute("Bill", 22);
|
142
|
+
@sth.finish
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_prepare_execute_with_transactions
|
147
|
+
@dbh["AutoCommit"] = false
|
148
|
+
config = DBDConfig.get_config['sqlite3']
|
149
|
+
|
150
|
+
# rollback 1 (the right way)
|
151
|
+
@sth = nil
|
152
|
+
@sth2 = nil
|
153
|
+
|
154
|
+
assert_nothing_raised do
|
155
|
+
@sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
|
156
|
+
@sth.execute("Billy", 23)
|
157
|
+
@sth2 = @dbh.prepare("select * from names where name = ?")
|
158
|
+
@sth2.execute("Billy")
|
159
|
+
end
|
160
|
+
assert_equal ["Billy", 23 ], @sth2.fetch
|
161
|
+
@sth2.finish
|
162
|
+
@sth.finish
|
163
|
+
assert_nothing_raised { @dbh.rollback }
|
164
|
+
|
165
|
+
@sth = @dbh.prepare("select * from names where name = ?")
|
166
|
+
@sth.execute("Billy")
|
167
|
+
assert_nil @sth.fetch
|
168
|
+
@sth.finish
|
169
|
+
|
170
|
+
# rollback 2 (without closing statements first)
|
171
|
+
|
172
|
+
@sth = nil
|
173
|
+
@sth2 = nil
|
174
|
+
|
175
|
+
assert_nothing_raised do
|
176
|
+
@sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
|
177
|
+
@sth.execute("Billy", 23)
|
178
|
+
@sth2 = @dbh.prepare("select * from names where name = ?")
|
179
|
+
@sth2.execute("Billy")
|
180
|
+
end
|
181
|
+
|
182
|
+
assert_equal ["Billy", 23], @sth2.fetch
|
183
|
+
|
184
|
+
# FIXME some throw here, some don't. we should probably normalize this
|
185
|
+
@dbh.rollback rescue true
|
186
|
+
|
187
|
+
@sth2.finish
|
188
|
+
@sth.finish
|
189
|
+
assert_nothing_raised { @dbh.rollback }
|
190
|
+
|
191
|
+
@sth = @dbh.prepare("select * from names where name = ?")
|
192
|
+
@sth.execute("Billy")
|
193
|
+
assert_nil @sth.fetch
|
194
|
+
@sth.finish
|
195
|
+
|
196
|
+
# commit
|
197
|
+
|
198
|
+
@sth = nil
|
199
|
+
@sth2 = nil
|
200
|
+
|
201
|
+
assert_nothing_raised do
|
202
|
+
@sth = @dbh.prepare("insert into names (name, age) values (?, ?)")
|
203
|
+
@sth.execute("Billy", 23)
|
204
|
+
@sth2 = @dbh.prepare("select * from names where name = ?")
|
205
|
+
@sth2.execute("Billy")
|
206
|
+
end
|
207
|
+
assert_equal ["Billy", 23 ], @sth2.fetch
|
208
|
+
@sth2.finish
|
209
|
+
@sth.finish
|
210
|
+
assert_nothing_raised { @dbh.commit }
|
211
|
+
|
212
|
+
@sth = @dbh.prepare("select * from names where name = ?")
|
213
|
+
@sth.execute("Billy")
|
214
|
+
assert_equal ["Billy", 23 ], @sth.fetch
|
215
|
+
@sth.finish
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_fetch
|
219
|
+
@sth = nil
|
220
|
+
assert_nothing_raised do
|
221
|
+
@sth = @dbh.prepare("select * from names order by age")
|
222
|
+
@sth.execute
|
223
|
+
end
|
224
|
+
|
225
|
+
# this tests that we're getting the rows in the right order,
|
226
|
+
# and that the types are being converted.
|
227
|
+
assert_equal ["Joe", 19], @sth.fetch
|
228
|
+
assert_equal ["Bob", 21], @sth.fetch
|
229
|
+
assert_equal ["Jim", 30], @sth.fetch
|
230
|
+
assert_nil @sth.fetch
|
231
|
+
|
232
|
+
@sth.finish
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_transaction_block
|
236
|
+
@dbh["AutoCommit"] = false
|
237
|
+
# this transaction should not fail because it called return early
|
238
|
+
@dbh.transaction do |dbh|
|
239
|
+
dbh.do('INSERT INTO names (name, age) VALUES (?, ?)', "Cooter", 69)
|
240
|
+
return 42
|
241
|
+
end
|
242
|
+
@sth = @dbh.prepare("select * from names where name = ?")
|
243
|
+
@sth.execute("Cooter")
|
244
|
+
row = @sth.fetch
|
245
|
+
assert row
|
246
|
+
assert_equal ["Cooter", 69], row
|
247
|
+
@sth.finish
|
248
|
+
end
|
249
|
+
end
|
@@ -0,0 +1,253 @@
|
|
1
|
+
@class = Class.new(DBDConfig.testbase(DBDConfig.current_dbtype)) do
|
2
|
+
def skip_bit
|
3
|
+
# FIXME this test fails because DBI's type system blows goats.
|
4
|
+
@sth = nil
|
5
|
+
|
6
|
+
assert_nothing_raised do
|
7
|
+
@sth = @dbh.prepare("insert into bit_test (mybit) values (?)")
|
8
|
+
@sth.bind_param(1, 0, DBI::SQL_TINYINT)
|
9
|
+
@sth.execute
|
10
|
+
# if dbtype == "postgresql"
|
11
|
+
# @sth.execute("0")
|
12
|
+
# else
|
13
|
+
# @sth.execute(0)
|
14
|
+
# end
|
15
|
+
@sth.finish
|
16
|
+
end
|
17
|
+
|
18
|
+
assert_nothing_raised do
|
19
|
+
@sth = @dbh.prepare("select * from bit_test")
|
20
|
+
@sth.execute
|
21
|
+
row = @sth.fetch
|
22
|
+
@sth.finish
|
23
|
+
|
24
|
+
assert_equal [0], row
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# FIXME
|
29
|
+
# Ideally, this test should be split across the DBI tests and DBD, but for
|
30
|
+
# now testing against the DBDs really doesn't cost us anything other than
|
31
|
+
# debugging time if something breaks.
|
32
|
+
def test_bind_coltype
|
33
|
+
# ensure type conv didn't get turned off somewhere.
|
34
|
+
assert(DBI.convert_types)
|
35
|
+
assert(@dbh.convert_types)
|
36
|
+
|
37
|
+
assert_nothing_raised do
|
38
|
+
@sth = @dbh.prepare("select name, age from names order by age")
|
39
|
+
assert(@sth.convert_types) # again
|
40
|
+
@sth.execute
|
41
|
+
@sth.bind_coltype(2, DBI::Type::Varchar)
|
42
|
+
assert_equal(
|
43
|
+
[
|
44
|
+
["Joe", "19"],
|
45
|
+
["Bob", "21"],
|
46
|
+
["Jim", "30"],
|
47
|
+
], @sth.fetch_all
|
48
|
+
)
|
49
|
+
@sth.finish
|
50
|
+
end
|
51
|
+
|
52
|
+
# just to be sure..
|
53
|
+
assert_nothing_raised do
|
54
|
+
@sth = @dbh.prepare("select name, age from names order by age")
|
55
|
+
@sth.execute
|
56
|
+
@sth.bind_coltype(2, DBI::Type::Float)
|
57
|
+
@sth.fetch_all.collect { |x| assert_kind_of(Float, x[1]) }
|
58
|
+
@sth.finish
|
59
|
+
end
|
60
|
+
|
61
|
+
# now, let's check some failure cases
|
62
|
+
@sth = @dbh.prepare("select name, age from names order by age")
|
63
|
+
|
64
|
+
# can't bind_coltype before execute
|
65
|
+
assert_raise(DBI::InterfaceError) { @sth.bind_coltype(1, DBI::Type::Float) }
|
66
|
+
# can't index < 1
|
67
|
+
assert_raise(DBI::InterfaceError) { @sth.bind_coltype(0, DBI::Type::Float) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_noconv
|
71
|
+
# XXX this test will fail the whole test suite miserably if it fails at any point.
|
72
|
+
assert(DBI.convert_types)
|
73
|
+
|
74
|
+
DBI.convert_types = false
|
75
|
+
@sth.finish rescue nil
|
76
|
+
@dbh.disconnect
|
77
|
+
set_base_dbh
|
78
|
+
|
79
|
+
assert(!@dbh.convert_types)
|
80
|
+
|
81
|
+
assert_nothing_raised do
|
82
|
+
@sth = @dbh.prepare("select * from names order by age")
|
83
|
+
assert(!@sth.convert_types)
|
84
|
+
@sth.execute
|
85
|
+
assert_equal(
|
86
|
+
[
|
87
|
+
["Joe", "19"],
|
88
|
+
["Bob", "21"],
|
89
|
+
["Jim", "30"],
|
90
|
+
], @sth.fetch_all
|
91
|
+
)
|
92
|
+
@sth.finish
|
93
|
+
end
|
94
|
+
|
95
|
+
DBI.convert_types = true
|
96
|
+
@sth.finish rescue nil
|
97
|
+
@dbh.disconnect
|
98
|
+
set_base_dbh
|
99
|
+
|
100
|
+
assert(DBI.convert_types)
|
101
|
+
assert(@dbh.convert_types)
|
102
|
+
|
103
|
+
assert_nothing_raised do
|
104
|
+
@sth = @dbh.prepare("select * from names order by age")
|
105
|
+
assert(@sth.convert_types)
|
106
|
+
@sth.execute
|
107
|
+
assert_equal(
|
108
|
+
[
|
109
|
+
["Joe", 19],
|
110
|
+
["Bob", 21],
|
111
|
+
["Jim", 30],
|
112
|
+
], @sth.fetch_all
|
113
|
+
)
|
114
|
+
@sth.finish
|
115
|
+
end
|
116
|
+
|
117
|
+
@dbh.convert_types = false
|
118
|
+
|
119
|
+
assert_nothing_raised do
|
120
|
+
@sth = @dbh.prepare("select * from names order by age")
|
121
|
+
assert(!@sth.convert_types)
|
122
|
+
@sth.execute
|
123
|
+
assert_equal(
|
124
|
+
[
|
125
|
+
["Joe", "19"],
|
126
|
+
["Bob", "21"],
|
127
|
+
["Jim", "30"],
|
128
|
+
], @sth.fetch_all
|
129
|
+
)
|
130
|
+
@sth.finish
|
131
|
+
end
|
132
|
+
|
133
|
+
@dbh.convert_types = true
|
134
|
+
|
135
|
+
assert_nothing_raised do
|
136
|
+
@sth = @dbh.prepare("select * from names order by age")
|
137
|
+
assert(@sth.convert_types)
|
138
|
+
@sth.convert_types = false
|
139
|
+
@sth.execute
|
140
|
+
assert_equal(
|
141
|
+
[
|
142
|
+
["Joe", "19"],
|
143
|
+
["Bob", "21"],
|
144
|
+
["Jim", "30"],
|
145
|
+
], @sth.fetch_all
|
146
|
+
)
|
147
|
+
@sth.finish
|
148
|
+
end
|
149
|
+
rescue Exception => e
|
150
|
+
DBI.convert_types = true
|
151
|
+
@sth.finish
|
152
|
+
@dbh.disconnect
|
153
|
+
set_base_dbh
|
154
|
+
raise e
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_null
|
158
|
+
assert_nothing_raised do
|
159
|
+
@sth = @dbh.prepare('insert into names (name, age) values (?, ?)')
|
160
|
+
@sth.execute("'NULL'", 201)
|
161
|
+
@sth.execute(nil, 202)
|
162
|
+
@sth.execute("NULL", 203)
|
163
|
+
@sth.finish
|
164
|
+
end
|
165
|
+
|
166
|
+
assert_nothing_raised do
|
167
|
+
@sth = @dbh.prepare('select * from names where age > 200 order by age')
|
168
|
+
@sth.execute
|
169
|
+
assert_equal(["'NULL'", 201], @sth.fetch)
|
170
|
+
assert_equal([nil, 202], @sth.fetch)
|
171
|
+
assert_equal(["NULL", 203], @sth.fetch)
|
172
|
+
@sth.finish
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_time
|
177
|
+
@sth = nil
|
178
|
+
t = nil
|
179
|
+
assert_nothing_raised do
|
180
|
+
@sth = @dbh.prepare("insert into time_test (mytime) values (?)")
|
181
|
+
t = Time.now
|
182
|
+
@sth.execute(t)
|
183
|
+
@sth.finish
|
184
|
+
end
|
185
|
+
|
186
|
+
assert_nothing_raised do
|
187
|
+
@sth = @dbh.prepare("select * from time_test")
|
188
|
+
@sth.execute
|
189
|
+
row = @sth.fetch
|
190
|
+
assert_kind_of DateTime, row[0]
|
191
|
+
assert_equal t.hour, row[0].hour
|
192
|
+
assert_equal t.min, row[0].min
|
193
|
+
assert_equal t.sec, row[0].sec
|
194
|
+
@sth.finish
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_timestamp
|
199
|
+
@sth = nil
|
200
|
+
# We omit fractional second testing here -- timestamp precision
|
201
|
+
# is a very slippery, dependent on driver and driver version.
|
202
|
+
t = DBI::Timestamp.new(2008, 3, 8, 10, 39, 1)
|
203
|
+
assert_nothing_raised do
|
204
|
+
@sth = @dbh.prepare("insert into timestamp_test (mytimestamp) values (?)")
|
205
|
+
@sth.execute(t)
|
206
|
+
@sth.finish
|
207
|
+
end
|
208
|
+
|
209
|
+
assert_nothing_raised do
|
210
|
+
@sth = @dbh.prepare("select * from timestamp_test")
|
211
|
+
@sth.execute
|
212
|
+
row = @sth.fetch
|
213
|
+
assert_kind_of DateTime, row[0]
|
214
|
+
assert_equal t.year, row[0].year
|
215
|
+
assert_equal t.month, row[0].month
|
216
|
+
assert_equal t.day, row[0].day
|
217
|
+
assert_equal t.hour, row[0].hour
|
218
|
+
assert_equal t.min, row[0].min
|
219
|
+
assert_equal t.sec, row[0].sec
|
220
|
+
# omit fractional tests
|
221
|
+
@sth.finish
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_boolean_return
|
226
|
+
@sth = nil
|
227
|
+
|
228
|
+
unless dbtype == "odbc" # ODBC has no boolean type
|
229
|
+
assert_nothing_raised do
|
230
|
+
@sth = @dbh.prepare("insert into boolean_test (num, mybool) values (?, ?)")
|
231
|
+
@sth.execute(1, true)
|
232
|
+
@sth.execute(2, false)
|
233
|
+
@sth.finish
|
234
|
+
end
|
235
|
+
|
236
|
+
assert_nothing_raised do
|
237
|
+
@sth = @dbh.prepare("select * from boolean_test order by num")
|
238
|
+
@sth.execute
|
239
|
+
|
240
|
+
pairs = @sth.fetch_all
|
241
|
+
|
242
|
+
assert_equal(
|
243
|
+
[
|
244
|
+
[1, true],
|
245
|
+
[2, false],
|
246
|
+
], pairs
|
247
|
+
)
|
248
|
+
|
249
|
+
@sth.finish
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
DBDConfig.set_testbase(:sqlanywhere, Class.new(Test::Unit::TestCase) do
|
2
|
+
def dbtype
|
3
|
+
"sqlanywhere"
|
4
|
+
end
|
5
|
+
|
6
|
+
def test_base
|
7
|
+
assert_equal(@dbh.driver_name, "SQLAnywhere")
|
8
|
+
assert_kind_of(DBI::DBD::SQLAnywhere::Database, @dbh.instance_variable_get(:@handle))
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_base_dbh
|
12
|
+
config = DBDConfig.get_config["sqlanywhere"]
|
13
|
+
@dbh = DBI.connect("dbi:SQLAnywhere:"+config["dbname"], config["username"], config["password"], { })
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup
|
17
|
+
set_base_dbh
|
18
|
+
DBDConfig.inject_sql(@dbh, dbtype, "dbd/sqlanywhere/up.sql")
|
19
|
+
end
|
20
|
+
|
21
|
+
def teardown
|
22
|
+
DBDConfig.inject_sql(@dbh, dbtype, "dbd/sqlanywhere/down.sql")
|
23
|
+
@dbh.disconnect
|
24
|
+
end
|
25
|
+
end
|
26
|
+
)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
drop view view_names;
|
2
|
+
---
|
3
|
+
drop table names;
|
4
|
+
---
|
5
|
+
drop table blob_test;
|
6
|
+
---
|
7
|
+
drop table boolean_test;
|
8
|
+
---
|
9
|
+
drop table time_test;
|
10
|
+
---
|
11
|
+
drop table timestamp_test;
|
12
|
+
---
|
13
|
+
drop table bit_test;
|
14
|
+
---
|
15
|
+
drop table field_types_test;
|
16
|
+
---
|
17
|
+
drop table db_specific_types_test;
|
18
|
+
---
|
19
|
+
drop table precision_test;
|
@@ -0,0 +1,28 @@
|
|
1
|
+
create table names (
|
2
|
+
name varchar(255),
|
3
|
+
age integer
|
4
|
+
);
|
5
|
+
---
|
6
|
+
insert into names (name, age) values ('Joe', 19);
|
7
|
+
---
|
8
|
+
insert into names (name, age) values ('Jim', 30);
|
9
|
+
---
|
10
|
+
insert into names (name, age) values ('Bob', 21);
|
11
|
+
---
|
12
|
+
create table precision_test (text_field varchar(20) primary key not null, integer_field decimal(2,1));
|
13
|
+
---
|
14
|
+
CREATE TABLE blob_test (name VARCHAR(30), data long binary);
|
15
|
+
---
|
16
|
+
create view view_names as select * from names;
|
17
|
+
---
|
18
|
+
create table boolean_test (num integer, mybool bit);
|
19
|
+
---
|
20
|
+
create table time_test (mytime time);
|
21
|
+
---
|
22
|
+
create table timestamp_test (mytimestamp timestamp);
|
23
|
+
---
|
24
|
+
create table bit_test (mybit bit);
|
25
|
+
---
|
26
|
+
create table field_types_test (foo integer not null primary key default 1);
|
27
|
+
---
|
28
|
+
create table db_specific_types_test (ts timestamp, dt date);
|
data/test/ts_dbd.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# figure out what tests to run
|
2
|
+
require 'yaml'
|
3
|
+
require 'test/unit/testsuite'
|
4
|
+
require 'test/unit/ui/console/testrunner'
|
5
|
+
|
6
|
+
if File.basename(Dir.pwd) == "test"
|
7
|
+
$:.unshift('../lib')
|
8
|
+
else
|
9
|
+
$:.unshift('lib')
|
10
|
+
end
|
11
|
+
|
12
|
+
module Test::Unit::Assertions
|
13
|
+
def build_message(head, template=nil, *arguments)
|
14
|
+
template += "\n" + "DATABASE: " + dbtype
|
15
|
+
template &&= template.chomp
|
16
|
+
return AssertionMessage.new(head, template, arguments)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module DBDConfig
|
21
|
+
@testbase = { }
|
22
|
+
@current_dbtype = nil
|
23
|
+
|
24
|
+
def self.get_config
|
25
|
+
config = nil
|
26
|
+
|
27
|
+
begin
|
28
|
+
config = YAML.load_file(File.join(ENV["HOME"], ".ruby-dbi.test-config.yaml"))
|
29
|
+
rescue Exception => e
|
30
|
+
config = { }
|
31
|
+
config["dbtypes"] = [ ]
|
32
|
+
end
|
33
|
+
|
34
|
+
return config
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.inject_sql(dbh, dbtype, file)
|
38
|
+
# splits by --- in the file, strips newlines and the semicolons.
|
39
|
+
# this way we can still manually import the file, but use it with our
|
40
|
+
# drivers for client-independent injection.
|
41
|
+
File.open(file).read.split(/\n*---\n*/, -1).collect { |x| x.gsub!(/\n/, ''); x.sub(/;\z/, '') }.each do |stmt|
|
42
|
+
tmp = STDERR.dup
|
43
|
+
STDERR.reopen('sql.log', 'a')
|
44
|
+
begin
|
45
|
+
dbh.commit rescue nil
|
46
|
+
dbh["AutoCommit"] = true rescue nil
|
47
|
+
dbh.do(stmt)
|
48
|
+
dbh.commit unless dbtype == 'sqlite3'
|
49
|
+
rescue Exception => e
|
50
|
+
tmp.puts "Error injecting '#{stmt}' for db #{dbtype}"
|
51
|
+
tmp.puts "Error: #{e.message}"
|
52
|
+
end
|
53
|
+
STDERR.reopen(tmp)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.current_dbtype
|
58
|
+
@current_dbtype
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.current_dbtype=(setting)
|
62
|
+
@current_dbtype = setting
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.testbase(klass_name)
|
66
|
+
return @testbase[klass_name]
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.set_testbase(klass_name, klass)
|
70
|
+
@testbase[klass_name] = klass
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.suite
|
74
|
+
@suite ||= []
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
if __FILE__ == $0
|
79
|
+
Dir.chdir("..") if File.basename(Dir.pwd) == "test"
|
80
|
+
$LOAD_PATH.unshift(File.join(Dir.pwd, "lib"))
|
81
|
+
Dir.chdir("test") rescue nil
|
82
|
+
|
83
|
+
begin
|
84
|
+
require 'dbi'
|
85
|
+
rescue LoadError => e
|
86
|
+
begin
|
87
|
+
require 'rubygems'
|
88
|
+
gem 'dbi'
|
89
|
+
require 'dbi'
|
90
|
+
rescue LoadError => e
|
91
|
+
abort "DBI must already be installed or must come with this package for tests to work."
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
Deprecate.set_action(proc { })
|
96
|
+
|
97
|
+
config = DBDConfig.get_config
|
98
|
+
|
99
|
+
config["dbtypes"] = ENV["DBTYPES"].split(/\s+/) if ENV["DBTYPES"]
|
100
|
+
|
101
|
+
if config and config["dbtypes"]
|
102
|
+
config["dbtypes"].each do |dbtype|
|
103
|
+
unless config[dbtype]
|
104
|
+
warn "#{dbtype} is selected for testing but not configured; see test/DBD_TESTS"
|
105
|
+
next
|
106
|
+
end
|
107
|
+
|
108
|
+
# base.rb is special, see DBD_TESTS
|
109
|
+
require "dbd/#{dbtype}/base.rb"
|
110
|
+
Dir["dbd/#{dbtype}/test*.rb"].each { |file| require file }
|
111
|
+
# run the general tests
|
112
|
+
DBDConfig.current_dbtype = dbtype.to_sym
|
113
|
+
Dir["dbd/general/test*.rb"].each { |file| load file; DBDConfig.suite << @class }
|
114
|
+
end
|
115
|
+
elsif !config["dbtypes"]
|
116
|
+
warn "Please see test/DBD_TESTS for information on configuring DBD tests."
|
117
|
+
end
|
118
|
+
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: dbd-sqlanywhere
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2008-11-
|
6
|
+
version: 0.1.1
|
7
|
+
date: 2008-11-07 00:00:00 -05:00
|
8
8
|
summary: Ruby DBI driver (DBD) for SQL Anywhere
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -29,10 +29,21 @@ post_install_message:
|
|
29
29
|
authors:
|
30
30
|
- Eric Farrar
|
31
31
|
files:
|
32
|
-
- lib/dbd/SQLAnywhere.rb
|
33
|
-
- lib/dbd/sqlanywhere/statement.rb
|
34
|
-
- lib/dbd/sqlanywhere/driver.rb
|
35
32
|
- lib/dbd/sqlanywhere/database.rb
|
33
|
+
- lib/dbd/sqlanywhere/driver.rb
|
34
|
+
- lib/dbd/sqlanywhere/statement.rb
|
35
|
+
- lib/dbd/SQLAnywhere.rb
|
36
|
+
- test/dbd
|
37
|
+
- test/dbd/general
|
38
|
+
- test/dbd/general/test_database.rb
|
39
|
+
- test/dbd/general/test_statement.rb
|
40
|
+
- test/dbd/general/test_types.rb
|
41
|
+
- test/dbd/sqlanywhere
|
42
|
+
- test/dbd/sqlanywhere/base.rb
|
43
|
+
- test/dbd/sqlanywhere/down.sql
|
44
|
+
- test/dbd/sqlanywhere/up.sql
|
45
|
+
- test/DBD_TESTS
|
46
|
+
- test/ts_dbd.rb
|
36
47
|
- README
|
37
48
|
- CHANGELOG
|
38
49
|
- LICENSE
|