2010-12-02 23:34:41 +00:00
< ? php
/*
* $Id : BasePeer . php 536 2007 - 01 - 10 14 : 30 : 38 Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
* LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL . For more information please see
* < http :// propel . phpdb . org >.
*/
include_once 'propel/adapter/DBAdapter.php' ;
include_once 'propel/map/ColumnMap.php' ;
include_once 'propel/map/DatabaseMap.php' ;
include_once 'propel/map/MapBuilder.php' ;
include_once 'propel/map/TableMap.php' ;
include_once 'propel/map/ValidatorMap.php' ;
include_once 'propel/validator/ValidationFailed.php' ;
/**
* This is a utility class for all generated Peer classes in the system .
*
* Peer classes are responsible for isolating all of the database access
* for a specific business object . They execute all of the SQL
* against the database . Over time this class has grown to include
* utility methods which ease execution of cross - database queries and
* the implementation of concrete Peers .
*
* @ author Hans Lellelid < hans @ xmpl . org > ( Propel )
* @ author Kaspars Jaudzems < kaspars . jaudzems @ inbox . lv > ( Propel )
* @ author Frank Y . Kim < frank . kim @ clearink . com > ( Torque )
* @ author John D . McNally < jmcnally @ collab . net > ( Torque )
* @ author Brett McLaughlin < bmclaugh @ algx . net > ( Torque )
* @ author Stephen Haberman < stephenh @ chase3000 . com > ( Torque )
* @ version $Revision : 536 $
* @ package propel . util
*/
class BasePeer
{
/** Array (hash) that contains the cached mapBuilders. */
private static $mapBuilders = array ();
/** Array (hash) that contains cached validators */
private static $validatorMap = array ();
/**
* phpname type
* e . g . 'AuthorId'
*/
const TYPE_PHPNAME = 'phpName' ;
/**
* column ( peer ) name type
* e . g . 'book.AUTHOR_ID'
*/
const TYPE_COLNAME = 'colName' ;
/**
* column fieldname type
* e . g . 'author_id'
*/
const TYPE_FIELDNAME = 'fieldName' ;
/**
* num type
* simply the numerical array index , e . g . 4
*/
const TYPE_NUM = 'num' ;
static public function getFieldnames ( $classname , $type = self :: TYPE_PHPNAME ) {
// TODO we should take care of including the peer class here
$peerclass = 'Base' . $classname . 'Peer' ; // TODO is this always true?
$callable = array ( $peerclass , 'getFieldnames' );
$args = array ( $type );
return call_user_func_array ( $callable , $args );
}
static public function translateFieldname ( $classname , $fieldname , $fromType , $toType ) {
// TODO we should take care of including the peer class here
$peerclass = 'Base' . $classname . 'Peer' ; // TODO is this always true?
$callable = array ( $peerclass , 'translateFieldname' );
$args = array ( $fieldname , $fromType , $toType );
return call_user_func_array ( $callable , $args );
}
/**
* Method to perform deletes based on values and keys in a
* Criteria .
*
* @ param Criteria $criteria The criteria to use .
* @ param Connection $con A Connection .
* @ return int The number of rows affected by last statement execution . For most
* uses there is only one delete statement executed , so this number
* will correspond to the number of rows affected by the call to this
* method . Note that the return value does require that this information
* is returned ( supported ) by the Creole db driver .
* @ throws PropelException
*/
public static function doDelete ( Criteria $criteria , Connection $con )
{
$db = Propel :: getDB ( $criteria -> getDbName ());
$dbMap = Propel :: getDatabaseMap ( $criteria -> getDbName ());
// Set up a list of required tables (one DELETE statement will
// be executed per table)
$tables_keys = array ();
foreach ( $criteria as $c ) {
foreach ( $c -> getAllTables () as $tableName ) {
$tableName2 = $criteria -> getTableForAlias ( $tableName );
if ( $tableName2 !== null ) {
$tables_keys [ $tableName2 . ' ' . $tableName ] = true ;
} else {
$tables_keys [ $tableName ] = true ;
}
}
} // foreach criteria->keys()
$affectedRows = 0 ; // initialize this in case the next loop has no iterations.
$tables = array_keys ( $tables_keys );
foreach ( $tables as $tableName ) {
$whereClause = array ();
$selectParams = array ();
foreach ( $dbMap -> getTable ( $tableName ) -> getColumns () as $colMap ) {
$key = $tableName . '.' . $colMap -> getColumnName ();
if ( $criteria -> containsKey ( $key )) {
$sb = " " ;
$criteria -> getCriterion ( $key ) -> appendPsTo ( $sb , $selectParams );
$whereClause [] = $sb ;
}
}
if ( empty ( $whereClause )) {
throw new PropelException ( " Cowardly refusing to delete from table $tableName with empty WHERE clause. " );
}
// Execute the statement.
try {
$sqlSnippet = implode ( " AND " , $whereClause );
if ( $criteria -> isSingleRecord ()) {
$sql = " SELECT COUNT(*) FROM " . $tableName . " WHERE " . $sqlSnippet ;
$stmt = $con -> prepareStatement ( $sql );
self :: populateStmtValues ( $stmt , $selectParams , $dbMap );
$rs = $stmt -> executeQuery ( ResultSet :: FETCHMODE_NUM );
$rs -> next ();
if ( $rs -> getInt ( 1 ) > 1 ) {
$rs -> close ();
throw new PropelException ( " Expecting to delete 1 record, but criteria match multiple. " );
}
$rs -> close ();
}
$sql = " DELETE FROM " . $tableName . " WHERE " . $sqlSnippet ;
Propel :: log ( $sql , Propel :: LOG_DEBUG );
$stmt = $con -> prepareStatement ( $sql );
self :: populateStmtValues ( $stmt , $selectParams , $dbMap );
$affectedRows = $stmt -> executeUpdate ();
} catch ( Exception $e ) {
Propel :: log ( $e -> getMessage (), Propel :: LOG_ERR );
throw new PropelException ( " Unable to execute DELETE statement. " , $e );
}
} // for each table
return $affectedRows ;
}
/**
* Method to deletes all contents of specified table .
*
* This method is invoked from generated Peer classes like this :
* < code >
* public static function doDeleteAll ( $con = null )
* {
* if ( $con === null ) $con = Propel :: getConnection ( self :: DATABASE_NAME );
* BasePeer :: doDeleteAll ( self :: TABLE_NAME , $con );
* }
* </ code >
*
* @ param string $tableName The name of the table to empty .
* @ param Connection $con A Connection .
* @ return int The number of rows affected by the statement . Note
* that the return value does require that this information
* is returned ( supported ) by the Creole db driver .
* @ throws PropelException - wrapping SQLException caught from statement execution .
*/
public static function doDeleteAll ( $tableName , Connection $con )
{
try {
$sql = " DELETE FROM " . $tableName ;
Propel :: log ( $sql , Propel :: LOG_DEBUG );
$stmt = $con -> prepareStatement ( $sql );
return $stmt -> executeUpdate ();
} catch ( Exception $e ) {
Propel :: log ( $e -> getMessage (), Propel :: LOG_ERR );
throw new PropelException ( " Unable to perform DELETE ALL operation. " , $e );
}
}
/**
* Method to perform inserts based on values and keys in a
* Criteria .
* < p >
* If the primary key is auto incremented the data in Criteria
* will be inserted and the auto increment value will be returned .
* < p >
* If the primary key is included in Criteria then that value will
* be used to insert the row .
* < p >
* If no primary key is included in Criteria then we will try to
* figure out the primary key from the database map and insert the
* row with the next available id using util . db . IDBroker .
* < p >
* If no primary key is defined for the table the values will be
* inserted as specified in Criteria and null will be returned .
*
* @ param Criteria $criteria Object containing values to insert .
* @ param Connection $con A Connection .
* @ return mixed The primary key for the new row if ( and only if ! ) the primary key
* is auto - generated . Otherwise will return < code > null </ code >.
* @ throws PropelException
*/
public static function doInsert ( Criteria $criteria , Connection $con ) {
// the primary key
$id = null ;
// Get the table name and method for determining the primary
// key value.
$keys = $criteria -> keys ();
if ( ! empty ( $keys )) {
$tableName = $criteria -> getTableName ( $keys [ 0 ] );
} else {
throw new PropelException ( " Database insert attempted without anything specified to insert " );
}
$dbMap = Propel :: getDatabaseMap ( $criteria -> getDbName ());
$tableMap = $dbMap -> getTable ( $tableName );
$keyInfo = $tableMap -> getPrimaryKeyMethodInfo ();
$useIdGen = $tableMap -> isUseIdGenerator ();
$keyGen = $con -> getIdGenerator ();
$pk = self :: getPrimaryKey ( $criteria );
// only get a new key value if you need to
// the reason is that a primary key might be defined
// but you are still going to set its value. for example:
// a join table where both keys are primary and you are
// setting both columns with your own values
// pk will be null if there is no primary key defined for the table
// we're inserting into.
if ( $pk !== null && $useIdGen && ! $criteria -> containsKey ( $pk -> getFullyQualifiedName ())) {
// If the keyMethod is SEQUENCE get the id before the insert.
if ( $keyGen -> isBeforeInsert ()) {
try {
$id = $keyGen -> getId ( $keyInfo );
} catch ( Exception $e ) {
throw new PropelException ( " Unable to get sequence id. " , $e );
}
$criteria -> add ( $pk -> getFullyQualifiedName (), $id );
}
}
try {
$qualifiedCols = $criteria -> keys (); // we need table.column cols when populating values
$columns = array (); // but just 'column' cols for the SQL
2011-10-12 10:05:16 -04:00
/**
* FIXED
* @ author Erik Amaru Ortiz
* We have troubles if on sql insert the columns names aren ' t being qualified quoted with words like RANGE and others
* to fix it we add quote identifier depending of db engine , using its respective Adapter :: quoteIdentifier () function
*/
$adapter = Propel :: getDB ( $criteria -> getDbName ());
2010-12-02 23:34:41 +00:00
foreach ( $qualifiedCols as $qualifiedCol ) {
2011-10-12 10:05:16 -04:00
$columns [] = $adapter -> quoteIdentifier ( substr ( $qualifiedCol , strpos ( $qualifiedCol , '.' ) + 1 ));
2010-12-02 23:34:41 +00:00
}
$sql = " INSERT INTO " . $tableName
. " ( " . implode ( " , " , $columns ) . " ) "
. " VALUES ( " . substr ( str_repeat ( " ?, " , count ( $columns )), 0 , - 1 ) . " ) " ;
Propel :: log ( $sql , Propel :: LOG_DEBUG );
$stmt = $con -> prepareStatement ( $sql );
self :: populateStmtValues ( $stmt , self :: buildParams ( $qualifiedCols , $criteria ), $dbMap );
$stmt -> executeUpdate ();
} catch ( Exception $e ) {
Propel :: log ( $e -> getMessage (), Propel :: LOG_ERR );
throw new PropelException ( " Unable to execute INSERT statement. " , $e );
}
// If the primary key column is auto-incremented, get the id
// now.
if ( $pk !== null && $useIdGen && $keyGen -> isAfterInsert ()) {
try {
$id = $keyGen -> getId ( $keyInfo );
} catch ( Exception $e ) {
throw new PropelException ( " Unable to get autoincrement id. " , $e );
}
}
return $id ;
}
/**
* Method used to update rows in the DB . Rows are selected based
* on selectCriteria and updated using values in updateValues .
* < p >
* Use this method for performing an update of the kind :
* < p >
* WHERE some_column = some value AND could_have_another_column =
* another value AND so on .
*
* @ param $selectCriteria A Criteria object containing values used in where
* clause .
* @ param $updateValues A Criteria object containing values used in set
* clause .
* @ param $con The Connection to use .
* @ return int The number of rows affected by last update statement . For most
* uses there is only one update statement executed , so this number
* will correspond to the number of rows affected by the call to this
* method . Note that the return value does require that this information
* is returned ( supported ) by the Creole db driver .
* @ throws PropelException
*/
public static function doUpdate ( Criteria $selectCriteria , Criteria $updateValues , Connection $con ) {
$db = Propel :: getDB ( $selectCriteria -> getDbName ());
$dbMap = Propel :: getDatabaseMap ( $selectCriteria -> getDbName ());
// Get list of required tables, containing all columns
$tablesColumns = $selectCriteria -> getTablesColumns ();
// we also need the columns for the update SQL
$updateTablesColumns = $updateValues -> getTablesColumns ();
$affectedRows = 0 ; // initialize this in case the next loop has no iterations.
foreach ( $tablesColumns as $tableName => $columns ) {
$whereClause = array ();
$selectParams = array ();
foreach ( $columns as $colName ) {
$sb = " " ;
$selectCriteria -> getCriterion ( $colName ) -> appendPsTo ( $sb , $selectParams );
$whereClause [] = $sb ;
}
$rs = null ;
$stmt = null ;
try {
$sqlSnippet = implode ( " AND " , $whereClause );
if ( $selectCriteria -> isSingleRecord ()) {
// Get affected records.
$sql = " SELECT COUNT(*) FROM " . $tableName . " WHERE " . $sqlSnippet ;
$stmt = $con -> prepareStatement ( $sql );
self :: populateStmtValues ( $stmt , $selectParams , $dbMap );
$rs = $stmt -> executeQuery ( ResultSet :: FETCHMODE_NUM );
$rs -> next ();
if ( $rs -> getInt ( 1 ) > 1 ) {
$rs -> close ();
throw new PropelException ( " Expected to update 1 record, multiple matched. " );
}
$rs -> close ();
}
2011-10-12 10:05:16 -04:00
/**
* FIXED
* @ author Erik Amaru Ortiz
* We have troubles if on sql insert the columns names aren ' t being qualified quoted with words like RANGE and others
* to fix it we add quote identifier depending of db engine , using its respective Adapter :: quoteIdentifier () function
*/
$adapter = Propel :: getDB ( $selectCriteria -> getDbName ());
2010-12-02 23:34:41 +00:00
$sql = " UPDATE " . $tableName . " SET " ;
foreach ( $updateTablesColumns [ $tableName ] as $col ) {
2011-10-12 10:05:16 -04:00
$sql .= $adapter -> quoteIdentifier ( substr ( $col , strpos ( $col , '.' ) + 1 )) . " = ?, " ;
2010-12-02 23:34:41 +00:00
}
$sql = substr ( $sql , 0 , - 1 ) . " WHERE " . $sqlSnippet ;
Propel :: log ( $sql , Propel :: LOG_DEBUG );
$stmt = $con -> prepareStatement ( $sql );
// Replace '?' with the actual values
self :: populateStmtValues ( $stmt , array_merge ( self :: buildParams ( $updateTablesColumns [ $tableName ], $updateValues ), $selectParams ), $dbMap );
$affectedRows = $stmt -> executeUpdate ();
$stmt -> close ();
} catch ( Exception $e ) {
if ( $rs ) $rs -> close ();
if ( $stmt ) $stmt -> close ();
Propel :: log ( $e -> getMessage (), Propel :: LOG_ERR );
throw new PropelException ( " Unable to execute UPDATE statement. " , $e );
}
} // foreach table in the criteria
return $affectedRows ;
}
/**
* Executes query build by createSelectSql () and returns ResultSet .
*
* @ param Criteria $criteria A Criteria .
* @ param Connection $con A connection to use .
* @ return ResultSet The resultset .
* @ throws PropelException
* @ see createSelectSql ()
*/
public static function doSelect ( Criteria $criteria , $con = null )
{
$dbMap = Propel :: getDatabaseMap ( $criteria -> getDbName ());
if ( $con === null )
$con = Propel :: getConnection ( $criteria -> getDbName ());
$stmt = null ;
try {
// Transaction support exists for (only?) Postgres, which must
// have SELECT statements that include bytea columns wrapped w/
// transactions.
if ( $criteria -> isUseTransaction ()) $con -> begin ();
$params = array ();
$sql = self :: createSelectSql ( $criteria , $params );
$stmt = $con -> prepareStatement ( $sql );
$stmt -> setLimit ( $criteria -> getLimit ());
$stmt -> setOffset ( $criteria -> getOffset ());
self :: populateStmtValues ( $stmt , $params , $dbMap );
$rs = $stmt -> executeQuery ( ResultSet :: FETCHMODE_NUM );
if ( $criteria -> isUseTransaction ()) $con -> commit ();
} catch ( Exception $e ) {
if ( $stmt ) $stmt -> close ();
if ( $criteria -> isUseTransaction ()) $con -> rollback ();
Propel :: log ( $e -> getMessage (), Propel :: LOG_ERR );
throw new PropelException ( $e );
}
return $rs ;
}
/**
* Applies any validators that were defined in the schema to the specified columns .
*
* @ param string $dbName The name of the database
* @ param string $tableName The name of the table
* @ param array $columns Array of column names as key and column values as value .
*/
public static function doValidate ( $dbName , $tableName , $columns )
{
$dbMap = Propel :: getDatabaseMap ( $dbName );
$tableMap = $dbMap -> getTable ( $tableName );
$failureMap = array (); // map of ValidationFailed objects
foreach ( $columns as $colName => $colValue ) {
if ( $tableMap -> containsColumn ( $colName )) {
$col = $tableMap -> getColumn ( $colName );
foreach ( $col -> getValidators () as $validatorMap ) {
$validator = BasePeer :: getValidator ( $validatorMap -> getClass ());
if ( $validator && ( $col -> isNotNull () || $colValue !== null ) && $validator -> isValid ( $validatorMap , $colValue ) === false ) {
if ( ! isset ( $failureMap [ $colName ])) { // for now we do one ValidationFailed per column, not per rule
$failureMap [ $colName ] = new ValidationFailed ( $colName , $validatorMap -> getMessage (), $validator );
}
}
}
}
}
return ( ! empty ( $failureMap ) ? $failureMap : true );
}
/**
* Helper method which returns the primary key contained
* in the given Criteria object .
*
* @ param Criteria $criteria A Criteria .
* @ return ColumnMap If the Criteria object contains a primary
* key , or null if it doesn ' t .
* @ throws PropelException
*/
private static function getPrimaryKey ( Criteria $criteria )
{
// Assume all the keys are for the same table.
$keys = $criteria -> keys ();
$key = $keys [ 0 ];
$table = $criteria -> getTableName ( $key );
$pk = null ;
if ( ! empty ( $table )) {
$dbMap = Propel :: getDatabaseMap ( $criteria -> getDbName ());
if ( $dbMap === null ) {
throw new PropelException ( " \$ dbMap is null " );
}
if ( $dbMap -> getTable ( $table ) === null ) {
throw new PropelException ( " \$ dbMap->getTable() is null " );
}
$columns = $dbMap -> getTable ( $table ) -> getColumns ();
foreach ( array_keys ( $columns ) as $key ) {
if ( $columns [ $key ] -> isPrimaryKey ()) {
$pk = $columns [ $key ];
break ;
}
}
}
return $pk ;
}
/**
* Method to create an SQL query based on values in a Criteria .
*
* This method creates only prepared statement SQL ( using ? where values
* will go ) . The second parameter ( $params ) stores the values that need
* to be set before the statement is executed . The reason we do it this way
* is to let the Creole layer handle all escaping & value formatting .
*
* @ param Criteria $criteria Criteria for the SELECT query .
* @ param array & $params Parameters that are to be replaced in prepared statement .
* @ return string
* @ throws PropelException Trouble creating the query string .
*/
public static function createSelectSql ( Criteria $criteria , & $params ) {
$db = Propel :: getDB ( $criteria -> getDbName ());
$dbMap = Propel :: getDatabaseMap ( $criteria -> getDbName ());
// redundant definition $selectModifiers = array();
$selectClause = array ();
$fromClause = array ();
$joinClause = array ();
$joinTables = array ();
$whereClause = array ();
$orderByClause = array ();
// redundant definition $groupByClause = array();
$orderBy = $criteria -> getOrderByColumns ();
$groupBy = $criteria -> getGroupByColumns ();
$ignoreCase = $criteria -> isIgnoreCase ();
$select = $criteria -> getSelectColumns ();
$aliases = $criteria -> getAsColumns ();
// simple copy
$selectModifiers = $criteria -> getSelectModifiers ();
// get selected columns
foreach ( $select as $columnName ) {
// expect every column to be of "table.column" formation
// it could be a function: e.g. MAX(books.price)
$tableName = null ;
$selectClause [] = $columnName ; // the full column name: e.g. MAX(books.price)
$parenPos = strpos ( $columnName , '(' );
$dotPos = strpos ( $columnName , '.' );
// [HL] I think we really only want to worry about adding stuff to
// the fromClause if this function has a TABLE.COLUMN in it at all.
// e.g. COUNT(*) should not need this treatment -- or there needs to
// be special treatment for '*'
if ( $dotPos !== false ) {
if ( $parenPos === false ) { // table.column
$tableName = substr ( $columnName , 0 , $dotPos );
} else { // FUNC(table.column)
$tableName = substr ( $columnName , $parenPos + 1 , $dotPos - ( $parenPos + 1 ));
// functions may contain qualifiers so only take the last
// word as the table name.
// COUNT(DISTINCT books.price)
$lastSpace = strpos ( $tableName , ' ' );
if ( $lastSpace !== false ) { // COUNT(DISTINCT books.price)
$tableName = substr ( $tableName , $lastSpace + 1 );
}
}
$tableName2 = $criteria -> getTableForAlias ( $tableName );
if ( $tableName2 !== null ) {
$fromClause [] = $tableName2 . ' ' . $tableName ;
} else {
$fromClause [] = $tableName ;
}
} // if $dotPost !== null
}
// set the aliases
foreach ( $aliases as $alias => $col ) {
$selectClause [] = $col . " AS " . $alias ;
}
// add the criteria to WHERE clause
// this will also add the table names to the FROM clause if they are not already
// invluded via a LEFT JOIN
foreach ( $criteria -> keys () as $key ) {
$criterion = $criteria -> getCriterion ( $key );
$someCriteria = $criterion -> getAttachedCriterion ();
$someCriteriaLength = count ( $someCriteria );
$table = null ;
for ( $i = 0 ; $i < $someCriteriaLength ; $i ++ ) {
$tableName = $someCriteria [ $i ] -> getTable ();
$table = $criteria -> getTableForAlias ( $tableName );
if ( $table !== null ) {
$fromClause [] = $table . ' ' . $tableName ;
} else {
$fromClause [] = $tableName ;
$table = $tableName ;
}
$ignoreCase =
(( $criteria -> isIgnoreCase ()
|| $someCriteria [ $i ] -> isIgnoreCase ())
&& ( $dbMap -> getTable ( $table ) -> getColumn ( $someCriteria [ $i ] -> getColumn ()) -> getType () == " string " )
);
$someCriteria [ $i ] -> setIgnoreCase ( $ignoreCase );
}
$criterion -> setDB ( $db );
$sb = " " ;
$criterion -> appendPsTo ( $sb , $params );
$whereClause [] = $sb ;
}
// handle RIGHT (straight) joins
// Loop through the joins,
// joins with a null join type will be added to the FROM clause and the condition added to the WHERE clause.
// joins of a specified type: the LEFT side will be added to the fromClause and the RIGHT to the joinClause
// New Code.
foreach (( array ) $criteria -> getJoins () as $join ) { // we'll only loop if there's actually something here
// The join might have been established using an alias name
$leftTable = $join -> getLeftTableName ();
$leftTableAlias = '' ;
if ( $realTable = $criteria -> getTableForAlias ( $leftTable )) {
$leftTableAlias = " $leftTable " ;
$leftTable = $realTable ;
}
$rightTable = $join -> getRightTableName ();
$rightTableAlias = '' ;
if ( $realTable = $criteria -> getTableForAlias ( $rightTable )) {
$rightTableAlias = " $rightTable " ;
$rightTable = $realTable ;
}
// determine if casing is relevant.
if ( $ignoreCase = $criteria -> isIgnoreCase ()) {
$leftColType = $dbMap -> getTable ( $leftTable ) -> getColumn ( $join -> getLeftColumnName ()) -> getType ();
$rightColType = $dbMap -> getTable ( $rightTable ) -> getColumn ( $join -> getRightColumnName ()) -> getType ();
$ignoreCase = ( $leftColType == 'string' || $rightColType == 'string' );
}
// build the condition
if ( $ignoreCase ) {
$condition = $db -> ignoreCase ( $join -> getLeftColumn ()) . '=' . $db -> ignoreCase ( $join -> getRightColumn ());
} else {
$condition = $join -> getLeftColumn () . '=' . $join -> getRightColumn ();
}
// add 'em to the queues..
if ( $joinType = $join -> getJoinType ()) {
if ( ! $fromClause ) {
$fromClause [] = $leftTable . $leftTableAlias ;
}
$joinTables [] = $rightTable . $rightTableAlias ;
$joinClause [] = $join -> getJoinType () . ' ' . $rightTable . $rightTableAlias . " ON ( $condition ) " ;
} else {
$fromClause [] = $leftTable . $leftTableAlias ;
$fromClause [] = $rightTable . $rightTableAlias ;
$whereClause [] = $condition ;
}
}
/****************************************************************************************************************/
/****************************************************************************************************************/
// handle RIGHT (straight) joins with multiple conditions
// Loop through the joins,
// joins with a null join type will be added to the FROM clause and the condition added to the WHERE clause.
// joins of a specified type: the LEFT side will be added to the fromClause and the RIGHT to the joinClause
// Custom Code.
foreach (( array ) $criteria -> getJoinsMC () as $join ) { // we'll only loop if there's actually something here
// The join might have been established using an alias name
$leftTable = $join -> getLeftTableName ( $join -> conditions [ 0 ][ 0 ]);
$leftTableAlias = '' ;
if ( $realTable = $criteria -> getTableForAlias ( $leftTable )) {
$leftTableAlias = " $leftTable " ;
$leftTable = $realTable ;
}
$rightTable = $join -> getRightTableName ( $join -> conditions [ 0 ][ 1 ]);
$rightTableAlias = '' ;
if ( $realTable = $criteria -> getTableForAlias ( $rightTable )) {
$rightTableAlias = " $rightTable " ;
$rightTable = $realTable ;
}
$condition = '' ;
foreach ( $join -> conditions as $aCondition ) {
// determine if casing is relevant.
if ( $ignoreCase = $criteria -> isIgnoreCase ()) {
$leftColType = $dbMap -> getTable ( $leftTable ) -> getColumn ( $join -> getLeftColumnName ( $aCondition [ 0 ])) -> getType ();
$rightColType = $dbMap -> getTable ( $rightTable ) -> getColumn ( $join -> getRightColumnName ( $aCondition [ 1 ])) -> getType ();
$ignoreCase = ( $leftColType == 'string' || $rightColType == 'string' );
}
// build the condition
if ( $ignoreCase ) {
$condition .= $db -> ignoreCase ( $aCondition [ 0 ]) . '=' . $db -> ignoreCase ( $aCondition [ 1 ]) . ' AND ' ;
} else {
$condition .= $aCondition [ 0 ] . '=' . $aCondition [ 1 ] . ' AND ' ;
}
}
$condition = substr ( $condition , 0 , - 5 );
// add 'em to the queues..
if ( $joinType = $join -> getJoinType ()) {
if ( ! $fromClause ) {
$fromClause [] = $leftTable . $leftTableAlias ;
}
$joinTables [] = $rightTable . $rightTableAlias ;
$joinClause [] = $join -> getJoinType () . ' ' . $rightTable . $rightTableAlias . " ON ( $condition ) " ;
} else {
$fromClause [] = $leftTable . $leftTableAlias ;
$fromClause [] = $rightTable . $rightTableAlias ;
$whereClause [] = $condition ;
}
}
/****************************************************************************************************************/
/****************************************************************************************************************/
// Unique from clause elements
$fromClause = array_unique ( $fromClause );
// tables should not exist in both the from and join clauses
if ( $joinTables && $fromClause ) {
foreach ( $fromClause as $fi => $ftable ) {
if ( in_array ( $ftable , $joinTables )) {
unset ( $fromClause [ $fi ]);
}
}
}
/*
// Old Code.
$joins =& $criteria -> getJoins ();
if ( ! empty ( $joins )) {
for ( $i = 0 , $joinSize = count ( $joins ); $i < $joinSize ; $i ++ ) {
$join =& $joins [ $i ];
$join1 = $join -> getLeftColumn ();
$join2 = $join -> getRightColumn ();
$tableName = substr ( $join1 , 0 , strpos ( $join1 , '.' ));
$table = $criteria -> getTableForAlias ( $tableName );
if ( $table !== null ) {
$fromClause [] = $table . ' ' . $tableName ;
} else {
$fromClause [] = $tableName ;
}
$dot = strpos ( $join2 , '.' );
$tableName = substr ( $join2 , 0 , $dot );
$table = $criteria -> getTableForAlias ( $tableName );
if ( $table !== null ) {
$fromClause [] = $table . ' ' . $tableName ;
} else {
$fromClause [] = $tableName ;
$table = $tableName ;
}
$ignoreCase = ( $criteria -> isIgnoreCase () && ( $dbMap -> getTable ( $table ) -> getColumn ( substr ( $join2 , $dot + 1 )) -> getType () == " string " ));
if ( $ignoreCase ) {
$whereClause [] = $db -> ignoreCase ( $join1 ) . '=' . $db -> ignoreCase ( $join2 );
} else {
$whereClause [] = $join1 . '=' . $join2 ;
}
if ( $join -> getJoinType ()) {
$leftTable = $fromClause [ count ( $fromClause ) - 2 ];
$rightTable = $fromClause [ count ( $fromClause ) - 1 ];
$onClause = $whereClause [ count ( $whereClause ) - 1 ];
unset ( $whereClause [ count ( $whereClause ) - 1 ]);
$fromClause [] = $leftTable . ' ' . $join -> getJoinType () . ' ' . $rightTable . ' ON ' . $onClause ;
// remove all references to joinTables made by selectColumns, criteriaColumns
for ( $i = 0 , $fromClauseSize = count ( $fromClause ); $i < $fromClauseSize ; $i ++ ) {
if ( $fromClause [ $i ] == $leftTable || $fromClause [ $i ] == $rightTable ) {
unset ( $fromClause [ $i ]);
}
}
} // If join type
} // Join for loop
} // If Joins
*/
// Add the GROUP BY columns
$groupByClause = $groupBy ;
$having = $criteria -> getHaving ();
$havingString = null ;
if ( $having !== null ) {
$sb = " " ;
$having -> appendPsTo ( $sb , $params );
$havingString = $sb ;
}
if ( ! empty ( $orderBy )) {
foreach ( $orderBy as $orderByColumn ) {
// Add function expression as-is.
if ( strpos ( $orderByColumn , '(' ) !== false ) {
$orderByClause [] = $orderByColumn ;
continue ;
}
// Split orderByColumn (i.e. "table.column DESC")
$dotPos = strpos ( $orderByColumn , '.' );
if ( $dotPos !== false ) {
$tableName = substr ( $orderByColumn , 0 , $dotPos );
$columnName = substr ( $orderByColumn , $dotPos + 1 );
}
else {
$tableName = '' ;
$columnName = $orderByColumn ;
}
$spacePos = strpos ( $columnName , ' ' );
if ( $spacePos !== false ) {
$direction = substr ( $columnName , $spacePos );
$columnName = substr ( $columnName , 0 , $spacePos );
}
else {
$direction = '' ;
}
$tableAlias = $tableName ;
if ( $aliasTableName = $criteria -> getTableForAlias ( $tableName )) {
$tableName = $aliasTableName ;
}
$columnAlias = $columnName ;
if ( $asColumnName = $criteria -> getColumnForAs ( $columnName )) {
$columnName = $asColumnName ;
}
$column = $tableName ? $dbMap -> getTable ( $tableName ) -> getColumn ( $columnName ) : null ;
if ( $column && $column -> getType () == 'string' ) {
$orderByClause [] = $db -> ignoreCaseInOrderBy ( " $tableAlias . $columnAlias " ) . $direction ;
$selectClause [] = $db -> ignoreCaseInOrderBy ( " $tableAlias . $columnAlias " );
}
else {
$orderByClause [] = $orderByColumn ;
}
}
}
// Build the SQL from the arrays we compiled
$sql = " SELECT "
. ( $selectModifiers ? implode ( " " , $selectModifiers ) . " " : " " )
. implode ( " , " , $selectClause )
. " FROM " . ( ( ! empty ( $joinClause ) && count ( $fromClause ) > 1 && ( substr ( get_class ( $db ), 0 , 7 ) == 'DBMySQL' )) ? " ( " . implode ( " , " , $fromClause ) . " ) " : implode ( " , " , $fromClause ) )
. ( $joinClause ? ' ' . implode ( ' ' , $joinClause ) : '' )
. ( $whereClause ? " WHERE " . implode ( " AND " , $whereClause ) : " " )
. ( $groupByClause ? " GROUP BY " . implode ( " , " , $groupByClause ) : " " )
. ( $havingString ? " HAVING " . $havingString : " " )
. ( $orderByClause ? " ORDER BY " . implode ( " , " , $orderByClause ) : " " );
Propel :: log ( $sql . ' [LIMIT: ' . $criteria -> getLimit () . ', OFFSET: ' . $criteria -> getOffset () . ']' , Propel :: LOG_DEBUG );
//echo $sql . "\n\n";
return $sql ;
}
/**
* Builds a params array , like the kind populated by Criterion :: appendPsTo () .
* This is useful for building an array even when it is not using the appendPsTo () method .
* @ param array $columns
* @ param Criteria $values
* @ return array params array ( 'column' => ... , 'table' => ... , 'value' => ... )
*/
private static function buildParams ( $columns , Criteria $values ) {
$params = array ();
foreach ( $columns as $key ) {
if ( $values -> containsKey ( $key )) {
$crit = $values -> getCriterion ( $key );
$params [] = array ( 'column' => $crit -> getColumn (), 'table' => $crit -> getTable (), 'value' => $crit -> getValue ());
}
}
return $params ;
}
/**
* Populates values in a prepared statement .
*
* @ param PreparedStatement $stmt
* @ param array $params array ( 'column' => ... , 'table' => ... , 'value' => ... )
* @ param DatabaseMap $dbMap
* @ return int The number of params replaced .
*/
private static function populateStmtValues ( $stmt , $params , DatabaseMap $dbMap )
{
$i = 1 ;
foreach ( $params as $param ) {
$tableName = $param [ 'table' ];
$columnName = $param [ 'column' ];
$value = $param [ 'value' ];
if ( $value === null ) {
$stmt -> setNull ( $i ++ );
} else {
$cMap = $dbMap -> getTable ( $tableName ) -> getColumn ( $columnName );
$setter = 'set' . CreoleTypes :: getAffix ( $cMap -> getCreoleType ());
$stmt -> $setter ( $i ++ , $value );
}
} // foreach
}
/**
* This function searches for the given validator $name under propel / validator / $name . php ,
* imports and caches it .
*
* @ param string $classname The dot - path name of class ( e . g . myapp . propel . MyValidator )
* @ return Validator object or null if not able to instantiate validator class ( and error will be logged in this case )
*/
public static function getValidator ( $classname )
{
try {
$v = isset ( self :: $validatorMap [ $classname ]) ? self :: $validatorMap [ $classname ] : null ;
if ( $v === null ) {
$cls = Propel :: import ( $classname );
$v = new $cls ();
self :: $validatorMap [ $classname ] = $v ;
}
return $v ;
} catch ( Exception $e ) {
Propel :: log ( " BasePeer::getValidator(): failed trying to instantiate " . $classname . " : " . $e -> getMessage (), Propel :: LOG_ERR );
}
}
/**
* This method returns the MapBuilder specified in the name
* parameter . You should pass in the full dot - path path to the class , ie :
* myapp . propel . MyMapMapBuilder . The MapBuilder instances are cached in
* this class for speed .
*
* @ param string $classname The dot - path name of class ( e . g . myapp . propel . MyMapBuilder )
* @ return MapBuilder or null ( and logs the error ) if the MapBuilder was not found .
* @ todo - cBasePeer Consider adding app - level caching support for map builders .
*/
public static function getMapBuilder ( $classname )
{
try {
$mb = isset ( self :: $mapBuilders [ $classname ]) ? self :: $mapBuilders [ $classname ] : null ;
if ( $mb === null ) {
$cls = Propel :: import ( $classname );
$mb = new $cls ();
self :: $mapBuilders [ $classname ] = $mb ;
}
if ( ! $mb -> isBuilt ()) {
$mb -> doBuild ();
}
return $mb ;
} catch ( Exception $e ) {
// Have to catch possible exceptions because method is
// used in initialization of Peers. Log the exception and
// return null.
Propel :: log ( " BasePeer::getMapBuilder() failed trying to instantiate " . $classname . " : " . $e -> getMessage (), Propel :: LOG_ERR );
}
}
}