ydbi 0.5.7 → 0.5.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +3 -0
  3. data/lib/dbi/version.rb +1 -1
  4. metadata +9 -128
  5. data/.github/workflows/ruby.yml +0 -35
  6. data/.gitignore +0 -8
  7. data/.travis.yml +0 -15
  8. data/Gemfile +0 -5
  9. data/Rakefile +0 -10
  10. data/TODO +0 -44
  11. data/bench/bench.rb +0 -79
  12. data/build/rake_task_lib.rb +0 -186
  13. data/doc/DBD_SPEC.rdoc +0 -88
  14. data/doc/DBI_SPEC.rdoc +0 -157
  15. data/doc/homepage/contact.html +0 -62
  16. data/doc/homepage/development.html +0 -124
  17. data/doc/homepage/index.html +0 -83
  18. data/doc/homepage/ruby-dbi.css +0 -91
  19. data/lib/dbd/Mysql.rb +0 -137
  20. data/lib/dbd/ODBC.rb +0 -89
  21. data/lib/dbd/Pg.rb +0 -188
  22. data/lib/dbd/SQLite.rb +0 -97
  23. data/lib/dbd/SQLite3.rb +0 -124
  24. data/lib/dbd/mysql/database.rb +0 -405
  25. data/lib/dbd/mysql/driver.rb +0 -125
  26. data/lib/dbd/mysql/statement.rb +0 -188
  27. data/lib/dbd/odbc/database.rb +0 -128
  28. data/lib/dbd/odbc/driver.rb +0 -38
  29. data/lib/dbd/odbc/statement.rb +0 -137
  30. data/lib/dbd/pg/database.rb +0 -504
  31. data/lib/dbd/pg/exec.rb +0 -47
  32. data/lib/dbd/pg/statement.rb +0 -160
  33. data/lib/dbd/pg/tuples.rb +0 -121
  34. data/lib/dbd/pg/type.rb +0 -209
  35. data/lib/dbd/sqlite/database.rb +0 -151
  36. data/lib/dbd/sqlite/statement.rb +0 -125
  37. data/lib/dbd/sqlite3/database.rb +0 -201
  38. data/lib/dbd/sqlite3/statement.rb +0 -78
  39. data/prototypes/types2.rb +0 -237
  40. data/setup.rb +0 -1585
  41. data/test/DBD_TESTS +0 -50
  42. data/test/TESTING +0 -16
  43. data/test/dbd/general/test_database.rb +0 -206
  44. data/test/dbd/general/test_statement.rb +0 -326
  45. data/test/dbd/general/test_types.rb +0 -296
  46. data/test/dbd/mysql/base.rb +0 -26
  47. data/test/dbd/mysql/down.sql +0 -19
  48. data/test/dbd/mysql/test_blob.rb +0 -18
  49. data/test/dbd/mysql/test_new_methods.rb +0 -7
  50. data/test/dbd/mysql/test_patches.rb +0 -111
  51. data/test/dbd/mysql/up.sql +0 -28
  52. data/test/dbd/odbc/base.rb +0 -30
  53. data/test/dbd/odbc/down.sql +0 -19
  54. data/test/dbd/odbc/test_new_methods.rb +0 -12
  55. data/test/dbd/odbc/test_ping.rb +0 -10
  56. data/test/dbd/odbc/test_statement.rb +0 -44
  57. data/test/dbd/odbc/test_transactions.rb +0 -58
  58. data/test/dbd/odbc/up.sql +0 -33
  59. data/test/dbd/postgresql/base.rb +0 -31
  60. data/test/dbd/postgresql/down.sql +0 -31
  61. data/test/dbd/postgresql/test_arrays.rb +0 -179
  62. data/test/dbd/postgresql/test_async.rb +0 -121
  63. data/test/dbd/postgresql/test_blob.rb +0 -36
  64. data/test/dbd/postgresql/test_bytea.rb +0 -87
  65. data/test/dbd/postgresql/test_ping.rb +0 -10
  66. data/test/dbd/postgresql/test_timestamp.rb +0 -77
  67. data/test/dbd/postgresql/test_transactions.rb +0 -58
  68. data/test/dbd/postgresql/testdbipg.rb +0 -307
  69. data/test/dbd/postgresql/up.sql +0 -60
  70. data/test/dbd/sqlite/base.rb +0 -32
  71. data/test/dbd/sqlite/test_database.rb +0 -30
  72. data/test/dbd/sqlite/test_driver.rb +0 -68
  73. data/test/dbd/sqlite/test_statement.rb +0 -112
  74. data/test/dbd/sqlite/up.sql +0 -25
  75. data/test/dbd/sqlite3/base.rb +0 -32
  76. data/test/dbd/sqlite3/test_database.rb +0 -77
  77. data/test/dbd/sqlite3/test_driver.rb +0 -67
  78. data/test/dbd/sqlite3/test_statement.rb +0 -88
  79. data/test/dbd/sqlite3/up.sql +0 -33
  80. data/test/ts_dbd.rb +0 -131
  81. data/ydbi.gemspec +0 -23
data/lib/dbd/pg/tuples.rb DELETED
@@ -1,121 +0,0 @@
1
- #
2
- # Tuples is a class to represent result sets.
3
- #
4
- # Many of these methods are extremely similar to the methods that deal with
5
- # result sets in DBI::BaseStatement and are wrapped by the StatementHandle.
6
- # Unless you plan on working on this driver, these methods should never be
7
- # called directly.
8
- #
9
- class DBI::DBD::Pg::Tuples
10
-
11
- def initialize(db, pg_result)
12
- @db = db
13
- @pg_result = pg_result
14
- @index = -1
15
- @row = []
16
- end
17
-
18
- # See DBI::BaseStatement#column_info. Additional attributes:
19
- #
20
- # * array_of_type: True if this is actually an array of this type. In this
21
- # case, +dbi_type+ will be the type authority for conversion.
22
- #
23
- def column_info
24
- a = []
25
- 0.upto(@pg_result.num_fields-1) do |i|
26
- str = @pg_result.fname(i)
27
-
28
- typeinfo = nil
29
-
30
- begin
31
- typmod = @pg_result.fmod(i)
32
- rescue
33
- end
34
-
35
- if typmod and typ = @pg_result.ftype(i)
36
- res = @db._exec("select format_type(#{typ}, #{typmod})")
37
- typeinfo = DBI::DBD::Pg.parse_type(res[0].values[0])
38
- end
39
-
40
- map = @db.type_map[@pg_result.ftype(i)] || { }
41
- h = { "name" => str }.merge(map)
42
-
43
- if typeinfo
44
- h["precision"] = typeinfo[:size]
45
- h["scale"] = typeinfo[:decimal]
46
- h["type"] = typeinfo[:type]
47
- h["array_of_type"] = typeinfo[:array]
48
-
49
- if typeinfo[:array]
50
- h['dbi_type'] =
51
- DBI::DBD::Pg::Type::Array.new(
52
- DBI::TypeUtil.type_name_to_module(typeinfo[:type])
53
- )
54
- end
55
- end
56
-
57
- a.push h
58
- end
59
-
60
- return a
61
- end
62
-
63
- def fetchrow
64
- @index += 1
65
- if @index < @pg_result.num_tuples && @index >= 0
66
- @row = Array.new
67
- 0.upto(@pg_result.num_fields-1) do |x|
68
- @row.push(@pg_result.getvalue(@index, x))
69
- end
70
- @row
71
- else
72
- nil
73
- end
74
- end
75
-
76
- #
77
- # Just don't use this method. It'll be fixed soon.
78
- #
79
- def fetch_scroll(direction, offset)
80
- # Exact semantics aren't too closely defined. I attempted to follow the DBI:Mysql example.
81
- case direction
82
- when SQL_FETCH_NEXT
83
- # Nothing special to do, besides the fetchrow
84
- when SQL_FETCH_PRIOR
85
- @index -= 2
86
- when SQL_FETCH_FIRST
87
- @index = -1
88
- when SQL_FETCH_LAST
89
- @index = @pg_result.num_tuples - 2
90
- when SQL_FETCH_ABSOLUTE
91
- # Note: if you go "out of range", all fetches will give nil until you get back
92
- # into range, this doesn't raise an error.
93
- @index = offset-1
94
- when SQL_FETCH_RELATIVE
95
- # Note: if you go "out of range", all fetches will give nil until you get back
96
- # into range, this doesn't raise an error.
97
- @index += offset - 1
98
- else
99
- raise NotSupportedError
100
- end
101
- self.fetchrow
102
- end
103
-
104
- #
105
- # The number of rows returned.
106
- #
107
- def row_count
108
- @pg_result.num_tuples
109
- end
110
-
111
- #
112
- # The row processed count. This is analogue to DBI::StatementHandle#rows.
113
- #
114
- def rows_affected
115
- @pg_result.cmdtuples
116
- end
117
-
118
- def finish
119
- @pg_result.clear
120
- end
121
- end # Tuples
data/lib/dbd/pg/type.rb DELETED
@@ -1,209 +0,0 @@
1
- #
2
- # Type Management for PostgreSQL-specific types.
3
- #
4
- # See DBI::Type and DBI::TypeUtil for more information.
5
- #
6
- module DBI::DBD::Pg::Type
7
- #
8
- # ByteA is a special escaped form of binary data, suitable for inclusion in queries.
9
- #
10
- # This class is an attempt to abstract that type so you do not have to
11
- # concern yourself with the conversion issues.
12
- #
13
- class ByteA
14
-
15
- attr_reader :original
16
- attr_reader :escaped
17
-
18
- #
19
- # Build a new ByteA object.
20
- #
21
- # The data supplied is the unescaped binary data you wish to put in the
22
- # database.
23
- #
24
- def initialize(obj)
25
- @original = obj
26
- @escaped = escape_bytea(obj)
27
- @original.freeze
28
- @escaped.freeze
29
- end
30
-
31
- #
32
- # Escapes the supplied data. Has no effect on the object.
33
- #
34
- def escape_bytea(str)
35
- PG::Connection.escape_bytea(str)
36
- end
37
-
38
- #
39
- # Returns the original data.
40
- #
41
- def to_s
42
- return @original.dup
43
- end
44
-
45
- #
46
- # Class method to escape the data into ByteA format.
47
- #
48
- def self.escape_bytea(str)
49
- self.new(str).escaped
50
- end
51
-
52
- #
53
- # Class method to unescape the ByteA data and present it as a string.
54
- #
55
- def self.parse(obj)
56
-
57
- return nil if obj.nil?
58
-
59
- # FIXME there's a bug in the upstream 'pg' driver that does not
60
- # properly decode bytea, leaving in an extra slash for each decoded
61
- # character.
62
- #
63
- # Fix this for now, but beware that we'll have to unfix this as
64
- # soon as they fix their end.
65
- ret = PG::Connection.unescape_bytea(obj)
66
-
67
- # XXX
68
- # String#split does not properly create a full array if the the
69
- # string ENDS in the split regex, unless this oddball -1 argument is supplied.
70
- #
71
- # Another way of saying this:
72
- # if foo = "foo\\\\\" and foo.split(/\\\\/), the result will be
73
- # ["foo"]. You can add as many delimiters to the end of the string
74
- # as you'd like - the result is no different.
75
- #
76
-
77
- ret = ret.split(/\\\\/, -1).collect { |x| x.length > 0 ? x.gsub(/\\[0-7]{3}/) { |y| y[1..3].oct.chr } : "" }.join("\\")
78
- ret.gsub!(/''/, "'")
79
- return ret
80
- end
81
- end
82
-
83
- #
84
- # PostgreSQL arrays are simply a specification that sits on top of normal
85
- # types. They have a specialized string grammar and this class facilitates
86
- # converting that syntax and the types within those arrays.
87
- #
88
- class Array
89
-
90
- attr_reader :base_type
91
-
92
- #
93
- # +base_type+ is a DBI::Type that is used to parse the inner types when
94
- # a non-array one is found.
95
- #
96
- # For instance, if you had an array of integer, one would pass
97
- # DBI::Type::Integer here.
98
- #
99
- def initialize(base_type)
100
- @base_type = base_type
101
- end
102
-
103
- #
104
- # Object method. Please note that this is different than most DBI::Type
105
- # classes! One must initialize an Array object with an appropriate
106
- # DBI::Type used to convert the indices of the array before this method
107
- # can be called.
108
- #
109
- # Returns an appropriately converted array.
110
- #
111
- def parse(obj)
112
- if obj.nil?
113
- nil
114
- elsif obj.index('{') == 0 and obj.rindex('}') == (obj.length - 1)
115
- convert_array(obj)
116
- else
117
- raise "Not an array"
118
- end
119
- end
120
-
121
- #
122
- # Parse a PostgreSQL-Array output and convert into ruby array. This
123
- # does the real parsing work.
124
- #
125
- def convert_array(str)
126
-
127
- array_nesting = 0 # nesting level of the array
128
- in_string = false # currently inside a quoted string ?
129
- escaped = false # if the character is escaped
130
- sbuffer = '' # buffer for the current element
131
- result_array = ::Array.new # the resulting Array
132
-
133
- str.each_byte { |char| # parse character by character
134
- char = char.chr # we need the Character, not it's Integer
135
-
136
- if escaped then # if this character is escaped, just add it to the buffer
137
- sbuffer += char
138
- escaped = false
139
- next
140
- end
141
-
142
- case char # let's see what kind of character we have
143
- #------------- {: beginning of an array ----#
144
- when '{'
145
- if in_string then # ignore inside a string
146
- sbuffer += char
147
- next
148
- end
149
-
150
- if array_nesting >= 1 then # if it's an nested array, defer for recursion
151
- sbuffer += char
152
- end
153
- array_nesting += 1 # inside another array
154
-
155
- #------------- ": string deliminator --------#
156
- when '"'
157
- in_string = !in_string
158
-
159
- #------------- \: escape character, next is regular character #
160
- when "\\" # single \, must be extra escaped in Ruby
161
- if array_nesting > 1
162
- sbuffer += char
163
- else
164
- escaped = true
165
- end
166
-
167
- #------------- ,: element separator ---------#
168
- when ','
169
- if in_string or array_nesting > 1 then # don't care if inside string or
170
- sbuffer += char # nested array
171
- else
172
- if !sbuffer.is_a? ::Array then
173
- sbuffer = @base_type.parse(sbuffer)
174
- end
175
- result_array << sbuffer # otherwise, here ends an element
176
- sbuffer = ''
177
- end
178
-
179
- #------------- }: End of Array --------------#
180
- when '}'
181
- if in_string then # ignore if inside quoted string
182
- sbuffer += char
183
- next
184
- end
185
-
186
- array_nesting -=1 # decrease nesting level
187
-
188
- if array_nesting == 1 # must be the end of a nested array
189
- sbuffer += char
190
- sbuffer = convert_array( sbuffer ) # recurse, using the whole nested array
191
- elsif array_nesting > 1 # inside nested array, keep it for later
192
- sbuffer += char
193
- else # array_nesting = 0, must be the last }
194
- if !sbuffer.is_a? ::Array then
195
- sbuffer = @base_type.parse( sbuffer )
196
- end
197
-
198
- result_array << sbuffer unless sbuffer.nil? # upto here was the last element
199
- end
200
-
201
- #------------- all other characters ---------#
202
- else
203
- sbuffer += char # simply append
204
- end
205
- }
206
- return result_array
207
- end # convert_array()
208
- end
209
- end
@@ -1,151 +0,0 @@
1
- #
2
- # See DBI::BaseDatabase.
3
- #
4
- class DBI::DBD::SQLite::Database < DBI::BaseDatabase
5
- attr_reader :db
6
- attr_reader :attr_hash
7
- attr_accessor :open_handles
8
-
9
- #
10
- # Constructor. Valid attributes:
11
- #
12
- # * AutoCommit: Commit after every statement execution.
13
- #
14
- def initialize(dbname, user, auth, attr_hash)
15
- # FIXME why isn't this crap being done in DBI?
16
- unless dbname.kind_of? String
17
- raise DBI::InterfaceError, "Database Name must be a string"
18
- end
19
-
20
- unless dbname.length > 0
21
- raise DBI::InterfaceError, "Database Name needs to be length > 0"
22
- end
23
-
24
- unless attr_hash.kind_of? Hash
25
- raise DBI::InterfaceError, "Attributes should be a hash"
26
- end
27
-
28
- # FIXME handle busy_timeout in SQLite driver
29
- # FIXME handle SQLite pragmas in SQLite driver
30
- @attr_hash = attr_hash
31
- @open_handles = 0
32
-
33
- self["AutoCommit"] = true if self["AutoCommit"].nil?
34
-
35
- # open the database
36
- begin
37
- @db = ::SQLite::Database.new(dbname)
38
- rescue Exception => e
39
- raise DBI::OperationalError, "Couldn't open database #{dbname}: #{e.message}"
40
- end
41
- end
42
-
43
- def disconnect
44
- rollback rescue nil
45
- @db.close if @db and !@db.closed?
46
- @db = nil
47
- end
48
-
49
- def database_name
50
- st = DBI::DBD::SQLite::Statement.new('PRAGMA database_list', self)
51
- st.execute
52
- row = st.fetch
53
- st.finish
54
-
55
- return row[2]
56
- end
57
-
58
- def prepare(stmt)
59
- return DBI::DBD::SQLite::Statement.new(stmt, self)
60
- end
61
-
62
- def ping
63
- return !@db.closed?
64
- end
65
-
66
- def tables
67
- sth = prepare("select name from sqlite_master where type in ('table', 'view')")
68
- sth.execute
69
- tables = sth.fetch_all.flatten
70
- sth.finish
71
- return tables
72
- # FIXME does sqlite use views too? not sure, but they need to be included according to spec
73
- end
74
-
75
- def commit
76
- @db.commit if @db.transaction_active?
77
- end
78
-
79
- #
80
- # Rollback the transaction. SQLite has some issues with open statement
81
- # handles when this happens. If there are still open handles, a
82
- # DBI::Warning exception will be raised.
83
- #
84
- def rollback
85
- if @open_handles > 0
86
- raise DBI::Warning, "Leaving unfinished select statement handles while rolling back a transaction can corrupt your database or crash your program"
87
- end
88
-
89
- @db.rollback if @db.transaction_active?
90
- end
91
-
92
- def [](key)
93
- return @attr_hash[key]
94
- end
95
-
96
- #
97
- # See DBI::BaseDatabase#[]=.
98
- #
99
- # If AutoCommit is set to +true+ using this method, was previously +false+,
100
- # and we are currently in a transaction, The act of setting this will cause
101
- # an immediate commit.
102
- #
103
- def []=(key, value)
104
-
105
- old_value = @attr_hash[key]
106
-
107
- @attr_hash[key] = value
108
-
109
- # special handling of settings
110
- case key
111
- when "AutoCommit"
112
- # if the value being set is true and the previous value is false,
113
- # commit the current transaction (if any)
114
- # FIXME I still think this is a horrible way of handling this.
115
- if value and !old_value
116
- begin
117
- @dbh.commit
118
- rescue Exception => e
119
- end
120
- end
121
- end
122
-
123
- return @attr_hash[key]
124
- end
125
-
126
- def columns(tablename)
127
- return nil unless tablename and tablename.kind_of? String
128
-
129
- sth = prepare("PRAGMA table_info(?)")
130
- sth.bind_param(1, tablename)
131
- sth.execute
132
- columns = [ ]
133
- while row = sth.fetch
134
- column = { }
135
- column["name"] = row[1]
136
-
137
- m = DBI::DBD::SQLite.parse_type(row[2])
138
- column["type_name"] = m[1]
139
- column["precision"] = m[3].to_i if m[3]
140
- column["scale"] = m[5].to_i if m[5]
141
-
142
- column["nullable"] = row[3].to_i == 0
143
- column["default"] = row[4]
144
- columns.push column
145
- end
146
-
147
- sth.finish
148
- return columns
149
- # XXX it'd be nice if the spec was changed to do this k/v with the name as the key.
150
- end
151
- end
@@ -1,125 +0,0 @@
1
- #
2
- # See DBI::BaseStatement.
3
- #
4
- class DBI::DBD::SQLite::Statement < DBI::BaseStatement
5
- DBI_TYPE_MAP = [
6
- [ /^INT(EGER)?$/i, DBI::SQL_INTEGER ],
7
- [ /^(OID|ROWID|_ROWID_)$/i, DBI::SQL_OTHER ],
8
- [ /^FLOAT$/i, DBI::SQL_FLOAT ],
9
- [ /^REAL$/i, DBI::SQL_REAL ],
10
- [ /^DOUBLE$/i, DBI::SQL_DOUBLE ],
11
- [ /^DECIMAL/i, DBI::SQL_DECIMAL ],
12
- [ /^(BOOL|BOOLEAN)$/i, DBI::SQL_BOOLEAN ],
13
- [ /^TIME$/i, DBI::SQL_TIME ],
14
- [ /^DATE$/i, DBI::SQL_DATE ],
15
- [ /^TIMESTAMP$/i, DBI::SQL_TIMESTAMP ],
16
- [ /^(VARCHAR|TEXT)/i, DBI::SQL_VARCHAR ],
17
- [ /^CHAR$/i, DBI::SQL_CHAR ],
18
- ]
19
-
20
- def initialize(stmt, dbh)
21
- @dbh = dbh
22
- @statement = DBI::SQL::PreparedStatement.new(@dbh, stmt)
23
- @attr = { }
24
- @params = [ ]
25
- @rows = [ ]
26
- @result_set = nil
27
- @dbh.open_handles += 1
28
- end
29
-
30
- #
31
- # See DBI::BaseStatement#bind_param. This method will also raise
32
- # DBI::InterfaceError if +param+ is not a Fixnum, to prevent incorrect
33
- # binding.
34
- #
35
- def bind_param(param, value, attributes=nil)
36
- unless param.kind_of? Fixnum
37
- raise DBI::InterfaceError, "Only numeric parameters are supported"
38
- end
39
-
40
- @params[param-1] = value
41
-
42
- # FIXME what to do with attributes? are they important in SQLite?
43
- end
44
-
45
- #
46
- # See DBI::BaseStatement#execute.
47
- #
48
- # In the event AutoCommit is off and no transaction is currently executing,
49
- # one will be opened at this point. It is your responsibility to #finish,
50
- # #cancel, #rollback, or #commit.
51
- #
52
- def execute
53
- sql = @statement.bind(@params)
54
- # XXX sqlite re-escapes this for us automatically, it's causing trouble with everything else.
55
- # this will probably break in a horrible manner and I will be forced to "fix" it again.
56
- sql.gsub!(/\\\\/) { '\\' }
57
- DBI::DBD::SQLite.check_sql(sql)
58
-
59
- begin
60
- unless @dbh.db.transaction_active?
61
- @dbh.db.transaction
62
- end
63
- @result_set = @dbh.db.query(sql)
64
- @dbh.commit if @dbh["AutoCommit"]
65
- rescue Exception => e
66
- raise DBI::DatabaseError, e.message
67
- end
68
- end
69
-
70
- alias :finish :cancel
71
-
72
- def finish
73
- # nil out the result set
74
- @result_set.close if @result_set
75
- @result_set = nil
76
- @rows = nil
77
- @dbh.open_handles -= 1
78
- end
79
-
80
- def fetch
81
- return nil if @result_set.eof?
82
-
83
- row = @result_set.next
84
- return nil unless row
85
-
86
- return row
87
- end
88
-
89
- def column_info
90
- columns = [ ]
91
-
92
- # FIXME this shit should *really* be abstracted into DBI
93
- # FIXME this still doesn't handle nullable/unique/default stuff.
94
- @result_set.columns.each_with_index do |name, i|
95
- columns[i] = { } unless columns[i]
96
- columns[i]["name"] = name
97
- type_name = @result_set.types[i]
98
-
99
- if type_name
100
- m = DBI::DBD::SQLite.parse_type(type_name)
101
-
102
- columns[i]["type_name"] = m[1]
103
- columns[i]["precision"] = m[3].to_i if m[3]
104
- columns[i]["scale"] = m[5].to_i if m[5]
105
- DBI_TYPE_MAP.each do |map|
106
- if columns[i]["type_name"] =~ map[0]
107
- columns[i]["sql_type"] = map[1]
108
- break
109
- end
110
- end
111
-
112
- case columns[i]["type_name"]
113
- when 'double'
114
- columns[i]["dbi_type"] = DBI::Type::Float
115
- end
116
- end
117
- end
118
-
119
- return columns
120
- end
121
-
122
- def rows
123
- return @dbh.db.changes
124
- end
125
- end