Index: rdbms/Criteria.class.php =================================================================== --- rdbms/Criteria.class.php (revision 6409) +++ rdbms/Criteria.class.php (working copy) @@ -4,18 +4,7 @@ * $Id$ */ - define('IN', 'in (?)'); - define('NOT_IN', 'not in (?)'); - define('IS', 'is ?'); - define('IS_NOT', 'is not ?'); - define('LIKE', 'like ?'); - define('EQUAL', '= ?'); - define('NOT_EQUAL', '!= ?'); - define('LESS_THAN', '< ?'); - define('GREATER_THAN', '> ?'); - define('LESS_EQUAL', '<= ?'); - define('GREATER_EQUAL', '>= ?'); - define('BIT_AND', ' & ? = ?'); + uses('rdbms.criterion.SimpleExpression'); define('ASCENDING', 'asc'); define('DESCENDING', 'desc'); @@ -36,45 +25,55 @@ /** * Constructor * + * Example: + * + * new Criteria(Restrictions::equal('domainname', 'xp-framework.net')); + * + * + * Alternative API example: + * + * new Criteria(array('domainname', 'xp-framework.net', EQUAL)); + * + * * @access public - * @param array* conditions + * @param rdbms.criterion.Criterion condition */ - function __construct() { - $this->conditions= func_get_args(); + function __construct($criterion) { + if (is('rdbms.criterion.Criterion', $criterion)) { + $this->conditions[]= &$criterion; + } else if (is_array($criterion)) { + $this->conditions[]= &new SimpleExpression($criterion[0], $criterion[1], $criterion[2]); + } } /** * Add a condition * - * The order parameter may be one of the following constants: - * + * Example: + * + * with ($c= &new Criteria()); { + * $c->add(Restrictions::equal('bz_id', 500)); + * $c->add(Restrictions::in('author', array(1549, 1552))); + * } + * * + * Alternative API example: + * + * with ($c= &new Criteria()); { + * $c->add('bz_id', 500, EQUAL); + * $c->add('author', array(1549, 1552), IN); + * } + * + * * @access public - * @param string key - * @param mixed value - * @param string comparison default EQUAL + * @param rdbms.criterion.Criterion criterion */ - function add($key, $value, $comparison= EQUAL) { - static $nullMapping= array( - EQUAL => IS, - NOT_EQUAL => IS_NOT - ); - - // Automatically convert '= NULL' to 'is NULL', former is not valid ANSI-SQL - if (NULL === $value && isset($nullMapping[$comparison])) - $comparison= $nullMapping[$comparison]; - - $this->conditions[]= array($key, $value, $comparison); + function add($criterion, $value= NULL, $comparison= EQUAL) { + if (is('rdbms.criterion.Criterion', $criterion)) { + $this->conditions[]= &$criterion; + } else { + $this->conditions[]= &new SimpleExpression($criterion, $value, $comparison); + } } /** @@ -82,8 +81,8 @@ * * * with ($c= &new Criteria()); { - * $this->add('bz_id', 500, EQUAL); - * $this->addOrderBy('created_at', DESCENDING); + * $c->add(Restriction::equal('bz_id', 500)); + * $c->addOrderBy('created_at', DESCENDING); * } * * @@ -120,11 +119,7 @@ function toString() { $s= $this->getClassName()."@{\n"; foreach ($this->conditions as $condition) { - $s.= sprintf( - " [%s %s]\n", - $condition[0], - str_replace('?', xp::stringOf($condition[1]), $condition[2]) - ); + $s.= ' '.xp::stringOf($condition); } return $s.'}'; } @@ -145,14 +140,7 @@ if (!empty($this->conditions)) { $sql.= ' where '; foreach ($this->conditions as $condition) { - if (!isset($types[$condition[0]])) { - return throw(new SQLStateException('Field "'.$condition[0].'" unknown')); - } - - $sql.= $condition[0].' '.$db->prepare( - str_replace('?', $types[$condition[0]], $condition[2]).' and ', - $condition[1] - ); + $sql.= $condition->asSql($db, $types).' and '; } $sql= substr($sql, 0, -4); } Index: net/xp_framework/unittest/rdbms/CriteriaTest.class.php =================================================================== --- net/xp_framework/unittest/rdbms/CriteriaTest.class.php (revision 6409) +++ net/xp_framework/unittest/rdbms/CriteriaTest.class.php (working copy) @@ -6,6 +6,8 @@ uses( 'rdbms.Criteria', + 'rdbms.criterion.Restrictions', + 'rdbms.criterion.Property', 'rdbms.DriverManager', 'net.xp_framework.unittest.rdbms.dataset.Job', 'util.profiling.unittest.TestCase' @@ -14,6 +16,10 @@ /** * Test criteria class * + * Note we're relying on the connection to be a sybase connection - + * otherwise, quoting and date representation may change and make + * this testcase fail. + * * @see xp://rdbms.Criteria * @purpose Unit Test */ @@ -94,13 +100,34 @@ $c->addOrderBy('valid_from'); } - // Note we're relying on the connection to be a sybase connection - - // otherwise, quoting and date representation may change and make - // this test fail. $this->assertSql( 'where job_id = 1 and valid_from >= "2006-01-01 12:00AM" and title like "Hello%" order by valid_from asc', $c ); } + + /** + * Tests the rdbms.criterion API + * + * @see xp://rdbms.criterion.Property + * @see xp://rdbms.criterion.Restrictions + * @access public + */ + #[@test] + function restrictionsFactory() { + $job_id= &Property::forName('job_id'); + $c= &new Criteria(Restrictions::anyOf( + Restrictions::not($job_id->in(array(1, 2, 3))), + Restrictions::allOf( + Restrictions::like('title', 'Hello%'), + Restrictions::greaterThan('valid_from', new Date('2006-01-01')) + ) + )); + + $this->assertSql( + 'where (not (job_id in (1, 2, 3)) or (title like "Hello%" and valid_from > "2006-01-01 12:00AM"))', + $c + ); + } } ?>