nitro 0.2.0 → 0.3.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/ChangeLog +186 -0
- data/README +40 -11
- data/RELEASES +10 -1
- data/Rakefile +5 -4
- data/bin/cluster.rb +3 -3
- data/{etc/new-project.rb → bin/new_app.rb} +1 -1
- data/examples/og/README +4 -0
- data/examples/og/run.rb +254 -0
- data/examples/simple/app.rb +3 -3
- data/examples/simple/conf/config.rb +10 -22
- data/examples/simple/conf/debug-config.rb +6 -32
- data/examples/simple/conf/live-config.rb +3 -23
- data/examples/simple/conf/requires.rb +5 -5
- data/examples/simple/env.rb +3 -4
- data/examples/simple/lib/articles/entities.rb +17 -15
- data/examples/simple/lib/articles/methods.rb +15 -15
- data/examples/simple/lib/articles/part.rb +7 -8
- data/examples/simple/root/comments.si +1 -1
- data/examples/simple/root/index.sx +1 -1
- data/examples/simple/root/view-article.sx +1 -2
- data/examples/tiny/app.rb +3 -3
- data/examples/tiny/conf/config.rb +4 -4
- data/examples/tiny/conf/requires.rb +3 -4
- data/lib/n/config.rb +50 -3
- data/lib/n/logger.rb +14 -2
- data/lib/n/og.rb +381 -0
- data/lib/n/og/backend.rb +252 -0
- data/lib/n/og/backends/mysql.rb +352 -0
- data/lib/n/og/backends/psql.rb +351 -0
- data/lib/n/og/connection.rb +253 -0
- data/lib/n/og/meta.rb +127 -0
- data/lib/n/properties.rb +6 -6
- data/lib/n/server.rb +4 -7
- data/lib/n/server/appserver.rb +58 -0
- data/lib/n/{app → server}/cluster.rb +3 -3
- data/lib/n/{app → server}/cookie.rb +3 -3
- data/lib/n/server/dispatcher.rb +55 -0
- data/lib/n/server/{filter.rb → filters.rb} +1 -1
- data/lib/n/{app → server}/filters/autologin.rb +5 -5
- data/lib/n/{app → server}/fragment.rb +3 -3
- data/lib/n/{app → server}/handlers.rb +4 -4
- data/lib/n/{app → server}/handlers/code-handler.rb +6 -6
- data/lib/n/{app → server}/handlers/page-handler.rb +9 -7
- data/lib/n/{app → server}/request.rb +8 -8
- data/lib/n/{app/request-part.rb → server/requestpart.rb} +4 -4
- data/lib/n/{app → server}/script.rb +5 -5
- data/lib/n/{app → server}/server.rb +1 -1
- data/lib/n/{app → server}/session.rb +5 -5
- data/lib/n/{app → server}/user.rb +1 -1
- data/lib/n/{app/webrick-servlet.rb → server/webrick.rb} +77 -20
- data/lib/n/shaders.rb +3 -2
- data/lib/n/std.rb +5 -32
- data/test/n/{app → server}/tc_cookie.rb +2 -2
- data/test/n/server/tc_filters.rb +38 -0
- data/test/n/{app → server}/tc_request.rb +6 -6
- data/test/n/{app → server}/tc_requestpart.rb +3 -3
- data/test/n/{app → server}/tc_session.rb +2 -2
- data/test/n/tc_og.rb +178 -0
- data/test/n/ui/tc_pager.rb +3 -3
- metadata +41 -65
- data/examples/ndb/README +0 -5
- data/examples/ndb/run.rb +0 -271
- data/lib/n/app/webrick.rb +0 -73
- data/lib/n/db.rb +0 -233
- data/lib/n/db/README +0 -232
- data/lib/n/db/connection.rb +0 -365
- data/lib/n/db/managed.rb +0 -233
- data/lib/n/db/mixins.rb +0 -279
- data/lib/n/db/mysql.rb +0 -345
- data/lib/n/db/psql.rb +0 -383
- data/lib/n/db/tools.rb +0 -106
- data/lib/n/db/utils.rb +0 -102
- data/lib/n/server/PLAYBACK.txt +0 -8
- data/lib/n/server/RESEARCH.txt +0 -13
- data/test/n/tc_db.rb +0 -223
- data/test/n/tc_db_mysql.rb +0 -241
data/lib/n/db/README
DELETED
@@ -1,232 +0,0 @@
|
|
1
|
-
= n/db README
|
2
|
-
|
3
|
-
== Table of Contents
|
4
|
-
|
5
|
-
1. Introduction
|
6
|
-
2. Features
|
7
|
-
3. Sample Code
|
8
|
-
4. Technical Information
|
9
|
-
5. Links
|
10
|
-
6. Current Version and Status
|
11
|
-
7. Feedback
|
12
|
-
8. Licence
|
13
|
-
|
14
|
-
|
15
|
-
== Introduction
|
16
|
-
|
17
|
-
The aim of this project is to deliver an efficient, yet simple,
|
18
|
-
Object-Relational Mapper Library. The library manages the
|
19
|
-
lifecycle of standard Ruby objects. Unlike similar projects, our
|
20
|
-
approach requires neither xml configuration files (i.e. J2EE), nor
|
21
|
-
SQL definitions (i.e. ActiveRecord).
|
22
|
-
|
23
|
-
By defining the Managed Objects (or Entities) using Ruby, we
|
24
|
-
leverage Ruby's OOP features to allow for OO definitions of DataBase
|
25
|
-
schemas. A simple meta-language is provided to allow fine-tuning
|
26
|
-
of the generated SQL code.
|
27
|
-
|
28
|
-
This library is designed to be integrated in a Web Application
|
29
|
-
Framework. This Framework will be released on a later day.
|
30
|
-
|
31
|
-
|
32
|
-
== Features
|
33
|
-
|
34
|
-
The library provides the following features:
|
35
|
-
|
36
|
-
+ Object-Relational mapping
|
37
|
-
+ Deserialize to Ruby Objects or ResultSets
|
38
|
-
+ Deserialize sql join queries to Ruby Objects
|
39
|
-
+ Serialize arbitrary ruby object graphs through Marshal
|
40
|
-
+ Connection pooling
|
41
|
-
+ Thread safety
|
42
|
-
+ SQL transactions
|
43
|
-
+ Callbacks
|
44
|
-
+ Simple support for cascading deletes
|
45
|
-
+ Hierarchical structures (preorder traversal, materialized paths)
|
46
|
-
+ Works safely as part of distributed application.
|
47
|
-
+ Simple implementation < 10k lines of code.
|
48
|
-
|
49
|
-
== Sample Code
|
50
|
-
|
51
|
-
require "n/db"
|
52
|
-
|
53
|
-
# initialize the DB interface
|
54
|
-
$db = N::Db.new(
|
55
|
-
:address => "localhost",
|
56
|
-
:database => "test",
|
57
|
-
:user => "postgres",
|
58
|
-
:password => "mypassword",
|
59
|
-
:connection_count => 20
|
60
|
-
)
|
61
|
-
|
62
|
-
# create a managed object
|
63
|
-
|
64
|
-
class MyObject
|
65
|
-
include N::Entity
|
66
|
-
manage {
|
67
|
-
prop String, :name
|
68
|
-
prop [Fixnum, "smallint default 1"], :level; sql_index :level
|
69
|
-
}
|
70
|
-
# non serialized attributes
|
71
|
-
attr_accessor value
|
72
|
-
end
|
73
|
-
|
74
|
-
class AnotherObject < MyObject
|
75
|
-
manage {
|
76
|
-
prop Time, :create_time
|
77
|
-
}
|
78
|
-
|
79
|
-
def initialize
|
80
|
-
@create_time = Time.now
|
81
|
-
super
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
obj = AnotherObject.new
|
86
|
-
obj.name = "gmosx"
|
87
|
-
|
88
|
-
# insert into db
|
89
|
-
$db << obj
|
90
|
-
|
91
|
-
obj.name = "drak"
|
92
|
-
|
93
|
-
# update
|
94
|
-
$db << obj
|
95
|
-
|
96
|
-
# get object id allocated when inserting
|
97
|
-
oid = obj.oid
|
98
|
-
|
99
|
-
# lookup
|
100
|
-
obj = $db.get(oid, AnotherObject)
|
101
|
-
|
102
|
-
# multiple commands
|
103
|
-
|
104
|
-
$db.open { |db|
|
105
|
-
obj = db.get(oid, AnotherObject)
|
106
|
-
db.delete(obj)
|
107
|
-
db.select("SELECT * FROM #{AnotherObject::DBTABLE} WHERE oid=1")
|
108
|
-
}
|
109
|
-
|
110
|
-
# graph like objects
|
111
|
-
|
112
|
-
class Child
|
113
|
-
include N::Entity
|
114
|
-
include N::Child
|
115
|
-
manage {
|
116
|
-
prop Time, :create_time
|
117
|
-
}
|
118
|
-
end
|
119
|
-
|
120
|
-
child = Child.new
|
121
|
-
child.set_parent(obj)
|
122
|
-
|
123
|
-
$db << child
|
124
|
-
|
125
|
-
# get children of class Child
|
126
|
-
|
127
|
-
$db.children(obj, Child, "ORDER BY create_time")
|
128
|
-
|
129
|
-
# sql transactions
|
130
|
-
|
131
|
-
$db.transaction {
|
132
|
-
...
|
133
|
-
}
|
134
|
-
|
135
|
-
# Lets say you have changed the definition of a managed object
|
136
|
-
# (for example you have added a new prop_accessor, and want to
|
137
|
-
# automatically update the database schema:
|
138
|
-
#
|
139
|
-
|
140
|
-
$db.alter_table(MyObject)
|
141
|
-
|
142
|
-
|
143
|
-
== Technical Information
|
144
|
-
|
145
|
-
=== Installation
|
146
|
-
|
147
|
-
Just uncompress the distribution and add the 'n' directory to
|
148
|
-
the Ruby path.
|
149
|
-
|
150
|
-
tar xvfz ndb-x.x.tar.gz
|
151
|
-
cd ndb
|
152
|
-
ruby n/.tc-db.rb
|
153
|
-
|
154
|
-
=== How the package is organized:
|
155
|
-
|
156
|
-
n/db.rb:
|
157
|
-
The main n/db file.
|
158
|
-
|
159
|
-
n/db/*:
|
160
|
-
The db related files.
|
161
|
-
|
162
|
-
n/utils/*:
|
163
|
-
Various utility files.
|
164
|
-
|
165
|
-
=== Testing:
|
166
|
-
|
167
|
-
Unit Test files start with the .tc- prefix, i.e. they are hidden
|
168
|
-
by default (Unix). You can run the db test unit as follows:
|
169
|
-
|
170
|
-
ruby n/.tc-db.rb
|
171
|
-
|
172
|
-
Before running this test unit, make sure tha the postgreSQL server
|
173
|
-
is running, and the 'test' database is created.
|
174
|
-
|
175
|
-
|
176
|
-
== Links
|
177
|
-
|
178
|
-
* http://www.navel.gr, Navel
|
179
|
-
* http://www.navel.gr/open-source, Project Home Page
|
180
|
-
|
181
|
-
|
182
|
-
== Current Version and Status
|
183
|
-
|
184
|
-
Version 0.3 was released on 15-10-2004. The source is cleaned up and
|
185
|
-
the API refined. Added preliminary support for multiple backends (the
|
186
|
-
included MySQL backend is not completed). Added support for
|
187
|
-
marshaled fields. Available as a RubyGem too.
|
188
|
-
|
189
|
-
Version 0.2 was released on 07-10-2004. The sofware is actually usable
|
190
|
-
but not tested in a production environment. Comments from the Ruby
|
191
|
-
community are critical in order to fix possible bugs and improve the
|
192
|
-
API. Suggestions for missing features are also welcome. This version
|
193
|
-
only supports the Postgres Database.
|
194
|
-
|
195
|
-
=== Contributors
|
196
|
-
|
197
|
-
* George Moschovitis <gm@navel.gr>: design, lead developer.
|
198
|
-
|
199
|
-
=== Future
|
200
|
-
|
201
|
-
* Support multiple DataBase backends (Postgres, MySQL, ...)
|
202
|
-
* Support prepared statements (pgsql)
|
203
|
-
* Support stored procedures (pgsql)
|
204
|
-
* Support caching
|
205
|
-
* Deserialize to OpenStruct
|
206
|
-
* Better documentation
|
207
|
-
* Code cleanup, refactoring
|
208
|
-
* Release as Gem, RPAbase
|
209
|
-
|
210
|
-
|
211
|
-
== Feedback
|
212
|
-
|
213
|
-
If you would like to report a bug, suggest a method for inclusion, or make
|
214
|
-
some other suggestion (documentation, package layout, etc.), please send
|
215
|
-
an email to ndb-feedback@navel.gr
|
216
|
-
|
217
|
-
|
218
|
-
== Licence
|
219
|
-
|
220
|
-
Copyright (c) 2004 Navel, all rights reserved. http://www.navel.gr
|
221
|
-
|
222
|
-
n/db (http://www.navel.gr/open-source) is copyrighted free software
|
223
|
-
created and maintained by George Moschovitis (mailto:gm@navel.gr)
|
224
|
-
and released under the same license as Ruby.
|
225
|
-
|
226
|
-
Standard disclaimer:
|
227
|
-
|
228
|
-
THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
229
|
-
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
230
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
231
|
-
PURPOSE.
|
232
|
-
|
data/lib/n/db/connection.rb
DELETED
@@ -1,365 +0,0 @@
|
|
1
|
-
# code:
|
2
|
-
# * George Moschovitis <gm@navel.gr>
|
3
|
-
#
|
4
|
-
# (c) 2004 Navel, all rights reserved.
|
5
|
-
# $Id: connection.rb 99 2004-10-22 09:50:28Z gmosx $
|
6
|
-
|
7
|
-
module N;
|
8
|
-
|
9
|
-
require "n/properties"
|
10
|
-
require "n/utils/array"
|
11
|
-
require "n/utils/time"
|
12
|
-
|
13
|
-
# = DbConnection
|
14
|
-
#
|
15
|
-
# A Connection to the Database.
|
16
|
-
#
|
17
|
-
# === design
|
18
|
-
#
|
19
|
-
# try to make the methods to work with oids.
|
20
|
-
# do not implement descendants, use a root id (rid).
|
21
|
-
#
|
22
|
-
# === todo
|
23
|
-
#
|
24
|
-
# - support caching
|
25
|
-
# - support prepared statements
|
26
|
-
# - foreign keys (delete cascade)
|
27
|
-
# - keep attribudes as marshaled!!
|
28
|
-
#
|
29
|
-
# === investigate
|
30
|
-
#
|
31
|
-
# - should we use retry_query ?
|
32
|
-
#
|
33
|
-
class DbConnection
|
34
|
-
include N::DbUtils
|
35
|
-
|
36
|
-
# the actual connection to the database.
|
37
|
-
attr_reader :rdb
|
38
|
-
|
39
|
-
# If set to true, the select methods deserialize the rows to
|
40
|
-
# create entities.
|
41
|
-
attr_accessor :deserialize
|
42
|
-
|
43
|
-
# Initializate a connection to the database.
|
44
|
-
#
|
45
|
-
def initialize(config)
|
46
|
-
super
|
47
|
-
@deserialize = true
|
48
|
-
$log.debug "Created connection."
|
49
|
-
end
|
50
|
-
|
51
|
-
# Close the connection to the database.
|
52
|
-
#
|
53
|
-
def close()
|
54
|
-
super
|
55
|
-
$log.debug "Closed connection."
|
56
|
-
end
|
57
|
-
|
58
|
-
# --------------------------------------------------------------------
|
59
|
-
# Basic methods
|
60
|
-
|
61
|
-
# Put an entity to the database. Insert if this is a new entity or
|
62
|
-
# update if this is an existing entity.
|
63
|
-
#
|
64
|
-
def put(entity)
|
65
|
-
if entity.oid
|
66
|
-
# entity allready inserted, update!
|
67
|
-
entity.__db_update(self)
|
68
|
-
else
|
69
|
-
# this is a new entity, insert!
|
70
|
-
entity.__db_insert(self)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
alias_method :<<, :put
|
74
|
-
|
75
|
-
# Force insertion of managed object.
|
76
|
-
# Typically used for NON-entities.
|
77
|
-
#
|
78
|
-
def insert(obj)
|
79
|
-
obj.__db_insert(self)
|
80
|
-
end
|
81
|
-
|
82
|
-
# Force update of managed object.
|
83
|
-
# Typically used for relations.
|
84
|
-
#
|
85
|
-
def update(obj)
|
86
|
-
obj.__db_update(self)
|
87
|
-
end
|
88
|
-
|
89
|
-
# Update only specific fields of the entity
|
90
|
-
#
|
91
|
-
# Input:
|
92
|
-
# sql = the sql code to updated the properties.
|
93
|
-
#
|
94
|
-
def update_properties(update_sql, ent_or_oid, klass = nil)
|
95
|
-
oid = ent_or_oid.to_i()
|
96
|
-
klass = ent_or_oid.class unless klass
|
97
|
-
|
98
|
-
sql = "UPDATE #{klass::DBTABLE} SET #{update_sql} WHERE oid=#{oid}"
|
99
|
-
retry_query(sql, klass)
|
100
|
-
end
|
101
|
-
alias_method :pupdate, :update_properties
|
102
|
-
|
103
|
-
# Get an entity from the database.
|
104
|
-
#
|
105
|
-
# COOL: klass can be the class to fetch or the DBTABLE of the class.
|
106
|
-
# thanks to duck typing it works correctly!
|
107
|
-
#
|
108
|
-
# Input:
|
109
|
-
# oid = the entity oid, OR the entity name.
|
110
|
-
#
|
111
|
-
def get(oid, klass)
|
112
|
-
if oid.to_i > 0 # a valid Fixnum ?
|
113
|
-
get_by_oid(oid, klass)
|
114
|
-
else
|
115
|
-
get_by_name(oid, klass)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# Get an entity by oid.
|
120
|
-
#
|
121
|
-
# COOL: klass can be the class to fetch or the DBTABLE of the class.
|
122
|
-
# thanks to duck typing it works correctly!
|
123
|
-
#
|
124
|
-
def get_by_oid(oid, klass)
|
125
|
-
rows = safe_query("SELECT * FROM #{DbUtils.sql_table(klass)} WHERE oid=#{oid}")
|
126
|
-
return deserialize_one(rows, klass)
|
127
|
-
end
|
128
|
-
|
129
|
-
# Get an entity by name.
|
130
|
-
#
|
131
|
-
# COOL: klass can be the class to fetch or the DBTABLE of the class.
|
132
|
-
# thanks to duck typing it works correctly!
|
133
|
-
#
|
134
|
-
def get_by_name(name, klass)
|
135
|
-
rows = safe_query("SELECT * FROM #{DbUtils.sql_table(klass)} WHERE name='#{name}'")
|
136
|
-
return deserialize_one(rows, klass)
|
137
|
-
end
|
138
|
-
|
139
|
-
# Get all entities of the given klass.
|
140
|
-
#
|
141
|
-
# COOL: klass can be the class to fetch or the DBTABLE of the class.
|
142
|
-
# thanks to duck typing it works correctly!
|
143
|
-
#
|
144
|
-
# Used to be called 'collect' in an earlier version.
|
145
|
-
#
|
146
|
-
def get_all(klass, extrasql = nil)
|
147
|
-
rows = safe_query("SELECT * FROM #{DbUtils.sql_table(klass)} #{extrasql}")
|
148
|
-
return deserialize_all(rows, klass)
|
149
|
-
end
|
150
|
-
|
151
|
-
# Delete an entity from the database. Allways perform a deep delete.
|
152
|
-
#
|
153
|
-
# DONT use ::DBTABLE (allow classes as table names).
|
154
|
-
#
|
155
|
-
# Input:
|
156
|
-
#
|
157
|
-
# entity = Entity or oid to delete.
|
158
|
-
# klass = klass of entity (can be nil if an entity is passed)
|
159
|
-
#
|
160
|
-
def delete(entity, klass = nil, cascade = true)
|
161
|
-
if entity.is_a?(Fixnum)
|
162
|
-
oid = entity
|
163
|
-
entity = klass.new
|
164
|
-
entity.oid = oid
|
165
|
-
end
|
166
|
-
|
167
|
-
transaction {
|
168
|
-
entity.__db_pre_delete(self)
|
169
|
-
exec_clear("DELETE FROM #{DbUtils.sql_table(entity.class)} WHERE oid=#{entity.oid}")
|
170
|
-
}
|
171
|
-
end
|
172
|
-
alias_method :delete!, :delete
|
173
|
-
|
174
|
-
# Recursively delete all descendants of this entity.
|
175
|
-
# Operates in a transaction.
|
176
|
-
#
|
177
|
-
def delete_descendants(pid, pclass)
|
178
|
-
return unless pclass.respond_to?(:__descendants_classes)
|
179
|
-
|
180
|
-
for dclass in pclass.__descendants_classes
|
181
|
-
if dclass.include?(N::ParentClass)
|
182
|
-
rs = exec("SELECT oid FROM #{dclass::DBTABLE} WHERE pid=#{pid} AND pclass='#{pclass}'")
|
183
|
-
exec_clear("DELETE FROM #{dclass::DBTABLE} where pid=#{pid} AND pclass='#{pclass}'")
|
184
|
-
else
|
185
|
-
rs = exec("SELECT oid FROM #{dclass::DBTABLE} WHERE pid=#{pid}")
|
186
|
-
exec_clear("DELETE FROM #{dclass::DBTABLE} where pid=#{pid}")
|
187
|
-
end
|
188
|
-
|
189
|
-
for tuple in (0...rs.num_tuples)
|
190
|
-
delete_descendants(rs.getvalue(tuple, 0), dclass)
|
191
|
-
end
|
192
|
-
|
193
|
-
rs.clear()
|
194
|
-
end
|
195
|
-
end
|
196
|
-
alias_method :delete_descendants!, :delete_descendants
|
197
|
-
|
198
|
-
# --------------------------------------------------------------------
|
199
|
-
# Graph methods
|
200
|
-
|
201
|
-
# = child
|
202
|
-
#
|
203
|
-
# Return one children of the parent
|
204
|
-
#
|
205
|
-
def child(entity, klass, extrasql = nil)
|
206
|
-
pid = entity.to_i()
|
207
|
-
|
208
|
-
sql = "SELECT * FROM #{klass::DBTABLE}"
|
209
|
-
sql << " WHERE pid=#{pid}" if pid > 0
|
210
|
-
sql << " #{extrasql}" if extrasql
|
211
|
-
|
212
|
-
rows = safe_query(sql)
|
213
|
-
|
214
|
-
return deserialize_one(rows, klass)
|
215
|
-
end
|
216
|
-
|
217
|
-
# = children
|
218
|
-
#
|
219
|
-
# entity = entity or oid.
|
220
|
-
# klass = the class of the children to return.
|
221
|
-
# extrasql = extra sql for limit/order etc.
|
222
|
-
#
|
223
|
-
# === Design:
|
224
|
-
#
|
225
|
-
# If the calculated pid is 0 returns all entities
|
226
|
-
# of the given class. It works like the older collect method.
|
227
|
-
# This make sense, the root of all objects has an oid = 0.
|
228
|
-
# INVESTIGATE: is this a security problem?
|
229
|
-
#
|
230
|
-
# only_oids is not needed use the limit modifiers instead.
|
231
|
-
# if you need oids, use specialized sql. You can use the
|
232
|
-
# extrasql parameter to change the where clause too.
|
233
|
-
#
|
234
|
-
def children(entity, klass, extrasql = nil)
|
235
|
-
pid = entity.to_i()
|
236
|
-
|
237
|
-
sql = "SELECT * FROM #{klass::DBTABLE}"
|
238
|
-
sql << " WHERE pid=#{pid}" if pid > 0
|
239
|
-
sql << " #{extrasql}" if extrasql
|
240
|
-
|
241
|
-
rows = safe_query(sql)
|
242
|
-
|
243
|
-
return deserialize_all(rows, klass)
|
244
|
-
end
|
245
|
-
|
246
|
-
# = count_children
|
247
|
-
#
|
248
|
-
# Use extrasql to change the where clause.
|
249
|
-
#
|
250
|
-
def count_children(entity, klass, extasql = nil)
|
251
|
-
pid = entity.to_i()
|
252
|
-
|
253
|
-
sql = "SELECT COUNT(pid) FROM #{klass::DBTABLE}"
|
254
|
-
sql << " WHERE pid=#{pid}" if pid > 0
|
255
|
-
|
256
|
-
if rows = safe_query(sql)
|
257
|
-
return rows[0][0].to_i()
|
258
|
-
end
|
259
|
-
|
260
|
-
return 0
|
261
|
-
end
|
262
|
-
|
263
|
-
# --------------------------------------------------------------------
|
264
|
-
# Transaction methods.
|
265
|
-
|
266
|
-
def start
|
267
|
-
exec_clear("START TRANSACTION")
|
268
|
-
end
|
269
|
-
|
270
|
-
def commit
|
271
|
-
exec_clear("COMMIT")
|
272
|
-
end
|
273
|
-
|
274
|
-
def rollback
|
275
|
-
exec_clear("ROLLBACK")
|
276
|
-
end
|
277
|
-
|
278
|
-
# Transaction helper
|
279
|
-
#
|
280
|
-
def transaction(&block)
|
281
|
-
begin
|
282
|
-
exec_clear("START TRANSACTION")
|
283
|
-
yield
|
284
|
-
exec_clear("COMMIT")
|
285
|
-
rescue => ex
|
286
|
-
$log.error "DB Error: ERROR IN TRANSACTION"
|
287
|
-
$log.error "DB Error: #{ex}, #{caller[0]} : #{caller[1]} : #{caller[2]}"
|
288
|
-
exec_clear("ROLLBACK")
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
# Useful in transactions
|
293
|
-
#
|
294
|
-
def exec(sql)
|
295
|
-
@rdb.exec(sql)
|
296
|
-
end
|
297
|
-
|
298
|
-
# Useful in transactions
|
299
|
-
# Exec an sql command and clear the resultset.
|
300
|
-
#
|
301
|
-
def exec_and_clear(sql)
|
302
|
-
rows = @rdb.exec(sql)
|
303
|
-
rows.clear()
|
304
|
-
end
|
305
|
-
alias_method :exec_clear, :exec_and_clear
|
306
|
-
|
307
|
-
# --------------------------------------------------------------------
|
308
|
-
# Standard SQL methods.
|
309
|
-
|
310
|
-
# Perform a standard SQL query to the database. Deserializes the
|
311
|
-
# results.
|
312
|
-
#
|
313
|
-
def select(sql, klass, join_fields = nil)
|
314
|
-
rows = safe_query(sql)
|
315
|
-
return deserialize_all(rows, klass, join_fields)
|
316
|
-
end
|
317
|
-
|
318
|
-
# Optimized for one result.
|
319
|
-
#
|
320
|
-
def select_one(sql, klass, join_fields = nil)
|
321
|
-
rows = safe_query(sql)
|
322
|
-
return deserialize_one(rows, klass, join_fields)
|
323
|
-
end
|
324
|
-
|
325
|
-
# Perform a standard SQL query to the database. Returns the result
|
326
|
-
# rows.
|
327
|
-
#
|
328
|
-
def query(sql)
|
329
|
-
return safe_query(sql)
|
330
|
-
end
|
331
|
-
alias_method :sql, :query
|
332
|
-
|
333
|
-
# Perform a standard SQL query to the database. Used for queries that
|
334
|
-
# return one row (typically with values) ie COUNT, etc.
|
335
|
-
#
|
336
|
-
def query_one(sql)
|
337
|
-
if rows = safe_query(sql)
|
338
|
-
return rows[0]
|
339
|
-
else
|
340
|
-
return nil
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
# Count the entities returned by the sql statement.
|
345
|
-
#
|
346
|
-
def count(sql)
|
347
|
-
if rows = safe_query(sql)
|
348
|
-
return rows[0][0].to_i()
|
349
|
-
end
|
350
|
-
|
351
|
-
return 0
|
352
|
-
end
|
353
|
-
|
354
|
-
# Match a query, return true if a resultset was found
|
355
|
-
#
|
356
|
-
def match(sql)
|
357
|
-
res = safe_query(sql)
|
358
|
-
return true if res and (res.num_tuples > 0)
|
359
|
-
end
|
360
|
-
alias_method :match?, :match
|
361
|
-
|
362
|
-
end
|
363
|
-
|
364
|
-
end # module
|
365
|
-
|