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
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # A sample Gemfile
2
+ source "https://rubygems.org"
3
+
4
+ gemspec
5
+ gem 'pg'
@@ -0,0 +1,10 @@
1
+ $:.unshift 'build'
2
+ if File.exists? 'lib/dbi'
3
+ require 'Rakefile.dbi'
4
+ elsif File.exists? 'lib/dbd'
5
+ require 'rake_task_lib'
6
+ build_dbd_tasks(File.basename(Dir['lib/dbd/*.rb'][0], '.rb').downcase)
7
+ else
8
+ abort "Well, this is odd; No DBI or DBD found."
9
+ end
10
+ require 'bundler/gem_tasks'
data/TODO ADDED
@@ -0,0 +1,44 @@
1
+ 0.4.0:
2
+ x Work
3
+ x Postgres quoting toggles
4
+ x Postgres binding toggles
5
+ x Test for #20489
6
+ * Release checklist:
7
+ x Update ChangeLog
8
+ x rake
9
+ x remove all related gems, install all DBI/DBD gems (check prereqs)
10
+ x write a few test scripts to make sure drivers are loading
11
+ x Update homepage (irc channel, git, other changes)
12
+ * tag as 0.4.0
13
+ * upload rdoc
14
+ * upload packages
15
+ * release announcement (rf, ruby-talk, dbi lists, other places?)
16
+ * rebase master from development
17
+ * BEER
18
+ 0.6.0:
19
+ * Cleanup:
20
+ * Arrays:
21
+ * Find some way to get the extents of an array type
22
+ * checked pg_type, pg_attribute and pg_class, can't find anything.
23
+ * I don't think this is possible, but let's slate it for 0.6.0 anyways.
24
+ * Tracing
25
+ * WTH do we want to do with this
26
+ * Wow, this module has *serious issues*. Crashes DBI without warning. Redo this completely.
27
+ * 0.6.0
28
+ * Re-institute drivers
29
+ * Proxy
30
+ * Slated for 0.6.0
31
+ * Finish type management system
32
+ * Unify ColumnInfo
33
+ * Should we enforce ColumnInfo requirements at the DBI level?
34
+ * At least test the result of statement colinfo uniformly
35
+ * 0.6.0
36
+ * Cleanup core
37
+ * Require code is a mess
38
+ * Just remove the case-sensitivity from the DBDs in general
39
+ * 0.6.0
40
+ * Find a good clean way to enumerate drivers in separate gems
41
+ * Some registration-on-require would be cleaner and safer
42
+ * 0.6.0
43
+ * Scripts
44
+ * bin/dbd_proxy seems to have never worked; slate it for 0.6.0
@@ -0,0 +1,79 @@
1
+ require 'rubygems'
2
+ $:.unshift File.dirname(__FILE__) + '/../lib'
3
+ require 'dbi'
4
+
5
+ class DbiBenchmark
6
+ attr_reader :db
7
+
8
+ def initialize db, quiet=false
9
+ @db = db
10
+ @quiet = quiet
11
+ end
12
+
13
+ def puts(*args)
14
+ super unless @quiet
15
+ end
16
+
17
+ def run
18
+ times = {}
19
+ %w[create_test_table selecting_floats selecting_datetimes].each do |name|
20
+ t = Time.now
21
+ puts "* #{name.tr('_', ' ').capitalize}"
22
+ send name
23
+ took = Time.now - t
24
+ puts " (took #{took} seconds)"
25
+ puts
26
+ times[name] = took
27
+ end
28
+ times
29
+ ensure
30
+ db.do 'drop table data'
31
+ end
32
+
33
+ def create_test_table
34
+ db.do <<-end
35
+ create table data (
36
+ date timestamp,
37
+ value float
38
+ )
39
+ end
40
+ db.do 'begin'
41
+ today = Date.today
42
+ 5_000.times do
43
+ db.do "insert into data values ('#{today + rand(100) - 50}', #{10 + rand * 30})"
44
+ end
45
+ db.do 'commit'
46
+ end
47
+
48
+ def selecting_floats
49
+ strs = db.select_all('select value from data').map { |v| v.to_s }
50
+ puts *strs[0, 5]
51
+ puts '...'
52
+ end
53
+
54
+ def selecting_datetimes
55
+ strs = db.select_all('select date from data').map { |v| v.to_s }
56
+ puts *strs[0, 5]
57
+ puts '...'
58
+ end
59
+ end
60
+
61
+ def bench
62
+ dbiurls = [
63
+ 'DBI:Mysql:dbitest:localhost',
64
+ 'DBI:ODBC:MYDBITEST',
65
+ 'DBI:Pg:dbitest:localhost',
66
+ 'DBI:ODBC:PGDBITEST',
67
+ ]
68
+ order = %w[create_test_table selecting_floats selecting_datetimes]
69
+ dbiurls.map do |url|
70
+ # assume all dbs have the same credentials
71
+ DBI.connect(url, *ARGV) do |db|
72
+ [url.first.sub('DBI:', ''), *DbiBenchmark.new(db, true).run.values_at(*order)]
73
+ end
74
+ end
75
+ end
76
+
77
+ puts 'Running benchmark:'
78
+ DBI::Utils::TableFormatter.ascii(%w[db insert float datetime], bench, nil, nil, nil, nil, 30)
79
+
@@ -0,0 +1,186 @@
1
+ $:.unshift 'lib'
2
+ require 'rake'
3
+ require 'rubygems'
4
+ require 'rubygems/package_task'
5
+ require 'rake/packagetask'
6
+ require 'rdoc/task'
7
+
8
+
9
+ DEFAULT_TASKS = [:clobber_package, :package, :gem]
10
+
11
+ DBD_GEM_DEP_MAP = {
12
+ 'pg' => 'pg',
13
+ 'mysql' => 'mysql',
14
+ 'sqlite' => 'sqlite-ruby',
15
+ 'sqlite3' => 'sqlite3-ruby'
16
+ }
17
+
18
+ #
19
+ # Packaging
20
+ #
21
+
22
+ PACKAGE_FILES = %w(Rakefile build/rake_task_lib.rb setup.rb)
23
+ DOC_FILES = %w(readme.md LICENSE ChangeLog)
24
+ EXCLUSIONS = %w(test/sql.log)
25
+ DBD_FILES = %w(test/DBD_TESTS)
26
+
27
+ #
28
+ # some inlines
29
+ #
30
+
31
+ def gem_files(code_files)
32
+ (code_files + DOC_FILES).collect { |x| Dir[x] }.reject { |x| EXCLUSIONS.include? x }.flatten
33
+ end
34
+
35
+ def package_files(code_files)
36
+ code_files + DOC_FILES + PACKAGE_FILES
37
+ end
38
+
39
+ def build_package_tasks(spec, code_files)
40
+ Gem::PackageTask.new(spec) do |s|
41
+ end
42
+
43
+ Rake::PackageTask.new('y'+spec.name, spec.version) do |p|
44
+ p.need_tar_gz = true
45
+ p.need_zip = true
46
+
47
+ package_files(code_files).each do |x|
48
+ p.package_files.include(x)
49
+ end
50
+
51
+ EXCLUSIONS.each do |x|
52
+ p.package_files.exclude(x)
53
+ end
54
+ end
55
+ end
56
+
57
+ def boilerplate_spec
58
+ gem = Gem::Specification.new
59
+ gem.authors = ['Erik Hollensbe', 'Christopher Maujean']
60
+ gem.email = 'zdavatz@ywesee.com'
61
+ gem.homepage = 'https://github.com/zdavatz/ydbi'
62
+ gem.platform = Gem::Platform::RUBY
63
+ gem.extra_rdoc_files = DOC_FILES
64
+ gem.required_ruby_version = '>= 1.8.0'
65
+ gem.rubyforge_project = 'ydbi'
66
+ return gem
67
+ end
68
+
69
+ # builds a dbd namespace from the DBD_PACKAGES hash
70
+ def dbd_namespace(dbd)
71
+ "ydbd-" + dbd.to_s.downcase
72
+ end
73
+
74
+ def dbd_code_files(dbd)
75
+ code_files = [
76
+ "test/dbd/general/**",
77
+ File.join("test", "dbd", dbd.downcase == "pg" ? "postgresql" : dbd.downcase, "*"),
78
+ File.join("lib", "dbd", dbd + ".rb"),
79
+ "lib/dbd/#{dbd.downcase}/*.rb",
80
+ ] + DBD_FILES
81
+ end
82
+
83
+ def dbd_gem_files(code_files)
84
+ DBD_FILES + gem_files(code_files)
85
+ end
86
+
87
+ def dbd_package_files(code_files)
88
+ DBD_FILES + package_files(code_files)
89
+ end
90
+
91
+ def dbd_gem_spec(dbd, dbd_const, code_files)
92
+ spec = boilerplate_spec
93
+ spec.name = dbd_namespace(dbd)
94
+ spec.version = dbd_version(dbd_const)
95
+ spec.test_file = 'test/ts_dbd.rb'
96
+ spec.files = gem_files(code_files)
97
+ spec.summary = dbd_description(dbd_const)
98
+ spec.description = dbd_description(dbd_const)
99
+ spec.add_dependency 'ydbi', DBI::VERSION
100
+
101
+ dcdbd = dbd.downcase
102
+
103
+ if DBD_GEM_DEP_MAP[dcdbd]
104
+ spec.add_dependency DBD_GEM_DEP_MAP[dcdbd]
105
+ end
106
+
107
+ return spec
108
+ end
109
+
110
+ def dbd_version(const)
111
+ DBI::DBD.const_get(const).const_get("VERSION")
112
+ end
113
+
114
+ def dbd_description(const)
115
+ DBI::DBD.const_get(const).const_get("DESCRIPTION")
116
+ end
117
+
118
+
119
+ def build_dbd_tasks(dbd)
120
+ task :default => DEFAULT_TASKS
121
+
122
+ begin
123
+ done = false
124
+ dbd_const = nil
125
+ Dir["lib/dbd/*.rb"].each do |dbd_file|
126
+ if File.basename(dbd_file.downcase, '.rb') == dbd.to_s.downcase
127
+ dbd_const = File.basename(dbd_file, '.rb')
128
+ require "dbd/#{dbd_const}"
129
+ done = true
130
+ end
131
+ end
132
+
133
+ abort "No DBD found even though we asked to make tasks for it" unless done
134
+
135
+ code_files = dbd_code_files(dbd_const)
136
+
137
+ spec = dbd_gem_spec(dbd, dbd_const, code_files)
138
+
139
+ build_package_tasks(spec, code_files)
140
+
141
+ # FIXME: convert to a rake_test_loader sooner or later
142
+ task :test do
143
+ ENV["DBTYPES"] = dbd
144
+ ruby "test/ts_dbd.rb"
145
+ end
146
+ rescue LoadError => e
147
+ DEFAULT_TASKS.each do |x|
148
+ task x do
149
+ end
150
+ end
151
+ warn "Skipping #{dbd_namespace(dbd)} because we can't require DBD"
152
+ end
153
+ end
154
+
155
+ def build_dbi_tasks
156
+ end
157
+
158
+ #
159
+ # basic tasks
160
+ #
161
+
162
+ task :dist => [:distclean, :package, :rdoc]
163
+ task :distclean => [:clobber_package, :clobber_rdoc]
164
+ task :clean => [:distclean]
165
+ task :default => [:test, :dist]
166
+
167
+ task :to_blog => [:clobber_rdoc, :rdoc] do
168
+ sh "rm -r $git/blog/content/docs/ruby-dbi && mv rdoc $git/blog/content/docs/ruby-dbi"
169
+ end
170
+
171
+ #
172
+ # Documentation
173
+ #
174
+
175
+ RDoc::Task.new do |rd|
176
+ rd.rdoc_dir = "rdoc"
177
+ rd.main = "readme.md"
178
+ rd.rdoc_files.include("./readme.md")
179
+ rd.rdoc_files.include("./ChangeLog")
180
+ rd.rdoc_files.include("./LICENSE")
181
+ rd.rdoc_files.include("./doc/**/*.rdoc")
182
+ rd.rdoc_files.include("./lib/**/*.rb")
183
+ rd.rdoc_files.include("./ext/**/*.c")
184
+ rd.options = %w(-a)
185
+ end
186
+
@@ -0,0 +1,88 @@
1
+ = DBD Specification Version 0.4.0
2
+ By Erik Hollensbe <erik@hollensbe.org>
3
+
4
+ == FOREWORD
5
+
6
+ DBI is still in a large state of flux. Previous versions of this
7
+ specification rarely reflected reality, and the 0.4.0 release is an
8
+ attempt to get the code and documentation in touch with each other to
9
+ better reflect said reality.
10
+
11
+ While this is a goal, nobody's perfect and there is still a lot of
12
+ code to check, sanitize, and otherwise clean up. If you find something
13
+ missing in these specifications while working on a new DBD or a patch
14
+ for DBI, please, do not do what everything else is doing; alert the
15
+ appropriate person to get the spec revised. Doing this will save
16
+ yourself (and the DBI authors) infinite amounts of time.
17
+
18
+ == WHAT A DBD IS
19
+
20
+ DBD stands for "DataBase Driver" and is the layer that DBI uses to interface
21
+ with the database. DBDs often employ a low level driver to do the real work
22
+ with the database, leaving the DBD itself to act as a medium between DBI and
23
+ that lower level API.
24
+
25
+ This allows a great deal of flexibility without having to sacrifice features
26
+ for compatibility. For example, instead of having one PostgreSQL DBD that
27
+ handles all version of PostgreSQL and attempts to limit it's functionality
28
+ based on what version it detects (a error-prone and time/design prohibitive
29
+ process), one can write two PostgreSQL DBD that handle the differences between
30
+ "new" and "old" postgres, all while talking to the same low-level driver (yet
31
+ leveraging different functionality). This method leads to cleaner internals and
32
+ puts the choice of which to use on the end-user, who is probably a lot more
33
+ informed about what features they want than your code.
34
+
35
+ One traditionally loads a DBD using the DBI.connect method (see DBD LOAD
36
+ PATHS below) which will attempt to load the DBD, connect to the database with
37
+ the arguments supplied and return a DatabaseHandle if successful. However, if
38
+ the DBD is written properly, requiring it directly without DBI's involvement
39
+ (or existence) should not be an issue.
40
+
41
+ == WHERE DBDs LIVE
42
+
43
+ DBDs have an expected require path to be loaded by DBI. DBI will attempt to
44
+ load the middle portion of the DBI.connect DSN provided.
45
+
46
+ Example: DBI.connect("dbi:Mysql:mydb") # requires 'dbd/Mysql'
47
+
48
+ Since rubygems potentially renders this path virtual, it is not OK to expect
49
+ this path physically exists in one spot on the filesystem. Many assuptions are
50
+ currently made about this and will be pruned in 0.6.0.
51
+
52
+ If you wish to create submodules for your DBD, create a directory in the 'dbd'
53
+ directory named the same as the DBD. (E.g., "dbd/Mysql" would have a directory
54
+ with files in it relating to the Mysql.rb file that DBI loads).
55
+
56
+ == HOW DBI INTERFACES WITH YOUR DBD
57
+
58
+ Your DBD will create classes representing a DBI::BaseDriver, DBI::BaseDatabase,
59
+ and DBI::BaseStatement. DBI will link these to DBI::DriverHandle,
60
+ DBI::DatabaseHandle, and DBI::StatementHandle respectively. Your classes will
61
+ be called by the Handle classes to retreive information to manipulate and send
62
+ to the user. This manipulation can be influenced in a number of ways.
63
+
64
+ It is strongly recommended you make the effort to read the RDoc for all six
65
+ of these classes, as they are the meat of this specification, not this
66
+ document.
67
+
68
+ == BUILDING A DBD FROM SCRATCH
69
+
70
+ For the purposes of this discussion, we'll call your driver 'Foo'.
71
+
72
+ Create your module, DBI::DBD::Foo. Store it somewhere in your load path under
73
+ dbd/Foo.rb.
74
+
75
+ Create classes Driver, Database, and Statement in this new namespace, which
76
+ inherit from DBI::BaseDriver, DBI::BaseDatabase, and DBI::BaseStatement.
77
+ Override (at mininum) the methods that return NotImplementedError in your new
78
+ classes.
79
+
80
+ Create a method in the root namespace named +driver_name+. This should return a
81
+ string with a short name for your driver, this key will be used in type
82
+ conversion.
83
+
84
+ Everything else is up to you, up to and including worrying about interacting
85
+ with the database.
86
+
87
+ At this point, you should be ready to test your driver. See test/DBD_TESTS for
88
+ information on how to configure that.
@@ -0,0 +1,157 @@
1
+ = DBI Interface Spec, for version 0.4.0
2
+
3
+ by Erik Hollensbe <erik@hollensbe.org>
4
+
5
+ == Foreword
6
+
7
+ DBI is still in a large state of flux. Previous versions of this
8
+ specification rarely reflected reality, and the 0.4.0 release is an
9
+ attempt to get the code and documentation more in sync.
10
+
11
+ While this is the goal, there is still a lot of
12
+ code to check, sanitize, and otherwise clean up. If you find something
13
+ missing in these specifications while working on a new DBD or a patch
14
+ for DBI, please bring it to our attention (in IRC or on the mailing list)
15
+ to get the spec revised. Doing this will save
16
+ yourself (and the DBI authors) a lot of time.
17
+
18
+ == Design
19
+
20
+ With DBI, there are the concepts of driver, database, and statement. The core
21
+ functionality for these concepts is provided by a database driver, or
22
+ DBD. DBI controls one or more drivers at once, a driver has databases, a
23
+ database may have statements.
24
+
25
+ DBI uses a delegation model to communicate with its DBDs through a
26
+ series of handles. When a connection to a database is requested, DBI contacts
27
+ the appropriate DBD and builds a handle in
28
+ its name that it aligns with a DBI base class for that concept. The
29
+ handle provided by the DBD is the first-class method of communication,
30
+ otherwise it resorts to calling the base class methods. This allows
31
+ DBI to provide a level of consistency unless the DBD author finds it
32
+ otherwise unnecessary.
33
+
34
+ For example: DBI will provide handy methods like fetch_all and
35
+ fetch_scroll which all leverage the fetch method in the base class,
36
+ and the fetch method must be implemented by the DBD. However, the DBD
37
+ may have an internal representation of fetch_scroll (as is the case
38
+ with the ODBC driver) that may be more suited to direct use, and
39
+ therefore DBI will never see the base class method. This is similar to
40
+ inheritance, but there is a distinct disconnect between the handles
41
+ and the base classes, intentionally so. This way the DBDs have no
42
+ access to the base class and DBI does all the delegation work. Also,
43
+ DBI has no idea what the DBD is doing underneath, nor does it need to
44
+ care as long as valid data is returned.
45
+
46
+ == Classes
47
+
48
+ These are the classes that make up the core of DBI and provide
49
+ various functionality:
50
+
51
+ === DBI
52
+ Core module, responsible for everything underneath it, kickstarting
53
+ connections and loading drivers.
54
+
55
+ === DBI::Row
56
+
57
+ Responsible for representing the result set and managing the type
58
+ conversion of the result set.
59
+
60
+ === DBI::Utils
61
+
62
+ Utility methods which propogate through the rest of DBI.
63
+
64
+ === DBI::SQL
65
+
66
+ Utility methods for working with SQL queries. Includes a
67
+ driver-independent SQL bind manager.
68
+
69
+ === DBI::ColumnInfo
70
+
71
+ Responsible for representing the information per column for both
72
+ queries and table descriptions.
73
+
74
+ === DBI::Type
75
+
76
+ Namespace for typecasting classes. These classes are provided with a
77
+ parse method which converts them to a native Ruby type from a string.
78
+
79
+ === DBI::TypeUtil
80
+
81
+ The inverse of DBI::Type, this provides functionality to turn native
82
+ Ruby types into a representation suitable for the DBD's queries.
83
+
84
+ === DBI::Binary
85
+
86
+ The representation of a BLOB/CLOB in a Ruby object. This will
87
+ eventually be rolled into DBI::Type::, but remains here currently for
88
+ compatibility purposes.
89
+
90
+ === DBI::Base* and DBI::*Handle
91
+
92
+ Please see the Design section above for the description of these modules.
93
+
94
+ == Exceptions
95
+
96
+ DBI has a slew of custom exceptions it uses to control program flow,
97
+ and alert the user to specific classes of problems.
98
+
99
+ They currently all live in the DBI namespace, although it's expected
100
+ that there will eventually be an exception namespace.
101
+
102
+ === DBI::Warning < RuntimeError
103
+ For important warnings such as data truncation, etc.
104
+
105
+ === DBI::Error < RuntimeError
106
+ Base class of all other error exceptions.
107
+ Rescue this to rescue all DBI errors.
108
+
109
+ === DBI::InterfaceError < DBI::Error
110
+ Exception for errors related to the DBI interface rather
111
+ than the database itself.
112
+
113
+ === DBI::NotImplementedError < DBI::InterfaceError
114
+ Exception raised if the DBD driver has not specified
115
+ a mandatory method.
116
+
117
+ === DBI::DatabaseError < DBI::Error
118
+ Exception for errors related to the database.
119
+
120
+ Has three attributes: ((|err|)), ((|errstr|)) and ((|state|)).
121
+
122
+ === DBI::DataError < DBI::DatabaseError
123
+ Exception for errors due to problems with the processed
124
+ data, such as division by zero, numeric value out of range, etc.
125
+
126
+ === DBI::OperationalError < DBI::DatabaseError
127
+ Exception for errors related to the database's operation which
128
+ are not necessarily under the control of the programmer. This would include
129
+ such things as unexpected disconnection, failure to find a datasource name,
130
+ failure to process a transaction, memory allocation errors, etc.
131
+
132
+ === DBI::IntegrityError < DBI::DatabaseError
133
+ Exception raised when the relational integrity of the database
134
+ is affected, such as when a foreign key constraint is violated.
135
+
136
+ === DBI::InternalError < DBI::DatabaseError
137
+ Exception raised when the database encounters an internal error,
138
+ such as a cursor not being valid anymore, or a transaction going out of
139
+ sync.
140
+
141
+ === DBI::ProgrammingError < DBI::DatabaseError
142
+ Exception raised for programming errors, e.g., table not found
143
+ or already exists, syntax error in SQL statement, wrong number
144
+ of parameters specified, etc.
145
+
146
+ === DBI::NotSupportedError < DBI::DatabaseError
147
+ Raised if, e.g., ((<commit>)) is called for a database that does not
148
+ support transactions.
149
+
150
+ == API
151
+
152
+ To save my sanity, I have joined the specification and the rdoc for
153
+ DBI. Please review the specification there.
154
+
155
+ If you wish to author your own DBD, please see DBD_SPEC.rdoc,
156
+ which is a more in-depth view of the communication between DBI and
157
+ DBDs.