dbi 0.4.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.
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
+