webmcp
diff libraries/mondelefant/mondelefant.lua @ 23:3a6fe8663b26
Code cleanup and documentation added; Year in copyright notice changed to 2009-2010
Details:
- Changed quoting style in auth.openid.xrds_document{...}
- Fixed documentation for auth.openid.initiate{...}
- Added documentation for mondelefant
- Code-cleanup in mondelefant:
-- removed unneccessary lines "rows = PQntuples(res); cols = PQnfields(res);"
-- avoided extra copy of first argument (self) in mondelefant_conn_query
-- no rawget in meta-method "__index" of database result lists and objects
-- removed unreachable "return 0;" in meta-method "__newindex" of database result lists and objects
- Year in copyright notice changed to 2009-2010
- Version string changed to "1.1.1"
Details:
- Changed quoting style in auth.openid.xrds_document{...}
- Fixed documentation for auth.openid.initiate{...}
- Added documentation for mondelefant
- Code-cleanup in mondelefant:
-- removed unneccessary lines "rows = PQntuples(res); cols = PQnfields(res);"
-- avoided extra copy of first argument (self) in mondelefant_conn_query
-- no rawget in meta-method "__index" of database result lists and objects
-- removed unreachable "return 0;" in meta-method "__newindex" of database result lists and objects
- Year in copyright notice changed to 2009-2010
- Version string changed to "1.1.1"
| author | jbe | 
|---|---|
| date | Fri Jun 04 19:00:34 2010 +0200 (2010-06-04) | 
| parents | 5cba83b3f411 | 
| children | a02c25eb3517 | 
   line diff
1.1 --- a/libraries/mondelefant/mondelefant.lua Thu Apr 22 20:46:29 2010 +0200 1.2 +++ b/libraries/mondelefant/mondelefant.lua Fri Jun 04 19:00:34 2010 +0200 1.3 @@ -76,31 +76,79 @@ 1.4 return self 1.5 end 1.6 1.7 +--[[-- 1.8 +selector = -- new selector 1.9 +<db_handle>:new_selector() 1.10 + 1.11 +Creates a new selector to operate on the given database handle. 1.12 +--]]-- 1.13 function connection_prototype:new_selector() 1.14 return init_selector(setmetatable({}, selector_metatable), self) 1.15 end 1.16 +--//-- 1.17 1.18 +--[[-- 1.19 +db_handle = -- handle of database connection 1.20 +<db_selector>:get_db_conn() 1.21 + 1.22 +Returns the database connection handle used by a selector. 1.23 + 1.24 +--]]-- 1.25 function selector_prototype:get_db_conn() 1.26 return self._db_conn 1.27 end 1.28 +--//-- 1.29 1.30 -- TODO: selector clone? 1.31 1.32 +--[[-- 1.33 +db_selector = -- same selector returned 1.34 +<db_selector>:single_object_mode() 1.35 + 1.36 +Sets selector to single object mode (mode "object" passed to "query" method of database handle). The selector is modified and returned. 1.37 + 1.38 +--]]-- 1.39 function selector_prototype:single_object_mode() 1.40 self._mode = "object" 1.41 return self 1.42 end 1.43 +--//-- 1.44 1.45 +--[[-- 1.46 +db_selector = -- same selector returned 1.47 +<db_selector>:optional_object_mode() 1.48 + 1.49 +Sets selector to single object mode (mode "opt_object" passed to "query" method of database handle). The selector is modified and returned. 1.50 + 1.51 +--]]-- 1.52 function selector_prototype:optional_object_mode() 1.53 self._mode = "opt_object" 1.54 return self 1.55 end 1.56 +--//-- 1.57 1.58 +--[[-- 1.59 +db_selector = -- same selector returned 1.60 +<db_selector>:empty_list_mode() 1.61 + 1.62 +Sets selector to empty list mode. The selector is modified and returned. When using the selector, no SQL query will be issued, but instead an empty database result list is returned. 1.63 + 1.64 +--]]-- 1.65 function selector_prototype:empty_list_mode() 1.66 self._mode = "empty_list" 1.67 return self 1.68 end 1.69 +--//-- 1.70 1.71 +--[[-- 1.72 +db_selector = -- same selector returned 1.73 +<db_selector>:add_distinct_on( 1.74 + expression -- expression as passed to "assemble_command" 1.75 +) 1.76 + 1.77 +Adds an DISTINCT ON expression to the selector. The selector is modified and returned. 1.78 + 1.79 +--]]-- 1.80 function selector_prototype:add_distinct_on(expression) 1.81 if self._distinct then 1.82 error("Can not combine DISTINCT with DISTINCT ON.") 1.83 @@ -108,7 +156,15 @@ 1.84 add(self._distinct_on, expression) 1.85 return self 1.86 end 1.87 +--//-- 1.88 1.89 +--[[-- 1.90 +db_selector = -- same selector returned 1.91 +<db_selector>:set_distinct() 1.92 + 1.93 +Sets selector to perform a SELECT DISTINCT instead of SELECT (ALL). The selector is modified and returned. This mode can not be combined with DISTINCT ON. 1.94 + 1.95 +--]]-- 1.96 function selector_prototype:set_distinct() 1.97 if #self._distinct_on > 0 then 1.98 error("Can not combine DISTINCT with DISTINCT ON.") 1.99 @@ -116,7 +172,21 @@ 1.100 self._distinct = true 1.101 return self 1.102 end 1.103 +--//-- 1.104 1.105 +--[[-- 1.106 +db_selector = -- same selector returned 1.107 +<db_selector>:add_from( 1.108 + expression, -- expression as passed to "assemble_command" 1.109 + alias, -- optional alias expression as passed to "assemble_command" 1.110 + condition -- optional condition expression as passed to "assemble_command" 1.111 +) 1.112 + 1.113 +Adds expressions for FROM clause to the selector. The selector is modified and returned. If an additional condition is given, an INNER JOIN will be used, otherwise a CROSS JOIN. 1.114 + 1.115 +This method is identical to "join". 1.116 + 1.117 +--]]-- 1.118 function selector_prototype:add_from(expression, alias, condition) 1.119 local first = (#self._from == 0) 1.120 if not first then 1.121 @@ -149,32 +219,92 @@ 1.122 end 1.123 return self 1.124 end 1.125 +--//-- 1.126 1.127 +--[[-- 1.128 +db_selector = -- same selector returned 1.129 +<db_selector>:add_where( 1.130 + expression -- expression as passed to "assemble_command" 1.131 +) 1.132 + 1.133 +Adds expressions for WHERE clause to the selector. The selector is modified and returned. Multiple calls cause expressions to be AND-combined. 1.134 + 1.135 +--]]-- 1.136 function selector_prototype:add_where(expression) 1.137 add(self._where, expression) 1.138 return self 1.139 end 1.140 +--//-- 1.141 1.142 +--[[-- 1.143 +db_selector = -- same selector returned 1.144 +<db_selector>:add_group_by( 1.145 + expression -- expression as passed to "assemble_command" 1.146 +) 1.147 + 1.148 +Adds expressions for GROUP BY clause to the selector. The selector is modified and returned. 1.149 + 1.150 +--]]-- 1.151 function selector_prototype:add_group_by(expression) 1.152 add(self._group_by, expression) 1.153 return self 1.154 end 1.155 +--//-- 1.156 1.157 +--[[-- 1.158 +db_selector = -- same selector returned 1.159 +<db_selector>:add_having( 1.160 + expression -- expression as passed to "assemble_command" 1.161 +) 1.162 + 1.163 +Adds expressions for HAVING clause to the selector. The selector is modified and returned. Multiple calls cause expressions to be AND-combined. 1.164 + 1.165 +--]]-- 1.166 function selector_prototype:add_having(expression) 1.167 add(self._having, expression) 1.168 return self 1.169 end 1.170 +--//-- 1.171 1.172 +--[[-- 1.173 +db_selector = -- same selector returned 1.174 +<db_selector>:add_combine( 1.175 + expression -- expression as passed to "assemble_command" 1.176 +) 1.177 + 1.178 +This function is used for UNION/INTERSECT/EXCEPT clauses. It does not need to be called directly. Use "union", "union_all", "intersect", "intersect_all", "except" and "except_all" instead. 1.179 + 1.180 +--]]-- 1.181 function selector_prototype:add_combine(expression) 1.182 add(self._combine, expression) 1.183 return self 1.184 end 1.185 +--//-- 1.186 1.187 +--[[-- 1.188 +db_selector = -- same selector returned 1.189 +<db_selector>:add_order_by( 1.190 + expression -- expression as passed to "assemble_command" 1.191 +) 1.192 + 1.193 +Adds expressions for ORDER BY clause to the selector. The selector is modified and returned. 1.194 + 1.195 +--]]-- 1.196 function selector_prototype:add_order_by(expression) 1.197 add(self._order_by, expression) 1.198 return self 1.199 end 1.200 +--//-- 1.201 1.202 +--[[-- 1.203 +db_selector = -- same selector returned 1.204 +<db_selector>:limit( 1.205 + count -- integer used as LIMIT 1.206 +) 1.207 + 1.208 +Limits the number of rows to a given number, by using LIMIT. The selector is modified and returned. 1.209 + 1.210 +--]]-- 1.211 function selector_prototype:limit(count) 1.212 if type(count) ~= "number" or count % 1 ~= 0 then 1.213 error("LIMIT must be an integer.") 1.214 @@ -182,7 +312,17 @@ 1.215 self._limit = count 1.216 return self 1.217 end 1.218 +--//-- 1.219 1.220 +--[[-- 1.221 +db_selector = -- same selector returned 1.222 +<db_selector>:offset( 1.223 + count -- integer used as OFFSET 1.224 +) 1.225 + 1.226 +Skips a given number of rows, by using OFFSET. The selector is modified and returned. 1.227 + 1.228 +--]]-- 1.229 function selector_prototype:offset(count) 1.230 if type(count) ~= "number" or count % 1 ~= 0 then 1.231 error("OFFSET must be an integer.") 1.232 @@ -190,34 +330,90 @@ 1.233 self._offset = count 1.234 return self 1.235 end 1.236 +--//-- 1.237 1.238 +--[[-- 1.239 +db_selector = -- same selector returned 1.240 +<db_selector>:for_share() 1.241 + 1.242 +Adds FOR SHARE to the statement, to share-lock all rows read. The selector is modified and returned. 1.243 + 1.244 +--]]-- 1.245 function selector_prototype:for_share() 1.246 self._read_lock.all = true 1.247 return self 1.248 end 1.249 +--//-- 1.250 1.251 +--[[-- 1.252 +db_selector = -- same selector returned 1.253 +<db_selector>:for_share_of( 1.254 + expression -- expression as passed to "assemble_command" 1.255 +) 1.256 + 1.257 +Adds FOR SHARE OF to the statement, to share-lock all rows read by the named table(s). The selector is modified and returned. 1.258 + 1.259 +--]]-- 1.260 function selector_prototype:for_share_of(expression) 1.261 add(self._read_lock, expression) 1.262 return self 1.263 end 1.264 +--//-- 1.265 1.266 +--[[-- 1.267 +db_selector = -- same selector returned 1.268 +<db_selector>:for_update() 1.269 + 1.270 +Adds FOR UPDATE to the statement, to exclusivly lock all rows read. The selector is modified and returned. 1.271 + 1.272 +--]]-- 1.273 function selector_prototype:for_update() 1.274 self._write_lock.all = true 1.275 return self 1.276 end 1.277 +--//-- 1.278 1.279 +--[[-- 1.280 +db_selector = -- same selector returned 1.281 +<db_selector>:for_update_of( 1.282 + expression -- expression as passed to "assemble_command" 1.283 +) 1.284 + 1.285 +Adds FOR SHARE OF to the statement, to exclusivly lock all rows read by the named table(s). The selector is modified and returned. 1.286 + 1.287 +--]]-- 1.288 function selector_prototype:for_update_of(expression) 1.289 add(self._write_lock, expression) 1.290 return self 1.291 end 1.292 +--//-- 1.293 1.294 +--[[-- 1.295 +db_selector = -- same selector returned 1.296 +<db_selector>:reset_fields() 1.297 + 1.298 +This method removes all fields added by method "add_field". The selector is modified and returned. 1.299 + 1.300 +--]]-- 1.301 function selector_prototype:reset_fields() 1.302 for idx in ipairs(self._fields) do 1.303 self._fields[idx] = nil 1.304 end 1.305 return self 1.306 end 1.307 +--//-- 1.308 1.309 +--[[-- 1.310 +db_selector = -- same selector returned 1.311 +<db_selector>:add_field( 1.312 + expression, -- expression as passed to "assemble_command" 1.313 + alias, -- optional alias expression as passed to "assemble_command" 1.314 + option_list -- optional list of options (may contain strings "distinct" or "grouped") 1.315 +) 1.316 + 1.317 +Adds fields to the selector. The selector is modified and returned. The third argument can be a list of options. If option "distinct" is given, then "add_distinct_on" will be executed for the given field or alias. If option "grouped" is given, then "add_group_by" will be executed for the given field or alias. 1.318 + 1.319 +--]]-- 1.320 function selector_prototype:add_field(expression, alias, options) 1.321 if alias then 1.322 add(self._fields, {'$ AS "$"', {expression}, {alias}}) 1.323 @@ -245,18 +441,58 @@ 1.324 end 1.325 return self 1.326 end 1.327 +--//-- 1.328 1.329 +--[[-- 1.330 +db_selector = -- same selector returned 1.331 +<db_selector>:join( 1.332 + expression, -- expression as passed to "assemble_command" 1.333 + alias, -- optional alias expression as passed to "assemble_command" 1.334 + condition -- optional condition expression as passed to "assemble_command" 1.335 +) 1.336 + 1.337 +Adds expressions for FROM clause to the selector. The selector is modified and returned. If an additional condition is given, an INNER JOIN will be used, otherwise a CROSS JOIN. 1.338 + 1.339 +This method is identical to "add_from". 1.340 + 1.341 +--]]-- 1.342 function selector_prototype:join(...) -- NOTE: alias for add_from 1.343 return self:add_from(...) 1.344 end 1.345 +--//-- 1.346 1.347 +--[[-- 1.348 +db_selector = -- same selector returned 1.349 +<db_selector>:from( 1.350 + expression, -- expression as passed to "assemble_command" 1.351 + alias, -- optional alias expression as passed to "assemble_command" 1.352 + condition -- optional condition expression as passed to "assemble_command" 1.353 +) 1.354 + 1.355 +Adds the first expression for FROM clause to the selector. The selector is modified and returned. If an additional condition is given, an INNER JOIN will be used, otherwise a CROSS JOIN. 1.356 + 1.357 +This method is identical to "add_from" or "join", except that an error is thrown, if there is already any FROM expression existent. 1.358 + 1.359 +--]]-- 1.360 function selector_prototype:from(expression, alias, condition) 1.361 if #self._from > 0 then 1.362 error("From-clause already existing (hint: try join).") 1.363 end 1.364 return self:join(expression, alias, condition) 1.365 end 1.366 +--//-- 1.367 1.368 +--[[-- 1.369 +db_selector = -- same selector returned 1.370 +<db_selector>:left_join( 1.371 + expression, -- expression as passed to "assemble_command" 1.372 + alias, -- optional alias expression as passed to "assemble_command" 1.373 + condition -- optional condition expression as passed to "assemble_command" 1.374 +) 1.375 + 1.376 +Adds expressions for FROM clause to the selector using a LEFT OUTER JOIN. The selector is modified and returned. 1.377 + 1.378 +--]]-- 1.379 function selector_prototype:left_join(expression, alias, condition) 1.380 local first = (#self._from == 0) 1.381 if not first then 1.382 @@ -277,42 +513,127 @@ 1.383 end 1.384 return self 1.385 end 1.386 +--//-- 1.387 1.388 +--[[-- 1.389 +db_selector = -- same selector returned 1.390 +<db_selector>:union( 1.391 + expression -- expression or selector without ORDER BY, LIMIT, FOR UPDATE or FOR SHARE 1.392 +) 1.393 + 1.394 +This method adds an UNION clause to the given selector. The selector is modified and returned. The selector (or expression) passed as argument to this function shall not contain any ORDER BY, LIMIT, FOR UPDATE or FOR SHARE clauses. 1.395 + 1.396 +--]]-- 1.397 function selector_prototype:union(expression) 1.398 self:add_combine{"UNION $", {expression}} 1.399 return self 1.400 end 1.401 +--//-- 1.402 1.403 +--[[-- 1.404 +db_selector = -- same selector returned 1.405 +<db_selector>:union_all( 1.406 + expression -- expression or selector without ORDER BY, LIMIT, FOR UPDATE or FOR SHARE 1.407 +) 1.408 + 1.409 +This method adds an UNION ALL clause to the given selector. The selector is modified and returned. The selector (or expression) passed as argument to this function shall not contain any ORDER BY, LIMIT, FOR UPDATE or FOR SHARE clauses. 1.410 + 1.411 +--]]-- 1.412 function selector_prototype:union_all(expression) 1.413 self:add_combine{"UNION ALL $", {expression}} 1.414 return self 1.415 end 1.416 +--//-- 1.417 1.418 +--[[-- 1.419 +db_selector = -- same selector returned 1.420 +<db_selector>:intersect( 1.421 + expression -- expression or selector without ORDER BY, LIMIT, FOR UPDATE or FOR SHARE 1.422 +) 1.423 + 1.424 +This method adds an INTERSECT clause to the given selector. The selector is modified and returned. The selector (or expression) passed as argument to this function shall not contain any ORDER BY, LIMIT, FOR UPDATE or FOR SHARE clauses. 1.425 + 1.426 +--]]-- 1.427 function selector_prototype:intersect(expression) 1.428 self:add_combine{"INTERSECT $", {expression}} 1.429 return self 1.430 end 1.431 +--//-- 1.432 1.433 +--[[-- 1.434 +db_selector = -- same selector returned 1.435 +<db_selector>:intersect_all( 1.436 + expression -- expression or selector without ORDER BY, LIMIT, FOR UPDATE or FOR SHARE 1.437 +) 1.438 + 1.439 +This method adds an INTERSECT ALL clause to the given selector. The selector is modified and returned. The selector (or expression) passed as argument to this function shall not contain any ORDER BY, LIMIT, FOR UPDATE or FOR SHARE clauses. 1.440 + 1.441 +--]]-- 1.442 function selector_prototype:intersect_all(expression) 1.443 self:add_combine{"INTERSECT ALL $", {expression}} 1.444 return self 1.445 end 1.446 +--//-- 1.447 1.448 +--[[-- 1.449 +db_selector = -- same selector returned 1.450 +<db_selector>:except( 1.451 + expression -- expression or selector without ORDER BY, LIMIT, FOR UPDATE or FOR SHARE 1.452 +) 1.453 + 1.454 +This method adds an EXCEPT clause to the given selector. The selector is modified and returned. The selector (or expression) passed as argument to this function shall not contain any ORDER BY, LIMIT, FOR UPDATE or FOR SHARE clauses. 1.455 + 1.456 +--]]-- 1.457 function selector_prototype:except(expression) 1.458 self:add_combine{"EXCEPT $", {expression}} 1.459 return self 1.460 end 1.461 +--//-- 1.462 1.463 +--[[-- 1.464 +db_selector = -- same selector returned 1.465 +<db_selector>:except_all( 1.466 + expression -- expression or selector without ORDER BY, LIMIT, FOR UPDATE or FOR SHARE 1.467 +) 1.468 + 1.469 +This method adds an EXCEPT ALL clause to the given selector. The selector is modified and returned. The selector (or expression) passed as argument to this function shall not contain any ORDER BY, LIMIT, FOR UPDATE or FOR SHARE clauses. 1.470 + 1.471 +--]]-- 1.472 function selector_prototype:except_all(expression) 1.473 self:add_combine{"EXCEPT ALL $", {expression}} 1.474 return self 1.475 end 1.476 +--//-- 1.477 1.478 +--[[-- 1.479 +db_selector = -- same selector returned 1.480 +<db_selector>:set_class( 1.481 + class -- database class (model) 1.482 +) 1.483 + 1.484 +This method makes the selector to return database result lists or objects of the given database class (model). The selector is modified and returned. 1.485 + 1.486 +--]]-- 1.487 function selector_prototype:set_class(class) 1.488 self._class = class 1.489 return self 1.490 end 1.491 +--//-- 1.492 1.493 +--[[-- 1.494 +db_selector = -- same selector returned 1.495 +<db_selector>:attach( 1.496 + mode, -- attachment type: "11" one to one, "1m" one to many, "m1" many to one 1.497 + data2, -- other database result list or object, the results of this selector shall be attached with 1.498 + field1, -- field name(s) in result list or object of this selector used for attaching 1.499 + field2, -- field name(s) in "data2" used for attaching 1.500 + ref1, -- name of reference field in the results of this selector after attaching 1.501 + ref2 -- name of reference field in "data2" after attaching 1.502 +) 1.503 + 1.504 +This method causes database result lists or objects of this selector to be attached with other database result lists after execution. This method does not need to be called directly. 1.505 + 1.506 +--]]-- 1.507 function selector_prototype:attach(mode, data2, field1, field2, ref1, ref2) 1.508 self._attach = { 1.509 mode = mode, 1.510 @@ -324,8 +645,7 @@ 1.511 } 1.512 return self 1.513 end 1.514 - 1.515 --- TODO: many-to-many relations 1.516 +--//-- 1.517 1.518 function selector_metatable:__tostring() 1.519 local parts = {sep = " "} 1.520 @@ -381,6 +701,14 @@ 1.521 return self._db_conn:assemble_command{"$", parts} 1.522 end 1.523 1.524 +--[[-- 1.525 +db_error, -- database error object, or nil in case of success 1.526 +result = -- database result list or object 1.527 +<db_selector>:try_exec() 1.528 + 1.529 +This method executes the selector on its database. First return value is an error object or nil in case of success. Second return value is the result list or object. 1.530 + 1.531 +--]]-- 1.532 function selector_prototype:try_exec() 1.533 if self._mode == "empty_list" then 1.534 if self._class then 1.535 @@ -410,7 +738,15 @@ 1.536 return nil 1.537 end 1.538 end 1.539 +--//-- 1.540 1.541 +--[[-- 1.542 +result = -- database result list or object 1.543 +<db_selector>:exec() 1.544 + 1.545 +This method executes the selector on its database. The result list or object is returned on success, otherwise an error is thrown. 1.546 + 1.547 +--]]-- 1.548 function selector_prototype:exec() 1.549 local db_error, result = self:try_exec() 1.550 if db_error then 1.551 @@ -419,8 +755,15 @@ 1.552 return result 1.553 end 1.554 end 1.555 +--//-- 1.556 1.557 --- NOTE: This function caches the result! 1.558 +--[[-- 1.559 +count = -- number of rows returned 1.560 +<db_selector>:count() 1.561 + 1.562 +This function wraps the given selector inside a subquery to count the number of rows returned by the database. NOTE: The result is cached inside the selector, thus the selector should NOT be modified afterwards. 1.563 + 1.564 +--]]-- 1.565 function selector_prototype:count() 1.566 if not self._count then 1.567 local count_selector = self:get_db_conn():new_selector() 1.568 @@ -431,6 +774,7 @@ 1.569 end 1.570 return self._count 1.571 end 1.572 +--//-- 1.573 1.574 1.575 1.576 @@ -453,6 +797,20 @@ 1.577 end 1.578 end 1.579 1.580 +--[[-- 1.581 +mondelefant.attach( 1.582 + mode, -- attachment type: "11" one to one, "1m" one to many, "m1" many to one 1.583 + data1, -- first database result list or object 1.584 + data2, -- second database result list or object 1.585 + key1, -- field name(s) in first result list or object used for attaching 1.586 + key2, -- field name(s) in second result list or object used for attaching 1.587 + ref1, -- name of reference field to be set in first database result list or object 1.588 + ref2 -- name of reference field to be set in second database result list or object 1.589 +) 1.590 + 1.591 +This function attaches database result lists/objects with each other. It does not need to be called directly. 1.592 + 1.593 +--]]-- 1.594 function attach(mode, data1, data2, key1, key2, ref1, ref2) 1.595 local many1, many2 1.596 if mode == "11" then 1.597 @@ -532,6 +890,7 @@ 1.598 end 1.599 end 1.600 end 1.601 +--//-- 1.602 1.603 1.604 1.605 @@ -539,15 +898,37 @@ 1.606 -- model system -- 1.607 ------------------ 1.608 1.609 +--[[-- 1.610 +<db_class>.primary_key 1.611 + 1.612 +Primary key of a database class (model). Defaults to "id". 1.613 + 1.614 +--]]-- 1.615 class_prototype.primary_key = "id" 1.616 +--//-- 1.617 1.618 +--[[-- 1.619 +db_handle = -- database connection handle used by this class 1.620 +<db_class>:get_db_conn() 1.621 + 1.622 +By implementing this method for a particular model or overwriting it in the default prototype "mondelefant.class_prototype", classes are connected with a particular database. This method needs to return a database connection handle. If it is not overwritten, an error is thrown, when invoking this method. 1.623 + 1.624 +--]]-- 1.625 function class_prototype:get_db_conn() 1.626 error( 1.627 "Method mondelefant class(_prototype):get_db_conn() " .. 1.628 "has to be implemented." 1.629 ) 1.630 end 1.631 +--//-- 1.632 1.633 +--[[-- 1.634 +string = -- string of form '"schemaname"."tablename"' or '"tablename"' 1.635 +<db_class>:get_qualified_table() 1.636 + 1.637 +This method returns a string with the (double quoted) qualified table name used to store objects of this class. 1.638 + 1.639 +--]]-- 1.640 function class_prototype:get_qualified_table() 1.641 if not self.table then error "Table unknown." end 1.642 if self.schema then 1.643 @@ -556,7 +937,15 @@ 1.644 return '"' .. self.table .. '"' 1.645 end 1.646 end 1.647 +--]]-- 1.648 1.649 +--[[-- 1.650 +string = -- single quoted string of form "'schemaname.tablename'" or "'tablename'" 1.651 +<db_class>:get_qualified_table_literal() 1.652 + 1.653 +This method returns a string with an SQL literal representing the given table. It causes ambiguities when the table name contains a dot (".") character. 1.654 + 1.655 +--]]-- 1.656 function class_prototype:get_qualified_table_literal() 1.657 if not self.table then error "Table unknown." end 1.658 if self.schema then 1.659 @@ -565,7 +954,15 @@ 1.660 return self.table 1.661 end 1.662 end 1.663 +--//-- 1.664 1.665 +--[[-- 1.666 +list = -- list of column names of primary key 1.667 +<db_class>:get_primary_key_list() 1.668 + 1.669 +This method returns a list of column names of the primary key. 1.670 + 1.671 +--]]-- 1.672 function class_prototype:get_primary_key_list() 1.673 local primary_key = self.primary_key 1.674 if type(primary_key) == "string" then 1.675 @@ -574,7 +971,15 @@ 1.676 return primary_key 1.677 end 1.678 end 1.679 +--//-- 1.680 1.681 +--[[-- 1.682 +columns = -- list of columns 1.683 +<db_class>:get_columns() 1.684 + 1.685 +This method returns a list of column names of the table used for the class. 1.686 + 1.687 +--]]-- 1.688 function class_prototype:get_columns() 1.689 if self._columns then 1.690 return self._columns 1.691 @@ -600,6 +1005,15 @@ 1.692 return columns 1.693 end 1.694 1.695 +--[[-- 1.696 +selector = -- new selector for selecting objects of this class 1.697 +<db_class>:new_selector( 1.698 + db_conn -- optional(!) database connection handle, defaults to result of :get_db_conn() 1.699 +) 1.700 + 1.701 +This method creates a new selector for selecting objects of the class. 1.702 + 1.703 +--]]-- 1.704 function class_prototype:new_selector(db_conn) 1.705 local selector = (db_conn or self:get_db_conn()):new_selector() 1.706 selector:set_class(self) 1.707 @@ -607,20 +1021,44 @@ 1.708 selector:add_field(self:get_qualified_table() .. ".*") 1.709 return selector 1.710 end 1.711 +--//-- 1.712 1.713 +--[[-- 1.714 +db_list = -- database result being an empty list 1.715 +<db_class>:create_list() 1.716 + 1.717 +Creates an empty database result representing a list of objects of the given class. 1.718 + 1.719 +--]]-- 1.720 function class_prototype:create_list() 1.721 local list = self:get_db_conn():create_list() 1.722 list._class = self 1.723 return list 1.724 end 1.725 +--//-- 1.726 1.727 +--[[-- 1.728 +db_object = -- database object (instance of model) 1.729 +<db_class>:new() 1.730 + 1.731 +Creates a new object of the given class. 1.732 + 1.733 +--]]-- 1.734 function class_prototype:new() 1.735 local object = self:get_db_conn():create_object() 1.736 object._class = self 1.737 object._new = true 1.738 return object 1.739 end 1.740 +--//-- 1.741 1.742 +--[[-- 1.743 +db_error = -- database error object, or nil in case of success 1.744 +<db_object>:try_save() 1.745 + 1.746 +This method saves changes to an object in the database. Returns nil on success, otherwise an error object is returned. 1.747 + 1.748 +--]]-- 1.749 function class_prototype.object:try_save() 1.750 if not self._class then 1.751 error("Cannot save object: No class information available.") 1.752 @@ -703,7 +1141,14 @@ 1.753 end 1.754 return nil 1.755 end 1.756 +--//-- 1.757 1.758 +--[[-- 1.759 +<db_object>:save() 1.760 + 1.761 +This method saves changes to an object in the database. Throws error, unless successful. 1.762 + 1.763 +--]]-- 1.764 function class_prototype.object:save() 1.765 local db_error = self:try_save() 1.766 if db_error then 1.767 @@ -711,7 +1156,15 @@ 1.768 end 1.769 return self 1.770 end 1.771 +--//-- 1.772 1.773 +--[[-- 1.774 +db_error = -- database error object, or nil in case of success 1.775 +<db_object>:try_destroy() 1.776 + 1.777 +This method deletes an object in the database. Returns nil on success, otherwise an error object is returned. 1.778 + 1.779 +--]]-- 1.780 function class_prototype.object:try_destroy() 1.781 if not self._class then 1.782 error("Cannot destroy object: No class information available.") 1.783 @@ -731,7 +1184,14 @@ 1.784 primary_key_compare 1.785 } 1.786 end 1.787 +--//-- 1.788 1.789 +--[[-- 1.790 +<db_object>:destroy() 1.791 + 1.792 +This method deletes an object in the database. Throws error, unless successful. 1.793 + 1.794 +--]]-- 1.795 function class_prototype.object:destroy() 1.796 local db_error = self:try_destroy() 1.797 if db_error then 1.798 @@ -739,7 +1199,22 @@ 1.799 end 1.800 return self 1.801 end 1.802 +--//-- 1.803 1.804 +--[[-- 1.805 +db_selector = 1.806 +<db_list>:get_reference_selector( 1.807 + ref_name, -- name of reference (e.g. "children") 1.808 + options, -- table options passed to the reference loader (e.g. { order = ... }) 1.809 + ref_alias, -- optional alias for the reference (e.g. "ordered_children") 1.810 + back_ref_alias -- back reference name (e.g. "parent") 1.811 +) 1.812 + 1.813 +This method returns a special selector for selecting referenced objects. It is prepared in a way, that on execution of the selector, all returned objects are attached with the objects of the existent list. The "ref" and "back_ref" arguments passed to "add_reference" are used for the attachment, unless aliases are given with "ref_alias" and "back_ref_alias". If "options" are set, these options are passed to the reference loader. The default reference loader supports only one option named "order". If "order" is set to nil, the default order is used, if "order" is set to false, no ORDER BY statment is included in the selector, otherwise the given expression is used for ordering. 1.814 + 1.815 +This method is not only available for database result lists but also for database result objects. 1.816 + 1.817 +--]]-- 1.818 function class_prototype.list:get_reference_selector( 1.819 ref_name, options, ref_alias, back_ref_alias 1.820 ) 1.821 @@ -774,22 +1249,86 @@ 1.822 ) 1.823 return selector 1.824 end 1.825 +--//-- 1.826 1.827 +--[[-- 1.828 +db_list_or_object = 1.829 +<db_list>:load( 1.830 + ref_name, -- name of reference (e.g. "children") 1.831 + options, -- table options passed to the reference loader (e.g. { order = ... }) 1.832 + ref_alias, -- optional alias for the reference (e.g. "ordered_children") 1.833 + back_ref_alias -- back reference name (e.g. "parent") 1.834 +) 1.835 + 1.836 +This method loads referenced objects and attaches them with the objects of the existent list. The "ref" and "back_ref" arguments passed to "add_reference" are used for the attachment, unless aliases are given with "ref_alias" and "back_ref_alias". If "options" are set, these options are passed to the reference loader. The default reference loader supports only one option named "order". If "order" is set to nil, the default order is used, if "order" is set to false, no ORDER BY statment is included in the selector, otherwise the given expression is used for ordering. 1.837 + 1.838 +This method is not only available for database result lists but also for database result objects. 1.839 + 1.840 +--]]-- 1.841 function class_prototype.list.load(...) 1.842 return class_prototype.list.get_reference_selector(...):exec() 1.843 end 1.844 +--//-- 1.845 1.846 +--[[-- 1.847 +db_object = 1.848 +<db_object>:get_reference_selector( 1.849 + ref_name, -- name of reference (e.g. "children") 1.850 + options, -- table options passed to the reference loader (e.g. { order = ... }) 1.851 + ref_alias, -- optional alias for the reference (e.g. "ordered_children") 1.852 + back_ref_alias -- back reference name (e.g. "parent") 1.853 +) 1.854 + 1.855 +This method returns a special selector for selecting referenced objects. It is prepared in a way, that on execution of the selector, all returned objects are attached with the objects of the existent list. The "ref" and "back_ref" arguments passed to "add_reference" are used for the attachment, unless aliases are given with "ref_alias" and "back_ref_alias". If "options" are set, these options are passed to the reference loader. The default reference loader supports only one option named "order". If "order" is set to nil, the default order is used, if "order" is set to false, no ORDER BY statment is included in the selector, otherwise the given expression is used for ordering. 1.856 + 1.857 +This method is not only available for database result objects but also for database result lists. 1.858 + 1.859 +--]]-- 1.860 function class_prototype.object:get_reference_selector(...) 1.861 local list = self._class:create_list() 1.862 list[1] = self 1.863 return list:get_reference_selector(...) 1.864 end 1.865 +--//-- 1.866 1.867 +--[[-- 1.868 +db_list_or_object = 1.869 +<db_object>:load( 1.870 + ref_name, -- name of reference (e.g. "children") 1.871 + options, -- table options passed to the reference loader (e.g. { order = ... }) 1.872 + ref_alias, -- optional alias for the reference (e.g. "ordered_children") 1.873 + back_ref_alias -- back reference name (e.g. "parent") 1.874 +) 1.875 + 1.876 +This method loads referenced objects and attaches them with the objects of the existent list. The "ref" and "back_ref" arguments passed to "add_reference" are used for the attachment, unless aliases are given with "ref_alias" and "back_ref_alias". If "options" are set, these options are passed to the reference loader. The default reference loader supports only one option named "order". If "order" is set to nil, the default order is used, if "order" is set to false, no ORDER BY statment is included in the selector, otherwise the given expression is used for ordering. 1.877 + 1.878 +This method is not only available for database result objects but also for database result lists. Calling this method for objects is unneccessary, unless additional options and/or an alias is used. 1.879 + 1.880 +--]]-- 1.881 function class_prototype.object.load(...) 1.882 return class_prototype.object.get_reference_selector(...):exec() 1.883 end 1.884 +--//-- 1.885 1.886 +--[[-- 1.887 +db_class = -- same class returned 1.888 +<db_class>:add_reference{ 1.889 + mode = mode, -- "11", "1m", "m1", or "mm" (one/many to one/many) 1.890 + to = to, -- referenced class (model), optionally as string or function returning the value (avoids autoload) 1.891 + this_key = this_key, -- name of key in this class (model) 1.892 + that_key = that_key, -- name of key in the other class (model) ("to" argument) 1.893 + ref = ref, -- name of reference in this class, referring to the other class 1.894 + back_ref = back_ref, -- name of reference in other class, referring to this class 1.895 + default_order = default_order, -- expression as passed to "assemble_command" used for sorting 1.896 + selector_generator = selector_generator, -- alternative function used as selector generator (use only, when you know what you are doing) 1.897 + connected_by_table = connected_by_table, -- connecting table used for many to many relations 1.898 + connected_by_this_key = connected_by_this_key, -- key in connecting table referring to "this_key" of this class (model) 1.899 + connected_by_that_key = connected_by_that_key -- key in connecting table referring to "that_key" in other class (model) ("to" argument) 1.900 +} 1.901 1.902 +Denotes a reference from one database class to another database class (model to model relation). There are 4 possible types of references: one-to-one (mode = "11"), one-to-many (mode = "1m"), many-to-one ("m1"), and many-to-many ("mm"). References usually should be defined in both models, which are related to each other, with mirrored mode (i.e. "1m" in one model, and "m1" in the other). One-to-one and one-to-many references may have a "back_ref" setting, which causes that loaded objects of the referenced class, refer back to the originating object. One-to-many and many-to-many references may have a "default_order" setting, which selects the default order for selected objects. When adding a many-to-many reference, the argument "connected_by_table", "connected_by_this_key" and "connected_by_that_key" must be set additionally. 1.903 + 1.904 +--]]-- 1.905 function class_prototype:add_reference(args) 1.906 local selector_generator = args.selector_generator 1.907 local mode = args.mode 1.908 @@ -885,3 +1424,5 @@ 1.909 end 1.910 return self 1.911 end 1.912 +--//-- 1.913 +