ydbi 0.5.2 → 0.5.7

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 (93) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +35 -0
  3. data/.gitignore +8 -0
  4. data/.travis.yml +15 -0
  5. data/ChangeLog +339 -314
  6. data/Gemfile +5 -0
  7. data/Rakefile +10 -0
  8. data/TODO +44 -0
  9. data/bench/bench.rb +79 -0
  10. data/build/rake_task_lib.rb +186 -0
  11. data/doc/DBD_SPEC.rdoc +88 -0
  12. data/doc/DBI_SPEC.rdoc +157 -0
  13. data/doc/homepage/contact.html +62 -0
  14. data/doc/homepage/development.html +124 -0
  15. data/doc/homepage/index.html +83 -0
  16. data/doc/homepage/ruby-dbi.css +91 -0
  17. data/lib/dbd/Mysql.rb +137 -0
  18. data/lib/dbd/ODBC.rb +89 -0
  19. data/lib/dbd/Pg.rb +188 -0
  20. data/lib/dbd/SQLite.rb +97 -0
  21. data/lib/dbd/SQLite3.rb +124 -0
  22. data/lib/dbd/mysql/database.rb +405 -0
  23. data/lib/dbd/mysql/driver.rb +125 -0
  24. data/lib/dbd/mysql/statement.rb +188 -0
  25. data/lib/dbd/odbc/database.rb +128 -0
  26. data/lib/dbd/odbc/driver.rb +38 -0
  27. data/lib/dbd/odbc/statement.rb +137 -0
  28. data/lib/dbd/pg/database.rb +504 -0
  29. data/lib/dbd/pg/exec.rb +47 -0
  30. data/lib/dbd/pg/statement.rb +160 -0
  31. data/lib/dbd/pg/tuples.rb +121 -0
  32. data/lib/dbd/pg/type.rb +209 -0
  33. data/lib/dbd/sqlite/database.rb +151 -0
  34. data/lib/dbd/sqlite/statement.rb +125 -0
  35. data/lib/dbd/sqlite3/database.rb +201 -0
  36. data/lib/dbd/sqlite3/statement.rb +78 -0
  37. data/lib/dbi.rb +14 -17
  38. data/lib/dbi/utils/date.rb +7 -3
  39. data/lib/dbi/version.rb +1 -1
  40. data/prototypes/types2.rb +237 -0
  41. data/readme.md +15 -0
  42. data/setup.rb +1585 -0
  43. data/test/DBD_TESTS +50 -0
  44. data/test/TESTING +16 -0
  45. data/test/dbd/general/test_database.rb +206 -0
  46. data/test/dbd/general/test_statement.rb +326 -0
  47. data/test/dbd/general/test_types.rb +296 -0
  48. data/test/dbd/mysql/base.rb +26 -0
  49. data/test/dbd/mysql/down.sql +19 -0
  50. data/test/dbd/mysql/test_blob.rb +18 -0
  51. data/test/dbd/mysql/test_new_methods.rb +7 -0
  52. data/test/dbd/mysql/test_patches.rb +111 -0
  53. data/test/dbd/mysql/up.sql +28 -0
  54. data/test/dbd/odbc/base.rb +30 -0
  55. data/test/dbd/odbc/down.sql +19 -0
  56. data/test/dbd/odbc/test_new_methods.rb +12 -0
  57. data/test/dbd/odbc/test_ping.rb +10 -0
  58. data/test/dbd/odbc/test_statement.rb +44 -0
  59. data/test/dbd/odbc/test_transactions.rb +58 -0
  60. data/test/dbd/odbc/up.sql +33 -0
  61. data/test/dbd/postgresql/base.rb +31 -0
  62. data/test/dbd/postgresql/down.sql +31 -0
  63. data/test/dbd/postgresql/test_arrays.rb +179 -0
  64. data/test/dbd/postgresql/test_async.rb +121 -0
  65. data/test/dbd/postgresql/test_blob.rb +36 -0
  66. data/test/dbd/postgresql/test_bytea.rb +87 -0
  67. data/test/dbd/postgresql/test_ping.rb +10 -0
  68. data/test/dbd/postgresql/test_timestamp.rb +77 -0
  69. data/test/dbd/postgresql/test_transactions.rb +58 -0
  70. data/test/dbd/postgresql/testdbipg.rb +307 -0
  71. data/test/dbd/postgresql/up.sql +60 -0
  72. data/test/dbd/sqlite/base.rb +32 -0
  73. data/test/dbd/sqlite/test_database.rb +30 -0
  74. data/test/dbd/sqlite/test_driver.rb +68 -0
  75. data/test/dbd/sqlite/test_statement.rb +112 -0
  76. data/test/dbd/sqlite/up.sql +25 -0
  77. data/test/dbd/sqlite3/base.rb +32 -0
  78. data/test/dbd/sqlite3/test_database.rb +77 -0
  79. data/test/dbd/sqlite3/test_driver.rb +67 -0
  80. data/test/dbd/sqlite3/test_statement.rb +88 -0
  81. data/test/dbd/sqlite3/up.sql +33 -0
  82. data/test/dbi/tc_columninfo.rb +4 -9
  83. data/test/dbi/tc_date.rb +2 -9
  84. data/test/dbi/tc_dbi.rb +3 -9
  85. data/test/dbi/tc_row.rb +17 -23
  86. data/test/dbi/tc_sqlbind.rb +6 -7
  87. data/test/dbi/tc_statementhandle.rb +3 -4
  88. data/test/dbi/tc_time.rb +2 -8
  89. data/test/dbi/tc_timestamp.rb +2 -16
  90. data/test/dbi/tc_types.rb +5 -11
  91. data/test/ts_dbd.rb +131 -0
  92. data/ydbi.gemspec +23 -0
  93. metadata +128 -10
@@ -0,0 +1,28 @@
1
+ create table names (
2
+ name varchar(255),
3
+ age integer
4
+ ) Engine=InnoDB;
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 integer, decimal_field decimal(2,1), numeric_field numeric(30,6));
13
+ ---
14
+ CREATE TABLE blob_test (name VARCHAR(30), data BLOB) Engine=InnoDB;
15
+ ---
16
+ create view view_names as select * from names;
17
+ ---
18
+ create table boolean_test (num integer, mybool boolean) Engine=InnoDB;
19
+ ---
20
+ create table time_test (mytime time) Engine=InnoDB;
21
+ ---
22
+ create table timestamp_test (mytimestamp timestamp) Engine=InnoDB;
23
+ ---
24
+ create table bit_test (mybit bit) Engine=InnoDB;
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);
@@ -0,0 +1,30 @@
1
+ require 'fileutils'
2
+
3
+ DBDConfig.set_testbase(:odbc, Class.new(Test::Unit::TestCase) do
4
+
5
+ def dbtype
6
+ "odbc"
7
+ end
8
+
9
+ def test_base
10
+ assert_equal(@dbh.driver_name, "odbc")
11
+ assert_kind_of(DBI::DBD::ODBC::Database, @dbh.instance_variable_get(:@handle))
12
+ end
13
+
14
+ def set_base_dbh
15
+ config = DBDConfig.get_config['odbc']
16
+ @dbh = DBI.connect("dbi:ODBC:#{config['dbname']}", config['username'], config['password'])
17
+ end
18
+
19
+ def setup
20
+ set_base_dbh
21
+ DBDConfig.inject_sql(@dbh, dbtype, "dbd/odbc/up.sql")
22
+ end
23
+
24
+ def teardown
25
+ @sth.finish if @sth && !@sth.finished?
26
+ DBDConfig.inject_sql(@dbh, dbtype, "dbd/odbc/down.sql")
27
+ @dbh.disconnect
28
+ end
29
+ end
30
+ )
@@ -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,12 @@
1
+ class TestODBCPing < DBDConfig.testbase(:odbc)
2
+ def test_database_name
3
+ #
4
+ # NOTE this test will fail if the database is not named "rubytest". I
5
+ # don't think there's a good way to get around this, so I've set it to
6
+ # what I typically use in my odbc.ini. - erikh
7
+ #
8
+ assert_nothing_raised do
9
+ assert_equal "rubytest", @dbh.database_name
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ class TestODBCPing < DBDConfig.testbase(:odbc)
2
+ def test_ping
3
+ config = DBDConfig.get_config['odbc']
4
+ dbh = DBI.connect("dbi:ODBC:#{config['dbname']}", config['username'], config['password'])
5
+ assert dbh
6
+ assert dbh.ping
7
+ dbh.disconnect
8
+ assert_raises(DBI::InterfaceError) { dbh.ping }
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ class TestODBCStatement < DBDConfig.testbase(:odbc)
2
+ def test_column_info
3
+ sth = nil
4
+
5
+ assert_nothing_raised do
6
+ sth = @dbh.prepare("select * from names")
7
+ sth.execute
8
+ end
9
+
10
+ assert_kind_of Array, sth.column_info
11
+ assert_kind_of DBI::ColumnInfo, sth.column_info[0]
12
+ assert_kind_of DBI::ColumnInfo, sth.column_info[1]
13
+ # XXX odbc seems to have a problem with this every other edition of unixodbc or so.
14
+ # yes, I know this test is important.
15
+ # assert_equal [
16
+ # {
17
+ # :table=>"names",
18
+ # :precision=>255,
19
+ # :searchable=>true,
20
+ # :name=>"name",
21
+ # :unsigned=>true,
22
+ # :length=>255,
23
+ # :sql_type=>12,
24
+ # :scale=>0,
25
+ # :nullable=>true,
26
+ # :type_name=>"VARCHAR"
27
+ # },
28
+ # {
29
+ # :table=>"names",
30
+ # :precision=>10,
31
+ # :searchable=>true,
32
+ # :name=>"age",
33
+ # :unsigned=>false,
34
+ # :length=>4,
35
+ # :sql_type=>4,
36
+ # :scale=>0,
37
+ # :nullable=>true,
38
+ # :type_name=>"INTEGER"
39
+ # }
40
+ # ], sth.column_info
41
+
42
+ sth.finish
43
+ end
44
+ end
@@ -0,0 +1,58 @@
1
+ class TestODBCTransaction < DBDConfig.testbase(:odbc)
2
+ def test_rollback
3
+ dbh = get_dbh
4
+ dbh["AutoCommit"] = false
5
+ @sth = dbh.prepare('insert into names (name, age) values (?, ?)')
6
+ @sth.execute("Foo", 51)
7
+ dbh.rollback
8
+ assert_equal 1, @sth.rows
9
+ @sth.finish
10
+
11
+
12
+ @sth = dbh.prepare('select name, age from names where name=?')
13
+ @sth.execute("Foo")
14
+ assert !@sth.fetch
15
+ @sth.finish
16
+ dbh.disconnect
17
+ end
18
+
19
+ def test_commit
20
+ dbh = get_dbh
21
+ dbh["AutoCommit"] = false
22
+ @sth = dbh.prepare('insert into names (name, age) values (?, ?)')
23
+ @sth.execute("Foo", 51)
24
+ dbh.commit
25
+ assert_equal 1, @sth.rows
26
+ @sth.finish
27
+
28
+ @sth = dbh.prepare('select name, age from names where name=?')
29
+ @sth.execute("Foo")
30
+ row = @sth.fetch
31
+ assert row
32
+ assert_equal "Foo", row[0]
33
+ assert_equal 51, row[1]
34
+ @sth.finish
35
+ dbh.disconnect
36
+ end
37
+
38
+ def test_select_transaction
39
+ # per bug #10466
40
+ dbh = get_dbh
41
+ dbh["AutoCommit"] = false
42
+ @sth = dbh.prepare('select * from test_insert(?, ?)');
43
+ @sth.execute("Foo", 51)
44
+ dbh.rollback
45
+ @sth.finish
46
+
47
+ @sth = dbh.prepare('select name, age from names where name=?')
48
+ @sth.execute("Foo")
49
+ assert !@sth.fetch
50
+ @sth.finish
51
+ dbh.disconnect
52
+ end
53
+
54
+ def get_dbh
55
+ config = DBDConfig.get_config['odbc']
56
+ DBI.connect("dbi:ODBC:#{config['dbname']}", config['username'], config['password'])
57
+ end
58
+ end
@@ -0,0 +1,33 @@
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 integer, decimal_field decimal(2,1), numeric_field numeric(30,6));
13
+ ---
14
+ CREATE TABLE blob_test (name VARCHAR(30), data OID);
15
+ ---
16
+ create view view_names as select * from names;
17
+ ---
18
+ create or replace function test_insert (varchar(255), integer)
19
+ returns integer
20
+ language sql
21
+ as 'insert into names (name, age) values ($1, $2); select age from names where name = $1';
22
+ ---
23
+ create table boolean_test (num integer, mybool boolean);
24
+ ---
25
+ create table time_test (mytime time);
26
+ ---
27
+ create table timestamp_test (mytimestamp timestamp);
28
+ ---
29
+ create table bit_test (mybit bit);
30
+ ---
31
+ create table field_types_test (foo integer not null primary key default 1);
32
+ ---
33
+ create table db_specific_types_test (foo integer);
@@ -0,0 +1,31 @@
1
+ require 'fileutils'
2
+
3
+ DBDConfig.set_testbase(:postgresql, Class.new(Test::Unit::TestCase) do
4
+
5
+ def dbtype
6
+ "postgresql"
7
+ end
8
+
9
+ def test_base
10
+ assert_equal(@dbh.driver_name, "Pg")
11
+ assert_kind_of(DBI::DBD::Pg::Database, @dbh.instance_variable_get(:@handle))
12
+ end
13
+
14
+ def set_base_dbh
15
+ config = DBDConfig.get_config['postgresql']
16
+ @dbh = DBI.connect("dbi:Pg:#{config['dbname']}", config['username'], config['password'])
17
+ end
18
+
19
+ def setup
20
+ set_base_dbh
21
+ DBDConfig.inject_sql(@dbh, dbtype, "dbd/postgresql/up.sql")
22
+ end
23
+
24
+ def teardown
25
+ @sth.finish if @sth && !@sth.finished?
26
+ config = DBDConfig.get_config['postgresql']
27
+ DBDConfig.inject_sql(@dbh, dbtype, "dbd/postgresql/down.sql")
28
+ @dbh.disconnect
29
+ end
30
+ end
31
+ )
@@ -0,0 +1,31 @@
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 array_test;
20
+ ---
21
+ drop table bytea_test;
22
+ ---
23
+ drop table precision_test;
24
+ ---
25
+ drop table enum_type_test;
26
+ ---
27
+ drop type enum_test;
28
+ ---
29
+ drop schema schema1 cascade;
30
+ ---
31
+ drop schema schema2 cascade;
@@ -0,0 +1,179 @@
1
+ class TestPostgresArray < DBDConfig.testbase(:postgresql)
2
+ def test_array_type
3
+ assert_nothing_raised do
4
+ cols = @dbh.columns("array_test")
5
+ assert_equal(
6
+ [
7
+ {
8
+ :name =>"foo",
9
+ :default =>nil,
10
+ :primary =>nil,
11
+ :scale =>nil,
12
+ :sql_type =>DBI::SQL_INTEGER,
13
+ :nullable =>true,
14
+ :indexed =>false,
15
+ :precision =>-1,
16
+ :type_name =>"integer",
17
+ :unique =>nil,
18
+ :array_of_type => true
19
+ },
20
+ {
21
+ :name =>"bar",
22
+ :default =>nil,
23
+ :primary =>nil,
24
+ :scale =>nil,
25
+ :sql_type =>DBI::SQL_INTEGER,
26
+ :nullable =>true,
27
+ :indexed =>false,
28
+ :precision =>-1,
29
+ :type_name =>"integer",
30
+ :unique =>nil,
31
+ :array_of_type => true
32
+ },
33
+ {
34
+ :name =>"baz",
35
+ :default =>nil,
36
+ :primary =>nil,
37
+ :scale =>nil,
38
+ :sql_type =>DBI::SQL_INTEGER,
39
+ :nullable =>true,
40
+ :indexed =>false,
41
+ :precision =>-1,
42
+ :type_name =>"integer",
43
+ :unique =>nil,
44
+ :array_of_type => true
45
+ },
46
+ {
47
+ :array_of_type=>true,
48
+ :unique=>nil,
49
+ :precision=>-1,
50
+ :name=>"quux",
51
+ :default=>nil,
52
+ :indexed=>false,
53
+ :scale=>nil,
54
+ :primary=>nil,
55
+ :sql_type=>12,
56
+ :nullable=>true,
57
+ :type_name=>"character varying"
58
+ }
59
+ ], cols.collect { |x| x.reject { |key, value| key == :dbi_type } }
60
+ )
61
+
62
+ assert_equal(([DBI::DBD::Pg::Type::Array] * 4), cols.collect { |x| x["dbi_type"].class })
63
+ assert_equal((([DBI::Type::Integer] * 3) + [DBI::Type::Varchar]), cols.collect { |x| x["dbi_type"].base_type })
64
+ end
65
+ end
66
+
67
+ def test_array_parser
68
+ # string representation
69
+ assert_nothing_raised do
70
+ sth = @dbh.prepare('insert into array_test (foo) values (?)')
71
+ sth.execute('{1,2,3}')
72
+ sth.finish
73
+ end
74
+
75
+ assert_nothing_raised do
76
+ sth = @dbh.prepare('insert into array_test (foo) values (?)')
77
+ sth.execute([1,2,3])
78
+ sth.finish
79
+ end
80
+
81
+ assert_nothing_raised do
82
+ sth = @dbh.prepare('insert into array_test (quux) values (?)')
83
+ sth.execute(["Hello\\ World", "Again\\"])
84
+ sth.finish
85
+ end
86
+
87
+ assert_nothing_raised do
88
+ sth = @dbh.prepare('select foo from array_test where foo is not null')
89
+ sth.execute
90
+ assert_equal(
91
+ [
92
+ [[1,2,3]],
93
+ [[1,2,3]],
94
+ ], sth.fetch_all
95
+ )
96
+ sth.finish
97
+
98
+ sth = @dbh.prepare('select quux from array_test where quux is not null')
99
+ sth.execute
100
+
101
+ assert_equal(
102
+ [
103
+ [["Hello\\ World", "Again\\"]]
104
+ ], sth.fetch_all
105
+ )
106
+
107
+ sth.finish
108
+ end
109
+ end
110
+
111
+ def test_array_boundaries
112
+ # bar has a max extents of 3
113
+ sth = @dbh.prepare('insert into array_test (bar) values (?)')
114
+
115
+ assert_nothing_raised do
116
+ sth.execute('{1,2,3}')
117
+ end
118
+
119
+ # XXX postgresql does not enforce extents on single-dimension arrays
120
+ assert_nothing_raised do
121
+ sth.execute('{1,2,3,4}')
122
+ end
123
+
124
+ sth.finish
125
+ sth = @dbh.prepare('insert into array_test(baz) values (?)')
126
+
127
+ assert_nothing_raised do
128
+ sth.execute('{{1,2,3}, {1,2,3}}')
129
+ end
130
+
131
+ assert_nothing_raised do
132
+ # XXX for the record, I have no fucking idea why this works, what
133
+ # it's technically represented as and what backwards array
134
+ # implementation would allow it to work.
135
+ #
136
+ # I'm hoping it'll break on some future version of postgresql so I
137
+ # can fix it.
138
+ sth.execute('{1,2,3}')
139
+ end
140
+
141
+ assert_raises(DBI::ProgrammingError) do
142
+ sth.execute('{{1,2,3,4}, {1,2,3}}')
143
+ end
144
+
145
+ assert_raises(DBI::ProgrammingError) do
146
+ sth.execute('{{1,2,3}, {1,2,3,4}}')
147
+ end
148
+
149
+ sth.finish
150
+ end
151
+
152
+ def test_array_type_parser
153
+ pc = DBI::DBD::Pg::Type::Array
154
+
155
+ assert_nothing_raised do
156
+ po = pc.new(DBI::Type::Integer)
157
+ assert_equal([1,2,3], po.parse("{1,2,3}"))
158
+ assert_equal([[1,2,3],[4,5,6]], po.parse("{{1,2,3},{4,5,6}}"))
159
+ end
160
+
161
+ assert_nothing_raised do
162
+ po = pc.new(DBI::Type::Varchar)
163
+ assert_equal(["one", "two", "three"], po.parse("{\"one\",\"two\",\"three\"}"))
164
+ assert_equal([["one"], ["two\\"]], po.parse("{{\"one\"},{\"two\\\\\"}}"))
165
+ assert_equal([["one", "two\\"], ["three\\", "four"]], po.parse("{{\"one\",\"two\\\\\"},{\"three\\\\\",\"four\"}}"))
166
+ end
167
+ end
168
+
169
+ def test_array_generator
170
+ pg = DBI::DBD::Pg
171
+
172
+ assert_nothing_raised do
173
+ assert_equal("{1,2,3}", pg.generate_array([1,2,3]))
174
+ assert_equal("{{1,2,3},{1,2,3}}", pg.generate_array([[1,2,3],[1,2,3]]))
175
+ assert_equal("{\"one\",\"two\"}", pg.generate_array(["one", "two"]))
176
+ assert_equal("{\"hello\\\\ world\",\"again\"}", pg.generate_array(["hello\\ world", "again"]))
177
+ end
178
+ end
179
+ end