anewt-developers team mailing list archive
-
anewt-developers team
-
Mailing list archive
-
Message #00121
[Branch ~uws/anewt/anewt.uws] Rev 1716: [database.old, autorecord.old] Remove obsolete modules
------------------------------------------------------------
revno: 1716
committer: Wouter Bolsterlee <uws@xxxxxxxxx>
branch nick: anewt.uws
timestamp: Sun 2009-08-02 13:07:28 +0200
message:
[database.old,autorecord.old] Remove obsolete modules
removed:
autorecord.old/
autorecord.old/autorecord.lib.php
autorecord.old/autorecord.test.php
autorecord.old/main.lib.php
database.old/
database.old/backend.lib.php
database.old/database.lib.php
database.old/database.test.php
database.old/main.lib.php
database.old/module.doc.xml
database.old/mssql/
database.old/mssql/backend.lib.php
database.old/mssql/resultset.lib.php
database.old/mysql/
database.old/mysql/backend.lib.php
database.old/mysql/resultset.lib.php
database.old/postgresql/
database.old/postgresql/backend.lib.php
database.old/postgresql/resultset.lib.php
database.old/preparedquery.lib.php
database.old/resultset.lib.php
database.old/sqlite/
database.old/sqlite/backend.lib.php
database.old/sqlite/resultset.lib.php
database.old/sqlite/test.php
database.old/sqltemplate.lib.php
--
lp:anewt
https://code.launchpad.net/~uws/anewt/anewt.uws
Your team Anewt developers is subscribed to branch lp:anewt.
To unsubscribe from this branch go to https://code.launchpad.net/~uws/anewt/anewt.uws/+edit-subscription.
=== removed directory 'autorecord.old'
=== removed file 'autorecord.old/autorecord.lib.php'
--- autorecord.old/autorecord.lib.php 2009-03-27 15:49:10 +0000
+++ autorecord.old/autorecord.lib.php 1970-01-01 00:00:00 +0000
@@ -1,1492 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, autorecord module
- *
- * Copyright (C) 2006 Wouter Bolsterlee <uws@xxxxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-anewt_include('database');
-
-
-/**
- * Automatic database record object.
- *
- * AutoRecord is an advanced database wrapper class implementing the active
- * record pattern. Each class wraps a single database table, providing you with
- * a convenient search API for querying and easy to use save(), insert() and
- * delete() methods for object manipulation.
- *
- * The query API consists of several static methods:
- *
- * - AutoRecord::find_all() retrieves all records in the database
- * - AutoRecord::find_by_id() and AutoRecord::find_one_by_id() return records
- * based on the primary key value
- * - AutoRecord::find_by_sql() and AutoRecord::find_one_by_sql() return records
- * based on constraints expressed as SQL query parts.
- * - AutoRecord::find_by_column() and AutoRecord::find_one_by_column() return
- * records where a specified column has the specified value.
- *
- * The data manipulation methods are instance methods that operate on object
- * instances themselves:
- *
- * - AutoRecord::save() saves the current record
- * - AutoRecord::delete() deletes the current record
- *
- * In order to create an AutoRecord subclass, you should name your own class
- * <code>Foo_</code> (with a trailing underscore), and override some of the methods
- * (_db_table() and _db_columns() are obligatory). See the documentation on the
- * methods below for more information. Right after your class definition, you
- * should register your AutoRecord subclass so that the actual magic can be put
- * into place: <code>AutoRecord::register('Foo')</code>. Now you can use the
- * <code>Foo</code> class. Example:
- * <code>$somefoo = Foo::find_one_by_id(12)</code>
- *
- * \todo
- * find_previous() and find_next() methods (based on sort order)
- */
-class AutoRecord extends Container
-{
- /** \{
- * \name Static methods
- */
-
- /**
- * Return a reference to the default database connection. Override this
- * method if you want to use a custom database instance.
- *
- * \return
- * A reference to a Database instance
- */
- protected static function _db()
- {
- $db = DB::get_instance();
- return $db;
- }
-
- /**
- * Return the name of the table to use. You must override this method for
- * your own classes. An example might be the following one-liner:
- * <code>return 'person';</code>
- *
- * \return
- * An string with the table name to use
- *
- * \see AutoRecord::_db_columns
- */
- protected static function _db_table()
- {
- throw new Exception('AutoRecord::_db_table() must be overridden.');
- }
-
- /**
- * Return an associative array of column name => column type mappings. You
- * must override this method for your own classes. An example might be the
- * following one-liner:
- * <code>return array('id' => 'int', 'name' => 'str', 'age' =>
- * 'int');</code>
- *
- * \return
- * An associative array with column name => type items
- *
- * \see AutoRecord::_db_table
- */
- protected static function _db_columns()
- {
- throw new Exception('AutoRecord::_db_columns() must be overridden.');
- }
-
- /**
- * Return an array of column names which should be skipped on insert queries
- * when no values are given. The database is expected to fill a default
- * value for these columns.
- */
- protected static function _db_skip_on_insert()
- {
- return array();
- }
-
- /**
- * Return an array of column names which should be skipped on update queries.
- * These are usually read-only values which don't need to get updated
- * every time.
- */
- protected static function _db_skip_on_update()
- {
- return array();
- }
-
- /**
- * \static \protected
- *
- * Return an array of column names which are read-only and should never be
- * written. The database is expected to fill a default value for these
- * columns.
- *
- * Note that like _db_skip_on_insert the values are still written on an
- * insert when they are supplied, but they are never written on an update.
- */
- protected static function _db_skip_on_save()
- {
- return array();
- }
-
- /**
- * \static \protected
- *
- * Return the name of the primary key. Override this method if you don't
- * want to use the default value 'id'.
- *
- * \return
- * The name of the primary key column
- */
- protected static function _db_primary_key()
- {
- return 'id';
- }
-
- /**
- * Return the name of the sequence used for the primary key (PostgreSQL
- * only). Override this function if you're using a non-standard sequence
- * for the primary key values of your table.
- *
- * \return
- * The name of the sequence used for the primary key value
- */
- protected static function _db_primary_key_sequence()
- {
- return null;
- }
-
- /**
- * Return the name of the default sort column. This column is used to sort
- * the records in some methods that return multiple columns. If you specify
- * order-by parameters to methods, this value is not used, but for simple
- * cases like find_all() it serves as the sort column. By default, the
- * primary key value is used. Override this method if you want a custom
- * column to be used, eg. a position or date column.
- *
- * It is also possible to order by multiple columns by returning an array
- * of columns. In this case you have to override _db_sort_order() as well
- * by letting it return an array with the same amount of elements.
- *
- * Furthermore you can specify table aliasses used in _db_join_one() by
- * using "table_alias.column" syntax.
- *
- * \return
- * The name of the default sort column or an array of columns in order
- * of high to low priority.
- *
- * \see AutoRecord::_db_sort_order
- */
- protected static function _db_sort_column()
- {
- return null;
- }
-
- /**
- * Return the default sort order. The value returned by this method should
- * be ASC or DESC. The default is ascending sort order. Override this method
- * if you want to change it.
- *
- * If you have overridden _db_sort_column() to return multiple column names,
- * then override this method as well to return the same amount of elements.
- *
- * \return
- * The default sort order (ASC or DESC) or an array of sort orders.
- *
- * \see AutoRecord::_db_sort_column
- */
- protected static function _db_sort_order()
- {
- return 'ASC';
- }
-
- /**
- * \todo document this
- */
- protected static function _db_has_many()
- {
- return array();
- }
-
- /**
- * \todo document this
- */
- protected static function _db_has_one()
- {
- return array();
- }
-
- /**
- * Override this method if you want the default queries to contain
- * joins with other tables, specified by other AutoRecord classes.
- *
- * The format is an nummeric array of associative arrays. The
- * associative arrays can have the following keys:
- * foreign_class - The AutoRecord class which corresponds to the
- * other table.
- * own_key - (optional) The foreign key in this table to
- * join on. Use this if the column in this table
- * doesn't match the primary key of the foreign
- * table.
- * foreign_alias - (optional) The alias name of the other table.
- * Use this if you want the same table joined
- * multiple times.
- * own_alias - (optional) Use this if 'own_key' is not part
- * of the table specified by this class; must be
- * a table name, not a class name.
- * join_type - (optional) the type of join. Defaults to
- * 'left', but can be 'right' or 'inner' or
- * anything which can go before the "JOIN"
- * keyword in the SQL syntax.
- * \return
- * A nummeric array of associative arrays.
- */
- protected static function _db_join_one()
- {
- return array();
- }
-
- /**
- * Register a class as an AutoRecord. This does some evil voodoo magic to
- * get things to work in a decent way. Your own class name should be called
- * Foo_ (with a trailing underscore) and should extend AutoRecord; this
- * method will dynamically create a class Foo extending your class with all
- * the static methods in place.
- *
- * \param $class
- * The name of the class to register as an "active record" class (without
- * the trailing underscore)
- */
- public static function register($class)
- {
- assert('is_string($class)');
-
- /* Extreme precautions because eval() is used */
- if (!preg_match('/^[a-z0-9_]+$/i', $class))
- trigger_error(sprintf(
- 'AutoRecord::register(): illegal class name \'%s\'',
- $class), E_USER_ERROR);
-
- /* There should be a base class with an underscore at the end */
- if (!class_exists($class . '_'))
- trigger_error(sprintf(
- 'AutoRecord::register(): class name \'%s_\' does not exist.',
- $class), E_USER_ERROR);
-
- /* Some useful variables */
- $class_ = $class . '_';
-
- /* Nasty hack to get some static methods in place, providing a nice API.
- * Too bad there is no way to retrieve the current class name when
- * calling static methods from derived classes (debug_backtrace() can be
- * used in PHP4, but this doesn't work for PHP5). */
-
- $methods = array();
-
- /* Select clause with all fields */
- $methods['_db_select_clause'] = 'protected static function _db_select_clause($table_alias=null, $joins=null) {
- $db = @@CLASS@@::_db();
- return @@CLASS@@::__db_select_clause(\'@@CLASS@@\', $table_alias, $joins, $db);
- }';
-
- /* From clause with all joins */
- $methods['_db_from_clause'] = 'function _db_from_clause($table_alias=null, $joins=null) {
- $db = &@@CLASS@@::_db();
- return @@CLASS@@::__db_from_clause(\'@@CLASS@@\', $table_alias, $joins, $db);
- }';
-
- /* Create instances from arrays (e.g. database records) */
- $methods['_db_object_from_array'] = 'protected static function _db_object_from_array($arr) {
- $r = @@CLASS@@::__db_object_from_array(\'@@CLASS@@\', $arr);
- return $r;
- }';
- $methods['_db_objects_from_arrays'] = 'protected static function _db_objects_from_arrays($arrs) {
- $r = @@CLASS@@::__db_objects_from_arrays(\'@@CLASS@@\', $arrs);
- return $r;
- }';
-
- /* Find all */
- $methods['find_all'] = 'public static function find_all() {
- $result = @@CLASS@@::find_by_sql();
- return $result;
- }';
-
- /* Find by id */
- $methods['find_by_id'] = 'public static function find_by_id($values) {
- $args = func_get_args();
- $num_args = func_num_args();
- /* Accept both multiple parameters and a single array */
- if (($num_args == 1) && is_array($args[0])) {
- $args = $args[0];
- }
- $db = @@CLASS@@::_db();
- $result = AutoRecord::__db_find_by_id(\'@@CLASS@@\', false, $args, $db);
- return $result;
- }';
-
- $methods['find_one_by_id'] = 'public static function find_one_by_id($value) {
- assert(\'is_int($value)\');
- /* Check for just one single parameter. This helps finding
- * bugs where find_by_id() was meant to be used */
- $num_args = func_num_args();
- assert(\'$num_args === 1\');
- $db = @@CLASS@@::_db();
- $result = AutoRecord::__db_find_by_id(\'@@CLASS@@\', true, array($value), $db);
- return $result;
- }';
-
- /* Find by SQL */
- $methods['find_by_sql'] = 'public static function find_by_sql($sql=null, $values=null) {
- $args = func_get_args();
- $sql = array_shift($args);
- if (count($args) == 1 && is_array($args[0])) $args = $args[0];
- $db = @@CLASS@@::_db();
- $result = AutoRecord::__db_find_by_sql(\'@@CLASS@@\', false, $sql, $args, $db);
- return $result;
- }';
- $methods['find_one_by_sql'] = 'public static function find_one_by_sql($sql=null, $values=null) {
- $args = func_get_args();
- $sql = array_shift($args);
- if (count($args) == 1 && is_array($args[0])) $args = $args[0];
- $db = @@CLASS@@::_db();
- $result = AutoRecord::__db_find_by_sql(\'@@CLASS@@\', true, $sql, $args, $db);
- return $result;
- }';
-
- /* Find by column */
- $methods['find_by_column'] = 'public static function find_by_column($column, $value) {
- $db = @@CLASS@@::_db();
- $result = AutoRecord::__db_find_by_column(\'@@CLASS@@\', false, $column, $value, $db);
- return $result;
- }';
- $methods['find_one_by_column'] = 'public static function find_one_by_column($column, $value) {
- $db = @@CLASS@@::_db();
- $result = AutoRecord::__db_find_by_column(\'@@CLASS@@\', true, $column, $value, $db);
- return $result;
- }';
-
- /* Has-many relations */
- $has_many_definitions = call_user_func(array($class_, '_db_has_many'));
- foreach ($has_many_definitions as $has_many_definition)
- {
- assert('is_numeric_array($has_many_definition)');
- assert('count($has_many_definition) == 4');
- list ($method_name, $foreign_class, $local_key, $foreign_key) = $has_many_definition;
- assert('is_string($method_name)');
- assert('is_string($foreign_class)');
- assert('is_string($local_key)');
- assert('is_string($foreign_key)');
- $methods[$method_name] = sprintf('
- var $__autorecord_%s;
- public function %s()
- {
- if (is_null($this->__autorecord_%s))
- $this->__autorecord_%s = %s::find_by_column(\'%s\', $this->get(\'%s\'));
-
- return $this->__autorecord_%s;
- }',
- $method_name, $method_name, $method_name, $method_name,
- $foreign_class, $foreign_key, $local_key, $method_name);
- }
-
- /* Has-one relations */
- $has_one_definitions = call_user_func(array($class_, '_db_has_one'));
- foreach ($has_one_definitions as $has_one_definition)
- {
- assert('is_numeric_array($has_one_definition)');
- assert('count($has_one_definition) == 4');
- list ($method_name, $foreign_class, $local_key, $foreign_key) = $has_one_definition;
- assert('is_string($method_name)');
- assert('is_string($foreign_class)');
- assert('is_string($local_key)');
- assert('is_string($foreign_key)');
- $methods[$method_name] = sprintf('
- var $__autorecord_%s;
- public function %s()
- {
- if (is_null($this->__autorecord_%s))
- $this->__autorecord_%s = %s::find_one_by_column(\'%s\', $this->get(\'%s\'));
-
- return $this->__autorecord_%s;
- }',
- $method_name, $method_name, $method_name, $method_name,
- $foreign_class, $foreign_key, $local_key, $method_name);
- }
-
- /* Custom extra methods */
- $extra_methods = call_user_func(array($class_, '_autorecord_extra_methods'));
- $methods = array_merge($methods, $extra_methods);
-
- /* Create the actual class definition string. */
- $class_code = array();
- $class_code[] = 'class @@CLASS@@ extends @@CLASS@@_ {';
- foreach ($methods as $m)
- $class_code[] = $m;
-
- $class_code[] = '}';
-
- /* Replace placeholders with actual values */
- $class_code = str_replace('@@CLASS@@', $class, join(NL, $class_code));
-
- /* Actually define the class */
- eval($class_code);
- }
-
- /**
- * Create a SQL query part with columns to select. The SELECT keyword is not
- * included.
- *
- * \param $class
- * The class name
- *
- * \param $table_alias
- * Optional string parameter to use as a table alias. If specified, this
- * string is prepended to all column names. This is useful if you do
- * selects from multiple tables (and identical column names) and you want
- * to select all columns from an AutoRecord table (eg. combined with
- * a join).
- *
- * \param $db
- * Reference to the database object instance.
- *
- * \return
- * String with comma-separated escaped column names. This string can be
- * used directly (unescaped) in the SELECT part of an SQL query.
- */
- protected static function __db_select_clause($class, $table_alias=null, $joins=null, $db)
- {
- assert('is_string($class)');
- assert('$db instanceof DB');
-
- $column_spec = array();
- $column_data = array();
-
- $columns = call_user_func(array($class, '_db_columns'));
-
- if (is_null($table_alias))
- $table_alias = call_user_func(array($class, '_db_table'));
-
- foreach(array_keys($columns) as $column)
- {
- $column_spec[] = "?table?.?column?";
- $column_data[] = $table_alias;
- $column_data[] = $column;
- }
-
- if (is_null($joins)) {
- $joins = call_user_func(array($class, '_db_join_one'));
- }
-
- foreach($joins as $join)
- {
- $foreign_class = $join['foreign_class'];
- $has_alias = false;
- assert('class_exists($foreign_class); // '.$foreign_class);
- if (array_has_key($join, 'foreign_alias'))
- {
- $foreign_alias = $join['foreign_alias'];
- $has_alias = true;
- } else
- $foreign_alias = call_user_func(array($foreign_class, '_db_table'));
-
- $columns = call_user_func(array($foreign_class, '_db_columns'));
- foreach(array_keys($columns) as $column)
- {
- if ($has_alias)
- {
- $column_spec[] = "?table?.?column? AS ?column?";
- $column_data[] = $foreign_alias;
- $column_data[] = $column;
- $column_data[] = sprintf("%s_%s", $foreign_alias, $column);
- } else {
- $column_spec[] = "?table?.?column?";
- $column_data[] = $foreign_alias;
- $column_data[] = $column;
- }
- }
- }
- $tpl = new SQLTemplate(join(",\n ", $column_spec), $db);
- return $tpl->fill($column_data);
- }
-
- /**
- * Create a SQL query part with tables to select from. The FROM keyword
- * is not included.
- *
- * \param $class
- * The class name
- *
- * \param $table_alias
- * Optional string parameter to use as a table alias.
- *
- * \param $db
- * Reference to the database object instance.
- *
- * \return
- * String with comma-separated escaped table names with join
- * conditions. This string can be used directly (unescaped) in the
- * FROM part of an SQL query.
- */
- protected static function __db_from_clause($class, $table_alias=null, $joins=null, $db)
- {
- assert('is_string($class)');
- assert('$db instanceof DB;');
-
- $from_clause = $db->backend->escape_table_name(call_user_func(array($class, '_db_table')));
-
- if (is_null($table_alias))
- $table_alias = $db->backend->escape_table_name(call_user_func(array($class, '_db_table')));
- else
- $from_clause = sprintf('%s %s', $from_clause, $table_alias);
-
- if (is_null($joins)) {
- $joins = call_user_func(array($class, '_db_join_one'));
- }
-
- foreach ($joins as $join)
- {
- $foreign_class = $join['foreign_class'];
- assert('class_exists($foreign_class)');
- $join_type = strtoupper(array_get_default($join, 'join_type', 'left'));
- $foreign_alias = array_get_default($join, 'foreign_alias');
- $own_alias = array_get_default($join, 'own_alias', $table_alias);
-
- $foreign_table = $db->backend->escape_table_name(call_user_func(array($foreign_class, '_db_table')));
- if (array_has_key($join, 'foreign_key'))
- $foreign_key = $join['foreign_key'];
- else
- $foreign_key = call_user_func(array($foreign_class, '_db_primary_key'));
- $own_key = array_get_default($join, 'own_key', $foreign_key);
-
- if (is_null($foreign_alias))
- $foreign_alias = $foreign_table;
- else
- $foreign_table = sprintf('%s %s', $foreign_table, $foreign_alias);
-
- $from_clause = sprintf(
- "%s\n %s JOIN %s ON (%s.%s = %s.%s)",
- $from_clause,
- $join_type,
- $foreign_table,
- $own_alias,
- $own_key,
- $foreign_alias,
- $foreign_key);
- }
-
- return $from_clause;
- }
-
- /**
- * Creates the order by part of an SQL query. The ORDER BY keyword is
- * not included.
- *
- * \param $class
- * The class name
- *
- * \param $table_alias
- * Optional string parameter to use as a table alias.
- *
- * \param $db
- * Reference to the database object instance.
- *
- * \return
- * String with comma-separated escaped order elements. This string
- * can be used directly (unescaped) in the FROM part of an SQL query.
- */
- protected static function __db_order_clause($class, $table_alias=null, $db)
- {
- if(is_null($table_alias))
- $table_alias = $db->backend->escape_table_name(call_user_func(array($class, '_db_table')));
-
- $sort_column = call_user_func(array($class, '_db_sort_column'));
- if (is_null($sort_column))
- $sort_column = call_user_func(array($class, '_db_primary_key'));
-
- if (!is_array($sort_column))
- $sort_column = array($sort_column);
-
- $sort_order = call_user_func(array($class, '_db_sort_order'));
- if (!is_array($sort_order))
- $sort_order = array($sort_order);
-
- $order_elements = array();
- foreach(array_keys($sort_column) as $key)
- {
- assert('($sort_order[$key] === "ASC") || ($sort_order[$key] === "DESC")');
- assert('is_string($sort_column[$key])');
- $parts = explode(".", $sort_column[$key], 2);
- if (count($parts) > 1)
- {
- $table = $db->backend->escape_table_name($parts[0]);
- $column = $db->backend->escape_column_name($parts[1]);
- } else {
- $table = $table_alias;
- $column = $db->backend->escape_column_name($sort_column[$key]);
- }
- $order_elements[] = $table . "." . $column . " " . $sort_order[$key];
- }
-
- return implode(', ', $order_elements);
- }
-
- /**
- * Converts a result row into an object instance.
- *
- * \param $class
- * The class name.
- *
- * \param $row
- * The row with data (or false).
- *
- * \return
- * A reference to a new instance or null if no data was provided
- *
- * \see AutoRecord::_db_objects_from_arrays
- */
- protected static function __db_object_from_array($class, $row)
- {
- if ($row === false)
- return null;
-
- assert('is_assoc_array($row)');
- $instance = new $class();
- $instance->_seed($row);
- return $instance;
- }
-
- /**
- * Convert result rows into object instances.
- *
- * \param $class
- * The class name.
- *
- * \param $rows
- * The rows with data (or an empty array).
- *
- * \return
- * An array with references to new instances or an empty array no data was provided
- *
- * \see AutoRecord::__db_object_from_array
- */
- protected static function __db_objects_from_arrays($class, $rows)
- {
- assert('is_numeric_array($rows)');
-
- $result = array();
- foreach ($rows as $row)
- $result[] = AutoRecord::__db_object_from_array($class, $row);
-
- return $result;
- }
-
- /**
- * Find one or more records by id. Don't use this method directly, use
- * find_by_id or find_one_by_id on the class itself.
- *
- * \param $class
- * The class name.
- *
- * \param $just_one_result
- * Whether to return just one instance (or null) or an array of instances
- * (possibly empty)
- *
- * \param $values
- * The values to search for (primary key values)
- *
- * \param $db
- * Reference to the database object instance.
- *
- * \return
- * A single instance (or null) or an array of instances (or empty array)
- */
- protected static function __db_find_by_id($class, $just_one_result, $values, $db)
- {
- assert('is_string($class)');
- assert('is_bool($just_one_result)');
- assert('is_numeric_array($values)');
- assert('$db instanceof DB');
-
- $table = call_user_func(array($class, '_db_table'));
- $primary_key = call_user_func(array($class, '_db_primary_key'));
-
- $select_clause = AutoRecord::__db_select_clause($class, null, null, $db);
- $from_clause = AutoRecord::__db_from_clause($class, null, null, $db);
-
- /* Single item requested: return an instance or null */
- if ($just_one_result)
- {
- $pq = $db->prepare("SELECT\n ?raw?\nFROM\n ?raw?\nWHERE ?table?.?column? = ?int?");
- $rs = $pq->execute($select_clause, $from_clause, $table, $primary_key, $values[0]);
- $row = $rs->fetch();
- $instance = AutoRecord::__db_object_from_array($class, $row);
- return $instance;
-
- /* Possibly multiple results: return an array with zero or more instances */
- } else
- {
- /* Return early if there are no id values at all */
- $num_values = count($values);
- if ($num_values == 0)
- {
- $r = array();
- return $r;
- }
-
- /* Build string for "WHERE id IN (...)" query */
- $where = join(', ', array_fill(0, $num_values, '?int?'));
- $tpl = new SQLTemplate($where, $db);
- $ids = $tpl->fill($values);
-
- /* Execute */
- $pq = $db->prepare("SELECT\n ?raw?\nFROM\n ?raw?\nWHERE ?table?.?column? IN (?raw?)");
- $rs = $pq->execute($select_clause, $from_clause, $table, $primary_key, $ids);
-
- /* Handle results */
- $rows = $rs->fetch_all();
- $instances = AutoRecord::__db_objects_from_arrays($class, $rows);
- return $instances;
- }
- }
-
- /**
- * Find one or more records by providing a part of the SQL query. Don't use
- * this method directly; use find_by_sql or find_one_by_sql on the instance
- * itself.
- *
- * \param $class
- * The class name.
- *
- * \param $just_one_result
- * Whether to return just one instance (or null) or an array of instances
- *
- * \param $sql
- * The constraints of the SQL query. This can be either null (no
- * constraints, selects all records), a string (the part of the WHERE
- * clause up to the end of the query) or an associative array (with
- * join, where, order-by, limit and offset indices, all optional).
- * You can use ?str?-style placholders for the data provided in
- * $values
- *
- * \param $values
- * The values to be substituted for the placeholders your provided with
- * your constraints.
- *
- * \param $db
- * Reference to the database object instance.
- */
- protected static function __db_find_by_sql($class, $just_one_result=false, $sql=null, $values=null, $db)
- {
- /* Input sanitizing */
- if (is_null($values))
- $values = array();
-
- assert('is_string($class)');
- assert('is_bool($just_one_result)');
- assert('is_null($sql) || is_string($sql) || is_assoc_array($sql)');
- assert('is_array($values)');
- assert('$db instanceof DB');
-
- /* Get basic database settings */
- $table = call_user_func(array($class, '_db_table'));
- $primary_key = call_user_func(array($class, '_db_primary_key'));
-
- /* Basic clauses */
- if (is_array($sql))
- $joins = array_get_default($sql, 'join', null);
- else
- $joins = null;
-
- $select_clause = AutoRecord::__db_select_clause($class, null, $joins, $db);
-
- $from_clause = AutoRecord::__db_from_clause($class, null, $joins, $db);
-
- $order_clause = AutoRecord::__db_order_clause($class, null, $db);
-
- /* Find all records when no sql was specified*/
- if (is_null($sql))
- {
- $pq = $db->prepare("SELECT\n ?raw?\nFROM\n ?raw?\nORDER BY ?raw?");
- $rs = $pq->execute($select_clause, $from_clause, $order_clause);
-
- /* Plain SQL */
- } elseif (is_string($sql))
- {
- $constraints_tpl = new SQLTemplate($sql, $db);
- $constraints_sql = $constraints_tpl->fill($values);
-
- $pq = $db->prepare("SELECT\n ?raw?\nFROM\n ?raw?\n?raw?");
- $rs = $pq->execute($select_clause, $from_clause, $constraints_sql);
-
- /* Associative array with constraints.
- * These may contain both literal values and placeholder strings. It's
- * just a fancy way of calling this method with a string parameters
- * (useful when using user input). Note that all constraints are treated
- * as plain strings. The parameters to be filled in for placeholders in
- * these strings should be specified in the $values array. */
- } else {
- $constraints = array();
-
- /* Where. Nothing fancy, just use it. */
- $where = array_get_default($sql, 'where', null);
- if (!is_null($where))
- $constraints[] = sprintf('WHERE %s', $where);
-
- /* Order by. Both 'order-by' and 'order' keys are recognized. */
- $order_by = array_get_default($sql, 'order-by', null);
- if (is_null($order_by))
- $order_by = array_get_default($sql, 'order', null);
-
- if (is_null($order_by))
- $constraints[] = sprintf("\nORDER BY %s", $order_clause);
- else
- $constraints[] = sprintf("\nORDER BY %s", $order_by);
-
- /* Limit. "Optimizing" this depending on the value of
- * $just_one_result is impossible since it may contain a placeholder
- * string and not a literal value. We take care of $just_one_result
- * when fetching the result rows. */
- $limit = array_get_default($sql, 'limit', null);
- if (!is_null($limit))
- $constraints[] = sprintf("\nLIMIT %s", $limit);
-
- /* Offset. How many rows to skip? */
- $offset = array_get_default($sql, 'offset', null);
- if (!is_null($offset))
- $constraints[] = sprintf("\nOFFSET %s", $offset);
-
- $constraints_tpl = new SQLTemplate(join(' ', $constraints), $db);
- $constraints_sql = $constraints_tpl->fill($values);
-
- $pq = $db->prepare("SELECT\n ?raw?\nFROM\n ?raw?\n?raw?");
- $rs = $pq->execute($select_clause, $from_clause, $constraints_sql);
- }
-
- if ($just_one_result)
- {
- $row = $rs->fetch();
- $instance = AutoRecord::__db_object_from_array($class, $row);
- $rs->free(); // don't need it anymore
- return $instance;
- } else {
- $rows = $rs->fetch_all();
- $instances = AutoRecord::__db_objects_from_arrays($class, $rows);
- return $instances;
- }
- }
-
-
- /**
- * Find one or more records by one column value. Don't use this method
- * directly, use find_by_column or find_one_by_column on the class itself.
- *
- * \param $class
- * The class name
- *
- * \param $just_one_result
- * Whether to return just one instance (or null) or an array of instances
- * (possibly empty)
- *
- * \param $column
- * The column to match
- *
- * \param $value
- * The value to match
- *
- * \param $db
- * Reference to the database object instance.
- */
- protected static function __db_find_by_column($class, $just_one_result, $column, $value, $db)
- {
- /* Input sanitizing */
- assert('is_string($class)');
- assert('is_bool($just_one_result)');
- assert('is_string($column)');
- assert('$db instanceof DB');
-
- $table = call_user_func(array($class, '_db_table'));
-
- /* Find out the column type */
- $columns = call_user_func(array($class, '_db_columns'));
- if (!array_has_key($columns, $column))
- trigger_error(sprintf("Column %s not found in column list of %s", $column, $class));
-
- /* The array form of __db_find_by_sql is used, so that the default sort
- * column is used. If a plain sql string is provided, no sorting will
- * be done at all. */
- if (is_null($value))
- {
- $where_clause = '?table?.?column? IS NULL';
- $placeholder_values = array($table, $column);
- } else
- {
- $where_clause = sprintf('?table?.?column? = ?%s?', $columns[$column]);
- $placeholder_values = array($table, $column, $value);
- }
-
- $result = AutoRecord::__db_find_by_sql(
- $class,
- $just_one_result,
- array('where' => $where_clause),
- $placeholder_values,
- $db);
- return $result;
- }
-
-
- /**
- * Convert a list of instances to a hash, based on a unique key of the
- * passed AutoRecord instances.
- *
- * \param $objects
- * A list of AutoRecord instances
- *
- * \param $column
- * The name of the (unique) column to use as the associative array.
- *
- * \return
- * An associative array with the (unique) column value as the key and the
- * object itself as the value
- *
- * \see AutoRecord::convert_to_primary_key_hash
- */
- public static function convert_to_key_hash($objects, $column)
- {
- assert('is_numeric_array($objects)');
- assert('is_string($column)');
-
- /* Handle empty lists */
- if (count($objects) == 0)
- return array();
-
- /* Now iterate over objects and put into hash */
- $r = array();
- foreach (array_keys($objects) as $object_key)
- {
- assert('$objects[$object_key] instanceof AutoRecord;');
- $r[$objects[$object_key]->_get($column)] = $objects[$object_key];
- }
- return $r;
- }
-
- /**
- * Convert a list of instances to a hash, based on the primary key of the
- * passed AutoRecord instances.
- *
- * \param $objects
- * A list of AutoRecord instances
- *
- * \return
- * An associative array with the primary key as the key and the object
- * itself as the value
- *
- * \see AutoRecord::convert_to_key_hash
- */
- public static function convert_to_primary_key_hash($objects)
- {
- assert('is_numeric_array($objects)');
-
- /* Handle empty lists */
- if (count($objects) == 0)
- return array();
-
- /* Find out the primary key column by looking in the first object */
- $primary_key_column = $objects[0]->_db_primary_key();
-
- $r = AutoRecord::convert_to_key_hash($objects, $primary_key_column);
- return $r;
- }
-
- /** \} */
-
-
- /** \{
- * \name Instance methods
- */
-
- /**
- * Inserts the data as a new record in the database. Don't use this method
- * directly, use save() instead.
- *
- * \param $skip_primary_key
- * Whether to skip the primary key in the column list.
- *
- * \see AutoRecord::save
- */
- protected function __db_insert($skip_primary_key=true)
- {
- $table = $this->_db_table();
- $columns = $this->_db_columns();
- $skip_on_insert = $this->_db_skip_on_insert();
- $skip_on_save = $this->_db_skip_on_save();
- $skip_on_insert = array_merge($skip_on_insert, $skip_on_save);
- $db = $this->_db();
- $primary_key = $this->_db_primary_key();
-
- $this->before_insert();
-
- /* Loop over the columns and build an INSERT query, which contains two
- * lists: one list of column names and one list of values to be inserted */
- $number_of_columns = 0;
- $names = array();
- $values = array();
- foreach ($columns as $name => $type)
- {
- assert('is_string($name)');
- assert('is_string($type)');
-
- /* Skip the primary key */
- if ($name === $primary_key && $skip_primary_key)
- continue;
-
- /* Skip columns which should be filled by the database */
- if (in_array($name, $skip_on_insert) && !$this->is_set($name))
- continue;
-
- $number_of_columns++;
- $names[] = $name;
- $value_types[] = sprintf('?%s:%s?', $type, $name); /* placeholder for real values */
- $values[$name] = $this->getdefault($name, null);
- }
-
- /* Create SQL for the list of column names */
- $columns_tpl = new SQLTemplate(
- join(', ', array_fill(0, $number_of_columns, '?column?')),
- $db);
- $columns_sql = $columns_tpl->fill($names);
-
- /* Create SQL for the list of column values */
- $values_tpl = new SQLTemplate(
- join(', ', $value_types),
- $db);
- $values_sql = $values_tpl->fill($values);
-
-
- /* Prepare and execute the query */
- $query = sprintf('INSERT INTO ?table? (%s) VALUES (%s)', $columns_sql, $values_sql);
- $pq = $db->prepare($query);
- $rs = $pq->execute($table);
-
- if ($skip_primary_key)
- {
- /* Find out the new primary key value */
- switch ($db->type)
- {
- /* MySQL has a custom SQL function */
- case 'mysql':
- $row = $db->prepare_execute_fetch(
- 'SELECT LAST_INSERT_ID() AS id');
- $this->_set($primary_key, $row['id']);
- break;
-
- /* SQLite has a special function */
- case 'sqlite':
- $this->_set($primary_key, sqlite_last_insert_rowid($db->backend->handle));
- break;
-
- /* PostgreSQL uses sequences */
- case 'postgresql':
- $primary_key_sequence = $this->_db_primary_key_sequence();
- if (is_null($primary_key_sequence))
- {
- /* Try to use PostgreSQL defaults */
- $primary_key_sequence = sprintf(
- '%s_%s_seq',
- $table,
- $primary_key);
- }
- assert('is_string($primary_key_sequence)');
- $row = $db->prepare_execute_fetch(
- 'SELECT currval(?string?) AS id',
- $primary_key_sequence);
- $this->_set($primary_key, $row['id']);
- break;
-
- /* Fallback for unsupported backends */
- default:
- $row = $db->prepare_execute_fetch(
- 'SELECT MAX(?column?) AS id FROM ?table?',
- $primary_key, $table);
- $this->_set($primary_key, $row['id']);
- break;
- }
- }
-
- $this->after_insert();
- }
-
- /**
- * Updates an existing record in the database with the current instance
- * data. Don't use this method directly, use save() instead.
- *
- * \see AutoRecord::save
- */
- protected function __db_update()
- {
- $table = $this->_db_table();
- $columns = $this->_db_columns();
- $db = $this->_db();
- $skip_on_update = $this->_db_skip_on_update();
- $skip_on_save = $this->_db_skip_on_save();
- $skip_on_update = array_merge($skip_on_update, $skip_on_save);
- $primary_key = $this->_db_primary_key();
- $primary_key_value = $this->get($primary_key);
-
- $this->before_update();
-
- /* Loop over the columns and build an UPDATE query */
- $placeholders = array();
- $values = array();
- foreach ($columns as $name => $type)
- {
- assert('is_string($name)');
- assert('is_string($type)');
-
- /* Skip the primary key */
- if ($name === $primary_key)
- continue;
-
- /* Skip read-only values */
- if (in_array($name, $skip_on_update))
- continue;
-
- $placeholders[] = sprintf('%s = ?%s:%s?', $db->backend->escape_column_name($name), $type, $name);
- $values[$name] = $this->getdefault($name, null);
- }
-
- if(count($placeholders))
- {
- /* Create SQL for the list of column names */
- $update_tpl = new SQLTemplate(join(', ', $placeholders), $db);
- $update_sql = $update_tpl->fill($values);
-
- /* Prepare and execute the query */
- $pq = $db->prepare('UPDATE ?table? SET ?raw? WHERE ?column? = ?int?');
- $rs = $pq->execute($table, $update_sql, $primary_key, $primary_key_value);
- }
-
- $this->after_update();
- }
-
- /**
- * Save this record in the database. If the record was previously unsaved
- * (no primary key value was set), an INSERT query is performed. Otherwise,
- * an UPDATE on the existing row is done.
- *
- * \param new
- * Whether or not we should insert a new row. Leave empty to check on the
- * primary key.
- */
- public function save($new=null)
- {
- $this->before_save();
-
- if (is_null($new))
- {
- /* Default behaviour */
- $primary_key = $this->_db_primary_key();
- if ($this->is_set($primary_key))
- $this->__db_update();
- else
- $this->__db_insert();
- } else
- {
- /* Forced new/existing record */
- if ($new)
- $this->__db_insert(false);
- else
- $this->__db_update();
- }
-
- $this->after_save();
- }
-
- /**
- * Delete this record from the database. If the record was previously
- * unsaved, this is a no-op. Note that this method overrides
- * Container::delete() (and Container::invalidate()). If you provide
- * a parameter, the call is handed off to Container::delete() instead of
- * deleting the record from the database.
- *
- * \param $name
- * Do not specify this! It's for code compatibility with Container only.
- *
- * \fixme See bug 173044
- */
- public function delete($name=null)
- {
- /* If there are any parameters, we propagate the call to Container,
- * instead of deleting the record from the database. This is evil and
- * should be solved in a clean way. See bug 173044. */
- if (!is_null($name))
- return Container::delete($name);
-
- $this->before_delete();
-
- $primary_key = $this->_db_primary_key();
- if ($this->is_set($primary_key))
- {
- $primary_key_value = $this->get($primary_key);
- $db = $this->_db();
- $table = $this->_db_table();
- $db->prepare_execute(
- 'DELETE FROM ?table? WHERE ?column? = ?int?;',
- $table, $primary_key, $primary_key_value);
- }
-
- $this->after_delete();
- }
-
- /**
- * Toggle a boolean value in this record. If the value was previously unset
- * (SQL NULL), the value is initialized to true.
- *
- * \param $column
- * The name of the column to toggle.
- */
- public function toggle($column)
- {
- assert('is_string($column)');
- $columns = $this->_db_columns();
- assert('array_has_key($columns, $column)');
- assert('SQLTemplate::column_type_from_string($columns[$column]) == ANEWT_DATABASE_TYPE_BOOLEAN;');
-
- $current_value = $this->getdefault($column, null);
- if (is_null($current_value))
- $new_value = true;
-
- else
- {
-
- /* Handle strings and integers, because some databases don't support
- * boolean column types (MySQL) and others don't support column
- * types at all (SQLite). */
- if (is_int($current_value))
- $current_value = (bool) $current_value;
- elseif (is_string($current_value))
- $current_value = ($current_value !== '0');
-
- assert('is_bool($current_value)');
- $new_value = !$current_value;
- }
- $this->set($column, $new_value);
- }
-
- /** \} */
-
-
- /**
- * \{
- * \name Callback methods
- *
- * Callback methods that can be overridden to add specific functionality.
- *
- * Autorecord instances call some special callback methods when certain
- * actions are about to take place (e.g. AutoRecord::before_save()) or have
- * just taken place (e.g. AutoRecord::after_delete). These methods do
- * nothing by default, but you can override one or more of them in your own
- * classes if you want to do specific things, e.g. to fix up values before
- * they enter the database (but you should really consider using
- * Container::get() and Container::set() for this purpose) or to break
- * foreign key references.
- */
-
- /** Callback before saving */
- public function before_save() {}
-
- /** Callback after saving */
- public function after_save() {}
-
- /** Callback before inserting */
- public function before_insert() {}
-
- /** Callback after inserting */
- public function after_insert() {}
-
- /** Callback before updating */
- public function before_update() {}
-
- /** Callback after updating */
- public function after_update() {}
-
- /** Callback before deletion */
- public function before_delete() {}
-
- /** Callback after deletion */
- public function after_delete() {}
-
- /** \} */
-
-
- /**\{
- * \name Static public API methods
- *
- * Note: These methods only have signatures, so that they can be documented.
- * The actual implementation is done using magic in the register() method.
- */
-
- /**
- * Select clause with all fields
- */
- protected static function _db_select_clause($table_alias=null) {}
-
- /**
- * Create instance from array.
- *
- * \param $arr
- * An associative array with data, e.g. a row from a database
- *
- * \return
- * AutoRecord instance
- *
- * \see _db_objects_from_arrays
- */
- protected static function _db_object_from_array($arr) {}
-
- /**
- * Create instances from arrays.
- *
- * \param $arrs
- * List of associative arrays with data, e.g. multiple rows from
- * a database
- *
- * \return
- * Array of AutoRecord instances (may be empty)
- *
- * \see _db_object_from_array
- */
- protected static function _db_objects_from_arrays($arrs) {}
-
- /**
- * Find all records in the database
- *
- * \return
- * Array of AutoRecord instances (may be empty)
- */
- public static function find_all() {}
-
- /**
- * Find records by id.
- *
- * \param $values
- * The primary key values of the records to retrieve
- *
- * \return
- * Array of AutoRecord instances (may be empty)
- *
- * \see find_one_by_id
- */
- public static function find_by_id($values) {}
-
- /**
- * Find a single record by id.
- *
- * \param $value
- * The primary key value of the record to retrieve
- *
- * \return
- * AutoRecord instance (or NULL)
- *
- * \see find_by_id
- */
- public static function find_one_by_id($value) {}
-
- /**
- * Find records by providing SQL contraints.
- *
- * \param $sql
- * The constraints of the SQL query. This can be either null (no
- * constraints, selects all records, but please use find_all() instead),
- * a string (the part of the WHERE clause up to the end of the query) or
- * an associative array (with where, order-by, limit and offset indices,
- * all optional). You can use ?str?-style placholders for the data
- * provided in $values
- *
- * \param $values
- * The values to be substituted for the placeholders your provided with
- * the constraints.
- *
- * \see find_one_by_sql
- */
- public static function find_by_sql($sql=null, $values=null) {}
-
- /**
- * Find a single record by providing SQL contraints.
- *
- * \param $sql
- * Contraints of the SQL query
- *
- * \param $values
- * Values to be substituted in the query
- *
- * \return
- * AutoRecord instance (or NULL)
- *
- * \see find_by_sql
- */
- public static function find_one_by_sql($sql=null, $values=null) {}
-
- /**
- * Find records by column value. This is a shorthand to find records based
- * on the value of a single column, e.g. a unique key.
- *
- * \param $column
- * The name of the column to use
- *
- * \param $value
- * The value for the column
- *
- * \return
- * Array of AutoRecord instances (may be empty)
- */
- public static function find_by_column($column, $value) {}
-
- /**
- * Find a single record by column value. This is a shorthand to find a record
- * based on the value of a single column, e.g. a unique key.
- *
- * \param $column
- * The name of the column to use
- *
- * \param $value
- * The value for the column
- *
- * \return
- * AutoRecord instance (or NULL)
- */
- public static function find_one_by_column($column, $value) {}
-
- /**
- * Returns an array of additional static methods to be included in the new class
- * on registering.
- *
- * The format of the array elements is $method_name => $method_code, where
- * $method_name is the name of the method, en $method_code is a string containing
- * the code of the method, including the "function" keyword.
- *
- * Every instance of @@CLASS@@ in $method_code will be substituted for the class
- * name of the registring function.
- */
- protected static function _autorecord_extra_methods() { return array(); }
-
- /** \} */
-}
-
-?>
=== removed file 'autorecord.old/autorecord.test.php'
--- autorecord.old/autorecord.test.php 2009-03-27 12:12:33 +0000
+++ autorecord.old/autorecord.test.php 1970-01-01 00:00:00 +0000
@@ -1,117 +0,0 @@
-<?php
-
-error_reporting(E_ALL | E_STRICT);
-require_once '../anewt.lib.php';
-
-anewt_include('autorecord');
-
-/**
- * Sample Person class with a simple database schema
- */
-class Person_ extends AutoRecord
-{
- /**
- * Table name
- */
- static function _db_table()
- {
- return 'person';
- }
-
- /**
- * Default sort column
- */
- static function _db_sort_column()
- {
- return 'age';
- }
-
- /**
- * Simple database layout
- */
- static function _db_columns()
- {
- return array(
- 'id' => 'integer',
- 'name' => 'string',
- 'age' => 'integer',
- 'is_happy' => 'boolean',
- );
- }
-}
-
-/* Register the Person/Person_ class as an AutoRecord */
-AutoRecord::register('Person');
-
-
-/* Database connection (in-memory SQLite database) */
-$db = DB::get_instance('sqlite', array(
- 'filename' => ':memory:',
- 'debug' => true,
- 'debug_print' => true,
- ));
-
-/* Create the schema (sqlite ignores column types, though) */
-$db->prepare_execute('CREATE TABLE Person (
- id INTEGER PRIMARY KEY,
- name VARCHAR(255),
- age INTEGER,
- is_happy BOOLEAN
- )');
-
-$pq = $db->prepare('INSERT INTO Person (id, name, age, is_happy) VALUES (?int?, ?str?, ?int?, ?bool?)');
-$pq->execute(1, 'A', 10, true);
-$pq->execute(2, 'B', 11, false);
-$pq->execute(3, 'C', 12, false);
-$pq->execute(4, 'D', 13, null);
-$pq->execute(5, 'E', 14, false);
-
-
-
-/* Test the AutoRecord retrieval methods */
-
-$result = Person::find_one_by_id(2);
-// $result = Person::find_by_id(2);
-// $result = Person::find_by_id(array(2, 4));
-// $result = Person::find_by_id(2, 3);
-
-// $result = Person::find_all();
-// $result = Person::find_by_sql();
-// $result = Person::find_by_sql('WHERE id > ?int? ORDER BY age DESC LIMIT ?int?', 2, 2);
-// $result = Person::find_one_by_sql(array(
-// 'where' => 'id > ?int?',
-// 'order-by' => 'age DESC',
-// 'limit' => '?int?',
-// ), 1, 3);
-
-var_dump($result);
-
-/* Test the save (update/insert) and delete methods */
-
-$p1 = Person::find_one_by_id(1);
-$p1->set('name', 'John');
-$p1->set('age', '12');
-$p1->save();
-
-$p2 = new Person();
-$p2->set('name', 'Foo');
-$p2->set('age', '2');
-$p2->set('is_happy', true);
-$p2->save();
-
-/* Test toggle() */
-
-$p1->toggle('is_happy');
-$p1->save();
-
-$p2->toggle('is_happy');
-$p2->save();
-
-
-/* Dump all data in the person table */
-$rows = $db->prepare_execute_fetch_all('SELECT * FROM person');
-foreach ($rows as $row) {
- echo array_format($row), "\n";
-}
-
-?>
=== removed file 'autorecord.old/main.lib.php'
--- autorecord.old/main.lib.php 2006-08-07 16:03:31 +0000
+++ autorecord.old/main.lib.php 1970-01-01 00:00:00 +0000
@@ -1,26 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, autorecord module
- *
- * Copyright (C) 2006 Wouter Bolsterlee <uws@xxxxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-anewt_include('autorecord/autorecord');
-
-?>
=== removed directory 'database.old'
=== removed file 'database.old/backend.lib.php'
--- database.old/backend.lib.php 2009-03-26 16:47:17 +0000
+++ database.old/backend.lib.php 1970-01-01 00:00:00 +0000
@@ -1,209 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2004-2006 Wouter Bolsterlee <uws@xxxxxxxxx>
- * Copyright (C) 2004-2005 Jasper Looije <jasper@xxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-/**
- * Base class for database backends. Most methods should be overridden in
- * subclasses that implement a specific backend.
- */
-abstract class DatabaseBackend
-{
- var $db; /**< \private Database object instance */
-
- /**
- * Returns the type of the database (must be overridden).
- */
- abstract function get_type();
-
-
- /* Connection handling */
-
- /**
- * Sets up the settings when using a deferred connection. Can be overridden.
- */
- function setup($settings) { }
-
- /**
- * Connects to the database.
- *
- * \param $settings
- * The database settings as an associative array.
- */
- abstract function connect(array $settings);
-
- /**
- * Disconnects from the database.
- */
- abstract function disconnect();
-
- /**
- * Selects the database to use.
- *
- * \param $name
- * The name of teh database to use.
- */
- abstract function select_db($name);
-
-
- /* Escaping */
-
- /**
- * Escapes a boolean for use in SQL queries. Override this method if the
- * specific type of database has better escaping functions available.
- *
- * \param $bool
- * The boolean to escape.
- *
- * \return
- * The escaped value.
- */
- function escape_boolean($bool)
- {
- assert('is_bool($bool)');
- return $bool ? '1' : '0';
- }
-
- /**
- * Escapes a string for use in SQL queries. Override this method if the
- * specific type of database has better escaping functions available.
- *
- * \param $str
- * The string to escape.
- *
- * \return
- * The escaped string.
- */
- function escape_string($str)
- {
- assert('is_string($str)');
- return sprintf("'%s'", addslashes($str));
- }
-
- /**
- * Escapes a table name for use in SQL queries. Override this method if the
- * specific type of database has better escaping functions available.
- *
- * \param $str
- * The string to escape.
- *
- * \return
- * The escaped string.
- */
- function escape_table_name($str)
- {
- assert('is_string($str)');
- return $str;
- }
-
- /**
- * Escapes a column name for use in SQL queries. Override this method if the
- * specific type of database has better escaping functions available.
- *
- * \param $str
- * The string to escape.
- *
- * \return
- * The escaped string.
- */
- function escape_column_name($str)
- {
- assert('is_string($str)');
- return $str;
- }
-
- /**
- * Escapes a date. This method only adds quotes.
- *
- * \param $date
- * The value to escape.
- *
- * \return
- * The escaped value.
- */
- function escape_date($date)
- {
- assert('is_string($date)');
- return sprintf("'%s'", $date);
- }
-
- /**
- * Escapes a time. This method only adds quotes.
- *
- * \param $time
- * The value to escape.
- *
- * \return
- * The escaped value.
- */
- function escape_time($time)
- {
- assert('is_string($time)');
- return sprintf("'%s'", $time);
- }
-
- /**
- * Escapes a datetime. This method only adds quotes.
- *
- * \param $datetime
- * The value to escape.
- *
- * \return
- * The escaped value.
- */
- function escape_datetime($datetime)
- {
- assert('is_string($datetime)');
- return sprintf("'%s'", $datetime);
- }
-
- /* Transaction-related methods */
-
- /**
- * Starts a transaction. Override this method for backends that need
- * customization.
- */
- function transaction_begin()
- {
- $this->db->prepare_execute('BEGIN');
- }
-
- /**
- * Commits a transaction. Override this method for backends that need
- * customization.
- */
- function transaction_commit()
- {
- $this->db->prepare_execute('COMMIT');
- }
-
- /**
- * Rolls back a transaction. Override this method for backends that need
- * customization.
- */
- function transaction_rollback()
- {
- $this->db->prepare_execute('ROLLBACK');
- }
-}
-
-?>
=== removed file 'database.old/database.lib.php'
--- database.old/database.lib.php 2009-03-27 15:48:32 +0000
+++ database.old/database.lib.php 1970-01-01 00:00:00 +0000
@@ -1,375 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2004-2006 Wouter Bolsterlee <uws@xxxxxxxxx>
- * Copyright (C) 2004-2005 Jasper Looije <jasper@xxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-anewt_include('database/backend');
-anewt_include('database/sqltemplate');
-anewt_include('database/preparedquery');
-anewt_include('database/resultset');
-
-
-/**
- * Database connection class.
- *
- * This class is used to represent a database connection. It support multiple
- * backends.
- *
- * This class provides a get_instance convenience method that eases development
- * with just one database connection (as is the case with almost all
- * applications).
- */
-class DB
-{
- /* Static methods */
-
- /**
- * Obtain a database instance. This method is modeled after the singleton
- * design pattern, but you will need to initialize it with the connection
- * settings. The first call to this method will initialize the database with
- * the provided settings. Subsequent files return a reference to the
- * database instance (and paramaters are ignored).
- *
- * \param $type
- * The type of database to be used.
- *
- * \param $settings
- * An associative array of connection settings.
- *
- * \see DB
- * \see DB::connect
- */
- static function get_instance($type=null, $settings=null)
- {
- static $db;
-
- if (is_null($db))
- {
- if (is_null($type))
- trigger_error('Cannot create instance of DB, no type is specified.', E_USER_ERROR);
-
- $db = new DB($type);
-
- if (!is_null($settings))
- $db->settings = $settings;
- }
-
- return $db;
- }
-
-
- /* Instance variables and methods */
-
- var $type; /**< \private Type of database being used */
- var $backend; /**< \private Database backend instance */
- var $databasename; /**< \private Current database name */
- var $connected; /**< \private Boolean indication the connection status */
- var $last_query; /**< \private Last query executed */
- var $num_queries_executed = 0; /**< \private Counter for the number of queries executed */
- var $settings; /**< \private Settings for DB::setup($settings) */
-
-
- /* Debugging */
- var $debug = false; /**< \private Enable/disable debugging */
- var $debug_print = false; /**< \private Print queries before execution */
- var $queries_executed = array(); /**< \private List of executed queries (only used
- if debugging is on)*/
-
- /**
- * Constructor initalizes the database layer.
- *
- * \param $type
- * The type of database to be used (e.g. \c mysql or \c sqlite).
- *
- * \param $settings
- * Optional argument to be passed to connect().
- *
- * \see connect
- */
- function DB($type='mysql', $settings=null)
- {
- assert('is_string($type)');
-
- /* Initialize the backend */
- anewt_include(sprintf('database/%s/backend', $type));
- $dbtype = ucfirst(strtolower($type)) . 'DB';
- $this->backend = new $dbtype();
- $this->backend->db = $this;
- $this->type = $type;
-
- /* Initial connection */
- $this->connected = false;
- if (!is_null($settings))
- {
- $settings['type'] = $type;
- $this->connect($settings);
- }
- }
-
- /**
- * Prepares the database layer for deferred connection.
- *
- * \param $settings
- * Associative array of connection settings.
- */
- function setup($settings)
- {
- assert('is_assoc_array($settings)');
- $dbtype = array_get_default($settings, 'type', 'mysql');
- $db = DB::get_instance($dbtype, $settings);
- return $db;
- }
-
- /**
- * Connects to the database using the specified connection settings.
- *
- * \param $settings
- * An associative array of connection settings. Set the \c debug and
- * \c debug_print keys to true if you want to debug your queries.
- */
- function connect($settings=null)
- {
- /* Connect only once */
- if (!$this->connected)
- {
- if (is_null($settings))
- {
- if (is_null($this->settings))
- trigger_error('Cannot connect to database, no settings are specified.', E_USER_ERROR);
-
- $settings = $this->settings;
- }
- assert('is_assoc_array($settings)');
- $this->backend->connect($settings);
- $this->connected = true;
- $this->debug = array_get_default($settings, 'debug', false);
- $this->debug_print = array_get_default($settings, 'debug_print', false);
- unset($this->settings);
- }
- }
-
- /**
- * Disconnects from the database. Not calling this method is harmless for
- * most database backends.
- */
- function disconnect()
- {
- if ($this->connected)
- {
- $this->backend->disconnect();
- $this->connected = false;
- }
- }
-
- /**
- * Selects the database to be used
- *
- * \param $name
- * The database name.
- */
- function select_db($name)
- {
- assert('is_string($name)');
- $this->backend->select_db($name);
- $this->databasename = $name;
- }
-
- /** \{
- * \name Query methods
- */
-
- /**
- * Prepares a query for execution.
- *
- * \param $sql
- * The SQL query to be prepared. Use <code>?fieldtype?</code> strings.
- *
- * \return
- * A new PreparedQuery instance that can be executed.
- */
- function prepare($sql)
- {
- is_string($sql) && (strlen($sql)>0)
- or trigger_error('DB::prepare() needs a string parameter',
- E_USER_ERROR);
-
- $pq = new PreparedQuery($sql, $this);
- $pq->debug = $this->debug;
- $pq->debug_print = $this->debug_print;
- return $pq;
- }
-
- /**
- * Convenience method to quickly execute a single query and fetch all
- * resulting rows from the result set. If you want to use a query multiple
- * times, you should obtain a PreparedQuery object by calling the prepare()
- * method, execute it and operate on the ResultSet object.
- *
- * \param $sql
- * The SQL query to execute. Placeholders (e.g. <code>?int?</code>) should be used.
- *
- * \param $params
- * Zero or more parameters to be filled in in the $query. The number of
- * parameters should match the number of placeholders in $query
- *
- * \see DB::prepare_execute
- * \see DB::prepare_execute_fetch
- * \see DB::prepare
- * \see PreparedQuery
- * \see ResultSet::fetch_all
- */
- function prepare_execute_fetch_all($sql, $params=null)
- {
- $args = func_get_args();
- assert('count($args) >= 1');
- array_shift($args); // remove first argument (sql query)
-
- if ((count($args) == 1) && (is_array($args[0]) || $args[0] instanceof Container))
- $args = $args[0];
-
- $pq = $this->prepare($sql);
- $rs = $pq->execute($args);
- return $rs->fetch_all();
- }
-
- /**
- * Convenience method to quickly execute a single query and fetch one
- * resulting row from the result set. See DB::prepare_execute_fetch_all for
- * more information.
- *
- * \param
- * $sql The SQL query to execute.
- *
- * \param
- * $params Zero or more parameters to be filled in in the $query.
- *
- * \see DB::prepare_execute
- * \see DB::prepare_execute_fetch_all
- * \see DB::prepare
- * \see PreparedQuery
- * \see ResultSet::fetch_all
- */
- function prepare_execute_fetch($sql, $params=null)
- {
- $args = func_get_args();
- assert('count($args) >= 1');
- array_shift($args); // remove first argument (sql query)
-
- if ((count($args) == 1) && (is_array($args[0]) || $args[0] instanceof Container))
- $args = $args[0];
-
- $pq = $this->prepare($sql);
- $rs = $pq->execute($args);
- $row = $rs->fetch();
- $rs->free();
- return $row;
- }
-
- /**
- * Convenience method to quickly execute a single query. No results are
- * retrieved. This method is pretty useless for SELECT queries, the number
- * of affected rows is returned instead of result rows. See
- * DB::prepare_execute_fetch_all for more information.
- *
- * \param $sql
- * The SQL query to execute.
- *
- * \param $params
- * Zero or more parameters to be filled in in the $query.
- *
- * \return
- * The number of rows affected by the query. This only works for queries
- * that operate on a number of rows, i.e. \c INSERT, \c UPDATE, \c
- * REPLACE, and \c DELETE queries. For other query types \c null is
- * returned.
- *
- * \see DB::prepare_execute_fetch
- * \see DB::prepare_execute_fetch_all
- * \see DB::prepare
- * \see PreparedQuery
- * \see ResultSet::fetch_all
- */
- function prepare_execute($sql, $params=null)
- {
- $args = func_get_args();
- assert('count($args) >= 1');
- array_shift($args); // remove first argument (sql query)
-
- if ((count($args) == 1) && (is_array($args[0]) || $args[0] instanceof Container))
- $args = $args[0];
-
- $pq = $this->prepare($sql);
- $rs = $pq->execute($args);
-
- $query_type = $rs->query_type();
- $ret = null;
- switch ($query_type)
- {
- case ANEWT_DATABASE_SQL_QUERY_TYPE_INSERT:
- case ANEWT_DATABASE_SQL_QUERY_TYPE_UPDATE:
- case ANEWT_DATABASE_SQL_QUERY_TYPE_REPLACE:
- case ANEWT_DATABASE_SQL_QUERY_TYPE_DELETE:
- $ret = $rs->count_affected();
- break;
-
- default:
- /* Return nothing */
- break;
- }
- $rs->free();
- return $ret;
- }
-
- /** \} */
-
- /** \{
- * \name Transaction methods
- */
-
- /**
- * Starts a transaction. This method calls into the backend.
- */
- function transaction_begin()
- {
- $this->backend->transaction_begin();
- }
-
- /**
- * Commits a transaction. This method calls into the backend.
- */
- function transaction_commit()
- {
- $this->backend->transaction_commit();
- }
-
- /**
- * Rolls back a transaction. This method calls into the backend.
- */
- function transaction_rollback()
- {
- $this->backend->transaction_rollback();
- }
-
- /** \} */
-}
-
-?>
=== removed file 'database.old/database.test.php'
--- database.old/database.test.php 2008-11-10 15:05:48 +0000
+++ database.old/database.test.php 1970-01-01 00:00:00 +0000
@@ -1,313 +0,0 @@
-<?php
-
-error_reporting(E_ALL | E_STRICT);
-require_once '../anewt.lib.php';
-
-anewt_include('database');
-
-$db = new DB('sqlite', array(
- 'filename' => ':memory:',
- 'debug' => true,
- 'debug_print' => false,
- ));
-
-$db->transaction_begin();
-$db->prepare_execute('CREATE TABLE typetesttable (
- boolean_col,
- integer_col,
- float_col,
- string_col,
- date_col,
- datetime_col,
- timestamp_col,
- time_col,
- raw_col)');
-$pq = $db->prepare('INSERT INTO typetesttable VALUES ( ?bool?, ?int?, ?float?, ?string?, ?date?, ?datetime?, ?timestamp?, ?time?, ?raw?)');
-
-/* Test null */
-$pq->execute(null, null, null, null, null, null, null, null, null);
-
-/* Test booleans */
-$pq->execute(true, null, null, null, null, null, null, null, null);
-$pq->execute(false, null, null, null, null, null, null, null, null);
-//$pq->execute('foo', null, null, null, null, null, null, null, null);
-
-/* Test ints */
-$pq->execute(null, 2, null, null, null, null, null, null, null);
-$pq->execute(null, '3', null, null, null, null, null, null, null);
-//$pq->execute(null, 'foo', null, null, null, null, null, null, null);
-
-/* Test floats */
-$pq->execute(null, null, 2.0, null, null, null, null, null, null);
-$pq->execute(null, null, 1.234, null, null, null, null, null, null);
-$pq->execute(null, null, 3, null, null, null, null, null, null);
-//$pq->execute(null, null, 'foo', null, null, null, null, null, null);
-
-/* Test strings */
-class StringWrap { function render() {return 'test';} }
-$pq->execute(null, null, null, 'Test', null, null, null, null, null);
-$pq->execute(null, null, null, 'Te\';st', null, null, null, null, null);
-$pq->execute(null, null, null, "\t\n;--'", null, null, null, null, null);
-$pq->execute(null, null, null, 2, null, null, null, null, null);
-$pq->execute(null, null, null, new StringWrap(), null, null, null, null, null);
-//$pq->execute(null, null, null, true, null, null, null, null, null);
-//$pq->execute(null, null, null, 1.234, null, null, null, null, null);
-
-/* Test dates */
-$pq->execute(null, null, null, null, '2006-06-06', null, null, null, null);
-$pq->execute(null, null, null, null, AnewtDateTime::now(), null, null, null, null);
-//$pq->execute(null, null, null, null, 'foo', null, null, null, null);
-//$pq->execute(null, null, null, null, true, null, null, null, null);
-//$pq->execute(null, null, null, null, 2, null, null, null, null);
-
-/* Test datetimes */
-$pq->execute(null, null, null, null, null, '2006-06-06 06:06:06', null, null, null);
-$pq->execute(null, null, null, null, null, AnewtDateTime::now(), null, null, null);
-$pq->execute(null, null, null, null, null, AnewtDateTime::sql(AnewtDateTime::now()), null, null, null);
-//$pq->execute(null, null, null, null, null, 'foo', null, null, null);
-//$pq->execute(null, null, null, null, null, true, null, null, null);
-//$pq->execute(null, null, null, null, null, 2, null, null, null);
-
-/* Test timestamps */
-$pq->execute(null, null, null, null, null, null, '2006-06-06 06:06:06', null, null);
-$pq->execute(null, null, null, null, null, null, AnewtDateTime::now(), null, null);
-$pq->execute(null, null, null, null, null, null, AnewtDateTime::sql(AnewtDateTime::now()), null, null);
-//$pq->execute(null, null, null, null, null, null, 'foo', null, null);
-//$pq->execute(null, null, null, null, null, null, true, null, null);
-//$pq->execute(null, null, null, null, null, null, 2, null, null);
-
-/* Test times */
-$pq->execute(null, null, null, null, null, null, null, '06:06:06', null);
-$pq->execute(null, null, null, null, null, null, null, AnewtDateTime::now(), null);
-$pq->execute(null, null, null, null, null, null, null, AnewtDateTime::sql_time(AnewtDateTime::now()), null);
-//$pq->execute(null, null, null, null, null, null, null, 'foo', null);
-//$pq->execute(null, null, null, null, null, null, null, true, null);
-//$pq->execute(null, null, null, null, null, null, null, 2, null);
-
-/* Test raw */
-$pq->execute(null, null, null, null, null, null, null, null, '"?int?"');
-
-/* Test all at once */
-$pq->execute(true, 3, 2.0, 'Test', '2006-06-06', '2006-06-06 06:06:06', '2006-06-06 06:06:06', '06:06:06', '"?raw?"');
-
-
-/* test named placeholders with associative arrays */
-$pq = $db->prepare('INSERT INTO typetesttable VALUES ( ?bool:bool_var?, ?int:int_var?, ?float:float_var?, ?string:string_var?, ?date:date_var?, ?datetime:datetime_var?, ?timestamp:timestamp_var?, ?time:time_var?, ?raw:raw_var?)');
-
-$values = array(
- 'bool_var' => null,
- 'int_var' => null,
- 'float_var' => null,
- 'string_var' => null,
- 'date_var' => null,
- 'datetime_var' => null,
- 'timestamp_var' => null,
- 'time_var' => null,
- 'raw_var' => null
-);
-
-/* Test null */
-$pq->execute($values);
-
-#/* Test booleans */
-$values['bool_var'] = true;
-$pq->execute($values);
-$values['bool_var'] = false;
-$pq->execute($values);
-
-$values['bool_var'] = null;
-
-#/* Test ints */
-$values['int_var'] = 2;
-$pq->execute($values);
-$values['int_var'] = '3';
-$pq->execute($values);
-$values['int_var'] = null;
-
-/* Test floats */
-$values['float_var'] = 2.0;
-$pq->execute($values);
-$values['float_var'] = 1.234;
-$pq->execute($values);
-$values['float_var'] = 3;
-$pq->execute($values);
-$values['float_var'] = null;
-
-
-/* Test strings */
-//class StringWrap { function render() {return 'test';} }
-$values['string_var'] = 'Test';
-$pq->execute($values);
-$values['string_var'] = 'Te\';st';
-$pq->execute($values);
-$values['string_var'] = "\t\n;--'";
-$pq->execute($values);
-$values['string_var'] = 2;
-$pq->execute($values);
-$values['string_var'] = new StringWrap();
-$pq->execute($values);
-$values['string_var'] = null;
-
-/* Test dates */
-$values['date_var'] = '2006-06-06';
-$pq->execute($values);
-$values['date_var'] = AnewtDateTime::now();
-$pq->execute($values);
-$values['date_var'] = null;
-
-/* Test datetimes */
-$values['datetime_var'] = '2006-06-06 06:06:06';
-$pq->execute($values);
-$values['datetime_var'] = AnewtDateTime::now();
-$pq->execute($values);
-$values['datetime_var'] = AnewtDateTime::sql(AnewtDateTime::now());
-$pq->execute($values);
-$values['datetime_var'] = null;
-
-/* Test timestamps */
-$values['timestamp_var'] = '2006-06-06 06:06:06';
-$pq->execute($values);
-$values['timestamp_var'] = AnewtDateTime::now();
-$pq->execute($values);
-$values['timestamp_var'] = AnewtDateTime::sql(AnewtDateTime::now());
-$pq->execute($values);
-$values['timestamp_var'] = null;
-
-/* Test times */
-$values['time_var'] = '06:06:06';
-$pq->execute($values);
-$values['time_var'] = AnewtDateTime::now();
-$pq->execute($values);
-$values['time_var'] = null;
-
-/* Test raw */
-$values['raw_var'] = '"?int?"';
-$pq->execute($values);
-$values['raw_var'] = null;
-
-/* Test all at once */
-$values = array(
- 'bool_var' => true,
- 'int_var' => 3,
- 'float_var' => 2.0,
- 'string_var' => 'Test',
- 'date_var' => '2006-06-06',
- 'datetime_var' => '2006-06-06 06:06:06',
- 'timestamp_var' => '2006-06-06 06:06:06',
- 'time_var' => '06:06:06',
- 'raw_var' => '"?raw?"'
-);
-$pq->execute($values);
-
-/* test named placeholders with containers */
-$values = new Container(array(
- 'bool_var' => null,
- 'int_var' => null,
- 'float_var' => null,
- 'string_var' => null,
- 'date_var' => null,
- 'datetime_var' => null,
- 'timestamp_var' => null,
- 'time_var' => null,
- 'raw_var' => null
-));
-
-/* Test null */
-$pq->execute($values);
-
-#/* Test booleans */
-$values->set('bool_var', true);
-$pq->execute($values);
-$values->set('bool_var', false);
-$pq->execute($values);
-
-$values->set('bool_var', null);
-
-#/* Test ints */
-$values->set('int_var', 2);
-$pq->execute($values);
-$values->set('int_var', '3');
-$pq->execute($values);
-$values->set('int_var', null);
-
-/* Test floats */
-$values->set('float_var', 2.0);
-$pq->execute($values);
-$values->set('float_var', 1.234);
-$pq->execute($values);
-$values->set('float_var', 3);
-$pq->execute($values);
-$values->set('float_var', null);
-
-
-/* Test strings */
-//class StringWrap { function render() {return 'test';} }
-$values->set('string_var', 'Test');
-$pq->execute($values);
-$values->set('string_var', 'Te\';st');
-$pq->execute($values);
-$values->set('string_var', "\t\n;--'");
-$pq->execute($values);
-$values->set('string_var', 2);
-$pq->execute($values);
-$values->set('string_var', new StringWrap());
-$pq->execute($values);
-$values->set('string_var', null);
-
-/* Test dates */
-$values->set('date_var', '2006-06-06');
-$pq->execute($values);
-$values->set('date_var', AnewtDateTime::now());
-$pq->execute($values);
-$values->set('date_var', null);
-
-/* Test datetimes */
-$values->set('datetime_var', '2006-06-06 06:06:06');
-$pq->execute($values);
-$values->set('datetime_var', AnewtDateTime::now());
-$pq->execute($values);
-$values->set('datetime_var', AnewtDateTime::sql(AnewtDateTime::now()));
-$pq->execute($values);
-$values->set('datetime_var', null);
-
-/* Test timestamps */
-$values->set('timestamp_var', '2006-06-06 06:06:06');
-$pq->execute($values);
-$values->set('timestamp_var', AnewtDateTime::now());
-$pq->execute($values);
-$values->set('timestamp_var', AnewtDateTime::sql(AnewtDateTime::now()));
-$pq->execute($values);
-$values->set('timestamp_var', null);
-
-/* Test times */
-$values->set('time_var', '06:06:06');
-$pq->execute($values);
-$values->set('time_var', AnewtDateTime::now());
-$pq->execute($values);
-$values->set('time_var', null);
-
-/* Test raw */
-$values->set('raw_var', '"?int?"');
-$pq->execute($values);
-$values->set('raw_var', null);
-
-/* Test all at once */
-$values->seed(array(
- 'bool_var' => true,
- 'int_var' => 3,
- 'float_var' => 2.0,
- 'string_var' => 'Test',
- 'date_var' => '2006-06-06',
- 'datetime_var' => '2006-06-06 06:06:06',
- 'timestamp_var' => '2006-06-06 06:06:06',
- 'time_var' => '06:06:06',
- 'raw_var' => '"?raw?"'
-));
-$pq->execute($values);
-$db->transaction_commit();
-
-/* TODO: test column and table types */
-
-$db->disconnect();
-
-?>
=== removed file 'database.old/main.lib.php'
--- database.old/main.lib.php 2006-05-16 07:08:18 +0000
+++ database.old/main.lib.php 1970-01-01 00:00:00 +0000
@@ -1,26 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2004 Wouter Bolsterlee <uws@xxxxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-anewt_include('database/database');
-
-?>
=== removed file 'database.old/module.doc.xml'
--- database.old/module.doc.xml 2008-04-20 14:01:47 +0000
+++ database.old/module.doc.xml 1970-01-01 00:00:00 +0000
@@ -1,595 +0,0 @@
-<anewt:module
- xmlns:anewt="http://anewt.net/ns/2008/04/documentation"
- id="database"
- >
-
- <anewt:title>Database module</anewt:title>
-
- <p>The database module provides a convenient way to communicate
- with databases. Key features are a convenient <strong>object
- oriented API</strong>, <strong>full data type safety and
- validation</strong>, and <strong>support for multiple database
- engines</strong>.</p>
-
- <p>The database module provides you with a consistent API that abstracts
- the engine-specific functions in PHP, while retaining the full power the
- individual database engines have to offer.</p>
-
- <p>This chapter explains the basic concepts and contains some
- examples to help you getting started. Refer to the API documentation
- for a more in-depth description of the available objects and
- methods.</p>
-
-
- <anewt:section>
-
- <anewt:title>Database support</anewt:title>
-
- <p>Anewt's database module can communicate with several database
- engines. Anewt currently supports the following databases:</p>
-
- <ul>
- <li>MySQL</li>
- <li>PostgreSQL</li>
- <li>MS SQL Server</li>
- <li>SQLite</li>
- </ul>
-
- <p>The database module uses a pluggable backend architecture to support
- different database engines. All database specific functionality is
- implemented in these backends. This not only includes the raw API calls
- like <anewt:functionname>mysql_query()</anewt:functionname> and
- <anewt:functionname>pg_fetch_assoc()</anewt:functionname>, but also quoting of user supplied
- values and type conversion of data returned by the database
- engine.</p>
-
- <p>In short, Anewt abstracts the boring details like connection to the
- database, executing queries, fetching resulting data and checking data
- types, but Anewt will never try to be smart with the SQL you provide. It
- also won't hide custom or specific database functionality your database
- offers. Relational databases are just too complex and too powerful to be
- wrapped in a simple abstraction layer.</p>
-
- <p>You may argue that, given the maturity and standarization of the SQL
- language, switching to another database engine is a trivial task. While
- it may look reasonable at first sight, database portability is not to be
- taken lightly. Most databases have very specific functionality that
- cannot easily be ported to other databases. Just changing the connection
- parameters is not enough to switch to another database engine! Support
- for foreign key constraints, subqueries, triggers, views, indices and
- sequences differs drastically between databases. Last but not least all
- major database engines support many non-portable SQL functions and data
- types. Not using the power your database offers is naive at best and just
- plain stupid for real world applications. Therefore the Anewt database
- module won't try to be smart about things the programmer knows
- better.</p>
-
- </anewt:section>
-
-
- <anewt:section>
-
- <anewt:title>Initialization</anewt:title>
-
- <p>First of all you will need to establish a connection to the
- database. You are likely to do this from a initialization file
- that you include in each file of your project. For maximum
- flexibility you can keep the <code>$db_settings</code>
- connection parameters in a separate config file. This is useful
- for version control and deployment, allowing you to use different
- settings for each machine your applications runs on. Note that the
- <code>$db_settings</code> variable is deleted after the
- connection has been made. This is not really needed, but a good
- idea since it makes sure your database password can never be
- accessed from other parts of your code.</p>
-
- <p>An example initialization may look like this:</p>
-
- <anewt:example src="database-initialization">
- <anewt:title>Initializing the database module</anewt:title>
- </anewt:example>
-
- <p>The first line load the database module, the following lines
- construct a new <anewt:classref>DB</anewt:classref> instance that connects
- to the database engine.</p>
-
- <p>If you want to use a singleton database instance (see the
- section about object oriented applications below), the
- initialization step looks like this:</p>
-
- <anewt:example src="database-initialization-singleton">
- <anewt:title>Initializing a singleton database
- instance</anewt:title>
- </anewt:example>
-
-
- </anewt:section>
-
-
- <anewt:section>
-
- <anewt:title>Interacting with the database</anewt:title>
-
- <p>Now that we have established a connection, we can retrieve
- data from the database. To accomplish this, we prepare a query
- and execute it. The data from the rows in the result set are
- simply printed. More information about prepared queries and result
- sets can be found in the next section.</p>
-
- <anewt:example src="database-simple-1">
- <anewt:title>Simple data retrieval</anewt:title>
- </anewt:example>
-
- <p>Prepared queries support special placeholder markers that can
- later be filled in with user data. You need to provide the data
- type for the value that will be substituted for the placeholder.
- Anewt takes care of all data validation and quoting, so you don't
- need to fiddle with functions like
- <anewt:functionname>addslashes()</anewt:functionname>
- or <anewt:functionname>mysql_escape_string()</anewt:functionname> to make your queries
- correct.</p>
-
- <anewt:example src="database-simple-2">
- <anewt:title>Providing query parameters</anewt:title>
- </anewt:example>
-
- <p> Anewt knows how to deal with many other data types. Read on
- to the section on type safety for more information. </p>
-
- <p>To retrieve the number of rows in a resultset, use the
- <anewt:functionref>count()</anewt:functionref> method on a
- <anewt:classref>ResultSet</anewt:classref> instance. To see how many rows
- are affected by a query, use
- <anewt:functionref>count_affected()</anewt:functionref>
- (if supported by the backend).</p>
-
- <anewt:example src="database-count">
- <anewt:title>Getting the number of result rows</anewt:title>
- </anewt:example>
-
- </anewt:section>
-
-
- <anewt:section>
-
- <anewt:title>Prepared queries and result sets</anewt:title>
-
- <p>As you might have seen in the examples above, Anewt uses these steps
- to fetch data from the database:</p>
-
- <ul>
- <li>Prepare a query using placeholders</li>
- <li>Execute the query, providing parameters for the
- placeholders</li>
- <li>Retrieve the resulting records</li>
- </ul>
-
- <p>The Anewt database module contains a couple of classes:
- <anewt:classref>DB</anewt:classref>,
- <anewt:classref>PreparedQuery</anewt:classref>,
- <anewt:classref>ResultSet</anewt:classref>, and
- <anewt:classref>SQLTemplate</anewt:classref>. A
- <anewt:classref>DB</anewt:classref>
- instance represents a database connection. It takes care of the
- initial connection setup phase and provides you with the
- <anewt:functionref>prepare()</anewt:functionref> method that allows you to create a
- new <anewt:classref>PreparedQuery</anewt:classref> instance. You should
- never create a <anewt:classref>PreparedQuery</anewt:classref> instance by
- directly calling its constructor: always use the
- <code>$db->prepare()</code> method! This is needed because
- prepared queries are tightly linked to the database connection and
- should be setup carefully to use the correct quoting and execution
- functions. Finally, the
- <anewt:classref>SQLTemplate</anewt:classref> class
- takes care of variable checking and placeholder substitution. Most
- likely you won't have to deal with this class directly. Instead
- you'll use the type safety it provides using the
- <anewt:classref>PreparedQuery</anewt:classref> class.</p>
-
- <p><anewt:classref>PreparedQuery</anewt:classref> instances can be executed by
- calling their <code>execute()</code> method. To execute the actual SQL
- query, you should provide valid values for the placeholders (if any). You
- can provide multiple parameters to the <code>execute</code> method, or
- you can provide a single array holding the values. Which method
- you should use depends on your code. The result is exactly the
- same.</p>
-
- <anewt:example src="database-prepared-query">
- <anewt:title>Executing a prepared query with
- parameters</anewt:title>
- </anewt:example>
-
- <p>The result of a <code>$pq->execute()</code> is a
- <anewt:classref>ResultSet</anewt:classref> instance. This object is used to
- retrieve the resulting rows. Note that only certain types of SQL
- queries may return a <anewt:classref>ResultSet</anewt:classref>
- (<code>SELECT</code> queries do, <code>UPDATE</code> queries
- don't). Fetching the row data can be done using these three
- functions:</p>
-
- <ul>
- <li><anewt:functionref>fetch()</anewt:functionref> returns one single row from
- the set</li>
- <li><anewt:functionref>fetch_all()</anewt:functionref> returns all rows in the
- set as an array</li>
- <li><anewt:functionref>fetch_many($howmany)</anewt:functionref> returns an array
- of <code>$howmany</code> rows</li>
- </ul>
-
- <p>The actual rows are associative arrays with the column name
- (or alias) as the key and the actual data as the value. Anewt does
- not support numeric arrays or numeric indices for result rows.
- This is deliberate since it encourages you to write unmaintainable
- and non-verbose code, so please don't ask for it.</p>
-
- </anewt:section>
-
- <anewt:section>
-
- <anewt:title>Type safety</anewt:title>
-
- <p>One of the strengths of the Anewt database module is
- <strong>type safety</strong>. This means that every variable
- related to the database, both input and output, has an explicit
- type. Although beginning programmers might think explicit types
- cause more frustration than it's worth, Anewt forces you take the
- safe route and makes sure SQL security is not something to take
- care of when it's too late. You'll learn to appreciate it,
- really.</p>
-
- <p>First of all, some background information. PHP supports
- <strong>type juggling</strong> (automatic conversion between
- types), but this often yields unpredictable and unwanted results.
- An example is the automatic conversion of a string to the integer
- value 0 if it's used in an integer context. That means that
- <code>'some text' + 5</code> results in the integer value
- <code>5</code> instead of an error stating that strings and
- numbers cannot be added together. Another example: <code>min('some
- text', 5, true)</code> yields the string <code>'some
- text'</code>. This is extremely non-obvious, given the
- different types of the operands passed to the
- <anewt:functionname>min()</anewt:functionname> function. When variables are silently
- converted to other types, programming mistakes can slip in
- unnoticed. This may cause an invalid state in your databases, or
- even cause your application to be compromised by malicious users,
- because a corrupted data model may cause unexpected
- results.</p>
-
- <p>The above code snippets show that implicit variable conversion
- can lead to unpredictable and therefore possibly unsafe
- applications. A second problem that needs to be tackled in a
- database application is: how to deal with user supplied input? A
- commonly known vulnerability that takes advantage of unsafe user
- input handling is called <strong>SQL injection</strong>. This
- problem is caused by unsufficient user input sanitizing and
- escaping, causing malformed queries to be executed. Those
- malformed queries can do harmful things, like bypass login
- mechanisms, steal data or corrupt the database.</p>
-
- <p>Building SQL queries from user input can be done in a couple
- of ways, of which <strong>variable substitution</strong> and
- <strong>string concatenation</strong> are the most obvious.
- Although variable substitution makes your code look
- straight-forward and easy to read, it introduces huge security
- problems caused by the lack of variable escaping. With string
- concatenation, it's possible to escape values by adding function
- calls around each variable, but this is error-prone (you're likely
- to forget this at least once in your program) and makes it
- impossible to reuse queries. String concatenation also leads to an
- unreadable mess of quotes, dots and spaces.</p>
-
- <anewt:warning>
-
- <p>Never use <strong>variable substitution</strong> or
- <strong>string concatenation</strong> to include user input or
- other variables in your SQL strings.</p>
-
- </anewt:warning>
-
- <p>This document won't go into details about the ways in which
- SQL injection and other SQL vulnerabilities can cause your
- application to be compromised. We just show two examples below of
- the techniques to avoid:</p>
-
- <anewt:example src="database-incorrect">
- <anewt:title>Incorrect ways to construct SQL queries</anewt:title>
- </anewt:example>
-
- <p>To overcome the problems outlined above, the Anewt database
- module requires you to specify placeholders with explicit data
- types for all the values in SQL queries. All SQL strings sent to
- the database must pass a mandatory type checking phase,
- implemented in the <anewt:classref>SQLTemplate</anewt:classref> class. When
- preparing a query to be executed, special placeholders mark the
- places where your variables will be filled in. Each placeholder
- looks like <code>?type?</code>, where the type can be one of
- the data types from the listing below:</p>
-
- <dl>
-
- <dt><code>bool</code></dt>
- <dt><code>boolean</code></dt>
- <dd>
- for boolean values
- (<code>true</code> or <code>false</code>)
- </dd>
-
- <dt><code>i</code></dt>
- <dt><code>int</code></dt>
- <dt><code>integer</code></dt>
- <dd>
- for integer numbers
- (eg. <code>12345</code> or <code>-10133</code>)
- </dd>
-
- <dt><code>f</code></dt>
- <dt><code>float</code></dt>
- <dt><code>double</code></dt>
- <dd>
- for floating point numbers
- (eg. <code>1.41</code> or <code>3.14</code>)
- </dd>
-
- <dt><code>s</code></dt>
- <dt><code>str</code></dt>
- <dt><code>string</code></dt>
- <dt><code>varchar</code></dt>
- <dd>
- for strings
- (eg. <code>John Doe</code> or <code>"Quotes" ain't
- funny</code>)
- </dd>
-
- <dt><code>date</code></dt>
- <dt><code>datetime</code></dt>
- <dt><code>time</code></dt>
- <dt><code>timestamp</code></dt>
- <dd>
- for date and time values
- (strings like <code>2006-03-14</code> or
- <code>1983-01-15 18:30:00</code>, but preferabely
- <anewt:classref>DateTimeAtom</anewt:classref> instances)
- </dd>
-
- </dl>
-
- <p>If the type check fails, an error is thrown and
- <strong>script execution immediately stops</strong>. Yes,
- Anewt is extremely strict about this: incorrect placeholder values
- will not pass through unnoticed, since the cause of the failed
- check is either a programming error or a malicious user trying to
- do nasty things. This means that you, as the programmer, have to
- make sure each variable is of the correct type before trying to
- substitute it into the SQL query template.</p>
-
- <anewt:example src="database-invalid-values">
- <anewt:title>Supplying invalid SQL values</anewt:title>
- </anewt:example>
-
- <p>Most placeholder types accept PHP strings as values for
- non-string placeholders, in addition to the corresponding native
- PHP type. For instance, if you supply the string
- <code>'12'</code> for an integer placeholder, the string
- will converted to a number and the result will be the same as if
- you supplied the integer value <code>12</code>. Note that
- this totally different from PHP's own implicit type juggling: it
- only works if your string looks likes the expected type! So, if
- you supply <code>'John'</code> for an integer placeholder, a
- fatal error occurs, whereas casting to an integer in PHP would
- cause the string to be converted to the integer value
- <code>0</code>, which is not what you want.</p>
-
- <anewt:example src="database-string-conversion">
- <anewt:title>Supplying string values for non-string
- placeholders</anewt:title>
- </anewt:example>
-
- <p>In addition to the types outline above, three additional data
- types are supported. However, you should not use those for
- user-supplied data. Only use them for your own internal purposes.
- Dynamically named table and column names are generally not a good
- idea, unless you really know what you're doing. You're even less
- likely to need raw values. The values supplied are substituted in
- the query template without any checks applied, bypassing all
- security precautions.</p>
-
- <dl>
-
- <dt><code>col</code></dt>
- <dt><code>column</code></dt>
- <dd>
- for column names
- (string values, just some basic escaping done)
- </dd>
-
- <dt><code>table</code></dt>
- <dd>
- for table names
- (string values, just some basic escaping done)
- </dd>
-
- <dt><code>r</code></dt>
- <dt><code>raw</code></dt>
- <dd>
- for literal values
- (any value, no checking or escaping)
- </dd>
-
- </dl>
-
- <anewt:warning>
-
- <p><strong>Never use <code>raw</code> for user-supplied
- data.</strong> If you do use it for user data, this has the
- same effect as not having input checking at all, thus leaving
- your application vulnerable for SQL exploits. Use with extreme
- care!</p>
-
- </anewt:warning>
-
- <p>In most cases, the type checking and query validation will be
- done for you by the <anewt:classref>PreparedQuery</anewt:classref> class.
- However, if you're building complex queries or doing other SQL
- magic, you can use <anewt:classref>SQLTemplate</anewt:classref> directly.
- Using this class without a
- <anewt:classref>PreparedQuery</anewt:classref>
- instance allows you to do variable escaping using the placeholder
- syntax outlined above without actually issuing the query to the
- database engine. Usage of
- <anewt:classref>SQLTemplate</anewt:classref> is
- pretty straight-forward, but since this is an advanced topic, this
- manual won't go into detail about it. Look at the API
- documentation for the exact usage. The
- <anewt:classref>AutoRecord</anewt:classref> source code also provides lots
- of examples to learn from.</p>
-
- </anewt:section>
-
-
- <anewt:section>
-
- <anewt:title>Type conversion</anewt:title>
-
- <p>Now that you know all about database input and data types,
- it's time to look into <strong>database output</strong>.
- Values in resulting rows from a query are automatically casted to
- an appropriate PHP type. For most simple types the conversion is
- pretty straightforward: <code>VARCHAR</code> columns become
- strings, <code>INT</code> columns become PHP integers. Guess
- how <code>FLOAT</code> and <code>BOOLEAN</code>
- (PostgreSQL) columns end up. Exactly. All unsupported column types
- are just the strings as returned by the lower level database
- specific row fetching functions.. </p>
-
- <p>A special case are date and time columns. Those are converted
- to <anewt:classref>DateTimeAtom</anewt:classref> instances (simple objects
- that represent a timestamp). The
- <anewt:classref>DateTime</anewt:classref>
- class provides static methods format these objects into strings.
- Simple example: <code>print DateTime::date($row['last_modification'])</code>.
- Read the chapter about the <code>DateTime</code> module for
- more information on how to handle dates and times.</p>
-
- <anewt:note>
-
- <p>Not all database backends support automatic type conversion.
- PostgreSQL and MySQL do, but SQLite does not (it has no concept
- of column types). Unsupported types are always strings, so for
- unsupported database engines all row values are strings.</p>
-
- </anewt:note>
-
- </anewt:section>
-
- <anewt:section>
-
- <anewt:title>Convenience methods</anewt:title>
-
- <p>The three steps required to fetch data from a database table
- (prepare, execute, fetch) allow for maximum flexibility. However,
- most of the time you don't need this flexibility, but just want to
- get some data without too much hassle. To overcome this, three
- convenience methods are provided for the three most common cases.
- You don't have to use these methods, but for the simple cases it
- makes your code shorter and a bit easier to read.</p>
-
- <p>The first one is
- <anewt:functionref>prepare_execute_fetch()</anewt:functionref>.
- It allows you to quickly fetch a single row from the database. The
- second one is
- <anewt:functionref>prepare_execute_fetch_all()</anewt:functionref>,
- which allows you to fetch all rows returned by a given query. The
- last one is <anewt:functionref>prepare_execute()</anewt:functionref>, which is
- useful for queries not returing result rows, eg. insert or update
- queries.</p>
-
- <p>All three convenience methods accept multiple parameters. The
- first one is the SQL template, all following values are the values
- used for parameter substitution.</p>
-
- <anewt:example src="database-convenience">
- <anewt:title>Database convenience methods</anewt:title>
- </anewt:example>
-
- <p>See the API documentation for more information about these
- methods.</p>
-
- </anewt:section>
-
- <anewt:section>
-
- <anewt:title>Databases in object-oriented applications</anewt:title>
-
- <p>Although Anewt supports more than one simultaneous connection
- (just instantiate multiple <anewt:classref>DB</anewt:classref> objects),
- most applications only use one database connection. If you're
- building an application the object-oriented way (objects with
- application logic and such) and your objects need to access the
- database, you have to make the <anewt:classref>DB</anewt:classref> instance
- available to these objects. Several solutions are possible:</p>
-
- <p>The first solution is to <strong>pass a reference</strong>
- to the database instance to each instance of your class and store
- it in the instance.</p>
-
- <anewt:example src="database-passing-instance">
- <anewt:title>Passing the database instance as a
- parameter</anewt:title>
- </anewt:example>
-
- <p>The second solution is to use a <strong>global database
- instance</strong>. Using global variables is generally not a
- good idea.</p>
-
- <anewt:example src="database-global-instance">
- <anewt:title>Using a global database instance</anewt:title>
- </anewt:example>
-
- <p>The third and most elegant solution is to use the
- <strong>singleton design pattern</strong> and treat the
- database instance as a singleton object. The PHP language is a bit
- limited (although it's gotten slightly better in PHP5), so we have
- to do some tricks to make it work. First of all, the database
- initialization step has to be changed. Instead of creating a new
- instance by using the <anewt:classref>DB</anewt:classref> constructor, we
- use the static class method <anewt:functionref>&DB::get_instance($type,
- $settings)</anewt:functionref> to setup the database connection. You do
- this just once; each subsequent call to the
- <anewt:functionref>&DB::get_instance()</anewt:functionref> method should have no
- parameters. See the section about initialization for more
- information about initializing a database.</p>
-
- <anewt:example src="database-singleton">
- <anewt:title>Using a singleton database instance</anewt:title>
- </anewt:example>
-
- <p>As you can see, you just use <code>$db =
- &DB::get_instance()</code> whenever you need the database
- object anywhere in your code.</p>
-
- </anewt:section>
-
- <anewt:section>
-
- <anewt:title>Transactions</anewt:title>
-
- <p>The <anewt:classref>DB</anewt:classref> class provides three simple
- methods to begin, commit or rollback a transaction:</p>
-
- <ul>
- <li><anewt:functionref>DB::transaction_begin()</anewt:functionref></li>
- <li><anewt:functionref>DB::transaction_commit()</anewt:functionref></li>
- <li><anewt:functionref>DB::transaction_rollback()</anewt:functionref></li>
- </ul>
-
- <p>Note that transaction support depends on the database you're
- using. PostgreSQL supports transactions by default, but MySQL does
- not (at least not in all versions). Don't rely on the above
- methods if you're not sure whether your database supports
- them.</p>
-
- </anewt:section>
-
-</anewt:module>
-
-<!-- vim: set tw=72 : -->
=== removed directory 'database.old/mssql'
=== removed file 'database.old/mssql/backend.lib.php'
--- database.old/mssql/backend.lib.php 2008-10-25 22:18:29 +0000
+++ database.old/mssql/backend.lib.php 1970-01-01 00:00:00 +0000
@@ -1,109 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2004-2006 Wouter Bolsterlee <uws@xxxxxxxxx>
- * Copyright (C) 2005 Daniel de Jong <djong@xxxxxxxx>
- * Copyright (C) 2006 Marijn Kruisselbrink <m.kruisselbrink@xxxxxxxxxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-anewt_include('database/mssql/resultset');
-
-
-/**
- * MS SQL database abstraction.
- */
-class MssqlDB extends DatabaseBackend {
-
- var $id; /**< \private The mysql connection id */
-
- /**
- * Connects to the MSSQL database.
- *
- * \param $settings
- * An associative array with connection settings: the 'hostname',
- * 'username' and 'password' indices will be used.
- */
- function connect(array $settings) {
- is_array($settings) && isset($settings['hostname'],
- $settings['username'], $settings['password'])
- or trigger_error('Invalid parameters to connect()', E_USER_ERROR);
-
- $this->id = &mssql_pconnect(
- $settings['hostname'],
- $settings['username'],
- $settings['password'])
- or trigger_error(sprintf('Could not connect to databaseserver (%s)',
- $settings['hostname']), E_USER_ERROR);
-
- // suppress warnings
- if (function_exists('mssql_min_client_severity')) mssql_min_client_severity(100);
- if (function_exists('mssql_min_server_severity')) mssql_min_server_severity(100);
- if (function_exists('mssql_min_message_severity')) mssql_min_message_severity(100);
- if (function_exists('mssql_min_error_severity')) mssql_min_error_severity(100);
-
- }
-
- /**
- * Disconnects from the MSSQL database.
- */
- function disconnect() {
- mssql_close($this->id);
- }
-
- /**
- * Selects the given database.
- *
- * \param $name
- * The name of the database to use.
- */
- function select_db($name) {
- assert('is_string($name)');
-
- mssql_select_db($name, $this->id) or trigger_error('Could not select database', E_USER_ERROR);
- }
-
- /**
- * Returns the type of this database backend.
- *
- * \return
- * Always returns the string 'mssql'.
- */
- function get_type() {
- return 'mssql';
- }
-
- /**
- * Escapes a string for SQL queries.
- *
- * \param $str
- * The string to escape.
- *
- * \return
- * The escaped string.
- */
- function escape_string($str) {
- if (is_null($str))
- return 'NULL';
-
- return "'" . str_replace("'", "''", $str) . "'";
- }
-}
-
-?>
=== removed file 'database.old/mssql/resultset.lib.php'
--- database.old/mssql/resultset.lib.php 2009-02-16 14:26:27 +0000
+++ database.old/mssql/resultset.lib.php 1970-01-01 00:00:00 +0000
@@ -1,96 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2004-2004 Wouter Bolsterlee <uws@xxxxxxxxx>
- * Copyright (C) 2005 Daniel de Jong <djong@xxxxxxxx>
- * Copyright (C) 2006 Marijn Kruisselbrink <m.kruisselbrink@xxxxxxxxxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-define(ANEWT_DATABASE_MSSQL_ROWS_AFFECTED_EXISTS, function_exists('mssql_rows_affected'));
-
-
-/**
- * MS SQL-specific database result set.
- */
-class MssqlResultSet extends ResultSet {
-
- var $backend; /**< \private The backend instance */
- var $rs; /**< \private A resultset instance */
- var $rowcount;/**< \private The number of affected rows (for update/insert/delete queries) */
-
- /**
- * Constructs a new MssqlResultSet.
- *
- * \param $sql
- * The sql query to execute.
- * \param $backend
- * A reference to the used backend.
- */
- function MssqlResultSet($sql, &$backend) {
- assert('is_string($sql)');
-
- $this->sql = $sql;
- $this->backend = &$backend;
-
- // Attention! Due to a bug in the mssql driver, when you use insert or
- // update, mssql_query() always returns false, so that error checking is
- // effectively impossible.
- $this->rs = mssql_query($sql, $this->backend->id);
-
- if (!ANEWT_DATABASE_MSSQL_ROWS_AFFECTED_EXISTS) {
- // For update/insert/delete queries, figure out the number of rows affected
- $kw = strtolower(substr(trim($sql), 0, 6));
- if ($kw == "delete" || $kw == "insert" || $kw == "update") {
- $rs = mssql_query("SELECT @@ROWCOUNT", $this->backend->id);
- list($this->rowcount) = mssql_fetch_row($rs);
- } else {
- $this->rowcount = 0;
- }
- }
- }
-
- function fetch() {
- // Attention! Due to a bug in the sybase driver, a boolean 'true' is
- // returned when the query was succesful but did not return any rows. We
- // work around this problem by checking for this 'true' value.
- if ($this->rs === true) {
- return false;
- }
- return mssql_fetch_assoc($this->rs);
- }
-
- function count() {
- // Attention! See notes above.
- if ($this->rs === true) {
- return 0;
- }
- return mssql_num_rows($this->rs);
- }
-
- function count_affected() {
- if (ANEWT_DATABASE_MSSQL_ROWS_AFFECTED_EXISTS) {
- return mssql_rows_affected($this->rs);
- } else {
- return $this->rowcount;
- }
- }
-}
-
-?>
=== removed directory 'database.old/mysql'
=== removed file 'database.old/mysql/backend.lib.php'
--- database.old/mysql/backend.lib.php 2008-11-07 11:41:40 +0000
+++ database.old/mysql/backend.lib.php 1970-01-01 00:00:00 +0000
@@ -1,166 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2004-2006 Wouter Bolsterlee <uws@xxxxxxxxx>
- * Copyright (C) 2004 Jasper Looije <jasper@xxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-anewt_include('database/mysql/resultset');
-
-
-/**
- * Class providing MySQL database connectivity.
- */
-class MysqlDB extends DatabaseBackend
-{
- var $id; /**< \private The database connection id */
-
- /**
- * Connects to the MySQL database.
- *
- * \param settings An associative array with connection settings: the
- * 'hostname', 'username' and 'password' indices will be used.
- */
- function connect(array $settings)
- {
- is_array($settings) &&
- isset($settings['hostname'], $settings['username'],
- $settings['password'])
- or trigger_error('Invalid parameters to connect()', E_USER_ERROR);
-
- $this->id = mysql_pconnect(
- $settings['hostname'],
- $settings['username'],
- $settings['password'],
- true)
- or trigger_error(sprintf('Could not connect to database (%d: %s)',
- mysql_errno($this->id), mysql_error($this->id)),
- E_USER_ERROR);
-
- if (array_has_key($settings, 'database'))
- $this->select_db($settings['database']);
-
- }
-
- /**
- * Disconnects from the MySQL database.
- */
- function disconnect()
- {
- mysql_close($this->id);
- }
-
- /**
- * Selects the given database.
- *
- * \param $name The name of the database to use.
- */
- function select_db($name)
- {
- assert('is_string($name)');
-
- mysql_select_db($name, $this->id) or trigger_error(sprintf('Could not select database (%d: %s)', mysql_errno($this->id), mysql_error($this->id)), E_USER_ERROR);
- }
-
- /**
- * Returns the type of this database backend.
- *
- * \return Always returns the string 'mysql'.
- */
- function get_type()
- {
- return 'mysql';
- }
-
- /**
- * Escapes a string for SQL queries.
- *
- * \param $str The string to escape.
- *
- * \return The escaped string.
- */
- function escape_string($str)
- {
- assert('is_string($str)');
-
- /* The mysql_real_escape_string function depends on a valid connection,
- * so it can only be used if $this->id is a mysql resource, otherwise
- * mysql_escape_string has to be used. The $this->id resource is null if
- * the database connection is (not yet) established and SQLTemplate is
- * used to escape SQL strings. */
-
- if (is_resource($this->id))
- $str = mysql_real_escape_string($str, $this->id);
- else
- $str = mysql_escape_string($str);
-
- $out = sprintf("'%s'", $str);
- return $out;
- }
-
- /**
- * Escapes a table name for SQL queries.
- *
- * \param $str The string to escape.
- *
- * \return The escaped string.
- */
- function escape_table_name($str)
- {
- assert('is_string($str)');
-
- $parts = explode('.', $str);
-
- if (count($parts) == 1)
- {
- /* Add quotes */
- $out = sprintf('`%s`', $str);
-
- } else {
- /* Add quotes around each part */
- $result = array();
- foreach ($parts as $part)
- $result[] = sprintf('`%s`', $part);
-
- $out = implode('.', $result);
- }
-
- return $out;
- }
-
- /**
- * Escapes a column name for SQL queries.
- *
- * \param $str The string to escape.
- *
- * \return The escaped string.
- */
- function escape_column_name($str)
- {
- assert('is_string($str)');
-
- /* Same as escape_table_name */
- $out = $this->escape_table_name($str);
- return $out;
- }
-
-}
-
-?>
=== removed file 'database.old/mysql/resultset.lib.php'
--- database.old/mysql/resultset.lib.php 2009-07-20 20:39:48 +0000
+++ database.old/mysql/resultset.lib.php 1970-01-01 00:00:00 +0000
@@ -1,162 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * This code is copyrighted and distributed under the terms of the GNU LGPL.
- * See the README file for more information.
- */
-
-
-/**
- * MySQL-specific database result set.
- */
-class MysqlResultSet extends ResultSet {
-
- var $backend; /**< \private The backend instance */
- var $rs; /**< \private A resultset instance */
- var $data_types; /**< \private The data types in this result set */
- var $completely_traversed; /**< \private Whether this result set has been completely traversed */
- var $num_rows; /**< \private Total number of rows; only valid if completely_traversed is true */
- var $freed; /**< \private Whether this result set has been freed */
-
- /**
- * Constructs a new MysqlResultSet
- *
- * \param $sql The sql query to execute.
- * \param $backend A reference to the used backend.
- */
- function MysqlResultSet($sql, &$backend)
- {
- assert('is_string($sql)');
-
- $this->sql = $sql;
- $this->backend = &$backend;
-
- $this->completely_traversed = false;
- $this->freed = false;
-
- $this->rs = mysql_query($sql, $this->backend->id) or
- trigger_error(sprintf('Query failed (%d: %s)',
- mysql_errno($this->backend->id),
- mysql_error($this->backend->id)), E_USER_ERROR);
-
-
- /* Deduce column types for SELECT queries */
-
- if ($this->query_type() == ANEWT_DATABASE_SQL_QUERY_TYPE_SELECT)
- $this->deduce_types();
- }
-
- /**
- * Free resources associated with this result set.
- */
- function free()
- {
- if (!$this->freed && is_resource($this->rs))
- mysql_free_result($this->rs);
-
- $this->freed = true;
- }
-
-
- /* Fetching results */
-
- function fetch()
- {
- if ($this->completely_traversed)
- return false;
-
- $row = mysql_fetch_assoc($this->rs);
-
- /* No more rows? */
- if ($row === false)
- {
- $this->completely_traversed = true;
- $this->free();
- return false;
- }
-
- $this->num_rows++;
- $this->cast_row($row);
- return $row;
- }
-
-
- /* Result counting */
-
- function count()
- {
- /* mysql_num_rows() fails if the result set was freed, so we return the
- * number of rows we fetched earlier */
- if ($this->completely_traversed)
- return $this->num_rows;
-
- return mysql_num_rows($this->rs);
- }
-
- function count_affected()
- {
- return mysql_affected_rows($this->backend->id);
- }
-
-
- /* Type casting */
-
- function deduce_types()
- {
- for ($i = 0; $i < mysql_num_fields($this->rs); $i++)
- {
- $name = mysql_field_name($this->rs, $i);
- $type = mysql_field_type($this->rs, $i);
- $this->data_types[$name] = $type;
- }
- }
-
- function cast_row(&$row)
- {
- assert('is_assoc_array($row)');
-
- foreach (array_keys($row) as $key)
- {
- $type = $this->data_types[$key];
- $value = &$row[$key];
-
- /* Don't cast null values */
- if (is_null($value))
- continue;
-
- switch ($type)
- {
- case 'int':
- $value = (int) $value;
- break;
-
- case 'real':
- $value = (float) $value;
- break;
-
- case 'string':
- case 'blob':
- $value = (string) $value;
- break;
-
- case 'date':
- case 'datetime':
- case 'time':
- case 'timestamp':
- $value = AnewtDateTime::parse_string($value);
- break;
-
- default:
- /* No conversion, leave as string */
- break;
- }
-
- $row[$key] = $value;
- unset($value);
- }
- }
-}
-
-?>
=== removed directory 'database.old/postgresql'
=== removed file 'database.old/postgresql/backend.lib.php'
--- database.old/postgresql/backend.lib.php 2009-03-27 15:44:13 +0000
+++ database.old/postgresql/backend.lib.php 1970-01-01 00:00:00 +0000
@@ -1,244 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2006 Wouter Bolsterlee <uws@xxxxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-anewt_include('database/postgresql/resultset');
-
-
-/**
- * Class providing PostgreSQL database connectivity.
- */
-class PostgreSQLDB extends DatabaseBackend {
-
- var $id; /**< \private The database connection id */
- var $settings; /**< \private Database connection settings */
-
- /**
- * Sets up the settings for this backend. This is used for deferred database
- * connections, when the settings are needed before a connection is made.
- * Will be overwritten by PostgreSQLDB::connect($settings).
- *
- * \see connect
- */
- function setup($settings) {
- $this->settings = $settings;
- }
-
- /**
- * Connects to the PostgreSQL database.
- *
- * \param settings An associative array with connection settings: the
- * 'hostname', 'username' and 'password' indices will be used for connection
- * setttings. The key 'keep_settings' can be used to indicate whether the
- * settings are stored. The 'escape_column_names' and 'escape_table_names'
- * keys can be set to indicate whether column and table names should be
- * escaped when using CRUD functions.
- */
- function connect(array $settings) {
- if (is_null($settings))
- $settings = array();
-
- assert('is_assoc_array($settings)');
-
- /* We support "hostname", "username" and "pass" too, although the
- * real connection string uses other names */
- $aliases = array(
- 'hostname' => 'host',
- 'pass' => 'password',
- 'username' => 'user',
- 'database' => 'dbname',
- );
- foreach ($aliases as $old => $new) {
- if (array_has_key($settings, $old)) {
- array_set_default($settings, $new, $settings[$old]);
- }
- }
-
- /* List of keywords that are allowed in the connection string: */
- $keywords = array('host', 'hostaddr', 'port', 'dbname', 'user',
- 'password', 'connect_timeout', 'options', 'sslmode', 'service');
-
- /* Create a connection string from the supplied values, leaving out
- * illegal (name, value) pairs */
- $options = array();
- foreach ($keywords as $keyword) {
- if (array_key_exists($keyword, $settings)) {
- $value = $settings[$keyword];
-
- assert('is_string($value)');
-
- /* Escape single and double quotes */
- $value = str_replace("'", "\'", $value);
- $value = str_replace('"', '\"', $value);
-
- $options[] = sprintf('%s=%s', $keyword, $value);
- }
- }
- $connection_string = implode(' ', $options);
-
- $this->id = pg_connect($connection_string) or
- trigger_error(sprintf('Could not connect to database %s',
- $settings['dbname']), E_USER_ERROR);
-
- /* Keep connection settings only if requested. This makes select_db()
- * work, but stores the plaintext password in the object's memory. */
- if (!array_get_default($settings, 'keep_settings', false)) {
- /* Unset both the aliases and the connection keywords */
- array_unset_keys($settings, array_keys($aliases));
- array_unset_keys($settings, $keywords);
- }
-
- $this->settings = $settings;
- }
-
- /**
- * Disconnects from the PostgreSQL database.
- */
- function disconnect() {
- pg_close($this->id);
- }
-
- /**
- * Selects the given database. PostgreSQL does not support run-time database
- * switching, so we connect again with a different dbname parameter. This
- * requires keep_settings to be true in the connection options passed to
- * connect().
- *
- * \param $name The name of the database to use.
- *
- * \see connect
- */
- function select_db($name) {
- assert('is_string($name)');
-
- if (isset($this->settings) && is_array($this->settings)) {
- $settings = $this->settings;
- $settings['dbname'] = $name;
- $this->connect($settings);
-
- } else {
- trigger_error('PostgreSQLDB::select_db() does not work if you
- didn\'t set keep_settings to true in the connection
- options.', E_USER_ERROR);
- }
- }
-
- /**
- * Returns the type of this database backend.
- *
- * \return Always returns the string 'postgresql'.
- */
- function get_type() {
- return 'postgresql';
- }
-
- /**
- * Escapes a boolean for SQL queries.
- *
- * \param $bool The boolean to escape.
- *
- * \return The escaped value.
- */
- function escape_boolean($bool) {
- assert('is_bool($bool)');
- return $bool ? 'true' : 'false';
- }
-
- /**
- * Escapes a string for SQL queries.
- *
- * \param $str The string to escape.
- *
- * \return The escaped string.
- */
- function escape_string($str) {
- assert('is_string($str)');
- return "'" . pg_escape_string($str) . "'";
- }
-
- /**
- * \private
- *
- * Escapes a column or table name unconditionally.
- *
- * \param $str
- * The string to escape
- *
- * \return
- * The escaped string.
- */
- function _escape_column_or_table_name($str) {
- assert('is_string($str)');
-
- $quote_char = '"';
- $parts = explode('.', $str);
-
- if (count($parts) === 1) {
- /* Add quotes */
- return $quote_char . $str . $quote_char;
-
- } else {
- /* Add quote only for the last part */
- $result = array();
- foreach ($parts as $part) {
- $result[] = $quote_char . $part . $quote_char;
- }
- return implode('.', $result);
- }
- }
-
- /**
- * Escapes a table name for SQL queries.
- *
- * \param $str The string to escape.
- *
- * \return The escaped string.
- */
- function escape_table_name($str) {
- assert('is_string($str)');
-
- if (!array_get_default($this->settings, 'escape_table_names', true))
- return $str;
-
- return $this->_escape_column_or_table_name($str);
- }
-
- /**
- * Escapes a column name for SQL queries.
- *
- * \param $str The string to escape.
- *
- * \return The escaped string.
- */
- function escape_column_name($str) {
- assert('is_string($str)');
-
- if (!array_get_default($this->settings, 'escape_column_names', true))
- return $str;
-
- return $this->_escape_column_or_table_name($str);
- }
-
-}
-
-
-?>
=== removed file 'database.old/postgresql/resultset.lib.php'
--- database.old/postgresql/resultset.lib.php 2009-07-20 20:39:48 +0000
+++ database.old/postgresql/resultset.lib.php 1970-01-01 00:00:00 +0000
@@ -1,180 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2006 Wouter Bolsterlee <uws@xxxxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-/**
- * PostgreSQL-specific database result set.
- */
-class PostgreSQLResultSet extends ResultSet
-{
- var $backend; /**< \private The backend instance */
- var $rs; /**< \private A resultset instance */
- var $data_types; /**< \private The data types in this result set */
- var $freed; /**< \private Whether this result set has been freed */
-
- /**
- * Constructs a new PostgreSQLResultSet
- *
- * \param $sql The sql query to execute.
- * \param $backend A reference to the used backend.
- */
- function PostgreSQLResultSet($sql, &$backend)
- {
- assert('is_string($sql)');
-
- $this->sql = $sql;
- $this->backend = &$backend;
-
- $this->freed = false;
-
- $this->rs = pg_query($this->backend->id, $sql) or
- trigger_error(sprintf('Query failed (%s)',
- pg_last_error($this->backend->id)), E_USER_ERROR);
-
-
- /* Deduce column types for SELECT queries */
-
- if ($this->query_type() == ANEWT_DATABASE_SQL_QUERY_TYPE_SELECT)
- $this->deduce_types();
- }
-
- /**
- * Free resources associated with this result set.
- */
- function free()
- {
- if (!$this->freed && is_resource($this->rs))
- pg_free_result($this->rs);
-
- $this->freed = true;
- }
-
-
- function fetch()
- {
- $row = pg_fetch_assoc($this->rs);
-
- /* No more rows? */
- if ($row === false)
- {
- $this->free();
- return false;
- }
-
- $this->cast_row($row);
- return $row;
- }
-
- function count()
- {
- return pg_num_rows($this->rs);
- }
-
- function count_affected()
- {
- return pg_affected_rows($this->rs);
- }
-
- /**
- * \private Deduces the data types in this result set. This uses information
- * about the resultset as provided by the database.
- *
- * \see PostgreSQLResultSet::cast_types
- */
- function deduce_types()
- {
- for ($i = 0; $i < pg_num_fields($this->rs); $i++)
- {
- $name = pg_field_name($this->rs, $i);
- $type = pg_field_type($this->rs, $i);
- $this->data_types[$name] = $type;
- }
- }
-
- /**
- * \private Casts a row of data into native PHP data types. The array is
- * modified in-place and no result is returned.
- *
- * \param $row
- * A row of data.
- *
- * \see PostgreSQLResultSet::deduce_types
- */
- function cast_row(&$row)
- {
- assert('is_assoc_array($row)');
-
- foreach (array_keys($row) as $key)
- {
- $type = $this->data_types[$key];
- $value = $row[$key];
-
- /* Don't cast null values */
- if (is_null($value))
- continue;
-
- switch ($type)
- {
- case 'int2':
- case 'int4':
- case 'int8':
- $value = (int) $value;
- break;
-
- case 'float4':
- case 'float8':
- case 'numeric':
- case 'money':
- $value = (float) $value;
- break;
-
- case 'varchar':
- case 'bpchar':
- $value = (string) $value;
- break;
-
- case 'bool':
- $value = ($value === 't');
- break;
-
- case 'timestamp':
- case 'date':
- case 'time':
- case 'datetime':
- $value = AnewtDateTime::parse_string($value);
- break;
-
- case 'inet':
- /* FIXME: What to do with these? */
-
- default:
- /* No conversion, leave as string */
- break;
- }
-
- $row[$key] = $value;
- unset($value);
- }
- }
-}
-
-?>
=== removed file 'database.old/preparedquery.lib.php'
--- database.old/preparedquery.lib.php 2009-03-27 15:48:32 +0000
+++ database.old/preparedquery.lib.php 1970-01-01 00:00:00 +0000
@@ -1,106 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2004-2006 Wouter Bolsterlee <uws@xxxxxxxxx>
- * Copyright (C) 2004-2005 Jasper Looije <jasper@xxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-/**
- * Prepared Query class. This class takes care of parameter checking and value
- * substitution.
- */
-class PreparedQuery {
- var $db; /**< \private Database object instance reference */
- var $sql_template; /**< \private SQLTemplate instance */
- var $debug = false; /**< Enable/disable debugging */
- var $debug_print = false; /**< Print queries before execution */
-
- /**
- * \private Constructs a new PreparedQuery. This instance can be executed
- * later. Don't use this method directly: use $db->prepare() instead.
- *
- * \param $sql_template_str
- * SQL query template with ?int? style placeholders.
- *
- * \param $db
- * Reference to the database object instance.
- *
- * \see SQLTemplate
- */
- function PreparedQuery($sql_template_str, &$db) {
-
- /* Sanity checks */
- assert('is_string($sql_template_str)');
- assert('is_object($db)');
-
- /* Initialize */
- $this->db = &$db;
- $this->sql_template = new SQLTemplate($sql_template_str, $db);
- }
-
-
- /**
- * Executes a query. This function takes a variable number of arguments or
- * one array parameter.
- *
- * \param $values
- * One array or multiple values that will be substituted for the
- * placeholders in the prepared query.
- *
- * \return
- * A ResultSet instance for this query.
- *
- * \see
- * SQLTemplate::fill()
- */
- function &execute($values=null) {
-
- /* Connect if that's still needed. */
- $this->db->connect();
-
- /* Pass along parameters to SQLTemplate::fill() */
- $args = func_get_args();
- if ((count($args) == 1) && (is_array($args[0]) || $args[0] instanceof Container))
- $args = $args[0];
- $query = $this->sql_template->fill($args);
-
- /* Debug mode? */
- if ($this->debug) {
- /* Don't keep too many queries since it may cause memory exhaustion */
- if (count($this->db->queries_executed) > 500)
- array_splice($this->db->queries_executed, 0, 250);
-
- $this->db->queries_executed[] = $query;
- }
- if ($this->debug_print) {
- echo $query, "\n";
- }
-
- $rstype = ucfirst(strtolower($this->db->backend->get_type())) . 'ResultSet';
- $this->db->num_queries_executed++;
- $this->db->last_query = $query;
-
- $rs = new $rstype($query, $this->db->backend);
- return $rs;
- }
-
-}
-
-?>
=== removed file 'database.old/resultset.lib.php'
--- database.old/resultset.lib.php 2009-02-16 15:31:56 +0000
+++ database.old/resultset.lib.php 1970-01-01 00:00:00 +0000
@@ -1,185 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * This code is copyrighted and distributed under the terms of the GNU LGPL.
- * See the README file for more information.
- */
-
-
-/**
- * Class representing database result sets.
- *
- * Several methods are available to fetch the actual data from the database.
- */
-class ResultSet
-{
- /**
- * Constructor executes the query.
- */
- function ResultSet($sql, &$backend) {
- trigger_error('ResultSet() must be overridden', E_USER_ERROR);
- }
-
- /**
- * Find out the type of the query for this ResultSet instance.
- *
- * \return
- * The type of the query. These are constants like
- * ANEWT_DATABASE_SQL_QUERY_TYPE_SELECT and
- * ANEWT_DATABASE_SQL_QUERY_TYPE_INSERT.
- */
- function query_type()
- {
- $first_word = preg_replace('/^([a-z]+).*$/s', '\1', strtolower(trim(substr(ltrim($this->sql), 0, 10))));
- switch ($first_word)
- {
- case 'select': return ANEWT_DATABASE_SQL_QUERY_TYPE_SELECT;
- case 'insert': return ANEWT_DATABASE_SQL_QUERY_TYPE_INSERT;
- case 'replace': return ANEWT_DATABASE_SQL_QUERY_TYPE_REPLACE;
- case 'update': return ANEWT_DATABASE_SQL_QUERY_TYPE_UPDATE;
- case 'delete': return ANEWT_DATABASE_SQL_QUERY_TYPE_DELETE;
-
- case 'create': return ANEWT_DATABASE_SQL_QUERY_TYPE_CREATE;
- case 'alter': return ANEWT_DATABASE_SQL_QUERY_TYPE_ALTER;
- case 'drop': return ANEWT_DATABASE_SQL_QUERY_TYPE_DROP;
-
- case 'begin': return ANEWT_DATABASE_SQL_QUERY_TYPE_BEGIN;
- case 'commit': return ANEWT_DATABASE_SQL_QUERY_TYPE_COMMIT;
- case 'rollback': return ANEWT_DATABASE_SQL_QUERY_TYPE_ROLLBACK;
-
- default: return ANEWT_DATABASE_SQL_QUERY_TYPE_UNKNOWN;
- }
- }
-
- /**
- * Free resources associated with this result set. You cannot use any
- * methods on the result set instance anymore after calling this method.
- *
- * This method should be overridden using backend-specific code.
- */
- function free()
- {
- /* Do nothing */
- }
-
- /* Fetching results */
-
- /**
- * Returns the next row in this result set.
- *
- * \return
- * An associative array containing all fields of the next result row from
- * the result set.
- *
- * \see ResultSet::fetch_all
- * \see ResultSet::fetch_many
- */
- function fetch()
- {
- trigger_error('ResultSet::fetch() must be overridden', E_USER_ERROR);
- }
-
- /**
- * Returns all remaining rows from the current resultset.
- *
- * \return
- * A numeric array containing the result rows as associative array (may be
- * an empty list).
- *
- * \see ResultSet::fetch
- * \see ResultSet::fetch_many
- */
- function fetch_all()
- {
- $rows = array();
- while ($row = $this->fetch())
- $rows[] = $row;
-
- return $rows;
- }
-
- /**
- * Returns the specified number of rows from the current resultset. Note
- * that the actual number of rows may be lower than the value specified,
- * since there may be less rows in the set.
- *
- * \param $num
- * The number of rows to return (optional, defaults to 1).
- *
- * \return
- * A numeric array containing the result rows as associative array
- * (the list may contain less than $num rows, or may even be empty).
- *
- * \see ResultSet::fetch
- * \see ResultSet::fetch_all
- */
- function fetch_many($num=1)
- {
- assert('is_int($num) && $num >= 1;');
-
- $rows = array();
- while ($num-- > 0)
- {
- $row = $this->fetch();
-
- if (!$row)
- break;
-
- $rows[] = $row;
- }
- return $rows;
- }
-
-
- /* Result counting */
-
- /**
- * Returns the number of resulting rows in this resultset. This method might
- * not be available for some databases (it works at least with MySQL and
- * PostgreSQL though).
- *
- * \return
- * The total number of result rows.
- */
- function count()
- {
- trigger_error('ResultSet::count() must be overridden', E_USER_ERROR);
- }
-
- /**
- * Returns the number of rows that where affected by the last executed
- * query. This method might nog be available for some databases (it works at
- * least with MySQL and PostgreSQL though).
- */
- function count_affected()
- {
- trigger_error('ResultSet::count_affected() must be overridden', E_USER_ERROR);
- }
-
-
- /* Type casting */
-
- /**
- * \private Deduces the data types in this result set. This method can be
- * implemented in backends to do automatic type conversion.
- */
- function deduce_types()
- {
- }
-
- /**
- * \private Casts a row of data into native PHP data types. The array is
- * modified in-place and no result is returned. This method can be
- * implemented in backend to do automatic type conversion.
- *
- * \param $row
- * A row of data.
- */
- function cast_row(&$row)
- {
- }
-}
-
-?>
=== removed directory 'database.old/sqlite'
=== removed file 'database.old/sqlite/backend.lib.php'
--- database.old/sqlite/backend.lib.php 2008-10-25 22:18:29 +0000
+++ database.old/sqlite/backend.lib.php 1970-01-01 00:00:00 +0000
@@ -1,102 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2006 Marijn Kruisselbrink <m.kruisselbrink@xxxxxxxxxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-anewt_include('database/sqlite/resultset');
-
-
-/**
- * Class providing SQLite database connectivity.
- */
-class SqliteDB extends DatabaseBackend {
-
- var $handle; /**< \private The database handle */
-
- /**
- * Returns the type of this database backend.
- *
- * \return
- * Always returns the string 'sqlite'.
- */
- function get_type() {
- return 'sqlite';
- }
-
- /**
- * Opens the SQLite database.
- *
- * \param settings An associative array with connection settings: the
- * 'filename' and 'mode' indices will be used (but mode is optional).
- */
- function connect(array $settings) {
- is_array($settings) && array_has_key($settings, 'filename')
- or trigger_error('Invalid parameters to connect()', E_USER_ERROR);
-
- $mode = array_get_default($settings, 'mode', 0666);
-
- $this->handle = sqlite_open(
- $settings['filename'],
- $mode,
- $error)
- or trigger_error(sprintf('Could not open database (%s)', $error),
- E_USER_ERROR);
- }
-
- /**
- * Closes the SQLite database.
- */
- function disconnect() {
- sqlite_close($this->handle);
- }
-
- /**
- * Selects the given database. This closes the current database, and opens
- * the given database with a default mode of 0666 (octal).
- *
- * \param $name
- * The filename of the database to use.
- */
- function select_db($name) {
- assert('is_string($name)');
-
- disconnect();
- connect(array('filename' => $name));
- }
-
- /**
- * Escapes a string for SQL queries.
- *
- * \param $str
- * The string to escape.
- *
- * \return
- * The escaped string.
- */
- function escape_string($str) {
- if (is_null($str))
- return 'NULL';
-
- return "'" . sqlite_escape_string($str) . "'";
- }
-}
-
-?>
=== removed file 'database.old/sqlite/resultset.lib.php'
--- database.old/sqlite/resultset.lib.php 2007-08-01 10:01:29 +0000
+++ database.old/sqlite/resultset.lib.php 1970-01-01 00:00:00 +0000
@@ -1,68 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2006 Marijn Kruisselbrink <m.kruisselbrink@xxxxxxxxxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-/**
- * Sqlite-specific database result set.
- */
-class SqliteResultSet extends ResultSet {
-
- var $backend; /**< \private The backend instance */
- var $rs; /**< \private A resultset instance */
- var $rows_affected; /**< \private The number of rows that was changed by this query */
-
- /**
- * Constructs a new SqliteResultSet
- *
- * \param $sql
- * The sql query to execute.
- *
- * \param $backend
- * A reference to the used backend.
- */
- function SqliteResultSet($sql, &$backend) {
- assert('is_string($sql)');
-
- $this->sql = $sql;
- $this->backend = &$backend;
-
- $this->rs = sqlite_query($this->backend->handle, $sql)
- or trigger_error(sprintf('Query failed (%s)',
- sqlite_error_string(sqlite_last_error($this->backend->handle))),
- E_USER_ERROR);
- $this->rows_affected = sqlite_changes($this->backend->handle);
- }
-
- function fetch() {
- return sqlite_fetch_array($this->rs, SQLITE_ASSOC, true);
- }
-
- function count() {
- return sqlite_num_rows($this->rs);
- }
-
- function count_affected() {
- return $this->rows_affected;
- }
-}
-
-?>
=== removed file 'database.old/sqlite/test.php'
--- database.old/sqlite/test.php 2006-06-04 21:15:22 +0000
+++ database.old/sqlite/test.php 1970-01-01 00:00:00 +0000
@@ -1,61 +0,0 @@
-<?php
-
-error_reporting(E_ALL);
-require_once '../../anewt.lib.php';
-anewt_include('database');
-
-// Create a database instance
-$db = new DB('sqlite', array('filename' => ':memory:'));
-
-// Create a table and insert some test rows
-$db->prepare_execute("BEGIN");
-$db->prepare_execute("CREATE TABLE foo (a)");
-$ins = $db->prepare("INSERT INTO foo (a) VALUES (?str?)");
-$ins->execute("foo");
-$ins->execute("b\"ar");
-$db->prepare_execute("COMMIT");
-
-// Retrieve the rows from the table
-$qry = $db->prepare("SELECT * FROM foo ORDER BY a");
-$rs = $qry->execute();
-assert('is_a($rs, "SqliteResultSet")');
-assert('$rs->count() === 2');
-$rows = $rs->fetch_all();
-assert('count($rows) === 2');
-assert('is_array($rows[0])');
-assert('is_array($rows[1])');
-assert('count($rows[0]) === 1');
-assert('$rows[0]["a"] === "b\"ar"');
-
-// Test retrieving of an empty resultset
-$qry = $db->prepare("SELECT * FROM foo WHERE a <> a");
-$rs = $qry->execute();
-assert('$rs->count() === 0');
-assert('$rs->fetch() === FALSE');
-assert('$rs->fetch() === FALSE');
-$rs = $qry->execute();
-assert('$rs->fetch_all() === array()');
-
-// Test resulting resultset for an update query
-$qry = $db->prepare("UPDATE foo SET a=?str? WHERE a=?str?");
-$rs = $qry->execute('boo', 'b"ar');
-assert('$rs->count_affected() === 1');
-assert('$rs->count() === 0');
-assert('$rs->fetch() === FALSE');
-$rs = $qry->execute('boo', 'bar');
-assert('$rs->count_affected() === 0');
-
-// Test transaction methods
-$db->transaction_begin();
-$db->prepare_execute("INSERT INTO foo (a) VALUES (?str?)", "marijn");
-$db->transaction_rollback();
-assert('count($db->prepare_execute_fetch_all("SELECT * FROM foo WHERE a=?str?", "marijn")) === 0');
-
-$db->transaction_begin();
-$db->prepare_execute("INSERT INTO foo (a) VALUES (?str?)", "marijn");
-$db->transaction_commit();
-assert('count($db->prepare_execute_fetch_all("SELECT * FROM foo WHERE a=?str?", "marijn")) === 1');
-
-$db->disconnect();
-
-?>
=== removed file 'database.old/sqltemplate.lib.php'
--- database.old/sqltemplate.lib.php 2009-07-20 20:39:48 +0000
+++ database.old/sqltemplate.lib.php 1970-01-01 00:00:00 +0000
@@ -1,504 +0,0 @@
-<?php
-
-/*
- * Anewt, Almost No Effort Web Toolkit, database module
- *
- * Copyright (C) 2004-2006 Wouter Bolsterlee <uws@xxxxxxxxx>
- * Copyright (C) 2004-2005 Jasper Looije <jasper@xxxxxxx>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+
- */
-
-
-
-/* Query types */
-mkenum(
- /* Data Manipulation Language (DML) */
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_SELECT',
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_INSERT',
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_UPDATE',
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_DELETE',
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_REPLACE',
-
- /* Data Definition Language (DDL) */
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_CREATE',
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_ALTER',
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_DROP',
-
- /* Transactions */
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_BEGIN',
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_COMMIT',
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_ROLLBACK',
-
- /* Unknown */
- 'ANEWT_DATABASE_SQL_QUERY_TYPE_UNKNOWN'
- );
-
-
-/* Column types */
-mkenum(
- /* Boolean */
- 'ANEWT_DATABASE_TYPE_BOOLEAN',
-
- /* Numeric */
- 'ANEWT_DATABASE_TYPE_INTEGER',
- 'ANEWT_DATABASE_TYPE_FLOAT',
-
- /* String */
- 'ANEWT_DATABASE_TYPE_STRING',
-
- /* Dates and times */
- 'ANEWT_DATABASE_TYPE_DATE',
- 'ANEWT_DATABASE_TYPE_TIME',
- 'ANEWT_DATABASE_TYPE_DATETIME',
- 'ANEWT_DATABASE_TYPE_TIMESTAMP',
-
- /* Raw */
- 'ANEWT_DATABASE_TYPE_RAW',
-
- /* SQL internals */
- 'ANEWT_DATABASE_TYPE_COLUMN',
- 'ANEWT_DATABASE_TYPE_TABLE'
-);
-
-
-
-/**
- * SQL Template class with mandatory type checking. This class implements the
- * type checking logic for SQL queries.
- */
-class SQLTemplate {
- var $db; /**< \private Database object instance reference */
- var $placeholders; /**< \private List of parameters (placeholders) */
- var $named_placeholders; /**< \private List of named parameters (placeholders) */
- var $named_mode = false; /**< \private are we using 'named mode' with named placeholders? */
- var $sql_template; /**< \private SQL template */
-
- /**
- * Constructs a new SQLTemplate instance.
- *
- * \param $sql_template
- * The template SQL string.
- *
- * \param $db
- * Reference to the database object instance.
- *
- * \see SQLTemplate::parse
- */
- function SQLTemplate($sql_template, &$db) {
- assert('is_string($sql_template)');
- assert('$db instanceof DB');
-
- /* Initial values */
- $this->db = &$db;
- $this->placeholders = array();
- $this->named_placeholders = array();
-
- /* Parse the template */
- $this->parse($sql_template);
- }
-
-
- /**
- * Convert a column type string into the associated constant. This function
- * returns one of the <code>ANEWT_DATABASE_TYPE_*</code> constants, and
- * triggers and error if $type_str is not a valid identifier.
- *
- * Example: The string <code>int</code> results in the
- * <code>ANEWT_DATABASE_TYPE_INTEGER</code> constant.
- *
- * \param $type_str
- * A string indicating a database type, e.g. <code>int</code>.
- *
- * \return
- * Associated <code>ANEWT_DATABASE_TYPE_*</code> constant.
- */
- public static function column_type_from_string($type_str)
- {
- assert('is_string($type_str);');
- $mapping = array(
- 'bool' => ANEWT_DATABASE_TYPE_BOOLEAN,
- 'boolean' => ANEWT_DATABASE_TYPE_BOOLEAN,
- 'i' => ANEWT_DATABASE_TYPE_INTEGER,
- 'int' => ANEWT_DATABASE_TYPE_INTEGER,
- 'integer' => ANEWT_DATABASE_TYPE_INTEGER,
- 'f' => ANEWT_DATABASE_TYPE_FLOAT,
- 'float' => ANEWT_DATABASE_TYPE_FLOAT,
- 'double' => ANEWT_DATABASE_TYPE_FLOAT,
- 's' => ANEWT_DATABASE_TYPE_STRING,
- 'str' => ANEWT_DATABASE_TYPE_STRING,
- 'string' => ANEWT_DATABASE_TYPE_STRING,
- 'varchar' => ANEWT_DATABASE_TYPE_STRING,
- 'date' => ANEWT_DATABASE_TYPE_DATE,
- 'datetime' => ANEWT_DATABASE_TYPE_DATETIME,
- 'time' => ANEWT_DATABASE_TYPE_TIME,
- 'timestamp' => ANEWT_DATABASE_TYPE_TIMESTAMP,
- 'r' => ANEWT_DATABASE_TYPE_RAW,
- 'raw' => ANEWT_DATABASE_TYPE_RAW,
- 'col' => ANEWT_DATABASE_TYPE_COLUMN,
- 'column' => ANEWT_DATABASE_TYPE_COLUMN,
- 'table' => ANEWT_DATABASE_TYPE_TABLE,
- );
-
- if (array_key_exists($type_str, $mapping))
- return $mapping[$type_str];
-
- trigger_error(sprintf('Field type "%s" is unknown', $type_str), E_USER_ERROR);
- }
-
- /**
- * Parses a template string and extracts placeholders.
- *
- * \param $sql_template
- * The template SQL string.
- */
- function parse($sql_template) {
- assert('is_string($sql_template)');
-
- /* Since vsprintf is used to substitute escaped values into the sql
- * query later on, % characters need to be escaped. */
- $sql_template = str_replace('%', '%%', $sql_template); // escape old values
-
- /* Find placeholders fields. All placeholders start with ? followed by
- * a keyword and end with ? too. Examples ?string? and ?int? */
- $fields = array();
- $named_fieldspattern = '/\?([a-z]+):([^?]*)\?/i';
- $fieldspattern = '/\?([a-z]+)\?/i';
-
- if (preg_match_all($named_fieldspattern, $sql_template, $fields)) {
- assert('!preg_match_all($fieldspattern, $sql_template, $dummy); // mixing named placeholders with anoymous placeholders is not supported');
- $this->named_mode = true; // switch to named placeholders
-
- /* $fields[1] now contains the matches inside the first
- * parenthesized expression. Assign the special types to the params
- * list, so that proper validation and escaping/quoting can be done
- * when providing values to these placeholders. */
- $match = 0;
- foreach ($fields[0] as $field)
- {
- $this->named_placeholders[] = array(
- 'type' => SQLTemplate::column_type_from_string($fields[1][$match]),
- 'var' => $fields[2][$match]
- );
- $match++;
- }
-
- /* Replace all ?type:var? parts with %s to allow easy vsprintf
- * substitution when filling in values. Quoting the values is taken
- * care of in the fill() method. */
- $sql_template = preg_replace($named_fieldspattern, '%s', $sql_template);
-
- } elseif (preg_match_all($fieldspattern, $sql_template, $fields)) {
- /* $fields[1] now contains the matches inside the first
- * parenthesized expression. Assign the special types to the params
- * list, so that proper validation and escaping/quoting can be done
- * when providing values to these placeholders. */
- foreach ($fields[1] as $field)
- {
- $this->placeholders[] = SQLTemplate::column_type_from_string($field);
- }
-
- /* Replace all ?field? parts with %s to allow easy vsprintf
- * substitution when filling in values. Quoting the values is taken
- * care of in the fill() method. */
- $sql_template = preg_replace($fieldspattern, '%s', $sql_template);
- }
- $this->sql_template = $sql_template;
- }
-
- /**
- * Fills in the valus in the SQL template. This method will check all values
- * for correctness to avoid nasty SQL injection vulnerabilities.
- *
- * \param $args
- * Array with values to use for substitution.
- *
- * \return
- * The query containing all values, quoted correctly.
- */
- function fill($args=null) {
- /* We accept either:
- * - no parameters
- * - multiple scalar parameters
- * - 1 array parameter with scalar elements
- * - 1 associative array parameter
- * - 1 container parameter
- */
- $args = func_get_args();
- if($this->named_mode) {
- if (count($args) != 1) {
- trigger_error('associative array or Container expected', E_USER_ERROR);
- }
- if($args[0] instanceof Container) {
- $args = $args[0]->to_array();
- } elseif(is_array($args[0])) {
- $args = $args[0];
- } else {
- trigger_error('associative array or Container expected', E_USER_ERROR);
- }
-
- $numargs = count($this->named_placeholders);
- } else {
- if ((count($args) == 1) && is_numeric_array($args[0]))
- $args = $args[0];
-
- assert('is_numeric_array($args)');
-
- if (count($args) != count($this->placeholders)) {
- trigger_error(sprintf(
- 'Incorrect number of parameters to SQLTemplate::fill(): expected %d, got %d',
- count($this->placeholders), count($args)), E_USER_ERROR);
- };
-
- $numargs = count($args);
- }
-
- /* Note: don't use foreach() here, because it copies the values in
- * memory and leaves the original values untouched! */
- for ($i = 0; $i < $numargs; $i++) {
- if($this->named_mode) {
- $fieldtype = $this->named_placeholders[$i]['type'];
- $var = $this->named_placeholders[$i]['var'];
- if(!isset($args[$var])) {
- $var = str_replace('-', '_', $var); // Container replaces '-' with '_'
- if(!array_key_exists($var, $args)) {
- trigger_error(sprintf('SQLTemplate::fill(): missing expected parameter "%s"',
- $this->named_placeholders[$i]['var']),
- E_USER_ERROR);
- }
- }
- $value = $args[$var];
- $argname = "`".$var."'";
- } else {
- $fieldtype = $this->placeholders[$i];
- $value = &$args[$i];
- $argname = $i + 1;
- }
-
- /* Handle NULL values here. Escaping is not needed for NULL values. */
- if (is_null($value)) {
- $value = 'NULL';
- if($this->named_mode) {
- $arglist[$i] = $value;
- }
- continue;
- }
-
- /* The value is non-null. Perform very restrictive input sanitizing
- * based on the field type. */
-
- switch ($fieldtype) {
-
- case ANEWT_DATABASE_TYPE_BOOLEAN:
-
- /* Integers: only accept 0 and 1 (no type juggling!) */
- if (is_int($value)) {
- if ($value === 0) {
- $value = false;
- } elseif ($value === 1) {
- $value = true;
- }
- }
-
- /* Strings: only accept literal "0" and "1" (no type juggling!) */
- if (is_string($value)) {
- if ($value === "0") {
- $value = false;
- } elseif ($value === "1") {
- $value = true;
- }
- }
-
- if (is_bool($value)) {
- $value = $this->db->backend->escape_boolean($value);
- break;
- }
-
- trigger_error(sprintf('Invalid boolean value: "%s" on argument %s', $value, $argname),
- E_USER_ERROR);
-
- case ANEWT_DATABASE_TYPE_INTEGER:
-
- if (is_int($value)) {
- $value = (string) $value;
- break;
- }
-
- if (is_string($value) && preg_match('/^-?\d+$/', $value))
- break;
-
- trigger_error(sprintf('Invalid integer value: "%s" on argument %s', $value, $argname),
- E_USER_ERROR);
-
- case ANEWT_DATABASE_TYPE_FLOAT:
-
- // FIXME: this does not accept .123 (without a leading zero)
- if (is_string($value) && preg_match('/^-?\d+(\.\d*)?$/', $value)) {
- /* Enough checks done by the regex, no need to do any
- * formatting/escaping */
- break;
-
- /* Locale-agnostic float formatting */
- } elseif (is_int($value) || is_float($value)) {
- $value = number_format($value, 10, '.', '');
- if (str_has_suffix($value, '.')) $value .= '0';
- break;
- }
-
- trigger_error(sprintf('Invalid float value: "%s" on argument %s', $value, $argname),
- E_USER_ERROR);
-
- case ANEWT_DATABASE_TYPE_STRING:
-
- /* Accept integers and objects with a render() method. */
- if (is_int($value)) {
- $value = (string) $value;
- } elseif (is_object($value) && method_exists($value, 'render')) {
- $value = $value->render();
- }
-
- /* From this point on, only strings are accepted. */
- if (is_string($value)) {
- $value = $this->db->backend->escape_string($value);
- break;
- }
-
- trigger_error(sprintf('Invalid string value: "%s" on argument %s', $value, $argname),
- E_USER_ERROR);
-
- case ANEWT_DATABASE_TYPE_DATE:
-
- if ($value instanceof AnewtDateTimeAtom)
- $value = AnewtDateTime::sql_date($value);
-
- if (is_string($value) && preg_match('/^\d{2,4}-\d{2}-\d{2}$/', $value)) {
- $value = $this->db->backend->escape_date($value);
- break;
- }
- if (is_string($value) && strtoupper($value) == "NOW") {
- $value = "NOW()";
- break;
- }
-
- if (is_string($value) && strtoupper($value) == 'NOW') {
- $value = 'NOW()';
- break;
- }
-
- trigger_error(sprintf('Invalid date value: "%s" on argument %s',
- $value, $argname), E_USER_ERROR);
-
- case ANEWT_DATABASE_TYPE_TIME:
-
- if ($value instanceof AnewtDateTimeAtom)
- $value = AnewtDateTime::sql_time($value);
-
- if (is_string($value) && preg_match('/^\d{2}:\d{2}(:\d{2})?$/', $value)) {
- $value = $this->db->backend->escape_time($value);
- break;
- }
- if (is_string($value) && strtoupper($value) == "NOW") {
- $value = "NOW()";
- break;
- }
-
- if (is_string($value) && strtoupper($value) == 'NOW') {
- $value = 'NOW()';
- break;
- }
-
- trigger_error(sprintf('Invalid time value: "%s" on argument %s',
- $value, $argname), E_USER_ERROR);
-
- case ANEWT_DATABASE_TYPE_DATETIME:
- case ANEWT_DATABASE_TYPE_TIMESTAMP:
-
- if ($value instanceof AnewtDateTimeAtom)
- $value = AnewtDateTime::sql($value);
-
- if (is_string($value) && preg_match('/^\d{2,4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $value)) {
- $value = $this->db->backend->escape_datetime($value);
- break;
- }
- if (is_string($value) && strtoupper($value) == "NOW") {
- $value = "NOW()";
- break;
- }
-
- if (is_string($value) && strtoupper($value) == 'NOW') {
- $value = 'NOW()';
- break;
- }
-
- trigger_error(sprintf('Invalid datetime or timestamp value: "%s" on argument %s',
- $value, $argname), E_USER_ERROR);
-
- case ANEWT_DATABASE_TYPE_RAW:
- /* No checking, no escaping... use at your own risk ;-) */
- break;
-
-
- /* The column and table type are mostly for internal usage, it's
- * a BAD idea to use user data for these fields! */
-
- case ANEWT_DATABASE_TYPE_COLUMN:
-
- if (is_string($value) && preg_match('/^([a-z0-9_-]+\.)*[a-z0-9_-]+$/i', $value)) {
- $value = $this->db->backend->escape_column_name($value);
- break;
- }
-
- trigger_error(sprintf('Invalid column value: "%s" on argument %s', $value, $argname),
- E_USER_ERROR);
-
-
- case ANEWT_DATABASE_TYPE_TABLE:
-
- if (is_string($value) && preg_match('/^([a-z0-9_-]+\.)*[a-z0-9_-]+$/i', $value)) {
- $value = $this->db->backend->escape_table_name($value);
- break;
- }
-
- trigger_error(sprintf('Invalid table value: "%s" on argument %s', $value, $argname),
- E_USER_ERROR);
-
-
- default:
- trigger_error('This is a bug! Fieldtype unknown',
- E_USER_ERROR);
- break;
- }
-
- assert('is_string($value)');
-
- if($this->named_mode) {
- $arglist[$i] = $value;
- }
- }
-
- /* Now that all supplied values are validated and escaped properly, we
- * can easily substitute them into the query template. The %s
- * placeholders were already prepared during initial parsing. */
- if($this->named_mode) {
- $query = vsprintf($this->sql_template, $arglist);
- } else {
- $query = vsprintf($this->sql_template, $args);
- }
-
- return $query;
- }
-}
-
-?>