iotaz 0.1.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/doc/PERSISTENT +137 -0
- data/doc/README +470 -0
- data/examples/example01.rb +105 -0
- data/examples/example02.rb +105 -0
- data/lib/iotaz.rb +35 -0
- data/lib/iotaz/DatabaseInterfaceFactory.rb +92 -0
- data/lib/iotaz/FirebirdInterface.rb +788 -0
- data/lib/iotaz/IotazError.rb +81 -0
- data/lib/iotaz/MetaData.rb +646 -0
- data/lib/iotaz/ObjectPool.rb +299 -0
- data/lib/iotaz/Persistent.rb +155 -0
- data/lib/iotaz/Query.rb +566 -0
- data/lib/iotaz/Session.rb +379 -0
- data/lib/iotaz/WorkSet.rb +295 -0
- data/test/ActionTest.rb +31 -0
- data/test/AtomTest.rb +90 -0
- data/test/AttributeTest.rb +64 -0
- data/test/DatabaseInterfaceFactoryTest.rb +41 -0
- data/test/FirebirdInterfaceTest.rb +276 -0
- data/test/GeneratedAttributeTest.rb +124 -0
- data/test/IotazErrorTest.rb +23 -0
- data/test/IotazMetaDataTest.rb +87 -0
- data/test/ObjectPoolTest.rb +106 -0
- data/test/PersistentTest.rb +102 -0
- data/test/QueryFieldTest.rb +152 -0
- data/test/QueryRowTest.rb +42 -0
- data/test/QueryTest.rb +59 -0
- data/test/SessionTest.rb +162 -0
- data/test/UnitTest.rb +17 -0
- data/test/ValueCallbackTest.rb +44 -0
- data/test/dbinfo.rb +7 -0
- metadata +75 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) Peter Wood, 2005
|
5
|
+
#
|
6
|
+
# The contents of this file are subject to the Mozilla Public License Version
|
7
|
+
# 1.1 (the "License"); you may not use this file except in compliance with the
|
8
|
+
# License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.mozilla.org/MPL/
|
11
|
+
#
|
12
|
+
# Software distributed under the License is distributed on an "AS IS" basis,
|
13
|
+
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
14
|
+
# the specificlanguage governing rights and limitations under the License.
|
15
|
+
#
|
16
|
+
# The Original Code is the FireRuby extension for the Ruby language.
|
17
|
+
#
|
18
|
+
# The Initial Developer of the Original Code is Peter Wood. All Rights
|
19
|
+
# Reserved.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'rubygems'
|
24
|
+
require_gem 'iotaz'
|
25
|
+
require_gem 'fireruby'
|
26
|
+
|
27
|
+
include FireRuby
|
28
|
+
include Iotaz
|
29
|
+
|
30
|
+
TABLE_SQL = 'create table account (id integer not null primary key,'\
|
31
|
+
'number varchar(10) not null, customer varchar(30), '\
|
32
|
+
'created timestamp not null, updated timestamp)'
|
33
|
+
DB_FILE = './accounts.fdb'
|
34
|
+
DB_USER_NAME = 'sysdba'
|
35
|
+
DB_PASSWORD = 'masterkey'
|
36
|
+
CONFIGURATION = {'iotaz.database' => 'firebird',
|
37
|
+
'iotaz.firebird.user' => DB_USER_NAME,
|
38
|
+
'iotaz.firebird.password' => DB_PASSWORD,
|
39
|
+
'iotaz.firebird.database' => DB_FILE}
|
40
|
+
|
41
|
+
# The definition for the persistable class.
|
42
|
+
class Account
|
43
|
+
attr_accessor :id, :number, :customer, :created, :updated
|
44
|
+
|
45
|
+
def initialize(number, customer)
|
46
|
+
@number = number
|
47
|
+
@customer = customer
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
"Id: #{@id}\nNumber: #{@number}\nCustomer: #{@customer}\n"\
|
52
|
+
"Created: #{@created}\nUpdated: #{@updated}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def Account.iotaz_meta_data
|
56
|
+
IotazMetaData.scan(Account)
|
57
|
+
end
|
58
|
+
|
59
|
+
private :id=, :created=, :updated=
|
60
|
+
end
|
61
|
+
|
62
|
+
def create(session)
|
63
|
+
account = Account.new('ACC/001', 'Test Customer')
|
64
|
+
session.save(account)
|
65
|
+
puts "Save->\n#{account}"
|
66
|
+
account.id
|
67
|
+
end
|
68
|
+
|
69
|
+
def update(id, session)
|
70
|
+
account = session.load(Account, id)
|
71
|
+
account.customer = 'Updated Customer'
|
72
|
+
session.save(account)
|
73
|
+
puts "Update->\n#{account}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def delete(id, session)
|
77
|
+
account = session.load(Account, id)
|
78
|
+
session.delete(account)
|
79
|
+
puts "Account record deleted."
|
80
|
+
end
|
81
|
+
|
82
|
+
begin
|
83
|
+
# Check if the database exists.
|
84
|
+
database = nil
|
85
|
+
if File.exist?(DB_FILE) == false
|
86
|
+
database = Database.create(DB_FILE, DB_USER_NAME, DB_PASSWORD, 1024, nil)
|
87
|
+
database.connect(DB_USER_NAME, DB_PASSWORD) do |connection|
|
88
|
+
connection.execute_immediate(TABLE_SQL)
|
89
|
+
Generator.create('ACCOUNT_ID_SQ', connection)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
factory = SessionFactory.new(CONFIGURATION)
|
94
|
+
session = factory.start
|
95
|
+
|
96
|
+
id = create(session)
|
97
|
+
update(id, session)
|
98
|
+
delete(id, session)
|
99
|
+
|
100
|
+
session.terminate
|
101
|
+
|
102
|
+
rescue Exception => error
|
103
|
+
puts error.message
|
104
|
+
error.backtrace.each {|step| puts " #{step}"}
|
105
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) Peter Wood, 2005
|
5
|
+
#
|
6
|
+
# The contents of this file are subject to the Mozilla Public License Version
|
7
|
+
# 1.1 (the "License"); you may not use this file except in compliance with the
|
8
|
+
# License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.mozilla.org/MPL/
|
11
|
+
#
|
12
|
+
# Software distributed under the License is distributed on an "AS IS" basis,
|
13
|
+
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
14
|
+
# the specificlanguage governing rights and limitations under the License.
|
15
|
+
#
|
16
|
+
# The Original Code is the FireRuby extension for the Ruby language.
|
17
|
+
#
|
18
|
+
# The Initial Developer of the Original Code is Peter Wood. All Rights
|
19
|
+
# Reserved.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'rubygems'
|
24
|
+
require_gem 'iotaz'
|
25
|
+
require_gem 'fireruby'
|
26
|
+
|
27
|
+
include FireRuby
|
28
|
+
include Iotaz
|
29
|
+
|
30
|
+
TABLE_SQL = 'create table account (id integer not null primary key,'\
|
31
|
+
'number varchar(10) not null, customer varchar(30), '\
|
32
|
+
'created timestamp not null, updated timestamp)'
|
33
|
+
DB_FILE = './accounts.fdb'
|
34
|
+
DB_USER_NAME = 'sysdba'
|
35
|
+
DB_PASSWORD = 'masterkey'
|
36
|
+
CONFIGURATION = {'iotaz.database' => 'firebird',
|
37
|
+
'iotaz.firebird.user' => DB_USER_NAME,
|
38
|
+
'iotaz.firebird.password' => DB_PASSWORD,
|
39
|
+
'iotaz.firebird.database' => DB_FILE}
|
40
|
+
|
41
|
+
# The definition for the persistable class.
|
42
|
+
class Account
|
43
|
+
include Persistent
|
44
|
+
|
45
|
+
sequence_attr :id
|
46
|
+
persistent_attr :number
|
47
|
+
persistent_attr :customer
|
48
|
+
timestamp_attr :created
|
49
|
+
timestamp_attr :updated, nil, false, true
|
50
|
+
|
51
|
+
def initialize(number, customer)
|
52
|
+
@number = number
|
53
|
+
@customer = customer
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
"Id: #{@id}\nNumber: #{@number}\nCustomer: #{@customer}\n"\
|
58
|
+
"Created: #{@created}\nUpdated: #{@updated}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def create(session)
|
63
|
+
account = Account.new('ACC/001', 'Test Customer')
|
64
|
+
session.save(account)
|
65
|
+
puts "Save->\n#{account}"
|
66
|
+
account.id
|
67
|
+
end
|
68
|
+
|
69
|
+
def update(id, session)
|
70
|
+
account = session.load(Account, id)
|
71
|
+
account.customer = 'Updated Customer'
|
72
|
+
session.save(account)
|
73
|
+
puts "Update->\n#{account}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def delete(id, session)
|
77
|
+
account = session.load(Account, id)
|
78
|
+
session.delete(account)
|
79
|
+
puts "Account record deleted."
|
80
|
+
end
|
81
|
+
|
82
|
+
begin
|
83
|
+
# Check if the database exists.
|
84
|
+
database = nil
|
85
|
+
if File.exist?(DB_FILE) == false
|
86
|
+
database = Database.create(DB_FILE, DB_USER_NAME, DB_PASSWORD, 1024, nil)
|
87
|
+
database.connect(DB_USER_NAME, DB_PASSWORD) do |connection|
|
88
|
+
connection.execute_immediate(TABLE_SQL)
|
89
|
+
Generator.create('ACCOUNT_ID_SQ', connection)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
factory = SessionFactory.new(CONFIGURATION)
|
94
|
+
session = factory.start
|
95
|
+
|
96
|
+
id = create(session)
|
97
|
+
update(id, session)
|
98
|
+
delete(id, session)
|
99
|
+
|
100
|
+
session.terminate
|
101
|
+
|
102
|
+
rescue Exception => error
|
103
|
+
puts error.message
|
104
|
+
error.backtrace.each {|step| puts " #{step}"}
|
105
|
+
end
|
data/lib/iotaz.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright � Peter Wood, 2005
|
5
|
+
#
|
6
|
+
# The contents of this file are subject to the Mozilla Public License Version
|
7
|
+
# 1.1 (the "License"); you may not use this file except in compliance with the
|
8
|
+
# License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.mozilla.org/MPL/
|
11
|
+
#
|
12
|
+
# Software distributed under the License is distributed on an "AS IS" basis,
|
13
|
+
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
14
|
+
# the specificlanguage governing rights and limitations under the License.
|
15
|
+
#
|
16
|
+
# The Original Code is the FireRuby extension for the Ruby language.
|
17
|
+
#
|
18
|
+
# The Initial Developer of the Original Code is Peter Wood. All Rights
|
19
|
+
# Reserved.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'iotaz/DatabaseInterfaceFactory'
|
24
|
+
require 'iotaz/FirebirdInterface'
|
25
|
+
require 'iotaz/IotazError'
|
26
|
+
require 'iotaz/MetaData'
|
27
|
+
require 'iotaz/ObjectPool'
|
28
|
+
require 'iotaz/Persistent'
|
29
|
+
require 'iotaz/Query'
|
30
|
+
require 'iotaz/Session'
|
31
|
+
require 'iotaz/WorkSet'
|
32
|
+
|
33
|
+
module Iotaz
|
34
|
+
IOTAZ_VERSION = [0, 1, 0].join('.')
|
35
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright � Peter Wood, 2005
|
5
|
+
#
|
6
|
+
# The contents of this file are subject to the Mozilla Public License Version
|
7
|
+
# 1.1 (the "License"); you may not use this file except in compliance with the
|
8
|
+
# License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.mozilla.org/MPL/
|
11
|
+
#
|
12
|
+
# Software distributed under the License is distributed on an "AS IS" basis,
|
13
|
+
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
14
|
+
# the specificlanguage governing rights and limitations under the License.
|
15
|
+
#
|
16
|
+
# The Original Code is the FireRuby extension for the Ruby language.
|
17
|
+
#
|
18
|
+
# The Initial Developer of the Original Code is Peter Wood. All Rights
|
19
|
+
# Reserved.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'thread'
|
24
|
+
require 'iotaz/IotazError'
|
25
|
+
require 'iotaz/FirebirdInterface'
|
26
|
+
|
27
|
+
module Iotaz
|
28
|
+
#
|
29
|
+
# This class represents a factory object that will be used to manufacture
|
30
|
+
# the database interfaces used by the library.
|
31
|
+
#
|
32
|
+
class DatabaseInterfaceFactory
|
33
|
+
# The list of supported databases.
|
34
|
+
@@databases = ['FIREBIRD']
|
35
|
+
|
36
|
+
|
37
|
+
#
|
38
|
+
# This is the constructor for the DatabaseInterfaceFactory class. With
|
39
|
+
# regards to the configuration passed to this class, the factory is
|
40
|
+
# only interested in one value - iotaz.database. For the moment the only
|
41
|
+
# supported value for this is 'firebird'.
|
42
|
+
#
|
43
|
+
# ==== Parameters
|
44
|
+
# configuration:: A reference to a Hash object containing the
|
45
|
+
# configuration information for use by the factory
|
46
|
+
# object and the database interfaces that it will
|
47
|
+
# produce.
|
48
|
+
#
|
49
|
+
# ==== Exceptions
|
50
|
+
# IotazError:: Generated whenever the iotaz.database configuration entry is
|
51
|
+
# not present or is set to an unsupported value.
|
52
|
+
#
|
53
|
+
def initialize(configuration)
|
54
|
+
if configuration.key?('iotaz.database')
|
55
|
+
name = configuration['iotaz.database'].upcase
|
56
|
+
if @@databases.include?(name) == false
|
57
|
+
raise IotazError.new("Unsupported database name specified for "\
|
58
|
+
"database interface factory. '{0}' is not "\
|
59
|
+
"the name of a supported database.")
|
60
|
+
end
|
61
|
+
else
|
62
|
+
raise IotazError.new('Database name missing from Iotaz configuration '\
|
63
|
+
'data.')
|
64
|
+
end
|
65
|
+
|
66
|
+
@configuration = configuration
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
#
|
71
|
+
# This method manufactures a new database interface object using the
|
72
|
+
# configuration information provided to the factory.
|
73
|
+
#
|
74
|
+
# ==== Exceptions
|
75
|
+
# IotazError:: Generated if any of the required configuration information
|
76
|
+
# for the interface object is invalid.
|
77
|
+
#
|
78
|
+
def create
|
79
|
+
name = @configuration['iotaz.database'].upcase
|
80
|
+
interface = nil
|
81
|
+
case name
|
82
|
+
when 'FIREBIRD' :
|
83
|
+
interface = FirebirdInterface.new(@configuration)
|
84
|
+
|
85
|
+
else
|
86
|
+
raise IotazError.new("Error manufacturing database interface. "\
|
87
|
+
"Unknown database name '{0}' encountered.")
|
88
|
+
end
|
89
|
+
interface
|
90
|
+
end
|
91
|
+
end # End of the DatabaseInterfaceFactory class.
|
92
|
+
end # End of the Iotaz module.
|
@@ -0,0 +1,788 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright � Peter Wood, 2005
|
5
|
+
#
|
6
|
+
# The contents of this file are subject to the Mozilla Public License Version
|
7
|
+
# 1.1 (the "License"); you may not use this file except in compliance with the
|
8
|
+
# License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.mozilla.org/MPL/
|
11
|
+
#
|
12
|
+
# Software distributed under the License is distributed on an "AS IS" basis,
|
13
|
+
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
14
|
+
# the specificlanguage governing rights and limitations under the License.
|
15
|
+
#
|
16
|
+
# The Original Code is the FireRuby extension for the Ruby language.
|
17
|
+
#
|
18
|
+
# The Initial Developer of the Original Code is Peter Wood. All Rights
|
19
|
+
# Reserved.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'iotaz/IotazError'
|
24
|
+
require 'iotaz/ObjectPool'
|
25
|
+
require 'iotaz/Session'
|
26
|
+
require 'stringio'
|
27
|
+
require 'rubygems'
|
28
|
+
require_gem 'fireruby'
|
29
|
+
|
30
|
+
include FireRuby
|
31
|
+
|
32
|
+
module Iotaz
|
33
|
+
#
|
34
|
+
# This class manufactures or destroys connections to a specific Firebird
|
35
|
+
# database. This class is used internally by the connection pool within
|
36
|
+
# the FirebirdInterface class.
|
37
|
+
#
|
38
|
+
class FirebirdConnectionFactory
|
39
|
+
#
|
40
|
+
# This is the constructor fo the FirebirdConnectionFactory class.
|
41
|
+
#
|
42
|
+
# ==== Parameters
|
43
|
+
# user:: The user name to connect as.
|
44
|
+
# password:: The user password to be used to obtain connections.
|
45
|
+
# database:: The database file specification to be used to obtain
|
46
|
+
# connections.
|
47
|
+
#
|
48
|
+
def initialize(user, password, database)
|
49
|
+
@database = Database.new(database)
|
50
|
+
@user = user
|
51
|
+
@password = password
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
#
|
56
|
+
# This method is used to manufacture a new connection to the database.
|
57
|
+
#
|
58
|
+
# ==== Exceptions
|
59
|
+
# IotazError:: Generated whenever a problem occurs obtaining a new
|
60
|
+
# database connection.
|
61
|
+
#
|
62
|
+
def create
|
63
|
+
@database.connect(@user, @password)
|
64
|
+
rescue FireRubyException => error
|
65
|
+
raise IotazError.new('Error opening new database connection. Cause: {0}',
|
66
|
+
error.message)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
#
|
71
|
+
# This method frees the resources associated with a connection previously
|
72
|
+
# created by the factory.
|
73
|
+
#
|
74
|
+
# ==== Exceptions
|
75
|
+
# IotazError:: Generated whenever a problem occurs closing the Firebird
|
76
|
+
# connection.
|
77
|
+
#
|
78
|
+
def destroy(connection)
|
79
|
+
connection.close
|
80
|
+
rescue FireRubyException => error
|
81
|
+
raise IotazError.new('Error closing database connection. Cause: {0}',
|
82
|
+
error.message)
|
83
|
+
end
|
84
|
+
end # End of the FirebirdConnectionFactory class
|
85
|
+
|
86
|
+
|
87
|
+
#
|
88
|
+
# This class represents the database interface for the Firebird database.
|
89
|
+
# The class makes use of the FireRuby library to interface with the database.
|
90
|
+
# The class currently recognises the following keys within the configuration
|
91
|
+
# data that is passed to it's constructor...
|
92
|
+
#
|
93
|
+
# - 'iotaz.firebird.user':
|
94
|
+
# The user name to be used in connecting to the database. A value for this
|
95
|
+
# entry must be specified.
|
96
|
+
#
|
97
|
+
# - 'iotaz.firebird.password':
|
98
|
+
# The password to be used to connect to the database. A value for this
|
99
|
+
# entry must be specified.
|
100
|
+
#
|
101
|
+
# - 'iotaz.firebird.database':
|
102
|
+
# The database file specification to be used to connect to the database. A
|
103
|
+
# value for this entry must be specified.
|
104
|
+
#
|
105
|
+
# - 'iotaz.firebird.connections.max':
|
106
|
+
# The maximum number of connections to be pooled by the interface. If not
|
107
|
+
# specified a default of 5 is used.
|
108
|
+
#
|
109
|
+
# - 'iotaz.firebird.connections.min':
|
110
|
+
# The minimum number of connections that the interface will have available
|
111
|
+
# in its connection pool. If not specified a default of 2 is used.
|
112
|
+
#
|
113
|
+
# - 'iotaz.firebird.connections.idle':
|
114
|
+
# The amount of time, in seconds, that a pooled connection can remain idle
|
115
|
+
# before it can be considered for automatic release. If not specified a
|
116
|
+
# default of 1800 is used.
|
117
|
+
#
|
118
|
+
# - 'iotaz.firebird.connections.interval':
|
119
|
+
# The interval, in seconds, that the interface will wait between attempts
|
120
|
+
# to clean up idle connections. If not specified a default of 300 is used.
|
121
|
+
#
|
122
|
+
class FirebirdInterface
|
123
|
+
# A definition for the configuration keys recognised by the class.
|
124
|
+
KEYS = ['iotaz.firebird.user',
|
125
|
+
'iotaz.firebird.password',
|
126
|
+
'iotaz.firebird.database',
|
127
|
+
'iotaz.firebird.connections.max',
|
128
|
+
'iotaz.firebird.connections.min',
|
129
|
+
'iotaz.firebird.connections.idle',
|
130
|
+
'iotaz.firebird.connections.interval']
|
131
|
+
|
132
|
+
|
133
|
+
#
|
134
|
+
# This is the constructor for the FirebirdInterface class.
|
135
|
+
#
|
136
|
+
# ==== Parameters
|
137
|
+
# config:: A hash containing the configuration elements for the interface.
|
138
|
+
#
|
139
|
+
# ==== Exceptions
|
140
|
+
# IotazError:: Generated whenever a required configuration element is not
|
141
|
+
# provided.
|
142
|
+
#
|
143
|
+
def initialize(config)
|
144
|
+
# Check for required values.
|
145
|
+
if config.key?(KEYS[0]) == false
|
146
|
+
raise IotazError.new("Require database interface configuration "\
|
147
|
+
"element '{0}' not specified.", KEYS[0])
|
148
|
+
end
|
149
|
+
if config.key?(KEYS[1]) == false
|
150
|
+
raise IotazError.new("Require database interface configuration "\
|
151
|
+
"element '{0}' not specified.", KEYS[1])
|
152
|
+
end
|
153
|
+
if config.key?('iotaz.firebird.database') == false
|
154
|
+
raise IotazError.new("Require database interface configuration "\
|
155
|
+
"element '{0}' not specified.", KEYS[2])
|
156
|
+
end
|
157
|
+
|
158
|
+
# Extract the required elements.
|
159
|
+
user = config[KEYS[0]]
|
160
|
+
password = config[KEYS[1]]
|
161
|
+
database = config[KEYS[2]]
|
162
|
+
|
163
|
+
# Create the interface connection pool.
|
164
|
+
factory = FirebirdConnectionFactory.new(user, password, database)
|
165
|
+
maximum = config.key?(KEYS[3]) ? config[KEYS[3]].to_i : 5
|
166
|
+
minimum = config.key?(KEYS[4]) ? config[KEYS[3]].to_i : 2
|
167
|
+
idle = config.key?(KEYS[5]) ? config[KEYS[3]].to_i : 1800
|
168
|
+
interval = config.key?(KEYS[6]) ? config[KEYS[3]].to_i : 300
|
169
|
+
@pool = ObjectPool.new(factory, maximum, minimum, idle, interval)
|
170
|
+
at_exit {@pool.shutdown}
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
#
|
175
|
+
# This method generates the SQL statement for the insertion of a new
|
176
|
+
# row into a database table based on a meta-data set and an object
|
177
|
+
# value. The function returns three values, the first is the SQL statement
|
178
|
+
# for the insertion. The second is an array of the callback objects that
|
179
|
+
# will be used to populate data values that will be available after the
|
180
|
+
# SQL execution. The third is an array of the parameter values to be used
|
181
|
+
# in conjunction with the SQL.
|
182
|
+
#
|
183
|
+
# ==== Parameters
|
184
|
+
# object:: A reference to the object to generate the insertion SQL
|
185
|
+
# statement for. This must be an instance of a class that
|
186
|
+
# implements the iotaz_meta_data method.
|
187
|
+
#
|
188
|
+
def get_insert_sql(object)
|
189
|
+
text = [StringIO.new, StringIO.new]
|
190
|
+
callbacks = []
|
191
|
+
parameters = []
|
192
|
+
metadata = object.class.iotaz_meta_data
|
193
|
+
|
194
|
+
# Insert the initial callbacks for the aspects of the SQL statement.
|
195
|
+
text[0] << "insert into #{metadata.table}("
|
196
|
+
text[1] << "values("
|
197
|
+
|
198
|
+
# Iterate over the attribute definitions.
|
199
|
+
added = false
|
200
|
+
metadata.each do |attribute|
|
201
|
+
# Check if the attribute is to be generated.
|
202
|
+
if attribute.is_generated?
|
203
|
+
# Check if the value is generated for inserts.
|
204
|
+
if attribute.events.include?("INSERT")
|
205
|
+
name = attribute.name
|
206
|
+
source = attribute.source
|
207
|
+
case attribute.type
|
208
|
+
when 'SEQUENCE' :
|
209
|
+
# Added the details to the SQL statement.
|
210
|
+
text[0] << ", " if added
|
211
|
+
text[0] << attribute.column
|
212
|
+
text[1] << ", " if added
|
213
|
+
text[1] << "?"
|
214
|
+
number = get_sequence_value(source)
|
215
|
+
parameters.push(number)
|
216
|
+
attribute.set(object, number)
|
217
|
+
added = true if added == false
|
218
|
+
when 'DATE', 'TIME', 'TIMESTAMP' :
|
219
|
+
# Generate an value callback to get the value assigned.
|
220
|
+
sql = get_value_select(attribute.name, object)
|
221
|
+
callbacks.push(ValueCallback.new(object,
|
222
|
+
attribute.name,
|
223
|
+
sql))
|
224
|
+
|
225
|
+
# Update the SQL statement.
|
226
|
+
text[0] << ", " if added
|
227
|
+
text[0] << attribute.column
|
228
|
+
text[1] << ", " if added
|
229
|
+
text[1] << "'#{attribute.source}'"
|
230
|
+
added = true if added == false
|
231
|
+
end
|
232
|
+
end
|
233
|
+
else
|
234
|
+
# Add the column name.
|
235
|
+
text[0] << ", " if added
|
236
|
+
text[0] << attribute.column
|
237
|
+
|
238
|
+
# Add the column value.
|
239
|
+
text[1] << ", " if added
|
240
|
+
text[1] << "?"
|
241
|
+
parameters.push(attribute.get(object))
|
242
|
+
added = true if added == false
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Terminate the aspects of the SQL statement.
|
247
|
+
text[0] << ") "
|
248
|
+
text[1] << ")"
|
249
|
+
|
250
|
+
#puts "INSERT SQL: #{text[0].string}#{text[1].string}"
|
251
|
+
#puts "PARAMETERS: #{parameters.join(', ')}"
|
252
|
+
[text[0].string + text[1].string, callbacks, parameters]
|
253
|
+
end
|
254
|
+
|
255
|
+
|
256
|
+
#
|
257
|
+
# This method generates the SQL statement for the update of an existing
|
258
|
+
# row into a database table based on a meta-data set and an object
|
259
|
+
# value. The function returns two values, the firsr is the SQL statement
|
260
|
+
# for the update. The second is a hash of generated values, mapping
|
261
|
+
# attribute names to generated values. This hash will either contain
|
262
|
+
# the generated value or a ValueCallback if the value will only be
|
263
|
+
# available after the statement has been executed.
|
264
|
+
#
|
265
|
+
# ==== Parameters
|
266
|
+
# object:: A reference to the object to generate the insertion SQL
|
267
|
+
# statement for. This must be an instance of a class that
|
268
|
+
# implements the iotaz_meta_data method.
|
269
|
+
#
|
270
|
+
def get_update_sql(object)
|
271
|
+
sql = StringIO.new
|
272
|
+
values = []
|
273
|
+
parameters = []
|
274
|
+
metadata = object.class.iotaz_meta_data
|
275
|
+
|
276
|
+
# Insert the initial values for the aspects of the SQL statement.
|
277
|
+
sql << "update #{metadata.table} set "
|
278
|
+
|
279
|
+
# Iterate over the attribute definitions.
|
280
|
+
added = false
|
281
|
+
metadata.each do |attribute|
|
282
|
+
# Check if the attribute is to be generated.
|
283
|
+
if attribute.is_generated?
|
284
|
+
# Check if the value is generated for inserts.
|
285
|
+
if attribute.events.include?("UPDATE")
|
286
|
+
name = attribute.name
|
287
|
+
source = attribute.source
|
288
|
+
case attribute.type
|
289
|
+
when 'SEQUENCE' :
|
290
|
+
# Added the details to the SQL statement.
|
291
|
+
sql << ", " if added
|
292
|
+
sql << attribute.column << " = ?"
|
293
|
+
number = get_sequence_value(source)
|
294
|
+
parameters.push(number)
|
295
|
+
attribute.set(object, number)
|
296
|
+
added = true if added == false
|
297
|
+
|
298
|
+
when 'DATE', 'TIME', 'TIMESTAMP' :
|
299
|
+
# Generate an value callback to get the value assigned.
|
300
|
+
statement = get_value_select(attribute.name, object)
|
301
|
+
values.push(ValueCallback.new(object,
|
302
|
+
attribute.name,
|
303
|
+
statement))
|
304
|
+
|
305
|
+
# Update the SQL statement.
|
306
|
+
sql << ", " if added
|
307
|
+
sql << attribute.column << " = '#{attribute.source}'"
|
308
|
+
added = true if added == false
|
309
|
+
end
|
310
|
+
end
|
311
|
+
else
|
312
|
+
# Add the column name and value.
|
313
|
+
sql << ", " if added
|
314
|
+
sql << attribute.column << " = ?"
|
315
|
+
parameters.push(attribute.get(object))
|
316
|
+
added = true if added == false
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
# Terminate the aspects of the SQL statement.
|
321
|
+
sql << " " << get_key_sql(object)
|
322
|
+
parameters.concat(get_key_values(object))
|
323
|
+
|
324
|
+
#puts "UPDATE SQL: #{sql.string}"
|
325
|
+
#puts "PARAMETERS: #{parameters.join(', ')}"
|
326
|
+
[sql.string, values, parameters]
|
327
|
+
end
|
328
|
+
|
329
|
+
|
330
|
+
#
|
331
|
+
# This method produces the SQL select statement that can be used to
|
332
|
+
# fetch an object instance for a given class from the database.
|
333
|
+
#
|
334
|
+
# ==== Parameters
|
335
|
+
# klass:: A reference to the class of the object that will be fetched
|
336
|
+
# from the database.
|
337
|
+
#
|
338
|
+
def get_fetch_sql(klass)
|
339
|
+
metadata = klass.iotaz_meta_data
|
340
|
+
sql = StringIO.new
|
341
|
+
added = false
|
342
|
+
|
343
|
+
# Load details of the attributes.
|
344
|
+
sql << "select "
|
345
|
+
metadata.each do |attribute|
|
346
|
+
sql << ', ' if added
|
347
|
+
sql << attribute.column
|
348
|
+
added = true if added == false
|
349
|
+
end
|
350
|
+
sql << " from #{metadata.table} #{get_key_sql(klass)}"
|
351
|
+
|
352
|
+
#puts "FETCH SQL: #{sql.string}"
|
353
|
+
sql.string
|
354
|
+
end
|
355
|
+
|
356
|
+
|
357
|
+
#
|
358
|
+
# This method produces the SQL statement that can be used to delete the
|
359
|
+
# database record for an object.
|
360
|
+
#
|
361
|
+
# ==== Parameters
|
362
|
+
# object:: Either a reference to an object or to a Class instance. If it
|
363
|
+
# is a Class instance then the class must implement the
|
364
|
+
# iotaz_meta_data method. If it's just a normal object then
|
365
|
+
# the objects class must implement the method.
|
366
|
+
#
|
367
|
+
def get_delete_sql(object)
|
368
|
+
metadata = nil
|
369
|
+
if object.instance_of?(Class)
|
370
|
+
metadata = object.iotaz_meta_data
|
371
|
+
else
|
372
|
+
metadata = object.class.iotaz_meta_data
|
373
|
+
end
|
374
|
+
#puts "DELETE SQL: delete from #{metadata.table} #{get_key_sql(object)}"
|
375
|
+
"delete from #{metadata.table} #{get_key_sql(object)}"
|
376
|
+
end
|
377
|
+
|
378
|
+
|
379
|
+
#
|
380
|
+
# This method initiates a transaction within the database. The value
|
381
|
+
# that is returned by the method should not be interpreted outside of
|
382
|
+
# this class.
|
383
|
+
#
|
384
|
+
def start_transaction
|
385
|
+
[@pool.acquire, nil]
|
386
|
+
end
|
387
|
+
|
388
|
+
|
389
|
+
#
|
390
|
+
# This method commits a transaction previously created using a call to the
|
391
|
+
# FirebirdInterface#start_transaction method.
|
392
|
+
#
|
393
|
+
# ==== Parameters
|
394
|
+
# transaction:: A reference to the transaction details to be committed.
|
395
|
+
#
|
396
|
+
# ==== Exception
|
397
|
+
# IotazError:: Generated whenever a problem occurs committing the work
|
398
|
+
# for the transaction.
|
399
|
+
#
|
400
|
+
def commit(transaction)
|
401
|
+
begin
|
402
|
+
transaction[1].commit if transaction[1] != nil
|
403
|
+
@pool.release(transaction[0])
|
404
|
+
transaction[0] = transaction[1] = nil
|
405
|
+
rescue FireRubyException => error
|
406
|
+
raise IotazError.new("Exception caught committing transaction. "\
|
407
|
+
"Cause: {0}", error.message)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
|
412
|
+
#
|
413
|
+
# This method rolls back a transaction created using a call to the
|
414
|
+
# FirebirdInterface#start_transaction method.
|
415
|
+
#
|
416
|
+
# ==== Parameters
|
417
|
+
# transaction:: A reference to the transaction details to be rolled back.
|
418
|
+
#
|
419
|
+
# ==== Exceptions
|
420
|
+
# IotazError:: Generated whenever a problem occurs rolling back the work
|
421
|
+
# for the transaction.
|
422
|
+
#
|
423
|
+
def rollback(transaction)
|
424
|
+
begin
|
425
|
+
transaction[1].rollback if transaction[1] != nil
|
426
|
+
@pool.release(transaction[0])
|
427
|
+
transaction[0] = transaction[1] = nil
|
428
|
+
rescue FireRubyException => error
|
429
|
+
raise IotazError.new("Exception caught rolling back transaction. "\
|
430
|
+
"Cause: {0}", error.message)
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
|
435
|
+
#
|
436
|
+
# This method executes a single unit of work represented by an Action
|
437
|
+
# object.
|
438
|
+
#
|
439
|
+
# ==== Parameters
|
440
|
+
# action:: A reference to the action to be executed.
|
441
|
+
# transaction:: A reference to the transaction entity to be used in the
|
442
|
+
# execution. This should have been previously obtained
|
443
|
+
# from a call to the start_transaction method.
|
444
|
+
#
|
445
|
+
# ==== Exceptions
|
446
|
+
# IotazError:: Generated whenever a problem occurs executing the work for
|
447
|
+
# the action.
|
448
|
+
#
|
449
|
+
def execute_action(action, transaction)
|
450
|
+
begin
|
451
|
+
# Check if a transaction needs to be started.
|
452
|
+
if transaction[1] == nil
|
453
|
+
transaction[1] = transaction[0].start_transaction
|
454
|
+
end
|
455
|
+
|
456
|
+
# Check if we've cached anything for this action.
|
457
|
+
statement = nil
|
458
|
+
if action.cache == nil
|
459
|
+
statement = Statement.new(transaction[0], transaction[1],
|
460
|
+
action.sql, 3)
|
461
|
+
action.cache = statement
|
462
|
+
else
|
463
|
+
statement = action.cache
|
464
|
+
end
|
465
|
+
|
466
|
+
# Execute the statement on a parameter set.
|
467
|
+
parameters = action.get_parameters
|
468
|
+
result = statement.execute_for(parameters)
|
469
|
+
result.close if result != nil
|
470
|
+
rescue FireRubyException => error
|
471
|
+
raise IotazError.new("Exception caught executing action. Cause: {0}",
|
472
|
+
error.message)
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
|
477
|
+
#
|
478
|
+
# This method executes a select statement to fetch the data for a value
|
479
|
+
# callback.
|
480
|
+
#
|
481
|
+
# ==== Parameters
|
482
|
+
# callback:: A reference to the ValueCallback object to be executed.
|
483
|
+
# transaction:: A reference to the transaction entity to be used in the
|
484
|
+
# execution. This should have been previously obtained
|
485
|
+
# from a call to the start_transaction method.
|
486
|
+
#
|
487
|
+
# ==== Exceptions
|
488
|
+
# IotazError:: Generated whenever a problem occurs executing the SQL for
|
489
|
+
# the callback object.
|
490
|
+
#
|
491
|
+
def execute_callback(callback, transaction)
|
492
|
+
data = nil
|
493
|
+
begin
|
494
|
+
# Check if a transaction has actually been started.
|
495
|
+
if transaction[1] == nil
|
496
|
+
transaction[1] = transaction[0].start_transaction
|
497
|
+
end
|
498
|
+
|
499
|
+
# Execute the fetch and check the result.
|
500
|
+
statement = nil
|
501
|
+
if callback.cache == nil
|
502
|
+
statement = Statement.new(transaction[0], transaction[1],
|
503
|
+
callback.sql, 3)
|
504
|
+
callback.cache = statement
|
505
|
+
else
|
506
|
+
statement = callback.cache
|
507
|
+
end
|
508
|
+
|
509
|
+
result = statement.execute_for(callback.parameters)
|
510
|
+
if result == nil
|
511
|
+
raise IotazError.new("Value callback SQL statement did not "\
|
512
|
+
"return a result set.")
|
513
|
+
end
|
514
|
+
|
515
|
+
# Extract the data and clean up.
|
516
|
+
data = result.fetch[0]
|
517
|
+
result.close
|
518
|
+
rescue FireRubyException => error
|
519
|
+
raise IotazError.new("Error executing value callback. Cause: {0}",
|
520
|
+
error.message)
|
521
|
+
end
|
522
|
+
data
|
523
|
+
end
|
524
|
+
|
525
|
+
|
526
|
+
#
|
527
|
+
# This method executes a SQL query, passed in the form of a Query object,
|
528
|
+
# against the database.
|
529
|
+
#
|
530
|
+
# ==== Parameters
|
531
|
+
# query:: A reference to the Query object that will provide the
|
532
|
+
# details for the query to execute.
|
533
|
+
# transaction:: A reference to the transaction entity, previously created
|
534
|
+
# by a call to the start_transaction method, that will be
|
535
|
+
# used to execute the query.
|
536
|
+
# maximum:: A reference to an integer indicating the maximum number
|
537
|
+
# of rows to fetch. This defaults to -1 to indicate that
|
538
|
+
# all rows for the query should be returned.
|
539
|
+
#
|
540
|
+
def execute_query(query, transaction, maximum=-1)
|
541
|
+
rows = []
|
542
|
+
|
543
|
+
# Check that the transaction entity is fully initialized.
|
544
|
+
if transaction[1] == nil
|
545
|
+
transaction[1] = transaction[0].start_transaction
|
546
|
+
end
|
547
|
+
|
548
|
+
# Extract the query details.
|
549
|
+
sql, parameters = query.to_sql
|
550
|
+
|
551
|
+
# Create the statement.
|
552
|
+
statement = Statement.new(transaction[0], transaction[1], sql, 3)
|
553
|
+
begin
|
554
|
+
# Get the result set.
|
555
|
+
results = statement.execute_for(parameters)
|
556
|
+
begin
|
557
|
+
if maximum > 0
|
558
|
+
1.upto(maximum) do |index|
|
559
|
+
entry = results.fetch
|
560
|
+
if entry != nil
|
561
|
+
row = QueryRow.new
|
562
|
+
0.upto(entry.column_count - 1) do |index|
|
563
|
+
row[entry.column_name(index)] = entry[index]
|
564
|
+
end
|
565
|
+
rows.push(row)
|
566
|
+
else
|
567
|
+
break;
|
568
|
+
end
|
569
|
+
end
|
570
|
+
else
|
571
|
+
results.each do |entry|
|
572
|
+
row = QueryRow.new
|
573
|
+
0.upto(entry.column_count - 1) do |index|
|
574
|
+
row[entry.column_name(index)] = entry[index]
|
575
|
+
end
|
576
|
+
rows.push(row)
|
577
|
+
end
|
578
|
+
end
|
579
|
+
ensure
|
580
|
+
results.close
|
581
|
+
end
|
582
|
+
ensure
|
583
|
+
statement.close
|
584
|
+
end
|
585
|
+
|
586
|
+
rows
|
587
|
+
end
|
588
|
+
|
589
|
+
|
590
|
+
#
|
591
|
+
# This method executes a SQL select statement, returning the rows fetched
|
592
|
+
# as a result. This method returns an array of hashes. Each contained
|
593
|
+
# hash represents a row of data from the select statement, mapping
|
594
|
+
# column names onto column values. Column names are set to be all upper
|
595
|
+
# case to simplify comparisons.
|
596
|
+
#
|
597
|
+
# ==== Parameters
|
598
|
+
# sql:: A string containing the SQL statement to be executed.
|
599
|
+
# parameters:: An array containing the parameters to be used in
|
600
|
+
# executing the SQL.
|
601
|
+
# transaction:: A reference to the transaction entity that will be used
|
602
|
+
# in executing the select.
|
603
|
+
# maximum:: An integer specifying the maximum number of rows to be
|
604
|
+
# fetched. This defaults to -1 to indicate that all rows
|
605
|
+
# should be fetched.
|
606
|
+
#
|
607
|
+
# ==== Exceptions
|
608
|
+
# IotazError:: Generated whenever a invalid number of parameters are
|
609
|
+
# specified, the SQL statement provided does not represent a
|
610
|
+
# select or an error occurs accessing the database.
|
611
|
+
#
|
612
|
+
def execute_select(sql, parameters, transaction, maximum=-1)
|
613
|
+
rows = []
|
614
|
+
|
615
|
+
# Check if a transaction is needed.
|
616
|
+
if transaction[1] == nil
|
617
|
+
transaction[1] = transaction[0].start_transaction
|
618
|
+
end
|
619
|
+
|
620
|
+
# Create the statement to execute the SQL.
|
621
|
+
statement = Statement.new(transaction[0], transaction[1], sql, 3)
|
622
|
+
if statement.is_query? == false
|
623
|
+
raise IotazError.new("Invalid SQL query. '{0}' is not a SQL select "\
|
624
|
+
"statement.", sql)
|
625
|
+
end
|
626
|
+
|
627
|
+
results = nil
|
628
|
+
begin
|
629
|
+
results = statement.execute_for(parameters)
|
630
|
+
if maximum > 0
|
631
|
+
count = 0
|
632
|
+
while count < maximum and rows.size == count
|
633
|
+
row = results.fetch
|
634
|
+
if row != nil
|
635
|
+
map = Hash.new
|
636
|
+
row.each_index do |index|
|
637
|
+
map[results.column_name(index).upcase] = row[index]
|
638
|
+
end
|
639
|
+
rows.push(map)
|
640
|
+
end
|
641
|
+
count += 1
|
642
|
+
end
|
643
|
+
else
|
644
|
+
results.each do |row|
|
645
|
+
map = Hash.new
|
646
|
+
|
647
|
+
0.upto(row.column_count - 1) do |index|
|
648
|
+
map[row.column_name(index).upcase] = row[index]
|
649
|
+
end
|
650
|
+
rows.push(map)
|
651
|
+
end
|
652
|
+
end
|
653
|
+
ensure
|
654
|
+
results.close if results != nil
|
655
|
+
end
|
656
|
+
|
657
|
+
rows
|
658
|
+
rescue FireRubyException => error
|
659
|
+
raise IotazError.new('Error executing select. Cause: {0}',
|
660
|
+
error.message)
|
661
|
+
end
|
662
|
+
|
663
|
+
|
664
|
+
#
|
665
|
+
# This method is used to clean up the items assigned to Action cache
|
666
|
+
# values as part of the work of executing the action.
|
667
|
+
#
|
668
|
+
# ==== Parameters
|
669
|
+
# cache:: An array of the cache items that are to be cleaned up.
|
670
|
+
#
|
671
|
+
# ==== Exceptions
|
672
|
+
# IotazError:: Generated whenever a problem is encountered cleaning up a
|
673
|
+
# cache item.
|
674
|
+
#
|
675
|
+
def clean_cache(cache)
|
676
|
+
begin
|
677
|
+
cache.each {|entry| entry.close if entry != nil}
|
678
|
+
rescue FireRubyException => error
|
679
|
+
raise IotazError.new("Error cleaning up cache item. Cause: {0}",
|
680
|
+
error.message)
|
681
|
+
end
|
682
|
+
end
|
683
|
+
|
684
|
+
|
685
|
+
#
|
686
|
+
# This method fetches the next value from a name Firebird generator.
|
687
|
+
#
|
688
|
+
# ==== Parameters
|
689
|
+
# sequence:: The name of the generator to fetch the value.
|
690
|
+
#
|
691
|
+
def get_sequence_value(sequence)
|
692
|
+
value = nil
|
693
|
+
@pool.acquire do |connection|
|
694
|
+
sequence = Generator.new(sequence, connection)
|
695
|
+
value = sequence.next(1)
|
696
|
+
end
|
697
|
+
value
|
698
|
+
end
|
699
|
+
|
700
|
+
|
701
|
+
#
|
702
|
+
# This method produces a SQL select statement to fetch a value from
|
703
|
+
# a specific database row.
|
704
|
+
#
|
705
|
+
# ==== Parameters
|
706
|
+
# name:: The name of the attribute to generate the select for.
|
707
|
+
# object:: The object to get the key values from. This must be an
|
708
|
+
# instance of a class that implements the iotaz_meta_data
|
709
|
+
# method.
|
710
|
+
#
|
711
|
+
def get_value_select(name, object)
|
712
|
+
metadata = object.class.iotaz_meta_data
|
713
|
+
attribute = metadata.get_attribute(name)
|
714
|
+
"select #{attribute.column} from #{metadata.table} #{get_key_sql(object)}"
|
715
|
+
end
|
716
|
+
|
717
|
+
|
718
|
+
#
|
719
|
+
# This method generates the where clause aspects of a SQL statement to
|
720
|
+
# uniquely pick out a database row for a given object. The SQL fragement
|
721
|
+
# returned by the method will not fill out the key ookup fields, providing
|
722
|
+
# substitution entries instead. This is done as the lookup of the key
|
723
|
+
# values is left to the latest possible moment.
|
724
|
+
#
|
725
|
+
# ==== Parameters
|
726
|
+
# object:: Either a reference to the object to generate the SQL statement
|
727
|
+
# clauses for or a Class instance. If an object is specified
|
728
|
+
# then its class must provides the iotaz_meta_data method. If
|
729
|
+
# its a class then it must have a iotaz_meta_data method.
|
730
|
+
#
|
731
|
+
def get_key_sql(object)
|
732
|
+
out = StringIO.new
|
733
|
+
metadata = nil
|
734
|
+
if object.instance_of?(Class)
|
735
|
+
metadata = object.iotaz_meta_data
|
736
|
+
else
|
737
|
+
metadata = object.class.iotaz_meta_data
|
738
|
+
end
|
739
|
+
|
740
|
+
added = false
|
741
|
+
out << 'where '
|
742
|
+
metadata.keys.each do |key|
|
743
|
+
attribute = metadata.get_attribute(key)
|
744
|
+
out << " and " if added
|
745
|
+
out << attribute.column << " = ?"
|
746
|
+
added = true if added == false
|
747
|
+
end
|
748
|
+
|
749
|
+
out.string
|
750
|
+
end
|
751
|
+
|
752
|
+
|
753
|
+
#
|
754
|
+
# This method looks up the values of the parameters associated with the
|
755
|
+
# keys for an object. The method returns an array of the values for the
|
756
|
+
# key attributes for the object.
|
757
|
+
#
|
758
|
+
# ==== Parameters
|
759
|
+
# object:: The object to look up the key values for. This must be an
|
760
|
+
# instance of a class that implements the iotaz_meta_data
|
761
|
+
# method.
|
762
|
+
#
|
763
|
+
def get_key_values(object)
|
764
|
+
values = []
|
765
|
+
metadata = object.class.iotaz_meta_data
|
766
|
+
|
767
|
+
metadata.keys.each do |key|
|
768
|
+
values.push(metadata.get_attribute(key).get(object))
|
769
|
+
end
|
770
|
+
|
771
|
+
values
|
772
|
+
end
|
773
|
+
|
774
|
+
|
775
|
+
#
|
776
|
+
# This method shutdown an instance of the FirebirdInterface class. The
|
777
|
+
# object that this method is called for should not be used again after
|
778
|
+
# making the call.
|
779
|
+
#
|
780
|
+
def shutdown
|
781
|
+
@pool.shutdown
|
782
|
+
end
|
783
|
+
|
784
|
+
|
785
|
+
# Method access alterations.
|
786
|
+
private :get_value_select
|
787
|
+
end # End of the Firebird interface class.
|
788
|
+
end # End of the Iotaz module.
|