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"
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 +

Impressum / About Us