ydbi 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/ChangeLog +3699 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/Rakefile +8 -0
  7. data/TODO +44 -0
  8. data/bench/bench.rb +79 -0
  9. data/bin/dbi +518 -0
  10. data/bin/test_broken_dbi +37 -0
  11. data/build/Rakefile.dbi.rb +60 -0
  12. data/build/rake_task_lib.rb +187 -0
  13. data/doc/DBD_SPEC.rdoc +88 -0
  14. data/doc/DBI_SPEC.rdoc +157 -0
  15. data/doc/homepage/contact.html +62 -0
  16. data/doc/homepage/development.html +124 -0
  17. data/doc/homepage/index.html +83 -0
  18. data/doc/homepage/ruby-dbi.css +91 -0
  19. data/examples/test1.pl +39 -0
  20. data/examples/test1.rb +20 -0
  21. data/examples/xmltest.rb +8 -0
  22. data/lib/dbd/Mysql.rb +137 -0
  23. data/lib/dbd/ODBC.rb +89 -0
  24. data/lib/dbd/Pg.rb +188 -0
  25. data/lib/dbd/SQLite.rb +97 -0
  26. data/lib/dbd/SQLite3.rb +124 -0
  27. data/lib/dbd/mysql/database.rb +405 -0
  28. data/lib/dbd/mysql/driver.rb +125 -0
  29. data/lib/dbd/mysql/statement.rb +188 -0
  30. data/lib/dbd/odbc/database.rb +128 -0
  31. data/lib/dbd/odbc/driver.rb +38 -0
  32. data/lib/dbd/odbc/statement.rb +137 -0
  33. data/lib/dbd/pg/database.rb +516 -0
  34. data/lib/dbd/pg/exec.rb +47 -0
  35. data/lib/dbd/pg/statement.rb +160 -0
  36. data/lib/dbd/pg/tuples.rb +121 -0
  37. data/lib/dbd/pg/type.rb +209 -0
  38. data/lib/dbd/sqlite/database.rb +151 -0
  39. data/lib/dbd/sqlite/statement.rb +125 -0
  40. data/lib/dbd/sqlite3/database.rb +201 -0
  41. data/lib/dbd/sqlite3/statement.rb +78 -0
  42. data/lib/dbi.rb +336 -0
  43. data/lib/dbi/base_classes.rb +12 -0
  44. data/lib/dbi/base_classes/database.rb +135 -0
  45. data/lib/dbi/base_classes/driver.rb +47 -0
  46. data/lib/dbi/base_classes/statement.rb +171 -0
  47. data/lib/dbi/binary.rb +25 -0
  48. data/lib/dbi/columninfo.rb +107 -0
  49. data/lib/dbi/exceptions.rb +65 -0
  50. data/lib/dbi/handles.rb +49 -0
  51. data/lib/dbi/handles/database.rb +241 -0
  52. data/lib/dbi/handles/driver.rb +60 -0
  53. data/lib/dbi/handles/statement.rb +408 -0
  54. data/lib/dbi/row.rb +269 -0
  55. data/lib/dbi/sql.rb +22 -0
  56. data/lib/dbi/sql/preparedstatement.rb +115 -0
  57. data/lib/dbi/sql_type_constants.rb +75 -0
  58. data/lib/dbi/trace.rb +91 -0
  59. data/lib/dbi/types.rb +218 -0
  60. data/lib/dbi/typeutil.rb +109 -0
  61. data/lib/dbi/utils.rb +60 -0
  62. data/lib/dbi/utils/date.rb +59 -0
  63. data/lib/dbi/utils/tableformatter.rb +112 -0
  64. data/lib/dbi/utils/time.rb +52 -0
  65. data/lib/dbi/utils/timestamp.rb +96 -0
  66. data/lib/dbi/utils/xmlformatter.rb +73 -0
  67. data/lib/dbi/version.rb +3 -0
  68. data/prototypes/types2.rb +237 -0
  69. data/readme.md +274 -0
  70. data/setup.rb +1585 -0
  71. data/test/DBD_TESTS +50 -0
  72. data/test/TESTING +16 -0
  73. data/test/dbd/general/test_database.rb +206 -0
  74. data/test/dbd/general/test_statement.rb +326 -0
  75. data/test/dbd/general/test_types.rb +296 -0
  76. data/test/dbd/mysql/base.rb +26 -0
  77. data/test/dbd/mysql/down.sql +19 -0
  78. data/test/dbd/mysql/test_blob.rb +18 -0
  79. data/test/dbd/mysql/test_new_methods.rb +7 -0
  80. data/test/dbd/mysql/test_patches.rb +111 -0
  81. data/test/dbd/mysql/up.sql +28 -0
  82. data/test/dbd/odbc/base.rb +30 -0
  83. data/test/dbd/odbc/down.sql +19 -0
  84. data/test/dbd/odbc/test_new_methods.rb +12 -0
  85. data/test/dbd/odbc/test_ping.rb +10 -0
  86. data/test/dbd/odbc/test_statement.rb +44 -0
  87. data/test/dbd/odbc/test_transactions.rb +58 -0
  88. data/test/dbd/odbc/up.sql +33 -0
  89. data/test/dbd/postgresql/base.rb +31 -0
  90. data/test/dbd/postgresql/down.sql +31 -0
  91. data/test/dbd/postgresql/test_arrays.rb +179 -0
  92. data/test/dbd/postgresql/test_async.rb +121 -0
  93. data/test/dbd/postgresql/test_blob.rb +36 -0
  94. data/test/dbd/postgresql/test_bytea.rb +87 -0
  95. data/test/dbd/postgresql/test_ping.rb +10 -0
  96. data/test/dbd/postgresql/test_timestamp.rb +77 -0
  97. data/test/dbd/postgresql/test_transactions.rb +58 -0
  98. data/test/dbd/postgresql/testdbipg.rb +307 -0
  99. data/test/dbd/postgresql/up.sql +60 -0
  100. data/test/dbd/sqlite/base.rb +32 -0
  101. data/test/dbd/sqlite/test_database.rb +30 -0
  102. data/test/dbd/sqlite/test_driver.rb +68 -0
  103. data/test/dbd/sqlite/test_statement.rb +112 -0
  104. data/test/dbd/sqlite/up.sql +25 -0
  105. data/test/dbd/sqlite3/base.rb +32 -0
  106. data/test/dbd/sqlite3/test_database.rb +77 -0
  107. data/test/dbd/sqlite3/test_driver.rb +67 -0
  108. data/test/dbd/sqlite3/test_statement.rb +88 -0
  109. data/test/dbd/sqlite3/up.sql +33 -0
  110. data/test/dbi/tc_columninfo.rb +94 -0
  111. data/test/dbi/tc_date.rb +88 -0
  112. data/test/dbi/tc_dbi.rb +184 -0
  113. data/test/dbi/tc_row.rb +256 -0
  114. data/test/dbi/tc_sqlbind.rb +168 -0
  115. data/test/dbi/tc_statementhandle.rb +29 -0
  116. data/test/dbi/tc_time.rb +77 -0
  117. data/test/dbi/tc_timestamp.rb +142 -0
  118. data/test/dbi/tc_types.rb +268 -0
  119. data/test/ts_dbd.rb +131 -0
  120. data/test/ts_dbi.rb +16 -0
  121. data/ydbi.gemspec +24 -0
  122. metadata +224 -0
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ load_path = false
4
+ gems = false
5
+ redefined = false
6
+
7
+ # these clauses are for installations which have RUBYOPT=-rubygems, etc.
8
+ if Object.const_defined? "Gem"
9
+ redefined = true
10
+ module Kernel
11
+ alias gem_require require
12
+ alias require gem_original_require
13
+ end
14
+ end
15
+
16
+ begin
17
+ require 'dbi'
18
+ load_path = true
19
+ rescue LoadError => e
20
+ end
21
+
22
+ if Object.const_defined? "Gem" and redefined
23
+ module Kernel
24
+ alias gem_original_require require
25
+ alias require gem_require
26
+ end
27
+ end
28
+
29
+ begin
30
+ require 'rubygems'
31
+ gem 'dbi'
32
+ gems = true
33
+ rescue LoadError
34
+ rescue Gem::LoadError
35
+ end
36
+
37
+ puts "Your installation of DBI is broken" if gems and load_path
@@ -0,0 +1,60 @@
1
+ require 'rake_task_lib'
2
+ require 'dbi'
3
+
4
+ DBD_PACKAGES = Dir['lib/dbd/*.rb'].collect { |x| File.basename(x, '.rb') }
5
+
6
+ # creates a number of tasks like dbi:task_name, dbd_mysql:task_name, so on.
7
+ # Builds these out into an array that can be used as a prereq for other tasks.
8
+ def map_task(task_name)
9
+ namespaces = (['dbi'] + DBD_PACKAGES.collect { |x| dbd_namespace(x) }).flatten
10
+ namespaces.collect { |x| [x, task_name].join(":") }
11
+ end
12
+
13
+ task :package => (map_task("package") + map_task("gem"))
14
+ task :clobber_package => map_task("clobber_package")
15
+
16
+ desc 'Run interface tests (no database connectivity required)'
17
+ task :test_dbi do
18
+ ruby("test/ts_dbi.rb")
19
+ end
20
+
21
+ desc 'Run database-specific tests'
22
+ task :test_dbd do
23
+ ruby("test/ts_dbd.rb")
24
+ end
25
+
26
+ desc 'Run full test suite'
27
+ task :test => [:test_dbi, :test_dbd]
28
+
29
+ build_dbi_tasks
30
+
31
+ #
32
+ # There's probably a better way to do this, but here's a boilerplate spec that we dup and modify.
33
+ #
34
+
35
+ task :dbi => DEFAULT_TASKS.collect { |x| "dbi:#{x.to_s}" }
36
+
37
+ namespace :dbi do
38
+ code_files = %w(examples/**/* bin/dbi build/Rakefile.dbi.rb lib/dbi.rb lib/dbi/**/*.rb test/ts_dbi.rb test/dbi/*)
39
+
40
+ spec = boilerplate_spec
41
+ spec.name = 'dbi'
42
+ spec.version = DBI::VERSION
43
+ spec.test_file = 'test/ts_dbi.rb'
44
+ spec.executables = ['dbi', 'test_broken_dbi']
45
+ spec.files = gem_files(code_files)
46
+ spec.summary = 'A vendor independent interface for accessing databases, similar to Perl\'s DBI'
47
+ spec.description = 'A vendor independent interface for accessing databases, similar to Perl\'s DBI'
48
+ spec.add_dependency 'deprecated', '= 2.0.1'
49
+
50
+ build_package_tasks(spec, code_files)
51
+ end
52
+
53
+ DBD_PACKAGES.each do |dbd|
54
+ my_namespace = dbd_namespace(dbd)
55
+
56
+ task my_namespace => DEFAULT_TASKS.collect { |x| "#{my_namespace}:#{x.to_s}" }
57
+ namespace my_namespace do
58
+ build_dbd_tasks(dbd)
59
+ end
60
+ end
@@ -0,0 +1,187 @@
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(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 = 'ruby-dbi-users@rubyforge.org'
61
+ gem.homepage = 'http://www.rubyforge.org/projects/ruby-dbi'
62
+ gem.platform = Gem::Platform::RUBY
63
+ gem.has_rdoc = true
64
+ gem.extra_rdoc_files = DOC_FILES
65
+ gem.required_ruby_version = '>= 1.8.0'
66
+ gem.rubyforge_project = 'ruby-dbi'
67
+ return gem
68
+ end
69
+
70
+ # builds a dbd namespace from the DBD_PACKAGES hash
71
+ def dbd_namespace(dbd)
72
+ "dbd-" + dbd.to_s.downcase
73
+ end
74
+
75
+ def dbd_code_files(dbd)
76
+ code_files = [
77
+ "test/dbd/general/**",
78
+ File.join("test", "dbd", dbd.downcase == "pg" ? "postgresql" : dbd.downcase, "*"),
79
+ File.join("lib", "dbd", dbd + ".rb"),
80
+ "lib/dbd/#{dbd.downcase}/*.rb",
81
+ ] + DBD_FILES
82
+ end
83
+
84
+ def dbd_gem_files(code_files)
85
+ DBD_FILES + gem_files(code_files)
86
+ end
87
+
88
+ def dbd_package_files(code_files)
89
+ DBD_FILES + package_files(code_files)
90
+ end
91
+
92
+ def dbd_gem_spec(dbd, dbd_const, code_files)
93
+ spec = boilerplate_spec
94
+ spec.name = dbd_namespace(dbd)
95
+ spec.version = dbd_version(dbd_const)
96
+ spec.test_file = 'test/ts_dbd.rb'
97
+ spec.files = gem_files(code_files)
98
+ spec.summary = dbd_description(dbd_const)
99
+ spec.description = dbd_description(dbd_const)
100
+ spec.add_dependency 'dbi', '>= 0.4.0'
101
+
102
+ dcdbd = dbd.downcase
103
+
104
+ if DBD_GEM_DEP_MAP[dcdbd]
105
+ spec.add_dependency DBD_GEM_DEP_MAP[dcdbd]
106
+ end
107
+
108
+ return spec
109
+ end
110
+
111
+ def dbd_version(const)
112
+ DBI::DBD.const_get(const).const_get("VERSION")
113
+ end
114
+
115
+ def dbd_description(const)
116
+ DBI::DBD.const_get(const).const_get("DESCRIPTION")
117
+ end
118
+
119
+
120
+ def build_dbd_tasks(dbd)
121
+ task :default => DEFAULT_TASKS
122
+
123
+ begin
124
+ done = false
125
+ dbd_const = nil
126
+ Dir["lib/dbd/*.rb"].each do |dbd_file|
127
+ if File.basename(dbd_file.downcase, '.rb') == dbd.to_s.downcase
128
+ dbd_const = File.basename(dbd_file, '.rb')
129
+ require "dbd/#{dbd_const}"
130
+ done = true
131
+ end
132
+ end
133
+
134
+ abort "No DBD found even though we asked to make tasks for it" unless done
135
+
136
+ code_files = dbd_code_files(dbd_const)
137
+
138
+ spec = dbd_gem_spec(dbd, dbd_const, code_files)
139
+
140
+ build_package_tasks(spec, code_files)
141
+
142
+ # FIXME: convert to a rake_test_loader sooner or later
143
+ task :test do
144
+ ENV["DBTYPES"] = dbd
145
+ ruby "test/ts_dbd.rb"
146
+ end
147
+ rescue LoadError => e
148
+ DEFAULT_TASKS.each do |x|
149
+ task x do
150
+ end
151
+ end
152
+ warn "Skipping #{dbd_namespace(dbd)} because we can't require DBD"
153
+ end
154
+ end
155
+
156
+ def build_dbi_tasks
157
+ end
158
+
159
+ #
160
+ # basic tasks
161
+ #
162
+
163
+ task :dist => [:distclean, :package, :rdoc]
164
+ task :distclean => [:clobber_package, :clobber_rdoc]
165
+ task :clean => [:distclean]
166
+ task :default => [:test, :dist]
167
+
168
+ task :to_blog => [:clobber_rdoc, :rdoc] do
169
+ sh "rm -r $git/blog/content/docs/ruby-dbi && mv rdoc $git/blog/content/docs/ruby-dbi"
170
+ end
171
+
172
+ #
173
+ # Documentation
174
+ #
175
+
176
+ RDoc::Task.new do |rd|
177
+ rd.rdoc_dir = "rdoc"
178
+ rd.main = "README"
179
+ rd.rdoc_files.include("./README")
180
+ rd.rdoc_files.include("./ChangeLog")
181
+ rd.rdoc_files.include("./LICENSE")
182
+ rd.rdoc_files.include("./doc/**/*.rdoc")
183
+ rd.rdoc_files.include("./lib/**/*.rb")
184
+ rd.rdoc_files.include("./ext/**/*.c")
185
+ rd.options = %w(-a)
186
+ end
187
+
@@ -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.