/**
* Object Based Database Query Builder and data store
*
- * PHP versions 4 and 5
+ * For PHP versions 4,5 and 6
*
- * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
* that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_0.txt. If you did not receive a copy of
+ * http://www.php.net/license/3_01.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @package DB_DataObject
* @author Alan Knowles <alan@akbkhome.com>
* @copyright 1997-2006 The PHP Group
- * @license http://www.php.net/license/3_0.txt PHP License 3.0
- * @version CVS: $Id: DataObject.php,v 1.439 2008/01/30 02:14:06 alan_k Exp $
+ * @license http://www.php.net/license/3_01.txt PHP License 3.01
+ * @version CVS: $Id: DataObject.php 291349 2009-11-27 09:15:18Z alan_k $
* @link http://pear.php.net/package/DB_DataObject
*/
* @access private
* @var string
*/
- var $_DB_DataObject_version = "1.8.8";
+ var $_DB_DataObject_version = "1.9.0";
/**
* The Database table (used by table extends)
/**
* An autoloading, caching static get method using key, value (based on get)
- *
+ * (depreciated - use ::get / and your own caching method)
+ *
* Usage:
* $object = DB_DataObject::staticGet("DbTable_mytable",12);
* or
}
$this->$key = $keyvalue;
}
-
-
-
+
+ // if we haven't set disable_null_strings to "full"
+ $ignore_null = !isset($options['disable_null_strings'])
+ || !is_string($options['disable_null_strings'])
+ || strtolower($options['disable_null_strings']) !== 'full' ;
+
+
foreach($items as $k => $v) {
// if we are using autoincrement - skip the column...
}
- if (!isset($this->$k)) {
+
+
+ // Ignore variables which aren't set to a value
+ if ( !isset($this->$k) && $ignore_null) {
continue;
}
// dont insert data into mysql timestamps
}
-
- if (!isset($options['disable_null_strings']) && is_string($this->$k) && (strtolower($this->$k) === 'null') && !($v & DB_DATAOBJECT_NOTNULL)) {
+ if (!($v & DB_DATAOBJECT_NOTNULL) && DB_DataObject::_is_null($this,$k)) {
$rightq .= " NULL ";
continue;
}
if ($leftq || $useNative) {
$table = ($quoteIdentifiers ? $DB->quoteIdentifier($this->__table) : $this->__table);
- $r = $this->_query("INSERT INTO {$table} ($leftq) VALUES ($rightq) ");
+
+ if (($dbtype == 'pgsql') && empty($leftq)) {
+ $r = $this->_query("INSERT INTO {$table} DEFAULT VALUES");
+ } else {
+ $r = $this->_query("INSERT INTO {$table} ($leftq) VALUES ($rightq) ");
+ }
+
$options = $_DB_DATAOBJECT['CONFIG'];
+ $ignore_null = !isset($options['disable_null_strings'])
+ || !is_string($options['disable_null_strings'])
+ || strtolower($options['disable_null_strings']) !== 'full' ;
+
+
foreach($items as $k => $v) {
- if (!isset($this->$k)) {
+
+ if (!isset($this->$k) && $ignore_null) {
continue;
}
// ignore stuff thats
}
// special values ... at least null is handled...
- if (!isset($options['disable_null_strings']) && (strtolower($this->$k) === 'null') && !($v & DB_DATAOBJECT_NOTNULL)) {
+ if (!($v & DB_DATAOBJECT_NOTNULL) && DB_DataObject::_is_null($this,$k)) {
$settings .= "$kSql = NULL ";
continue;
}
* build the condition only using the object parameters.
*
* @access public
- * @return mixed True on success, false on failure, 0 on no data affected
+ * @return mixed Int (No. of rows affected) on success, false on failure, 0 on no data affected
*/
function delete($useWhere = false)
{
if (($this->_query !== false) && $this->_query['condition']) {
$table = ($quoteIdentifiers ? $DB->quoteIdentifier($this->__table) : $this->__table);
- $sql = "DELETE FROM {$table} {$this->_query['condition']}{$extra_cond}";
+ $sql = "DELETE ";
+ // using a joined delete. - with useWhere..
+ $sql .= (!empty($this->_join) && $useWhere) ?
+ "{$table} FROM {$table} {$this->_join} " :
+ "FROM {$table} ";
+
+ $sql .= $this->_query['condition']. $extra_cond;
// add limit..
}
$keys = $this->keys();
- if (!$keys[0] && !is_string($countWhat)) {
+ if (empty($keys[0]) && (!is_string($countWhat) || (strtoupper($countWhat) == 'DISTINCT'))) {
$this->raiseError(
- "You cannot do run count without keys - use \$do->keys('id');",
+ "You cannot do run count without keys - use \$do->count('id'), or use \$do->count('distinct id')';",
DB_DATAOBJECT_ERROR_INVALIDARGS,PEAR_ERROR_DIE);
return false;
}
$table = ($quoteIdentifiers ? $DB->quoteIdentifier($this->__table) : $this->__table);
- $key_col = ($quoteIdentifiers ? $DB->quoteIdentifier($keys[0]) : $keys[0]);
+ $key_col = empty($keys[0]) ? '' : (($quoteIdentifiers ? $DB->quoteIdentifier($keys[0]) : $keys[0]));
$as = ($quoteIdentifiers ? $DB->quoteIdentifier('DATAOBJECT_NUM') : 'DATAOBJECT_NUM');
// support distinct on default keys.
}
-
+ $_DB_DATAOBJECT['INI'][$this->_database] = array();
foreach ($schemas as $ini) {
if (file_exists($ini) && is_file($ini)) {
- $_DB_DATAOBJECT['INI'][$this->_database] = parse_ini_file($ini, true);
+
+ $_DB_DATAOBJECT['INI'][$this->_database] = array_merge(
+ $_DB_DATAOBJECT['INI'][$this->_database],
+ parse_ini_file($ini, true)
+ );
+
if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
if (!is_readable ($ini)) {
$this->debug("ini file is not readable: $ini","databaseStructure",1);
// technically postgres native here...
// we need to get the new improved tabledata sorted out first.
- if ( in_array($dbtype , array('psql', 'mysql', 'mysqli', 'mssql', 'ifx')) &&
+ if ( in_array($dbtype , array('pgsql', 'mysql', 'mysqli', 'mssql', 'ifx')) &&
($table[$usekey] & DB_DATAOBJECT_INT) &&
isset($realkeys[$usekey]) && ($realkeys[$usekey] == 'N')
) {
$this->_loadConfig();
}
// Set database driver for reference
- $db_driver = empty($_DB_DATAOBJECT['CONFIG']['db_driver']) ? 'DB' : $_DB_DATAOBJECT['CONFIG']['db_driver'];
- // is it already connected ?
-
+ $db_driver = empty($_DB_DATAOBJECT['CONFIG']['db_driver']) ?
+ 'DB' : $_DB_DATAOBJECT['CONFIG']['db_driver'];
+
+ // is it already connected ?
if ($this->_database_dsn_md5 && !empty($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5])) {
+
+ // connection is an error...
if (PEAR::isError($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5])) {
return $this->raiseError(
$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]->message,
}
- if (!$this->_database) {
+ if (empty($this->_database)) {
$this->_database = $_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]->dsn['database'];
$hasGetDatabase = method_exists($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5], 'getDatabase');
// try and work out what to use for the dsn !
$options= &$_DB_DATAOBJECT['CONFIG'];
+ // if the databse dsn dis defined in the object..
$dsn = isset($this->_database_dsn) ? $this->_database_dsn : null;
if (!$dsn) {
$this->_database = isset($options["table_{$this->__table}"]) ? $options["table_{$this->__table}"] : null;
}
if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
- $this->debug("Checking for database database_{$this->_database} in options","CONNECT");
+ $this->debug("Checking for database specific ini ('{$this->_database}') : database_{$this->_database} in options","CONNECT");
}
if ($this->_database && !empty($options["database_{$this->_database}"])) {
-
$dsn = $options["database_{$this->_database}"];
} else if (!empty($options['database'])) {
$dsn = $options['database'];
+
}
}
if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
$this->debug("USING CACHED CONNECTION", "CONNECT",3);
}
+
+
+
if (!$this->_database) {
$hasGetDatabase = method_exists($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5], 'getDatabase');
return true;
}
if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
- $this->debug("NEW CONNECTION", "CONNECT",3);
+ $this->debug("NEW CONNECTION TP DATABASE :" .$this->_database , "CONNECT",3);
/* actualy make a connection */
$this->debug(print_r($dsn,true) ." {$this->_database_dsn_md5}", "CONNECT",3);
}
);
}
-
- if (!$this->_database) {
+
+ if (empty($this->_database)) {
$hasGetDatabase = method_exists($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5], 'getDatabase');
$this->_database = ($db_driver != 'DB' && $hasGetDatabase)
$t= explode(' ',microtime());
$_DB_DATAOBJECT['QUERYENDTIME'] = $time = $t[0]+$t[1];
-
- do {
- if ($_DB_driver == 'DB') {
- $result = $DB->query($string);
- } else {
- switch (strtolower(substr(trim($string),0,6))) {
+ for ($tries = 0;$tries < 3;$tries++) {
- case 'insert':
- case 'update':
- case 'delete':
- $result = $DB->exec($string);
- break;
-
- default:
- $result = $DB->query($string);
- break;
+ if ($_DB_driver == 'DB') {
+
+ $result = $DB->query($string);
+ } else {
+ switch (strtolower(substr(trim($string),0,6))) {
+
+ case 'insert':
+ case 'update':
+ case 'delete':
+ $result = $DB->exec($string);
+ break;
+
+ default:
+ $result = $DB->query($string);
+ break;
+ }
+ }
+
+ // see if we got a failure.. - try again a few times..
+ if (!is_a($result,'PEAR_Error')) {
+ break;
}
+ if ($result->getCode() != -14) { // *DB_ERROR_NODBSELECTED
+ break; // not a connection error..
+ }
+ sleep(1); // wait before retyring..
+ $DB->connect($DB->dsn);
}
-
- // try to reconnect, at most 3 times
- $again = false;
- if (is_a($result, 'PEAR_Error')
- AND $result->getCode() == DB_ERROR_NODBSELECTED
- AND $cpt++<3) {
- $DB->disconnect();
- sleep(1);
- $DB->connect($DB->dsn);
- $again = true;
- }
-
- } while ($again);
+
if (is_a($result,'PEAR_Error')) {
if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
$x = new DB_DataObject;
$this->_query= $x->_query;
}
-
+
+
foreach($keys as $k => $v) {
// index keys is an indexed array
/* these filter checks are a bit suspicious..
continue;
}
- if (!isset($options['disable_null_strings']) && (strtolower($this->$k) === 'null') && !($v & DB_DATAOBJECT_NOTNULL)) {
+ if (!($v & DB_DATAOBJECT_NOTNULL) && DB_DataObject::_is_null($this,$k)) {
$this->whereAdd(" $kSql IS NULL");
continue;
}
* use @ to silence it (if you are sure it is acceptable)
* eg. $do = @DB_DataObject::factory('person')
*
- * table name will eventually be databasename/table
+ * table name can bedatabasename/table
* - and allow modular dataobjects to be written..
* (this also helps proxy creation)
*
- *
+ * Experimental Support for Multi-Database factory eg. mydatabase.mytable
+ *
+ *
* @param string $table tablename (use blank to create a new instance of the same class.)
* @access private
* @return DataObject|PEAR_Error
function factory($table = '') {
global $_DB_DATAOBJECT;
+
+
+ // multi-database support.. - experimental.
+ $database = '';
+
+ if (strpos( $table,'/') !== false ) {
+ list($database,$table) = explode('.',$table, 2);
+
+ }
+
if (empty($_DB_DATAOBJECT['CONFIG'])) {
DB_DataObject::_loadConfig();
}
+ // no configuration available for database
+ if (!empty($database) && empty($_DB_DATAOBJECT['CONFIG']['database_'.$database])) {
+ return DB_DataObject::raiseError(
+ "unable to find database_{$database} in Configuration, It is required for factory with database"
+ , 0, PEAR_ERROR_DIE );
+ }
+
+
if ($table === '') {
if (is_a($this,'DB_DataObject') && strlen($this->__table)) {
}
}
+ // does this need multi db support??
+ $cp = isset($_DB_DATAOBJECT['CONFIG']['class_prefix']) ?
+ explode(PATH_SEPARATOR, $_DB_DATAOBJECT['CONFIG']['class_prefix']) : '';
- $p = isset($_DB_DATAOBJECT['CONFIG']['class_prefix']) ?
- $_DB_DATAOBJECT['CONFIG']['class_prefix'] : '';
- $class = $p . preg_replace('/[^A-Z0-9]/i','_',ucfirst($table));
+ // multiprefix support.
+ $tbl = preg_replace('/[^A-Z0-9]/i','_',ucfirst($table));
+ if (is_array($cp)) {
+ $class = array();
+ foreach($cp as $cpr) {
+ $ce = substr(phpversion(),0,1) > 4 ? class_exists($cpr . $tbl,false) : class_exists($cpr . $tbl);
+ if ($ce) {
+ $class = $cpr . $tbl;
+ break;
+ }
+ $class[] = $cpr . $tbl;
+ }
+ } else {
+ $class = $tbl;
+ $ce = substr(phpversion(),0,1) > 4 ? class_exists($class,false) : class_exists($class);
+ }
- $ce = substr(phpversion(),0,1) > 4 ? class_exists($class,false) : class_exists($class);
- $class = $ce ? $class : DB_DataObject::_autoloadClass($class);
+
+ $rclass = $ce ? $class : DB_DataObject::_autoloadClass($class, $table);
// proxy = full|light
- if (!$class && isset($_DB_DATAOBJECT['CONFIG']['proxy'])) {
+ if (!$rclass && isset($_DB_DATAOBJECT['CONFIG']['proxy'])) {
+
+ DB_DataObject::debug("FAILED TO Autoload $database.$table - using proxy.","FACTORY",1);
+
+
$proxyMethod = 'getProxy'.$_DB_DATAOBJECT['CONFIG']['proxy'];
+ // if you have loaded (some other way) - dont try and load it again..
class_exists('DB_DataObject_Generator') ? '' :
require_once 'DB/DataObject/Generator.php';
return $x->$proxyMethod( $d->_database, $table);
}
- if (!$class) {
+ if (!$rclass) {
return DB_DataObject::raiseError(
- "factory could not find class $class from $table",
+ "factory could not find class " .
+ (is_array($class) ? implode(PATH_SEPARATOR, $class) : $class ).
+ "from $table",
DB_DATAOBJECT_ERROR_INVALIDCONFIG);
}
-
- return new $class;
+ $ret = new $rclass;
+ if (!empty($database)) {
+ DB_DataObject::debug("Setting database to $database","FACTORY",1);
+ $ret->database($database);
+ }
+ return $ret;
}
/**
* autoload Class
*
- * @param string $class Class
+ * @param string|array $class Class
+ * @param string $table Table trying to load.
* @access private
* @return string classname on Success
*/
- function _autoloadClass($class)
+ function _autoloadClass($class, $table=false)
{
global $_DB_DATAOBJECT;
$class_prefix = empty($_DB_DATAOBJECT['CONFIG']['class_prefix']) ?
'' : $_DB_DATAOBJECT['CONFIG']['class_prefix'];
- $table = substr($class,strlen($class_prefix));
+ $table = $table ? $table : substr($class,strlen($class_prefix));
// only include the file if it exists - and barf badly if it has parse errors :)
if (!empty($_DB_DATAOBJECT['CONFIG']['proxy']) || empty($_DB_DATAOBJECT['CONFIG']['class_location'])) {
return false;
}
+ // support for:
+ // class_location = mydir/ => maps to mydir/Tablename.php
+ // class_location = mydir/myfile_%s.php => maps to mydir/myfile_Tablename
+ // with directory sepr
+ // class_location = mydir/:mydir2/: => tries all of thes locations.
+ $cl = $_DB_DATAOBJECT['CONFIG']['class_location'];
- if (strpos($_DB_DATAOBJECT['CONFIG']['class_location'],'%s') !== false) {
- $file = sprintf($_DB_DATAOBJECT['CONFIG']['class_location'], preg_replace('/[^A-Z0-9]/i','_',ucfirst($table)));
- } else {
- $file = $_DB_DATAOBJECT['CONFIG']['class_location'].'/'.preg_replace('/[^A-Z0-9]/i','_',ucfirst($table)).".php";
+ switch (true) {
+ case (strpos($cl ,'%s') !== false):
+ $file = sprintf($cl , preg_replace('/[^A-Z0-9]/i','_',ucfirst($table)));
+ break;
+
+ case (strpos($cl , PATH_SEPARATOR) !== false):
+ $file = array();
+ foreach(explode(PATH_SEPARATOR, $cl ) as $p) {
+ $file[] = $p .'/'.preg_replace('/[^A-Z0-9]/i','_',ucfirst($table)).".php";
+ }
+ break;
+ default:
+ $file = $cl .'/'.preg_replace('/[^A-Z0-9]/i','_',ucfirst($table)).".php";
+ break;
}
- if (!file_exists($file)) {
+ $cls = is_array($class) ? $class : array($class);
+
+ if (is_array($file) || !file_exists($file)) {
$found = false;
- foreach(explode(PATH_SEPARATOR, ini_get('include_path')) as $p) {
- if (file_exists("$p/$file")) {
- $file = "$p/$file";
- $found = true;
+
+ $file = is_array($file) ? $file : array($file);
+ $search = implode(PATH_SEPARATOR, $file);
+ foreach($file as $f) {
+ foreach(explode(PATH_SEPARATOR, '' . PATH_SEPARATOR . ini_get('include_path')) as $p) {
+ $ff = empty($p) ? $f : "$p/$f";
+
+ if (file_exists($ff)) {
+ $file = $ff;
+ $found = true;
+ break;
+ }
+ }
+ if ($found) {
break;
}
}
if (!$found) {
DB_DataObject::raiseError(
- "autoload:Could not find class {$class} using class_location value",
+ "autoload:Could not find class " . implode(',', $cls) .
+ " using class_location value :" . $search .
+ " using include_path value :" . ini_get('include_path'),
DB_DATAOBJECT_ERROR_INVALIDCONFIG);
return false;
}
include_once $file;
-
- $ce = substr(phpversion(),0,1) > 4 ? class_exists($class,false) : class_exists($class);
-
+
+ $ce = false;
+ foreach($cls as $c) {
+ $ce = substr(phpversion(),0,1) > 4 ? class_exists($c,false) : class_exists($c);
+ if ($ce) {
+ $class = $c;
+ break;
+ }
+ }
if (!$ce) {
DB_DataObject::raiseError(
- "autoload:Could not autoload {$class}",
+ "autoload:Could not autoload " . implode(',', $cls) ,
DB_DATAOBJECT_ERROR_INVALIDCONFIG);
return false;
}
}
-
+ $_DB_DATAOBJECT['LINKS'][$this->_database] = array();
foreach ($schemas as $ini) {
$links =
$_DB_DATAOBJECT['CONFIG']["links_{$this->_database}"] :
str_replace('.ini','.links.ini',$ini);
- if (empty($_DB_DATAOBJECT['LINKS'][$this->_database]) && file_exists($links) && is_file($links)) {
+ if (file_exists($links) && is_file($links)) {
/* not sure why $links = ... here - TODO check if that works */
- $_DB_DATAOBJECT['LINKS'][$this->_database] = parse_ini_file($links, true);
+ $_DB_DATAOBJECT['LINKS'][$this->_database] = array_merge(
+ $_DB_DATAOBJECT['LINKS'][$this->_database],
+ parse_ini_file($links, true)
+ );
+
if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
$this->debug("Loaded links.ini file: $links","links",1);
}
}
if ($link) {
if ($obj->get($link, $this->$row)) {
- $obj->free();
return $obj;
}
return false;
}
if ($obj->get($this->$row)) {
- $obj->free();
return $obj;
}
return false;
return;
}
-
+ //echo '<PRE>'; print_r(func_get_args());
$useWhereAsOn = false;
// support for 2nd argument as an array of options
if (is_array($joinType)) {
$DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
+ /// CHANGED 26 JUN 2009 - we prefer links from our local table over the remote one.
-
+ /* otherwise see if there are any links from this table to the obj. */
+ //print_r($this->links());
+ if (($ofield === false) && ($links = $this->links())) {
+ foreach ($links as $k => $v) {
+ /* link contains {this column} = {linked table}:{linked column} */
+ $ar = explode(':', $v);
+ // Feature Request #4266 - Allow joins with multiple keys
+ if (strpos($k, ',') !== false) {
+ $k = explode(',', $k);
+ }
+ if (strpos($ar[1], ',') !== false) {
+ $ar[1] = explode(',', $ar[1]);
+ }
+
+ if ($ar[0] == $obj->__table) {
+ if ($joinCol !== false) {
+ if ($k == $joinCol) {
+ $tfield = $k;
+ $ofield = $ar[1];
+ break;
+ } else {
+ continue;
+ }
+ } else {
+ $tfield = $k;
+ $ofield = $ar[1];
+ break;
+ }
+ }
+ }
+ }
/* look up the links for obj table */
//print_r($obj->links());
if (!$ofield && ($olinks = $obj->links())) {
}
}
- /* otherwise see if there are any links from this table to the obj. */
- //print_r($this->links());
- if (($ofield === false) && ($links = $this->links())) {
- foreach ($links as $k => $v) {
- /* link contains {this column} = {linked table}:{linked column} */
- $ar = explode(':', $v);
- // Feature Request #4266 - Allow joins with multiple keys
- if (strpos($k, ',') !== false) {
- $k = explode(',', $k);
- }
- if (strpos($ar[1], ',') !== false) {
- $ar[1] = explode(',', $ar[1]);
- }
-
- if ($ar[0] == $obj->__table) {
- if ($joinCol !== false) {
- if ($k == $joinCol) {
- $tfield = $k;
- $ofield = $ar[1];
- break;
- } else {
- continue;
- }
- } else {
- $tfield = $k;
- $ofield = $ar[1];
- break;
- }
- }
- }
- }
// finally if these two table have column names that match do a join by default on them
if (($ofield === false) && $joinCol) {
DB_DATAOBJECT_ERROR_INVALIDCONFIG);
return false;
}
+
+ $ignore_null = !isset($options['disable_null_strings'])
+ || !is_string($options['disable_null_strings'])
+ || strtolower($options['disable_null_strings']) !== 'full' ;
+
foreach($items as $k => $v) {
- if (!isset($obj->$k)) {
+ if (!isset($obj->$k) && $ignore_null) {
continue;
}
$kSql = ($quoteIdentifiers ? $DB->quoteIdentifier($k) : $k);
+ if (DB_DataObject::_is_null($obj,$k)) {
+ $obj->whereAdd("{$joinAs}.{$kSql} IS NULL");
+ continue;
+ }
if ($v & DB_DATAOBJECT_STR) {
$obj->whereAdd("{$joinAs}.{$kSql} = " . $this->_quote((string) (
if (PEAR::isError($value)) {
$this->raiseError($value->getMessage() ,DB_DATAOBJECT_ERROR_INVALIDARG);
return false;
- }
- if (!isset($options['disable_null_strings']) && strtolower($value) === 'null') {
- $obj->whereAdd("{$joinAs}.{$kSql} IS NULL");
- continue;
- } else {
- $obj->whereAdd("{$joinAs}.{$kSql} = $value");
- continue;
- }
+ }
+ $obj->whereAdd("{$joinAs}.{$kSql} = $value");
+ continue;
}
case 'RIGHT': // others??? .. cross, left outer, right outer, natural..?
// Feature Request #4266 - Allow joins with multiple keys
- $this->_join .= "\n {$joinType} JOIN {$objTable} {$fullJoinAs}";
+ $jadd = "\n {$joinType} JOIN {$objTable} {$fullJoinAs}";
+ //$this->_join .= "\n {$joinType} JOIN {$objTable} {$fullJoinAs}";
if (is_array($ofield)) {
$key_count = count($ofield);
for($i = 0; $i < $key_count; $i++) {
if ($i == 0) {
- $this->_join .= " ON ({$joinAs}.{$ofield[$i]}={$table}.{$tfield[$i]}) ";
+ $jadd .= " ON ({$joinAs}.{$ofield[$i]}={$table}.{$tfield[$i]}) ";
}
else {
- $this->_join .= " AND {$joinAs}.{$ofield[$i]}={$table}.{$tfield[$i]} ";
+ $jadd .= " AND {$joinAs}.{$ofield[$i]}={$table}.{$tfield[$i]} ";
}
}
- $this->_join .= ' ' . $appendJoin . ' ';
+ $jadd .= ' ' . $appendJoin . ' ';
} else {
- $this->_join .= " ON ({$joinAs}.{$ofield}={$table}.{$tfield}) {$appendJoin} ";
+ $jadd .= " ON ({$joinAs}.{$ofield}={$table}.{$tfield}) {$appendJoin} ";
}
-
+ // jadd avaliable for debugging join build.
+ //echo $jadd ."\n";
+ $this->_join .= $jadd;
break;
case '': // this is just a standard multitable select..
continue;
}
- if (empty($from[$k]) && $skipEmpty) {
+ if (empty($from[sprintf($format,$k)]) && $skipEmpty) {
continue;
}
- if (!isset($from[sprintf($format,$k)])) {
+ if (!isset($from[sprintf($format,$k)]) && !DB_DataObject::_is_null($from, sprintf($format,$k))) {
continue;
}
// if not null - and it's not set.......
- if (!isset($this->$key) && ($val & DB_DATAOBJECT_NOTNULL)) {
+ if ($val & DB_DATAOBJECT_NOTNULL && DB_DataObject::_is_null($this, $key)) {
// dont check empty sequence key values..
if (($key == $seq[0]) && ($seq[1] == true)) {
continue;
}
- if (!isset($options['disable_null_strings']) && is_string($this->$key) && (strtolower($this->$key) == 'null')) {
+ if (DB_DataObject::_is_null($this, $key)) {
if ($val & DB_DATAOBJECT_NOTNULL) {
$this->debug("'null' field used for '$key', but it is defined as NOT NULL", 'VALIDATION', 4);
$ret[$key] = false;
//echo "FROM VALUE $col, {$cols[$col]}, $value\n";
switch (true) {
// set to null and column is can be null...
- case (!isset($options['disable_null_strings']) && (strtolower($value) == 'null') && (!($cols[$col] & DB_DATAOBJECT_NOTNULL))):
+ case ((!($cols[$col] & DB_DATAOBJECT_NOTNULL)) && DB_DataObject::_is_null($value, false)):
case (is_object($value) && is_a($value,'DB_DataObject_Cast')):
$this->$col = $value;
return true;
// fail on setting null on a not null field..
- case (!isset($options['disable_null_strings']) && (strtolower($value) == 'null') && ($cols[$col] & DB_DATAOBJECT_NOTNULL)):
+ case (($cols[$col] & DB_DATAOBJECT_NOTNULL) && DB_DataObject::_is_null($value,false)):
+
return false;
case (($cols[$col] & DB_DATAOBJECT_DATE) && ($cols[$col] & DB_DATAOBJECT_TIME)):
if (isset($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5])) {
$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]->num_rows = array();
}
+
+ if (is_array($this->_link_loaded)) {
+ foreach ($this->_link_loaded as $do) {
+ $do->free();
+ }
+ }
+
}
+ /**
+ * Evaluate whether or not a value is set to null, taking the 'disable_null_strings' option into account.
+ * If the value is a string set to "null" and the "disable_null_strings" option is not set to
+ * true, then the value is considered to be null.
+ * If the value is actually a PHP NULL value, and "disable_null_strings" has been set to
+ * the value "full", then it will also be considered null. - this can not differenticate between not set
+ *
+ *
+ * @param object|array $obj_or_ar
+ * @param string|false $prop prperty
+ * @access private
+ * @return bool object
+ */
+ function _is_null($obj_or_ar , $prop)
+ {
+ global $_DB_DATAOBJECT;
+
+
+ $isset = $prop === false ? isset($obj_or_ar) :
+ (is_array($obj_or_ar) ? isset($obj_or_ar[$prop]) : isset($obj_or_ar->$prop));
+
+ $value = $isset ?
+ ($prop === false ? $obj_or_ar :
+ (is_array($obj_or_ar) ? $obj_or_ar[$prop] : $obj_or_ar->$prop))
+ : null;
+
+
+
+ $options = $_DB_DATAOBJECT['CONFIG'];
+
+ $null_strings = !isset($options['disable_null_strings'])
+ || $options['disable_null_strings'] === false;
+
+ $crazy_null = isset($options['disable_null_strings'])
+ && is_string($options['disable_null_strings'])
+ && strtolower($options['disable_null_strings'] === 'full');
+
+ if ( $null_strings && $isset && is_string($value) && (strtolower($value) === 'null') ) {
+ return true;
+ }
+
+ if ( $crazy_null && !$isset ) {
+ return true;
+ }
+
+ return false;
+
+
+ }
/* ---- LEGACY BC METHODS - NOT DOCUMENTED - See Documentation on New Methods. ---*/
}
}
+