data_objects 0.2.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.
- data/LICENSE +20 -0
- data/README +4 -0
- data/Rakefile +33 -0
- data/TODO +5 -0
- data/lib/data_objects.rb +345 -0
- metadata +52 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2007 Yehuda Katz
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
GEM = "data_objects"
|
5
|
+
VERSION = "0.2.0"
|
6
|
+
AUTHOR = "Yehuda Katz"
|
7
|
+
EMAIL = "wycats@gmail.com"
|
8
|
+
HOMEPAGE = "http://dataobjects.devjavu.com"
|
9
|
+
SUMMARY = "The Core DataObjects class"
|
10
|
+
|
11
|
+
spec = Gem::Specification.new do |s|
|
12
|
+
s.name = GEM
|
13
|
+
s.version = VERSION
|
14
|
+
s.platform = Gem::Platform::RUBY
|
15
|
+
s.has_rdoc = true
|
16
|
+
s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
|
17
|
+
s.summary = SUMMARY
|
18
|
+
s.description = s.summary
|
19
|
+
s.author = AUTHOR
|
20
|
+
s.email = EMAIL
|
21
|
+
s.homepage = HOMEPAGE
|
22
|
+
s.require_path = 'lib'
|
23
|
+
s.autorequire = GEM
|
24
|
+
s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,specs}/**/*")
|
25
|
+
end
|
26
|
+
|
27
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
28
|
+
pkg.gem_spec = spec
|
29
|
+
end
|
30
|
+
|
31
|
+
task :install => [:package] do
|
32
|
+
sh %{sudo gem install pkg/#{GEM}-#{VERSION}}
|
33
|
+
end
|
data/TODO
ADDED
data/lib/data_objects.rb
ADDED
@@ -0,0 +1,345 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
# Thanks http://www.rubyweeklynews.org/20051120
|
5
|
+
class DateTime
|
6
|
+
def to_time
|
7
|
+
Time.mktime(year, mon, day, hour, min, sec)
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_date
|
11
|
+
Date.new(year, mon, day)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Time
|
16
|
+
def to_datetime
|
17
|
+
DateTime.civil(year, mon, day, hour, min, sec)
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s_db
|
21
|
+
strftime("%Y-%m-%d %X")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module DataObject
|
26
|
+
STATE_OPEN = 0
|
27
|
+
STATE_CLOSED = 1
|
28
|
+
|
29
|
+
class Connection
|
30
|
+
|
31
|
+
attr_reader :timeout, :database, :datasource, :server_version, :state
|
32
|
+
|
33
|
+
def initialize(connection_string)
|
34
|
+
end
|
35
|
+
|
36
|
+
def logger
|
37
|
+
@logger || @logger = Logger.new(nil)
|
38
|
+
end
|
39
|
+
|
40
|
+
def logger=(value)
|
41
|
+
@logger = value
|
42
|
+
end
|
43
|
+
|
44
|
+
def begin_transaction
|
45
|
+
# TODO: Hook this up
|
46
|
+
Transaction.new
|
47
|
+
end
|
48
|
+
|
49
|
+
def change_database(database_name)
|
50
|
+
raise NotImplementedError
|
51
|
+
end
|
52
|
+
|
53
|
+
def open
|
54
|
+
raise NotImplementedError
|
55
|
+
end
|
56
|
+
|
57
|
+
def close
|
58
|
+
raise NotImplementedError
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_command(text)
|
62
|
+
Command.new(self, text)
|
63
|
+
end
|
64
|
+
|
65
|
+
def closed?
|
66
|
+
@state == STATE_CLOSED
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
class Transaction
|
72
|
+
|
73
|
+
attr_reader :connection
|
74
|
+
|
75
|
+
def initialize(conn)
|
76
|
+
@connection = conn
|
77
|
+
end
|
78
|
+
|
79
|
+
# Commits the transaction
|
80
|
+
def commit
|
81
|
+
raise NotImplementedError
|
82
|
+
end
|
83
|
+
|
84
|
+
# Rolls back the transaction
|
85
|
+
def rollback(savepoint = nil)
|
86
|
+
raise NotImplementedError
|
87
|
+
end
|
88
|
+
|
89
|
+
# Creates a savepoint for rolling back later (not commonly supported)
|
90
|
+
def save(name)
|
91
|
+
raise NotImplementedError
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
class Reader
|
97
|
+
include Enumerable
|
98
|
+
|
99
|
+
attr_reader :field_count, :records_affected, :fields
|
100
|
+
|
101
|
+
def each
|
102
|
+
raise NotImplementedError
|
103
|
+
end
|
104
|
+
|
105
|
+
def has_rows?
|
106
|
+
@has_rows
|
107
|
+
end
|
108
|
+
|
109
|
+
def current_row
|
110
|
+
ret = []
|
111
|
+
field_count.times do |i|
|
112
|
+
ret[i] = item(i)
|
113
|
+
end
|
114
|
+
ret
|
115
|
+
end
|
116
|
+
|
117
|
+
def open?
|
118
|
+
@state != STATE_CLOSED
|
119
|
+
end
|
120
|
+
|
121
|
+
def close
|
122
|
+
real_close
|
123
|
+
@reader = nil
|
124
|
+
@state = STATE_CLOSED
|
125
|
+
true
|
126
|
+
end
|
127
|
+
|
128
|
+
def real_close
|
129
|
+
raise NotImplementedError
|
130
|
+
end
|
131
|
+
|
132
|
+
# retrieves the Ruby data type for a particular column number
|
133
|
+
def data_type_name(col)
|
134
|
+
raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
|
135
|
+
end
|
136
|
+
|
137
|
+
# retrieves the name of a particular column number
|
138
|
+
def name(col)
|
139
|
+
raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
|
140
|
+
end
|
141
|
+
|
142
|
+
# retrives the index of the column with a particular name
|
143
|
+
def get_index(name)
|
144
|
+
raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
|
145
|
+
end
|
146
|
+
|
147
|
+
def item(idx)
|
148
|
+
raise ReaderClosed, "You cannot ask for information once the reader is closed" if state_closed?
|
149
|
+
end
|
150
|
+
|
151
|
+
# returns an array of hashes containing the following information
|
152
|
+
#
|
153
|
+
# name: the column name
|
154
|
+
# index: the index of the column
|
155
|
+
# max_size: the maximum allowed size of the data in the column
|
156
|
+
# precision: the precision (for column types that support it)
|
157
|
+
# scale: the scale (for column types that support it)
|
158
|
+
# unique: boolean specifying whether the values must be unique
|
159
|
+
# key: boolean specifying whether this column is, or is part
|
160
|
+
# of, the primary key
|
161
|
+
# catalog: the name of the database this column is part of
|
162
|
+
# base_name: the original name of the column (if AS was used,
|
163
|
+
# this will provide the original name)
|
164
|
+
# schema: the name of the schema (if supported)
|
165
|
+
# table: the name of the table this column is part of
|
166
|
+
# data_type: the name of the Ruby data type used
|
167
|
+
# allow_null: boolean specifying whether nulls are allowed
|
168
|
+
# db_type: the type specified by the DB
|
169
|
+
# aliased: boolean specifying whether the column has been
|
170
|
+
# renamed using AS
|
171
|
+
# calculated: boolean specifying whether the field is calculated
|
172
|
+
# serial: boolean specifying whether the field is a serial
|
173
|
+
# column
|
174
|
+
# blob: boolean specifying whether the field is a BLOB
|
175
|
+
# readonly: boolean specifying whether the field is readonly
|
176
|
+
def get_schema
|
177
|
+
raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
|
178
|
+
end
|
179
|
+
|
180
|
+
# specifies whether the column identified by the passed in index
|
181
|
+
# is null.
|
182
|
+
def null?(idx)
|
183
|
+
raise ReaderClosed, "You cannot ask for column information once the reader is closed" if state_closed?
|
184
|
+
end
|
185
|
+
|
186
|
+
# Consumes the next result. Returns true if a result is consumed and
|
187
|
+
# false if none is
|
188
|
+
def next
|
189
|
+
raise ReaderClosed, "You cannot increment the cursor once the reader is closed" if state_closed?
|
190
|
+
end
|
191
|
+
|
192
|
+
protected
|
193
|
+
def state_closed?
|
194
|
+
@state == STATE_CLOSED
|
195
|
+
end
|
196
|
+
|
197
|
+
def native_type
|
198
|
+
raise ReaderClosed, "You cannot check the type of a column once the reader is closed" if state_closed?
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
class ResultData
|
204
|
+
|
205
|
+
def initialize(conn, affected_rows, last_insert_row = nil)
|
206
|
+
@conn, @affected_rows, @last_insert_row = conn, affected_rows, last_insert_row
|
207
|
+
end
|
208
|
+
|
209
|
+
attr_reader :affected_rows, :last_insert_row
|
210
|
+
alias_method :to_i, :affected_rows
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
class Schema < Array
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
class Command
|
219
|
+
|
220
|
+
attr_reader :text, :timeout, :connection
|
221
|
+
|
222
|
+
# initialize creates a new Command object
|
223
|
+
def initialize(connection, text)
|
224
|
+
@connection, @text = connection, text
|
225
|
+
end
|
226
|
+
|
227
|
+
def execute_non_query(*args)
|
228
|
+
raise LostConnectionError, "the connection to the database has been lost" if @connection.closed?
|
229
|
+
end
|
230
|
+
|
231
|
+
def execute_reader(*args)
|
232
|
+
raise LostConnectionError, "the connection to the database has been lost" if @connection.closed?
|
233
|
+
end
|
234
|
+
|
235
|
+
def prepare
|
236
|
+
raise NotImplementedError
|
237
|
+
end
|
238
|
+
|
239
|
+
# Escape a string of SQL with a set of arguments.
|
240
|
+
# The first argument is assumed to be the SQL to escape,
|
241
|
+
# the remaining arguments (if any) are assumed to be
|
242
|
+
# values to escape and interpolate.
|
243
|
+
#
|
244
|
+
# ==== Examples
|
245
|
+
# escape_sql("SELECT * FROM zoos")
|
246
|
+
# # => "SELECT * FROM zoos"
|
247
|
+
#
|
248
|
+
# escape_sql("SELECT * FROM zoos WHERE name = ?", "Dallas")
|
249
|
+
# # => "SELECT * FROM zoos WHERE name = `Dallas`"
|
250
|
+
#
|
251
|
+
# escape_sql("SELECT * FROM zoos WHERE name = ? AND acreage > ?", "Dallas", 40)
|
252
|
+
# # => "SELECT * FROM zoos WHERE name = `Dallas` AND acreage > 40"
|
253
|
+
#
|
254
|
+
# ==== Warning
|
255
|
+
# This method is meant mostly for adapters that don't support
|
256
|
+
# bind-parameters.
|
257
|
+
def escape_sql(args)
|
258
|
+
sql = text.dup
|
259
|
+
|
260
|
+
unless args.empty?
|
261
|
+
sql.gsub!(/\?/) do |x|
|
262
|
+
quote_value(args.shift)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
sql
|
267
|
+
end
|
268
|
+
|
269
|
+
def quote_value(value)
|
270
|
+
return 'NULL' if value.nil?
|
271
|
+
|
272
|
+
case value
|
273
|
+
when Numeric then quote_numeric(value)
|
274
|
+
when String then quote_string(value)
|
275
|
+
when Class then quote_class(value)
|
276
|
+
when Time then quote_time(value)
|
277
|
+
when DateTime then quote_datetime(value)
|
278
|
+
when Date then quote_date(value)
|
279
|
+
when TrueClass, FalseClass then quote_boolean(value)
|
280
|
+
when Array then quote_array(value)
|
281
|
+
when Symbol then quote_symbol(value)
|
282
|
+
else
|
283
|
+
if value.respond_to?(:to_sql)
|
284
|
+
value.to_sql
|
285
|
+
else
|
286
|
+
raise "Don't know how to quote #{value.inspect}"
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def quote_symbol(value)
|
292
|
+
quote_string(value.to_s)
|
293
|
+
end
|
294
|
+
|
295
|
+
def quote_numeric(value)
|
296
|
+
value.to_s
|
297
|
+
end
|
298
|
+
|
299
|
+
def quote_string(value)
|
300
|
+
"'#{value.gsub("'", "''")}'"
|
301
|
+
end
|
302
|
+
|
303
|
+
def quote_class(value)
|
304
|
+
"'#{value.name}'"
|
305
|
+
end
|
306
|
+
|
307
|
+
def quote_time(value)
|
308
|
+
"'#{value.xmlschema}'"
|
309
|
+
end
|
310
|
+
|
311
|
+
def quote_datetime(value)
|
312
|
+
"'#{value.dup}'"
|
313
|
+
end
|
314
|
+
|
315
|
+
def quote_date(value)
|
316
|
+
"'#{value.strftime("%Y-%m-%d")}'"
|
317
|
+
end
|
318
|
+
|
319
|
+
def quote_boolean(value)
|
320
|
+
value.to_s.upcase
|
321
|
+
end
|
322
|
+
|
323
|
+
def quote_array(value)
|
324
|
+
"(#{value.map { |entry| quote_value(entry) }.join(', ')})"
|
325
|
+
end
|
326
|
+
|
327
|
+
end
|
328
|
+
|
329
|
+
class NotImplementedError < StandardError; end
|
330
|
+
|
331
|
+
class ConnectionFailed < StandardError; end
|
332
|
+
|
333
|
+
class ReaderClosed < StandardError; end
|
334
|
+
|
335
|
+
class ReaderError < StandardError; end
|
336
|
+
|
337
|
+
class QueryError < StandardError; end
|
338
|
+
|
339
|
+
class NoInsertError < StandardError; end
|
340
|
+
|
341
|
+
class LostConnectionError < StandardError; end
|
342
|
+
|
343
|
+
class UnknownError < StandardError; end
|
344
|
+
|
345
|
+
end
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: data_objects
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2007-11-11 00:00:00 -08:00
|
8
|
+
summary: The Core DataObjects class
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: wycats@gmail.com
|
12
|
+
homepage: http://dataobjects.devjavu.com
|
13
|
+
rubyforge_project:
|
14
|
+
description: The Core DataObjects class
|
15
|
+
autorequire: data_objects
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Yehuda Katz
|
31
|
+
files:
|
32
|
+
- LICENSE
|
33
|
+
- README
|
34
|
+
- Rakefile
|
35
|
+
- TODO
|
36
|
+
- lib/data_objects.rb
|
37
|
+
test_files: []
|
38
|
+
|
39
|
+
rdoc_options: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README
|
43
|
+
- LICENSE
|
44
|
+
- TODO
|
45
|
+
executables: []
|
46
|
+
|
47
|
+
extensions: []
|
48
|
+
|
49
|
+
requirements: []
|
50
|
+
|
51
|
+
dependencies: []
|
52
|
+
|