ribs 0.0.1
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/README +139 -0
- data/Rakefile +64 -0
- data/lib/antlr-2.7.6.jar +0 -0
- data/lib/commons-collections-3.1.jar +0 -0
- data/lib/dom4j-1.6.1.jar +0 -0
- data/lib/hibernate3.jar +0 -0
- data/lib/javassist-3.4.GA.jar +0 -0
- data/lib/jruby-complete.jar +0 -0
- data/lib/jta-1.1.jar +0 -0
- data/lib/ribs.jar +0 -0
- data/lib/ribs.rb +78 -0
- data/lib/ribs/core_ext/time.rb +21 -0
- data/lib/ribs/db.rb +188 -0
- data/lib/ribs/definition.rb +329 -0
- data/lib/ribs/meat.rb +33 -0
- data/lib/ribs/session.rb +237 -0
- data/lib/slf4j-api-1.5.2.jar +0 -0
- data/lib/slf4j-jdk14-1.5.2.jar +0 -0
- data/test/artist_spec.rb +94 -0
- data/test/find_spec.rb +2 -0
- data/test/simple_select_spec.rb +79 -0
- data/test/test_helper.rb +83 -0
- data/test/track_spec.rb +415 -0
- data/test/type_spec.rb +2 -0
- metadata +80 -0
@@ -0,0 +1,329 @@
|
|
1
|
+
module Ribs
|
2
|
+
# Ribs::ClassMethods contains all the methods that gets mixed in to
|
3
|
+
# a model class.
|
4
|
+
module ClassMethods
|
5
|
+
# Get the metadata for the current model
|
6
|
+
attr_reader :ribs_metadata
|
7
|
+
|
8
|
+
# Create a new instance of this model object, optionally setting
|
9
|
+
# properties based on +attrs+.
|
10
|
+
def new(attrs = {})
|
11
|
+
obj = super()
|
12
|
+
attrs.each do |k,v|
|
13
|
+
obj.send("#{k}=", v)
|
14
|
+
end
|
15
|
+
obj
|
16
|
+
end
|
17
|
+
|
18
|
+
# First creates a model object based on the values in +attrs+ and
|
19
|
+
# then saves this to the database directly.
|
20
|
+
def create(attrs = {})
|
21
|
+
val = new(attrs)
|
22
|
+
val.save
|
23
|
+
val
|
24
|
+
end
|
25
|
+
|
26
|
+
# Depending on the value of +id_or_sym+, tries to find the model
|
27
|
+
# with a specified id, or if +id_or_sym+ is <tt>:all</tt> returns
|
28
|
+
# all instances of this model.
|
29
|
+
def find(id_or_sym)
|
30
|
+
Ribs.with_session do |s|
|
31
|
+
s.find(self.ribs_metadata.persistent_class.entity_name, id_or_sym)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Destroys the model with the id +id+.
|
36
|
+
def destroy(id)
|
37
|
+
Ribs.with_session do |s|
|
38
|
+
s.delete(find(id))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
# TODO: add inspect here
|
44
|
+
end
|
45
|
+
|
46
|
+
# Ribs::InstanceMethods provides the methods that gets mixed in to
|
47
|
+
# all instances of a model object.
|
48
|
+
module InstanceMethods
|
49
|
+
# Returns the Meat instance for this instance.
|
50
|
+
def __ribs_meat
|
51
|
+
@__ribs_meat ||= Ribs::Meat.new(self)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns an inspection based on current values of the data in the
|
55
|
+
# database.
|
56
|
+
def inspect
|
57
|
+
"#<#{self.class.name}: #{self.__ribs_meat.properties.inspect}>"
|
58
|
+
end
|
59
|
+
|
60
|
+
# Saves this instance to the database. If the instance already
|
61
|
+
# exists, it will update the database, otherwise it will create
|
62
|
+
# it.
|
63
|
+
def save
|
64
|
+
Ribs.with_session do |s|
|
65
|
+
s.save(self)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Removes this instance from the database.
|
70
|
+
def destroy!
|
71
|
+
__ribs_meat.destroyed = true
|
72
|
+
Ribs.with_session do |s|
|
73
|
+
s.delete(self)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Collects all the meta data about a specific Ribs model
|
79
|
+
class MetaData
|
80
|
+
# The table to connect to
|
81
|
+
attr_accessor :table
|
82
|
+
# The persistent class that Hibernate uses as a definition for
|
83
|
+
# this model.
|
84
|
+
attr_accessor :persistent_class
|
85
|
+
# The Rib that defines all the mapping data
|
86
|
+
attr_accessor :rib
|
87
|
+
|
88
|
+
# Return the property instance for the given +name+.
|
89
|
+
def [](name)
|
90
|
+
self.persistent_class.get_property(name.to_s) rescue nil
|
91
|
+
end
|
92
|
+
|
93
|
+
# Return all the properties for this model.
|
94
|
+
def properties
|
95
|
+
self.persistent_class.property_iterator.to_a.inject({}) do |h, value|
|
96
|
+
h[value.name] = value
|
97
|
+
h
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Contains the mapping data that gets created when calling the
|
103
|
+
# {Ribs!} method.
|
104
|
+
class Rib
|
105
|
+
# List of all the columns defined
|
106
|
+
attr_reader :columns
|
107
|
+
# List of all primary keys defined
|
108
|
+
attr_reader :primary_keys
|
109
|
+
# List of all columns to avoid
|
110
|
+
attr_reader :to_avoid
|
111
|
+
|
112
|
+
# Initializes object
|
113
|
+
def initialize
|
114
|
+
@columns = { }
|
115
|
+
@primary_keys = { }
|
116
|
+
@to_avoid = []
|
117
|
+
end
|
118
|
+
|
119
|
+
# Gets or sets the table name to work with. If +name+ is nil,
|
120
|
+
# returns the table name, if not sets the table name to +name+.
|
121
|
+
def table(name = nil)
|
122
|
+
if name
|
123
|
+
@table = name
|
124
|
+
else
|
125
|
+
@table
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Adds a new column mapping for a specific column.
|
130
|
+
def col(column, property = column, options = {})
|
131
|
+
@columns[column.to_s.downcase] = [property.to_s, options]
|
132
|
+
end
|
133
|
+
|
134
|
+
# Adds a new primary key mapping for a column.
|
135
|
+
def primary_key(column, property = column, options = {})
|
136
|
+
@primary_keys[column.to_s.downcase] = property.to_s
|
137
|
+
@columns[column.to_s.downcase] = [property.to_s, options]
|
138
|
+
end
|
139
|
+
|
140
|
+
# Avoids all the provided columns
|
141
|
+
def avoid(*columns)
|
142
|
+
@to_avoid += columns.map{|s| s.to_s.downcase}
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
Table = org.hibernate.mapping.Table
|
147
|
+
Column = org.hibernate.mapping.Column
|
148
|
+
Property = org.hibernate.mapping.Property
|
149
|
+
SimpleValue = org.hibernate.mapping.SimpleValue
|
150
|
+
|
151
|
+
# A simple helper class that allows the Java parts of the system to
|
152
|
+
# get the Ruby class from the PersistentClass instance.
|
153
|
+
class RubyRootClass < org.hibernate.mapping.RootClass
|
154
|
+
include org.jruby.ribs.WithRubyClass
|
155
|
+
|
156
|
+
# The Ruby class
|
157
|
+
attr_accessor :ruby_class
|
158
|
+
|
159
|
+
def initialize(*args)
|
160
|
+
super
|
161
|
+
end
|
162
|
+
|
163
|
+
# Get the Ruby class. Implementation of the WithRubyClass
|
164
|
+
# interface.
|
165
|
+
def getRubyClass
|
166
|
+
@ruby_class
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class << self
|
171
|
+
# Define a rib for the class +on+. If a block is given, will first
|
172
|
+
# yield an instance of Rib to it and then base the mapping
|
173
|
+
# definition on that.
|
174
|
+
#
|
175
|
+
# +options+ have several possible values:
|
176
|
+
# * <tt>:db</tt> - the database to connect this model to
|
177
|
+
#
|
178
|
+
def define_ribs(on, options = {})
|
179
|
+
rib = Rib.new
|
180
|
+
yield rib if block_given?
|
181
|
+
|
182
|
+
define_metadata_on_class on
|
183
|
+
rm = on.ribs_metadata
|
184
|
+
rm.rib = rib
|
185
|
+
|
186
|
+
db = nil
|
187
|
+
with_session(options[:db] || :default) do |s|
|
188
|
+
db = s.db
|
189
|
+
m = s.meta_data
|
190
|
+
name = rib.table || table_name_for(on.name, m)
|
191
|
+
|
192
|
+
tables = m.get_tables nil, nil, name.to_s, %w(TABLE VIEW ALIAS SYNONYM).to_java(:String)
|
193
|
+
if tables.next
|
194
|
+
table = Table.new(tables.get_string(3))
|
195
|
+
rm.table = table
|
196
|
+
c = tables.get_string(1)
|
197
|
+
table.catalog = c if c && c.length > 0
|
198
|
+
c = tables.get_string(2)
|
199
|
+
table.schema = c if c && c.length > 0
|
200
|
+
|
201
|
+
columns_rs = m.get_columns table.catalog, table.schema, table.name, nil
|
202
|
+
|
203
|
+
while columns_rs.next
|
204
|
+
c = Column.new(columns_rs.get_string(4))
|
205
|
+
c.default_value = columns_rs.get_string(13)
|
206
|
+
c.length = columns_rs.get_int(7)
|
207
|
+
c.nullable = columns_rs.get_string(18) == 'YES'
|
208
|
+
c.precision = columns_rs.get_int(10)
|
209
|
+
c.scale = columns_rs.get_int(9)
|
210
|
+
c.sql_type = columns_rs.get_string(6)
|
211
|
+
c.sql_type_code = java.lang.Integer.new(columns_rs.get_int(5))
|
212
|
+
|
213
|
+
table.add_column(c)
|
214
|
+
end
|
215
|
+
columns_rs.close rescue nil
|
216
|
+
tables.close rescue nil
|
217
|
+
|
218
|
+
pc = RubyRootClass.new
|
219
|
+
pc.ruby_class = on
|
220
|
+
pc.entity_name = on.name
|
221
|
+
pc.table = table
|
222
|
+
pc.add_tuplizer(org.hibernate.EntityMode::MAP, "org.jruby.ribs.RubyTuplizer")
|
223
|
+
|
224
|
+
rm.persistent_class = pc
|
225
|
+
|
226
|
+
table.column_iterator.each do |c|
|
227
|
+
unless rib.to_avoid.include?(c.name.downcase)
|
228
|
+
prop = Property.new
|
229
|
+
prop.persistent_class = pc
|
230
|
+
prop.name = ((v=rib.columns[c.name.downcase]) && v[0]) || c.name
|
231
|
+
val = SimpleValue.new(table)
|
232
|
+
val.add_column(c)
|
233
|
+
val.type_name = get_type_for_sql(c.sql_type, c.sql_type_code)
|
234
|
+
prop.value = val
|
235
|
+
|
236
|
+
if (!rib.primary_keys.empty? && rib.primary_keys[c.name.downcase]) || c.name.downcase == 'id'
|
237
|
+
pc.identifier_property = prop
|
238
|
+
pc.identifier = val
|
239
|
+
else
|
240
|
+
pc.add_property(prop)
|
241
|
+
end
|
242
|
+
|
243
|
+
define_meat_accessor(on, prop.name)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
pc.create_primary_key
|
247
|
+
db.mappings.add_class(pc)
|
248
|
+
else
|
249
|
+
tables.close rescue nil
|
250
|
+
raise "No table found for: #{name}"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
db.reset_session_factory!
|
255
|
+
end
|
256
|
+
|
257
|
+
JTypes = java.sql.Types
|
258
|
+
|
259
|
+
private
|
260
|
+
# Defines the actual accessor for a specific property on a
|
261
|
+
# class. This will define methods that use the Meat to get data.
|
262
|
+
def define_meat_accessor(clazz, name)
|
263
|
+
downcased = name.downcase
|
264
|
+
clazz.class_eval <<CODE
|
265
|
+
def #{downcased}
|
266
|
+
self.__ribs_meat[:"#{name}"]
|
267
|
+
end
|
268
|
+
|
269
|
+
def #{downcased}=(value)
|
270
|
+
self.__ribs_meat[:"#{name}"] = value
|
271
|
+
end
|
272
|
+
CODE
|
273
|
+
end
|
274
|
+
|
275
|
+
# Returns the Java type for a specific combination of a type name
|
276
|
+
# and an SQL type code
|
277
|
+
def get_type_for_sql(name, code)
|
278
|
+
case code
|
279
|
+
when JTypes::VARCHAR
|
280
|
+
"string"
|
281
|
+
when JTypes::INTEGER
|
282
|
+
"int"
|
283
|
+
when JTypes::TIME
|
284
|
+
"java.sql.Time"
|
285
|
+
when JTypes::DATE
|
286
|
+
"java.sql.Date"
|
287
|
+
when JTypes::TIMESTAMP
|
288
|
+
"java.sql.Timestamp"
|
289
|
+
when JTypes::BLOB
|
290
|
+
"java.sql.Blob"
|
291
|
+
when JTypes::CLOB
|
292
|
+
"java.sql.Clob"
|
293
|
+
when JTypes::DOUBLE
|
294
|
+
"double"
|
295
|
+
when JTypes::SMALLINT
|
296
|
+
"boolean"
|
297
|
+
when JTypes::DECIMAL
|
298
|
+
"java.math.BigDecimal"
|
299
|
+
else
|
300
|
+
$stderr.puts [name, code].inspect
|
301
|
+
nil
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
# Tries to figure out if a table name should be in lower case or
|
306
|
+
# upper case, and returns the table name based on that.
|
307
|
+
def table_name_for(str, metadata)
|
308
|
+
if metadata.stores_lower_case_identifiers
|
309
|
+
str.downcase
|
310
|
+
elsif metadata.stores_upper_case_identifiers
|
311
|
+
str.upcase!
|
312
|
+
else
|
313
|
+
str
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
# Defines the meta data information on a class, and mixes in
|
318
|
+
# ClassMethods and InstanceMethods to it.
|
319
|
+
def define_metadata_on_class(clazz)
|
320
|
+
clazz.instance_variable_set :@ribs_metadata, Ribs::MetaData.new
|
321
|
+
class << clazz
|
322
|
+
include ClassMethods
|
323
|
+
end
|
324
|
+
clazz.class_eval do
|
325
|
+
include InstanceMethods
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
data/lib/ribs/meat.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Ribs
|
2
|
+
# The Meat is what actually includes data. This is the holder object
|
3
|
+
# for all data that comes from a database. This allows Ribs to avoid
|
4
|
+
# polluting model objects with loads of instance variables. Instead
|
5
|
+
# everything is kept in one instance of Meat. The Meat also keeps
|
6
|
+
# track of whether the object is persistent or if it's been
|
7
|
+
# destroyed. Note that Meat is very implementation dependent, and
|
8
|
+
# should not be relied upon.
|
9
|
+
class Meat
|
10
|
+
# All the data for this instance
|
11
|
+
attr_reader :properties
|
12
|
+
# Is this instance persistent yet, or not?
|
13
|
+
attr_accessor :persistent
|
14
|
+
# Has this instance been destroyed?
|
15
|
+
attr_accessor :destroyed
|
16
|
+
|
17
|
+
# +inside+ is the instance this Meat belongs to.
|
18
|
+
def initialize(inside)
|
19
|
+
@inside = inside
|
20
|
+
@properties = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Gets the current value of a property
|
24
|
+
def [](ix)
|
25
|
+
@properties[ix]
|
26
|
+
end
|
27
|
+
|
28
|
+
# Sets the current value of a property
|
29
|
+
def []=(ix, value)
|
30
|
+
@properties[ix] = value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/ribs/session.rb
ADDED
@@ -0,0 +1,237 @@
|
|
1
|
+
module Ribs
|
2
|
+
# A Ribs session maps many-to-one with a Hibernate session. When
|
3
|
+
# there are no more Ribs sessions left, the Hibernate session will
|
4
|
+
# be released too.
|
5
|
+
#
|
6
|
+
# The methods in Session is not to be used outside the framework in
|
7
|
+
# most cases, since they are internal, brittle, not based on
|
8
|
+
# Hibernate in all cases, and very much subject to change. Currently
|
9
|
+
# they provide capabilities that aren't part of the framework yet,
|
10
|
+
# such as migrations and setting up test data.
|
11
|
+
#
|
12
|
+
class Session
|
13
|
+
# This error is thrown when an operation on a session is
|
14
|
+
# attempted but the internal Hibernate session has already
|
15
|
+
# been closed.
|
16
|
+
#
|
17
|
+
class NotConnectedError < StandardError;end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
# Returns a session object from the database +from+. The
|
21
|
+
# available values for from is either one of the existing
|
22
|
+
# defined database names, or <tt>:default</tt>, which will give
|
23
|
+
# a session to the default database.
|
24
|
+
#
|
25
|
+
def get(from = :default)
|
26
|
+
db = case from
|
27
|
+
when :default
|
28
|
+
Ribs::DB::get
|
29
|
+
when Ribs::DB
|
30
|
+
from
|
31
|
+
else
|
32
|
+
Ribs::DB::get(from)
|
33
|
+
end
|
34
|
+
db.session
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# The current database for this session
|
39
|
+
attr_reader :db
|
40
|
+
|
41
|
+
# Creates a new session that points to the provided +db+ and
|
42
|
+
# +hibernate_session+
|
43
|
+
#
|
44
|
+
def initialize(db, hibernate_session)
|
45
|
+
@db = db
|
46
|
+
@connected = true
|
47
|
+
@hibernate_session = hibernate_session
|
48
|
+
end
|
49
|
+
|
50
|
+
# Releases this session from the database. This will possibly
|
51
|
+
# result in closing the internal Hibernate session, if this is the
|
52
|
+
# last Ribs session pointing to that Hibernate session.
|
53
|
+
def release
|
54
|
+
chk_conn
|
55
|
+
@connected = false
|
56
|
+
@db.release(self)
|
57
|
+
end
|
58
|
+
|
59
|
+
# LOW LEVEL - shouldn't be used except by Ribs
|
60
|
+
def hibernate_session # :nodoc:
|
61
|
+
@hibernate_session
|
62
|
+
end
|
63
|
+
|
64
|
+
# LOW LEVEL - shouldn't be used except by Ribs
|
65
|
+
def find(entity_name, id) # :nodoc:
|
66
|
+
chk_conn
|
67
|
+
if id == :all
|
68
|
+
@hibernate_session.create_criteria(entity_name).list.to_a
|
69
|
+
else
|
70
|
+
@hibernate_session.get(entity_name, java.lang.Integer.new(id))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# LOW LEVEL - shouldn't be used except by Ribs
|
75
|
+
def save(obj) # :nodoc:
|
76
|
+
chk_conn
|
77
|
+
tx = @hibernate_session.begin_transaction
|
78
|
+
if obj.__ribs_meat.persistent
|
79
|
+
@hibernate_session.update(obj)
|
80
|
+
else
|
81
|
+
@hibernate_session.save(obj)
|
82
|
+
obj.__ribs_meat.persistent = true
|
83
|
+
end
|
84
|
+
tx.commit
|
85
|
+
obj
|
86
|
+
end
|
87
|
+
|
88
|
+
# LOW LEVEL - shouldn't be used except by Ribs
|
89
|
+
def delete(obj) # :nodoc:
|
90
|
+
chk_conn
|
91
|
+
tx = @hibernate_session.begin_transaction
|
92
|
+
@hibernate_session.delete(obj)
|
93
|
+
tx.commit
|
94
|
+
obj
|
95
|
+
end
|
96
|
+
|
97
|
+
# LOW LEVEL - shouldn't be used except by Ribs
|
98
|
+
def meta_data # :nodoc:
|
99
|
+
chk_conn
|
100
|
+
@hibernate_session.connection.meta_data
|
101
|
+
end
|
102
|
+
|
103
|
+
# LOW LEVEL - shouldn't be used except by Ribs
|
104
|
+
def ddl(string) # :nodoc:
|
105
|
+
chk_conn
|
106
|
+
execute(string)
|
107
|
+
end
|
108
|
+
|
109
|
+
# LOW LEVEL - shouldn't be used except by Ribs
|
110
|
+
def insert(template, *data) # :nodoc:
|
111
|
+
chk_conn
|
112
|
+
conn = @hibernate_session.connection
|
113
|
+
stmt = conn.prepare_statement(template)
|
114
|
+
data.each do |d|
|
115
|
+
d.each_with_index do |item, index|
|
116
|
+
if item.kind_of?(Array)
|
117
|
+
set_prepared_statement(stmt, item[0], index+1, item[1])
|
118
|
+
else
|
119
|
+
set_prepared_statement(stmt, item, index+1, nil)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
stmt.execute_update
|
123
|
+
end
|
124
|
+
conn.commit
|
125
|
+
ensure
|
126
|
+
stmt.close rescue nil
|
127
|
+
end
|
128
|
+
|
129
|
+
# LOW LEVEL - shouldn't be used except by Ribs
|
130
|
+
def select(string) # :nodoc:
|
131
|
+
chk_conn
|
132
|
+
conn = @hibernate_session.connection
|
133
|
+
stmt = conn.create_statement
|
134
|
+
rs = stmt.execute_query(string)
|
135
|
+
result = []
|
136
|
+
meta = rs.meta_data
|
137
|
+
cols = meta.column_count
|
138
|
+
while rs.next
|
139
|
+
row = []
|
140
|
+
(1..cols).each do |n|
|
141
|
+
row << from_database_type(rs.get_object(n))
|
142
|
+
end
|
143
|
+
result << row
|
144
|
+
end
|
145
|
+
result
|
146
|
+
ensure
|
147
|
+
rs.close rescue nil
|
148
|
+
stmt.close rescue nil
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
# Raise a NotConnectedError if not connected
|
153
|
+
def chk_conn
|
154
|
+
raise NotConnectedError unless @connected
|
155
|
+
end
|
156
|
+
|
157
|
+
# Tries to turn a Java object from the database into an equivalent
|
158
|
+
# Ruby object. Currently supports:
|
159
|
+
#
|
160
|
+
# * Strings
|
161
|
+
# * Floats
|
162
|
+
# * Integers
|
163
|
+
# * nil
|
164
|
+
# * booleans
|
165
|
+
# * Dates
|
166
|
+
# * Times
|
167
|
+
# * Timestamps
|
168
|
+
# * Blobs
|
169
|
+
# * Clobs
|
170
|
+
# * BigDecimals
|
171
|
+
def from_database_type(obj)
|
172
|
+
case obj
|
173
|
+
when String, Float, Integer, NilClass, TrueClass, FalseClass
|
174
|
+
obj
|
175
|
+
when java.sql.Date, java.sql.Time, java.sql.Timestamp
|
176
|
+
Time.at(obj.time/1000)
|
177
|
+
when java.sql.Blob
|
178
|
+
String.from_java_bytes(obj.get_bytes(1,obj.length))
|
179
|
+
when java.sql.Clob
|
180
|
+
obj.get_sub_string(1, obj.length)
|
181
|
+
when java.math.BigDecimal
|
182
|
+
BigDecimal.new(obj.to_s)
|
183
|
+
else
|
184
|
+
raise "Can't find correct type to convert #{obj.inspect} into"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# Tries to set an entry on a prepared statement, based on type
|
189
|
+
def set_prepared_statement(stmt, item, index, type)
|
190
|
+
case item
|
191
|
+
when NilClass
|
192
|
+
stmt.set_object index, nil
|
193
|
+
when String
|
194
|
+
case type
|
195
|
+
when :binary
|
196
|
+
stmt.set_bytes index, item.to_java_bytes
|
197
|
+
when :text
|
198
|
+
stmt.set_string index, item
|
199
|
+
else
|
200
|
+
stmt.set_string index, item
|
201
|
+
end
|
202
|
+
when Symbol
|
203
|
+
stmt.set_string index, item.to_s
|
204
|
+
when Integer
|
205
|
+
stmt.set_int index, item
|
206
|
+
when Float
|
207
|
+
stmt.set_float index, item
|
208
|
+
when Time
|
209
|
+
case type
|
210
|
+
when :date
|
211
|
+
stmt.set_date index, item.to_java_sql_date
|
212
|
+
when :time
|
213
|
+
stmt.set_time index, item.to_java_sql_time
|
214
|
+
when :timestamp
|
215
|
+
stmt.set_timestamp index, item.to_java_sql_time_stamp
|
216
|
+
end
|
217
|
+
when BigDecimal
|
218
|
+
stmt.set_big_decimal index, java.math.BigDecimal.new(item.to_s('F'))
|
219
|
+
when TrueClass, FalseClass
|
220
|
+
stmt.set_boolean index, item
|
221
|
+
else
|
222
|
+
raise "Can't find correct type to set prepared statement for #{item.inspect}"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# Executes a SQL string against the current hibernate
|
227
|
+
# session. This should be an updating SQL string, not a query.
|
228
|
+
def execute(string)
|
229
|
+
conn = @hibernate_session.connection
|
230
|
+
stmt = conn.create_statement
|
231
|
+
stmt.execute_update(string)
|
232
|
+
conn.commit
|
233
|
+
ensure
|
234
|
+
stmt.close rescue nil
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|