dbi 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/ChangeLog +3694 -0
  2. data/LICENSE +25 -0
  3. data/README +271 -0
  4. data/bin/dbi +518 -0
  5. data/build/Rakefile.dbi.rb +57 -0
  6. data/examples/test1.pl +39 -0
  7. data/examples/test1.rb +20 -0
  8. data/examples/xmltest.rb +8 -0
  9. data/lib/dbi.rb +323 -0
  10. data/lib/dbi/base_classes.rb +12 -0
  11. data/lib/dbi/base_classes/database.rb +135 -0
  12. data/lib/dbi/base_classes/driver.rb +47 -0
  13. data/lib/dbi/base_classes/statement.rb +167 -0
  14. data/lib/dbi/binary.rb +25 -0
  15. data/lib/dbi/columninfo.rb +106 -0
  16. data/lib/dbi/exceptions.rb +65 -0
  17. data/lib/dbi/handles.rb +49 -0
  18. data/lib/dbi/handles/database.rb +211 -0
  19. data/lib/dbi/handles/driver.rb +60 -0
  20. data/lib/dbi/handles/statement.rb +375 -0
  21. data/lib/dbi/row.rb +249 -0
  22. data/lib/dbi/sql.rb +23 -0
  23. data/lib/dbi/sql/preparedstatement.rb +115 -0
  24. data/lib/dbi/sql_type_constants.rb +75 -0
  25. data/lib/dbi/trace.rb +91 -0
  26. data/lib/dbi/types.rb +158 -0
  27. data/lib/dbi/typeutil.rb +108 -0
  28. data/lib/dbi/utils.rb +60 -0
  29. data/lib/dbi/utils/date.rb +59 -0
  30. data/lib/dbi/utils/tableformatter.rb +112 -0
  31. data/lib/dbi/utils/time.rb +52 -0
  32. data/lib/dbi/utils/timestamp.rb +96 -0
  33. data/lib/dbi/utils/xmlformatter.rb +73 -0
  34. data/test/dbi/tc_columninfo.rb +94 -0
  35. data/test/dbi/tc_date.rb +88 -0
  36. data/test/dbi/tc_dbi.rb +178 -0
  37. data/test/dbi/tc_row.rb +256 -0
  38. data/test/dbi/tc_sqlbind.rb +168 -0
  39. data/test/dbi/tc_statementhandle.rb +16 -0
  40. data/test/dbi/tc_time.rb +77 -0
  41. data/test/dbi/tc_timestamp.rb +142 -0
  42. data/test/dbi/tc_types.rb +220 -0
  43. data/test/dbi/trace.rb +26 -0
  44. data/test/ts_dbi.rb +15 -0
  45. metadata +108 -0
@@ -0,0 +1,178 @@
1
+ ######################################################################
2
+ # tc_dbi.rb
3
+ #
4
+ # Test case for the DBI module (dbi.rb).
5
+ ######################################################################
6
+ $LOAD_PATH.unshift(Dir.pwd)
7
+ $LOAD_PATH.unshift(File.dirname(Dir.pwd))
8
+ $LOAD_PATH.unshift("../../lib")
9
+ $LOAD_PATH.unshift("../../lib/dbi")
10
+ $LOAD_PATH.unshift("lib")
11
+
12
+ require 'dbi'
13
+ require 'test/unit'
14
+
15
+ class TC_DBI < Test::Unit::TestCase
16
+ def setup
17
+ @db_error = DBI::DatabaseError.new("test", 1, "montana")
18
+ @db_binary = DBI::Binary.new("test")
19
+ @url_basic = 'dbi:foo:bar'
20
+ @url_inter = 'dbi:foo:bar:host'
21
+ @url_advan = 'dbi:foo:database=db;host=xx;port=99'
22
+ end
23
+
24
+ def test_dbi_version
25
+ assert_equal("0.4.0", DBI::VERSION)
26
+ end
27
+
28
+ def test_dbd_module
29
+ assert_equal("0.3", DBI::DBD::API_VERSION)
30
+ end
31
+
32
+ def test_fetch_scroll_constants
33
+ assert_equal(1, DBI::SQL_FETCH_NEXT)
34
+ assert_equal(2, DBI::SQL_FETCH_PRIOR)
35
+ assert_equal(3, DBI::SQL_FETCH_FIRST)
36
+ assert_equal(4, DBI::SQL_FETCH_LAST)
37
+ assert_equal(5, DBI::SQL_FETCH_ABSOLUTE)
38
+ assert_equal(6, DBI::SQL_FETCH_RELATIVE)
39
+ end
40
+
41
+ def test_sql_type_constants
42
+ assert_equal(1, DBI::SQL_CHAR)
43
+ assert_equal(2, DBI::SQL_NUMERIC)
44
+ assert_equal(3, DBI::SQL_DECIMAL)
45
+ assert_equal(4, DBI::SQL_INTEGER)
46
+ assert_equal(5, DBI::SQL_SMALLINT)
47
+ assert_equal(6, DBI::SQL_FLOAT)
48
+ assert_equal(7, DBI::SQL_REAL)
49
+ assert_equal(8, DBI::SQL_DOUBLE)
50
+ assert_equal(9, DBI::SQL_DATE)
51
+ assert_equal(10, DBI::SQL_TIME)
52
+ assert_equal(11, DBI::SQL_TIMESTAMP)
53
+ assert_equal(12, DBI::SQL_VARCHAR)
54
+ assert_equal(100, DBI::SQL_OTHER)
55
+ assert_equal(-1, DBI::SQL_LONGVARCHAR)
56
+ assert_equal(-2, DBI::SQL_BINARY)
57
+ assert_equal(-3, DBI::SQL_VARBINARY)
58
+ assert_equal(-4, DBI::SQL_LONGVARBINARY)
59
+ assert_equal(-5, DBI::SQL_BIGINT)
60
+ assert_equal(-6, DBI::SQL_TINYINT)
61
+ assert_equal(-7, DBI::SQL_BIT)
62
+ assert_equal(-10, DBI::SQL_BLOB)
63
+ assert_equal(-11, DBI::SQL_CLOB)
64
+ end
65
+
66
+ def test_sql_type_names
67
+ assert_equal('BIT', DBI::SQL_TYPE_NAMES[DBI::SQL_BIT])
68
+ assert_equal('TINYINT', DBI::SQL_TYPE_NAMES[DBI::SQL_TINYINT])
69
+ assert_equal('SMALLINT', DBI::SQL_TYPE_NAMES[DBI::SQL_SMALLINT])
70
+ assert_equal('INTEGER', DBI::SQL_TYPE_NAMES[DBI::SQL_INTEGER])
71
+ assert_equal('BIGINT', DBI::SQL_TYPE_NAMES[DBI::SQL_BIGINT])
72
+ assert_equal('FLOAT', DBI::SQL_TYPE_NAMES[DBI::SQL_FLOAT])
73
+ assert_equal('REAL', DBI::SQL_TYPE_NAMES[DBI::SQL_REAL])
74
+ assert_equal('DOUBLE', DBI::SQL_TYPE_NAMES[DBI::SQL_DOUBLE])
75
+ assert_equal('NUMERIC', DBI::SQL_TYPE_NAMES[DBI::SQL_NUMERIC])
76
+ assert_equal('DECIMAL', DBI::SQL_TYPE_NAMES[DBI::SQL_DECIMAL])
77
+ assert_equal('CHAR', DBI::SQL_TYPE_NAMES[DBI::SQL_CHAR])
78
+ assert_equal('VARCHAR', DBI::SQL_TYPE_NAMES[DBI::SQL_VARCHAR])
79
+ assert_equal('LONG VARCHAR', DBI::SQL_TYPE_NAMES[DBI::SQL_LONGVARCHAR])
80
+ assert_equal('DATE', DBI::SQL_TYPE_NAMES[DBI::SQL_DATE])
81
+ assert_equal('TIME', DBI::SQL_TYPE_NAMES[DBI::SQL_TIME])
82
+ assert_equal('TIMESTAMP', DBI::SQL_TYPE_NAMES[DBI::SQL_TIMESTAMP])
83
+ assert_equal('BINARY', DBI::SQL_TYPE_NAMES[DBI::SQL_BINARY])
84
+ assert_equal('VARBINARY', DBI::SQL_TYPE_NAMES[DBI::SQL_VARBINARY])
85
+ assert_equal('LONG VARBINARY',
86
+ DBI::SQL_TYPE_NAMES[DBI::SQL_LONGVARBINARY])
87
+ assert_equal('BLOB', DBI::SQL_TYPE_NAMES[DBI::SQL_BLOB])
88
+ assert_equal('CLOB', DBI::SQL_TYPE_NAMES[DBI::SQL_CLOB])
89
+ assert_equal(nil, DBI::SQL_TYPE_NAMES[DBI::SQL_OTHER])
90
+ end
91
+
92
+ def test_dbi_exception_classes
93
+ assert(DBI::Error)
94
+ assert(DBI::Warning)
95
+ assert(DBI::InterfaceError)
96
+ assert(DBI::NotImplementedError)
97
+ assert(DBI::DatabaseError)
98
+ assert(DBI::DataError)
99
+ assert(DBI::OperationalError)
100
+ assert(DBI::IntegrityError)
101
+ assert(DBI::InternalError)
102
+ assert(DBI::ProgrammingError)
103
+ assert(DBI::NotSupportedError)
104
+ end
105
+
106
+ # This error class gets extra testing since it defines some custom
107
+ # accessors.
108
+ def test_dbi_database_error
109
+ assert_respond_to(@db_error, :errstr)
110
+ assert_respond_to(@db_error, :err)
111
+ assert_respond_to(@db_error, :state)
112
+ assert_equal("test", @db_error.errstr)
113
+ assert_equal(1, @db_error.err)
114
+ assert_equal("montana", @db_error.state)
115
+ end
116
+
117
+ def test_binary_datatype
118
+ assert_respond_to(@db_binary, :data)
119
+ assert_respond_to(@db_binary, :to_s)
120
+ assert_equal("test", @db_binary.data)
121
+ assert_equal("test", @db_binary.to_s)
122
+ end
123
+
124
+ def test_misc_constants
125
+ assert_equal(2, DBI::DEFAULT_TRACE_MODE)
126
+ assert_equal(STDERR, DBI::DEFAULT_TRACE_OUTPUT)
127
+ end
128
+
129
+ def test_connect
130
+ assert_respond_to(DBI, :connect)
131
+ end
132
+
133
+ def test_available_drivers
134
+ assert_respond_to(DBI, :available_drivers)
135
+ end
136
+
137
+ # PRIVATE METHODS
138
+ def test_parse_url
139
+ assert_nothing_raised{ DBI.send(:parse_url, "dbi:foo:bar") }
140
+ assert_equal(["foo","bar"], DBI.send(:parse_url, @url_basic))
141
+ assert_equal(["foo","bar:host"], DBI.send(:parse_url, @url_inter))
142
+ assert_equal(["foo","database=db;host=xx;port=99"],
143
+ DBI.send(:parse_url, @url_advan)
144
+ )
145
+ end
146
+
147
+ def test_parse_url_expected_errors
148
+ assert_raises(DBI::InterfaceError){ DBI.send(:parse_url, 'dbi') }
149
+ assert_raises(DBI::InterfaceError){ DBI.send(:parse_url, 'dbi::foo') }
150
+
151
+ # XXX we're looking for a specific exception message here
152
+ assert_nothing_raised do
153
+ begin
154
+ DBI.send(:parse_url, 'dbi:blah')
155
+ rescue DBI::InterfaceError => e
156
+ assert true
157
+ assert_kind_of DBI::InterfaceError, e
158
+ assert_equal "Invalid Data Source Name", e.message
159
+ end
160
+ end
161
+ end
162
+
163
+ def test_available_drivers
164
+ assert_equal(
165
+ [
166
+ "dbi:Mysql:",
167
+ "dbi:ODBC:",
168
+ "dbi:Pg:",
169
+ "dbi:SQLite3:",
170
+ "dbi:SQLite:"
171
+ ], DBI.available_drivers.sort)
172
+ end
173
+
174
+ def teardown
175
+ @db_error = nil
176
+ @db_binary = nil
177
+ end
178
+ end
@@ -0,0 +1,256 @@
1
+ ######################################################################
2
+ # tc_row.rb
3
+ #
4
+ # Test case for the DBI::Row class.
5
+ ######################################################################
6
+ $LOAD_PATH.unshift(Dir.pwd)
7
+ $LOAD_PATH.unshift(File.dirname(Dir.pwd))
8
+ $LOAD_PATH.unshift("../../lib")
9
+ $LOAD_PATH.unshift("../../lib/dbi")
10
+ $LOAD_PATH.unshift("lib")
11
+
12
+ require 'test/unit'
13
+ require 'dbi'
14
+
15
+ class TC_DBI_Row < Test::Unit::TestCase
16
+ def setup
17
+ @data = %w/Daniel Berger 36/
18
+ @cols = %w/first last age/
19
+ @coltypes = [DBI::Type::Varchar, DBI::Type::Varchar, DBI::Type::Integer]
20
+ @row = DBI::Row.new(@cols, @coltypes, @data.clone)
21
+ @row_noconv = DBI::Row.new(@cols, @coltypes, @data.clone, false)
22
+ end
23
+
24
+ def teardown
25
+ @data = nil
26
+ @cols = nil
27
+ @row = nil
28
+ end
29
+
30
+ def test_row_multiassign # this should only be an issue in 1.8.7 and up, if at all.
31
+ first, last, age = @row
32
+ assert_equal("Daniel", first)
33
+ assert_equal("Berger", last)
34
+ assert_equal(36, age)
35
+ end
36
+
37
+ def test_row_noconv
38
+ assert_nothing_raised do
39
+ assert_equal(
40
+ [
41
+ 'Daniel',
42
+ 'Berger',
43
+ 36
44
+ ], @row
45
+ )
46
+ assert_equal(@data, @row_noconv)
47
+ end
48
+ end
49
+
50
+ # Ensure that constructor only allows Integers or Arrays (or nil)
51
+ def test_row_constructor
52
+ assert_nothing_raised{ DBI::Row.new(@cols, @coltypes) }
53
+ assert_nothing_raised{ DBI::Row.new(@cols, @coltypes, 1) }
54
+ assert_nothing_raised{ DBI::Row.new(@cols, @coltypes, nil) }
55
+ assert_nothing_raised{ DBI::Row.new(@cols, @coltypes, [1,2,3])}
56
+ assert_raises(ArgumentError){ DBI::Row.new }
57
+ assert_raises(ArgumentError){ DBI::Row.new(@cols) }
58
+ assert_raises(TypeError){ DBI::Row.new(@cols, @coltypes, {}) }
59
+ end
60
+
61
+ # Test added to ensure that Row#at is equivalent to Row#by_index. When the
62
+ # latter method is (hopefully) removed, this test can be removed as well.
63
+ def test_at
64
+ assert_respond_to(@row, :at)
65
+ assert_equal(@data[0].to_s, @row.at(0).to_s)
66
+ assert_equal(@data[1].to_s, @row.at(1).to_s)
67
+ assert_equal(@data[2].to_s, @row.at(2).to_s)
68
+ assert_equal(@data[99].to_s, @row.at(99).to_s)
69
+ end
70
+
71
+ # Should respond to Array and Enumerable methods
72
+ def test_row_delegate
73
+ assert_respond_to(@row, :length)
74
+ assert_respond_to(@row, :each)
75
+ assert_respond_to(@row, :grep)
76
+ end
77
+
78
+ def test_row_length
79
+ assert_equal(3, @row.length)
80
+ assert_equal(3, DBI::Row.new(@cols, @coltypes).length)
81
+ end
82
+
83
+ def test_row_data_by_index
84
+ assert_equal(@data[0], @row.by_index(0))
85
+ assert_equal(@data[1], @row.by_index(1))
86
+ assert_equal(@data[2], @row.by_index(2).to_s)
87
+ assert_nil(@row.by_index(3))
88
+ end
89
+
90
+ def test_row_data_by_field
91
+ assert_equal @data[0], @row.by_field('first')
92
+ assert_equal @data[1], @row.by_field('last')
93
+ assert_equal @data[2], @row.by_field('age').to_s
94
+ assert_equal nil, @row.by_field('unknown')
95
+ end
96
+
97
+ def test_row_set_values
98
+ assert_respond_to(@row, :set_values)
99
+ assert_nothing_raised{ @row.set_values(["John", "Doe", 23]) }
100
+ assert_equal("John", @row.by_index(0))
101
+ assert_equal("Doe", @row.by_index(1))
102
+ assert_equal(23, @row.by_index(2))
103
+ end
104
+
105
+ def test_row_to_h
106
+ assert_respond_to(@row, :to_h)
107
+ assert_nothing_raised{ @row.to_h }
108
+ assert_kind_of(Hash, @row.to_h)
109
+ assert_equal({"first"=>"Daniel", "last"=>"Berger", "age"=>36}, @row.to_h)
110
+ end
111
+
112
+ def test_row_column_names
113
+ assert_respond_to(@row, :column_names)
114
+ assert_nothing_raised{ @row.column_names }
115
+ assert_kind_of(Array, @row.column_names)
116
+ assert_equal(["first", "last", "age"], @row.column_names)
117
+ end
118
+
119
+ # An alias for column_names
120
+ def test_row_field_names
121
+ assert_respond_to(@row, :column_names)
122
+ assert_nothing_raised{ @row.column_names }
123
+ assert_kind_of(Array, @row.column_names)
124
+ assert_equal(["first", "last", "age"], @row.column_names)
125
+ end
126
+
127
+ def test_indexing_numeric
128
+ assert_equal(@data[0], @row[0])
129
+ assert_equal(@data[1], @row[1])
130
+ assert_equal(@data[2], @row[2].to_s)
131
+ end
132
+
133
+ def test_indexing_string_or_symbol
134
+ assert_equal(@data[0], @row['first'])
135
+ assert_equal(@data[0], @row[:first])
136
+ assert_equal(@data[1], @row['last'])
137
+ assert_equal(@data[2], @row['age'].to_s)
138
+ assert_equal(nil, @row['unknown'])
139
+ end
140
+
141
+ def test_indexing_regexp
142
+ assert_equal(["Daniel"], @row[/first/])
143
+ assert_equal(["Berger"], @row[/last/])
144
+ assert_equal([36], @row[/age/])
145
+ assert_equal(["Daniel", "Berger"], @row[/first|last/])
146
+ assert_equal([], @row[/bogus/])
147
+ end
148
+
149
+ def test_indexing_array
150
+ assert_equal(["Daniel"], @row[[0]])
151
+ assert_equal(["Daniel"], @row[["first"]])
152
+ assert_equal(["Berger"], @row[[1]])
153
+ assert_equal([36], @row[[2]])
154
+ assert_equal([nil], @row[[3]])
155
+ assert_equal(["Daniel", 36], @row[[0,2]])
156
+ assert_equal(["Daniel", 36], @row[[0,:age]])
157
+ end
158
+
159
+ def test_indexing_range
160
+ assert_equal(["Daniel","Berger"], @row[0..1])
161
+ assert_equal(["Berger",36], @row[1..2])
162
+ assert_equal(["Berger",36], @row[1..99])
163
+ assert_equal(nil, @row[90..100])
164
+ end
165
+
166
+ # The two argument reference should behave like the second form of Array#[]
167
+ def test_indexing_two_args
168
+ assert_equal([], @row[0,0])
169
+ assert_equal(["Daniel"], @row[0,1])
170
+ assert_equal(["Daniel", "Berger"], @row[0,2])
171
+ assert_equal(["Daniel", "Berger", 36], @row[0,3])
172
+ assert_equal(["Daniel", "Berger", 36], @row[0,99])
173
+ end
174
+
175
+ def test_indexing_multiple_args
176
+ assert_equal(["Berger", 36, "Daniel"], @row[:last, :age, :first])
177
+ assert_equal(["Berger", 36, "Daniel"], @row[1, :age, :first])
178
+ assert_equal(["Berger", 36, "Daniel"], @row[1, 2, :first])
179
+ assert_equal(["Berger", 36, "Daniel"], @row[1, 2, 0])
180
+ assert_equal(["Berger", 36, "Daniel", nil], @row[1, 2, 0, 9])
181
+ assert_equal(["Berger", 36, "Daniel", nil], @row[1, 2, 0, :bogus])
182
+ end
183
+
184
+ def test_indexing_assignment
185
+ assert_nothing_raised{ @row[0] = "kirk" }
186
+ assert_equal("kirk", @row[0])
187
+
188
+ assert_nothing_raised{ @row[:age] = 29 }
189
+ assert_equal(29, @row[:age])
190
+
191
+ assert_nothing_raised{ @row[1,2] = "francis" }
192
+ assert_equal("francis", @row[:last])
193
+ assert_nil(@row[:age])
194
+ end
195
+
196
+ def test_clone_with
197
+ another_row = @row.clone_with(["Jane", "Smith", 33])
198
+ assert_kind_of(DBI::Row, another_row)
199
+ assert_equal "Jane", another_row.by_index(0)
200
+ assert_equal "Smith", another_row.by_index(1)
201
+ assert_equal 33, another_row.by_index(2)
202
+ assert(@row != another_row)
203
+ end
204
+
205
+ def test_iteration
206
+ expect = @data.clone
207
+ @row.each { |value|
208
+ assert_equal(expect.shift, value.to_s)
209
+ }
210
+ assert_equal([], expect)
211
+ @row.collect { |value| "Field=#{value}" }
212
+ end
213
+
214
+ def test_row_each_with_name
215
+ assert_respond_to(@row, :each_with_name)
216
+ assert_nothing_raised{ @row.each_with_name{ } }
217
+
218
+ @row.each_with_name{ |value, column|
219
+ assert(@cols.include?(column))
220
+ assert(@data.include?(value.to_s))
221
+ }
222
+ end
223
+
224
+ def test_to_a
225
+ assert_respond_to(@row, :to_a)
226
+ assert_equal(@data, DBI::Row.new(@cols, @coltypes, @data).to_a.collect { |x| x.to_s })
227
+ end
228
+
229
+ def test_dup_clone
230
+ dupped = nil
231
+ cloned = nil
232
+
233
+ assert_nothing_raised{ dupped = @row.dup }
234
+ assert_nothing_raised{ cloned = @row.clone }
235
+ assert_nothing_raised{ @row.set_values(["Bill", "Jones", 16])}
236
+
237
+ assert_equal(@data, dupped.to_a.collect { |x| x.to_s })
238
+ assert_equal(@data, cloned.to_a.collect { |x| x.to_s })
239
+
240
+ assert(dupped.object_id != @row.object_id)
241
+ assert(cloned.object_id != @row.object_id)
242
+ end
243
+
244
+ def test_dup_ruby18
245
+ res = []
246
+ r = DBI::Row.new(["col1","col2"],[nil,nil])
247
+
248
+ [["one",1],["two",2],["three",3]].each do |x,y|
249
+ r["col1"] = x
250
+ r["col2"] = y
251
+ res << r.dup
252
+ end
253
+
254
+ assert_equal res, [["one", 1], ["two", 2], ["three", 3]]
255
+ end
256
+ end
@@ -0,0 +1,168 @@
1
+ $: << 'lib'
2
+ require 'test/unit'
3
+ require "dbi/sql"
4
+
5
+ # ====================================================================
6
+ class TestSqlBind < Test::Unit::TestCase
7
+
8
+ def bind(quoter, sql, args)
9
+ ps = DBI::SQL::PreparedStatement.new(quoter, sql)
10
+ ps.bind(DBI::Utils::ConvParam.conv_param('default', *args))
11
+ end
12
+
13
+ def test_one
14
+ assert_equal "10", bind(self, "?", [10])
15
+ assert_equal "'hi'", bind(self, "?", ["hi"])
16
+ assert_equal "I 'don''t' know", bind(self, "I ? know", ["don't"])
17
+ end
18
+
19
+ def test_many
20
+ assert_equal "WHERE age=12 AND name='Jim'",
21
+ bind(self, "WHERE age=? AND name=?", [12, 'Jim'])
22
+ end
23
+
24
+ def test_too_many
25
+ assert_raise (RuntimeError) {
26
+ bind(self, "age=?", [10, 11])
27
+ }
28
+ end
29
+
30
+ def test_too_few
31
+ assert_raise (RuntimeError) {
32
+ bind(self, "age in (?, ?, ?)", [10, 11])
33
+ }
34
+ end
35
+
36
+ def test_embedded_questions
37
+ assert_equal "10 ? 11", bind(self, "? ?? ?", [10, 11])
38
+ assert_equal "????", bind(self, "????????", [])
39
+ end
40
+
41
+ def test_questions_in_param
42
+ assert_equal "WHERE c='connected?'",
43
+ bind(self, "WHERE c=?", ["connected?"])
44
+
45
+ assert_equal "WHERE c='connected?' AND d='???'",
46
+ bind(self, "WHERE c=? AND d=?", ["connected?", "???"])
47
+ end
48
+
49
+ def test_questions_in_quotes
50
+ assert_equal "WHERE c='connected?' AND d=10",
51
+ bind(self, "WHERE c='connected?' AND d=?", [10])
52
+ end
53
+
54
+ def test_comment_dan
55
+ sql = %{--Dan's query\n--random comment\nselect column1, column2\nfrom table1\nwhere somevalue = ?}
56
+ res = %{--Dan's query\n--random comment\nselect column1, column2\nfrom table1\nwhere somevalue = 10}
57
+ assert_equal res, bind(self, sql, [10])
58
+ end
59
+
60
+ def test_minus_bug
61
+ sql = "SELECT 1 - 3"
62
+ res = "SELECT 1 - 3"
63
+ assert_equal res, bind(self, sql, [])
64
+ end
65
+
66
+ def test_minus2
67
+ sql = "SELECT * from test --Dan's query"
68
+ assert_equal sql, bind(self, sql, [])
69
+ end
70
+
71
+ def test_slash
72
+ sql = "SELECT 5 / 4"
73
+ res = "SELECT 5 / 4"
74
+ assert_equal res, bind(self, sql, [])
75
+ end
76
+
77
+ def test_much
78
+ sql = <<ENDSQL
79
+ SELECT s.id, cwajga_magic_number((cwajga_product(r.rating) ^ (1 / 1)), MAX(lastplay.lastheard), 5) as magic
80
+ INTO TEMP magic_order
81
+ FROM song AS s LEFT OUTER JOIN rating AS r ON s.id = r.song LEFT OUTER JOIN last play ON lastplay.song = s.id
82
+ WHERE r.name ILIKE 'omega697'
83
+ GROUP BY s.id;
84
+
85
+ SELECT SUM(magic) as total INTO TEMP magic_tot FROM magic_order;
86
+
87
+ SELECT id, 100.0*magic/total as percent
88
+ FROM magic_order, magic_tot
89
+ order by percent;
90
+ ENDSQL
91
+ res = sql
92
+ assert_equal res, bind(self, sql, [])
93
+ end
94
+
95
+ def test_nested_insert
96
+ sql = "insert into logins (user_id, hostmask) values ((select id from users where username = ?), ?)"
97
+ res = sql.sub(/\?/, "1")
98
+ res.sub!(/\?/, "'foo@bar'")
99
+ assert_equal res, bind(self, sql, [1, "foo@bar"])
100
+ end
101
+
102
+ end
103
+
104
+ ######################################################################
105
+ class TestLex < Test::Unit::TestCase
106
+
107
+ def tokens(sql)
108
+ DBI::SQL::PreparedStatement.tokens(sql)
109
+ end
110
+
111
+ def test_non_strings
112
+ assert_equal ['This is _a t35t'],
113
+ tokens("This is _a t35t")
114
+ end
115
+
116
+ def test_simple_strings
117
+ assert_equal ["hi ", "'hello world'"],
118
+ tokens("hi 'hello world'")
119
+ assert_equal ["c = ", "''"],
120
+ tokens("c = ''")
121
+ end
122
+
123
+ def test_strings_with_quotes
124
+ assert_equal ["hi ", "'''lo world'"],
125
+ tokens("hi '''lo world'")
126
+ assert_equal ['a', "''''", 'b'],
127
+ tokens("a''''b")
128
+ end
129
+
130
+ def test_strings_with_escaped_quotes
131
+ assert_equal ["hi ", "'don\\'t do that'"],
132
+ tokens("hi 'don\\'t do that'")
133
+ assert_equal ['a', "'\\''", 'b'],
134
+ tokens("a'\\''b")
135
+ end
136
+
137
+ def test_simple_dq_strings
138
+ assert_equal ["hi ", '"hello world"'],
139
+ tokens('hi "hello world"')
140
+ assert_equal ["c = ", '""'],
141
+ tokens('c = ""')
142
+ end
143
+
144
+ def test_dq_strings_with_quotes
145
+ assert_equal ["hi ", '"""lo world"'],
146
+ tokens('hi """lo world"')
147
+ assert_equal ['a', '""""', 'b'],
148
+ tokens('a""""b')
149
+ end
150
+
151
+ def test_dq_strings_with_escaped_quotes
152
+ assert_equal ["hi ", '"don\"t do that"'],
153
+ tokens('hi "don\"t do that"')
154
+ assert_equal ['a', '"\""', 'b'],
155
+ tokens('a"\""b')
156
+ end
157
+
158
+ def test_qmarks
159
+ assert_equal ["a = ", "?"],
160
+ tokens("a = ?")
161
+ assert_equal ["'?'", " = ", "?"],
162
+ tokens("'?' = ?")
163
+ assert_equal ["'?'", " = ", "??"],
164
+ tokens("'?' = ??")
165
+ end
166
+
167
+ end
168
+