diff options
49 files changed, 0 insertions, 11171 deletions
| diff --git a/.gitattributes b/.gitattributes index 6f464940..37006a6b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2356,11 +2356,6 @@ framework/3rdParty/WsdlGen/WsdlGenerator.php -text  framework/3rdParty/WsdlGen/WsdlMessage.php -text  framework/3rdParty/WsdlGen/WsdlOperation.php -text  framework/3rdParty/readme.html -text -framework/Base/TBehavior.php -text -framework/Base/TEvent.php -text -framework/Base/TModel.php -text -framework/Base/TModelBehavior.php -text -framework/Base/TModelEvent.php -text  framework/Caching/TAPCCache.php -text  framework/Caching/TCache.php -text  framework/Caching/TDbCache.php -text @@ -2798,43 +2793,6 @@ framework/TComponent.php -text  framework/TModule.php -text  framework/TService.php -text  framework/TShellApplication.php -text -framework/Testing/Data/ActiveRecord/Relations/DEPRECATED_COMPATIBILITY_REASONS_ONLY -text -framework/Testing/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php -text -framework/Testing/Data/ActiveRecord/TActiveFinder.php -text -framework/Testing/Data/ActiveRecord/TActiveRecord.php -text -framework/Testing/Data/ActiveRecord/TActiveRecordBehavior.php -text -framework/Testing/Data/ActiveRecord/TActiveRecordCriteria.php -text -framework/Testing/Data/Analysis/TDbStatementAnalysis.php eol=lf -framework/Testing/Data/Analysis/TSimpleDbStatementAnalysis.php eol=lf -framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDataSourceConfig.php eol=lf -framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbConnection.php eol=lf -framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbTransaction.php eol=lf -framework/Testing/Data/Distributed/TDistributedDataSourceConfig.php eol=lf -framework/Testing/Data/Distributed/TDistributedDbConnection.php eol=lf -framework/Testing/Data/Schema/TDbColumnSchema.php -text -framework/Testing/Data/Schema/TDbCommandBuilder.php -text -framework/Testing/Data/Schema/TDbCriteria.php -text -framework/Testing/Data/Schema/TDbExpression.php -text -framework/Testing/Data/Schema/TDbSchema.php -text -framework/Testing/Data/Schema/TDbTableSchema.php -text -framework/Testing/Data/Schema/mssql/TMssqlColumnSchema.php -text -framework/Testing/Data/Schema/mssql/TMssqlCommandBuilder.php -text -framework/Testing/Data/Schema/mssql/TMssqlPdoAdapter.php -text -framework/Testing/Data/Schema/mssql/TMssqlSchema.php -text -framework/Testing/Data/Schema/mssql/TMssqlTableSchema.php -text -framework/Testing/Data/Schema/mysql/TMysqlColumnSchema.php -text -framework/Testing/Data/Schema/mysql/TMysqlSchema.php -text -framework/Testing/Data/Schema/mysql/TMysqlTableSchema.php -text -framework/Testing/Data/Schema/oci/TOciColumnSchema.php -text -framework/Testing/Data/Schema/oci/TOciCommandBuilder.php -text -framework/Testing/Data/Schema/oci/TOciSchema.php -text -framework/Testing/Data/Schema/oci/TOciTableSchema.php -text -framework/Testing/Data/Schema/pgsql/TPgsqlColumnSchema.php -text -framework/Testing/Data/Schema/pgsql/TPgsqlSchema.php -text -framework/Testing/Data/Schema/pgsql/TPgsqlTableSchema.php -text -framework/Testing/Data/Schema/sqlite/TSqliteColumnSchema.php -text -framework/Testing/Data/Schema/sqlite/TSqliteCommandBuilder.php -text -framework/Testing/Data/Schema/sqlite/TSqliteSchema.php -text  framework/Util/TDataFieldAccessor.php -text  framework/Util/TDateTimeStamp.php -text  framework/Util/TLogRouter.php -text diff --git a/framework/Base/TBehavior.php b/framework/Base/TBehavior.php deleted file mode 100644 index 4e0b8454..00000000 --- a/framework/Base/TBehavior.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php -/** - * TBehavior class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -/** - * TBehavior is a convenient base class for behavior classes. - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CBehavior.php 564 2009-01-21 22:07:10Z qiang.xue $ - * @package system.base - * @since 1.0.2 - */ -class TBehavior extends TComponent implements IBehavior -{ -	private $_enabled; -	private $_owner; - -	/** -	 * Declares events and the corresponding event handler methods. -	 * The events are defined by the {@link owner} component, while the handler -	 * methods by the behavior class. The handlers will be attached to the corresponding -	 * events when the behavior is attached to the {@link owner} component; and they -	 * will be detached from the events when the behavior is detached from the component. -	 * @return array events (array keys) and the corresponding event handler methods (array values). -	 */ -	public function events() -	{ -		return array(); -	} - -	/** -	 * Attaches the behavior object to the component. -	 * The default implementation will set the {@link owner} property -	 * and attach event handlers as declared in {@link events}. -	 * Make sure you call the parent implementation if you override this method. -	 * @param TComponent the component that this behavior is to be attached to. -	 */ -	public function attach($owner) -	{ -		$this->_owner=$owner; -		foreach($this->events() as $event=>$handler) -			$owner->attachEventHandler($event,array($this,$handler)); -	} - -	/** -	 * Detaches the behavior object from the component. -	 * The default implementation will unset the {@link owner} property -	 * and detach event handlers declared in {@link events}. -	 * Make sure you call the parent implementation if you override this method. -	 * @param TComponent the component that this behavior is to be detached from. -	 */ -	public function detach($owner) -	{ -		foreach($this->events() as $event=>$handler) -			$owner->detachEventHandler($event,array($this,$handler)); -		$this->_owner=null; -	} - -	/** -	 * @return CComponent the owner component that this behavior is attached to. -	 */ -	public function getOwner() -	{ -		return $this->_owner; -	} - -	/** -	 * @return boolean whether this behavior is enabled -	 */ -	public function getEnabled() -	{ -		return $this->_enabled; -	} - -	/** -	 * @param boolean whether this behavior is enabled -	 */ -	public function setEnabled($value) -	{ -		$this->_enabled=$value; -	} -} - -/** - * IBehavior interfaces is implemented by all behavior classes. - * - * A behavior is a way to enhance a component with additional methods that - * are defined in the behavior class and not available in the component class. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: interfaces.php 956 2009-04-21 15:16:03Z qiang.xue@gmail.com $ - * @package system.base - * @since 1.0.2 - */ -interface IBehavior -{ -	/** -	 * Attaches the behavior object to the component. -	 * @param TComponent the component that this behavior is to be attached to. -	 */ -	public function attach($component); -	/** -	 * Detaches the behavior object from the component. -	 * @param TComponent the component that this behavior is to be detached from. -	 */ -	public function detach($component); -	/** -	 * @return boolean whether this behavior is enabled -	 */ -	public function getEnabled(); -	/** -	 * @param boolean whether this behavior is enabled -	 */ -	public function setEnabled($value); -}
\ No newline at end of file diff --git a/framework/Base/TEvent.php b/framework/Base/TEvent.php deleted file mode 100644 index c09816d1..00000000 --- a/framework/Base/TEvent.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * TEvent is the base class for all event classes. - * - * It encapsulates the parameters associated with an event. - * The {@link sender} property describes who raises the event. - * And the {@link handled} property indicates if the event is handled. - * If an event handler sets {@link handled} to true, those handlers - * that are not invoked yet will not be invoked anymore. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TEvent.php 978 2009-05-06 03:36:09Z qiang.xue $ - * @package system.base - * @since 1.0 - */ -class TEvent extends TComponent -{ -	/** -	 * @var object the sender of this event -	 */ -	public $sender; -	/** -	 * @var boolean whether the event is handled. Defaults to false. -	 * When a handler sets this true, the rest uninvoked handlers will not be invoked anymore. -	 */ -	public $handled=false; - -	/** -	 * Constructor. -	 * @param mixed sender of the event -	 */ -	public function __construct($sender=null) -	{ -		$this->sender=$sender; -	} -}
\ No newline at end of file diff --git a/framework/Base/TModel.php b/framework/Base/TModel.php deleted file mode 100644 index e05f26b6..00000000 --- a/framework/Base/TModel.php +++ /dev/null @@ -1,567 +0,0 @@ -<?php -/** - * CModel class file. - *  - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -Prado::using('System.Base.TModelEvent'); - -/** - * TModel is the base class providing the common features needed by data model objects. - * - * TModel defines the basic framework for data models that need to be validated. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TModel.php 1093 2009-06-05 13:09:17Z qiang.xue $ - * @package system.base - * @since 1.0 - */ -abstract class TModel extends TComponent implements IteratorAggregate, ArrayAccess -{ -	private $_errors=array();	// attribute name => array of errors -	private $_validators;  		// validators -	private $_scenario='';  	// scenario - - 	/** - 	 * THE FOLLOWING METHOD IS NEEDED BECAUSE OF COMPATIBILITY REASONS WITH PRADO - 	 * raiseEvent adapter method for TComponent - 	 * Was necessary because CActiveRecord doesnt use the third parameter - 	 * @param string EventName - 	 * @param TEvent Event - 	 */ - 	public function raiseEvent($name, $event, $param=null) - 	{ -		parent::raiseEvent($name, $event, new TEventParameter()); - 	} -	 -	/** -	 * Returns the list of attribute names of the model. -	 * @return array list of attribute names. -	 * @since 1.0.1 -	 */ -	abstract public function attributeNames(); - -	/** -	 * Returns the validation rules for attributes. -	 * -	 * This method should be overridden to declare validation rules. -	 * Each rule is an array with the following structure: -	 * <pre> -	 * array('attribute list', 'validator name', 'on'=>'scenario name', ...validation parameters...) -	 * </pre> -	 * where -	 * <ul> -	 * <li>attribute list: specifies the attributes (separated by commas) to be validated;</li> -	 * <li>validator name: specifies the validator to be used. It can be the name of a model class -	 *   method, the name of a built-in validator, or a validator class (or its path alias). -	 *   A validation method must have the following signature: -	 * <pre> -	 * // $params refers to validation parameters given in the rule -	 * function validatorName($attribute,$params) -	 * </pre> -	 *   A built-in validator refers to one of the validators declared in {@link CValidator::builtInValidators}. -	 *   And a validator class is a class extending {@link CValidator}.</li> -	 * <li>on: this specifies the scenarios when the validation rule should be performed. -	 *   Separate different scenarios with commas. If this option is not set, the rule -	 *   will be applied in any scenario. Please see {@link scenario} for more details about this option.</li> -	 * <li>additional parameters are used to initialize the corresponding validator properties. -	 *   Please refer to individal validator class API for possible properties.</li> -	 * </ul> -	 * -	 * The following are some examples: -	 * <pre> -	 * array( -	 *     array('username', 'required'), -	 *     array('username', 'length', 'min'=>3, 'max'=>12), -	 *     array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'), -	 *     array('password', 'authenticate', 'on'=>'login'), -	 * ); -	 * </pre> -	 * -	 * Note, in order to inherit rules defined in the parent class, a child class needs to -	 * merge the parent rules with child rules using functions like array_merge(). -	 * -	 * @return array validation rules to be applied when {@link validate()} is called. -	 * @see scenario -	 */ -	public function rules() -	{ -		return array(); -	} - -	/** -	 * Returns a list of behaviors that this model should behave as. -	 * The return value should be an array of behavior configurations indexed by -	 * behavior names. Each behavior configuration can be either a string specifying -	 * the behavior class or an array of the following structure: -	 * <pre> -	 * 'behaviorName'=>array( -	 *     'class'=>'path.to.BehaviorClass', -	 *     'property1'=>'value1', -	 *     'property2'=>'value2', -	 * ) -	 * </pre> -	 * -	 * Note, the behavior classes must implement {@link IBehavior} or extend from -	 * {@link CBehavior}. Behaviors declared in this method will be attached -	 * to the model when it is instantiated. -	 * -	 * For more details about behaviors, see {@link CComponent}. -	 * @return array the behavior configurations (behavior name=>behavior configuration) -	 * @since 1.0.2 -	 */ -	public function behaviors() -	{ -		return array(); -	} - -	/** -	 * Returns the attribute labels. -	 * Attribute labels are mainly used in error messages of validation. -	 * By default an attribute label is generated using {@link generateAttributeLabel}. -	 * This method allows you to explicitly specify attribute labels. -	 * -	 * Note, in order to inherit labels defined in the parent class, a child class needs to -	 * merge the parent labels with child labels using functions like array_merge(). -	 * -	 * @return array attribute labels (name=>label) -	 * @see generateAttributeLabel -	 */ -	public function attributeLabels() -	{ -		return array(); -	} - -	/** -	 * Performs the validation. -	 * -	 * This method executes the validation rules as declared in {@link rules}. -	 * Only the rules applicable to the current {@link scenario} will be executed. -	 * A rule is considered applicable to a scenario if its 'on' option is not set -	 * or contains the scenario. -	 * -	 * Errors found during the validation can be retrieved via {@link getErrors}. -	 * -	 * @param array list of attributes that should be validated. Defaults to null, -	 * meaning any attribute listed in the applicable validation rules should be -	 * validated. If this parameter is given as a list of attributes, only -	 * the listed attributes will be validated. -	 * @return boolean whether the validation is successful without any error. -	 * @see beforeValidate -	 * @see afterValidate -	 */ -	public function validate($attributes=null) -	{ -		$this->clearErrors(); -		if($this->beforeValidate()) -		{ -			foreach($this->getValidators() as $validator) -				$validator->validate($this,$attributes); -			$this->afterValidate(); -			return !$this->hasErrors(); -		} -		else -			return false; -	} - -	/** -	 * This method is invoked before validation starts. -	 * The default implementation calls {@link onBeforeValidate} to raise an event. -	 * You may override this method to do preliminary checks before validation. -	 * Make sure the parent implementation is invoked so that the event can be raised. -	 * @return boolean whether validation should be executed. Defaults to true. -	 */ -	protected function beforeValidate() -	{ -		$event=new TModelEvent($this); -		$this->onBeforeValidate($event); -		return $event->isValid; -	} - -	/** -	 * This method is invoked after validation ends. -	 * The default implementation calls {@link onAfterValidate} to raise an event. -	 * You may override this method to do postprocessing after validation. -	 * Make sure the parent implementation is invoked so that the event can be raised. -	 */ -	protected function afterValidate() -	{ -		$this->onAfterValidate(new TEvent($this)); -	} - -	/** -	 * This event is raised before the validation is performed. -	 * @param CModelEvent the event parameter -	 * @since 1.0.2 -	 */ -	public function onBeforeValidate($event) -	{ -		$this->raiseEvent('onBeforeValidate',$event); -	} - -	/** -	 * This event is raised after the validation is performed. -	 * @param CEvent the event parameter -	 * @since 1.0.2 -	 */ -	public function onAfterValidate($event) -	{ -		$this->raiseEvent('onAfterValidate',$event); -	} - -	/** -	 * Returns the validators applicable to the current {@link scenario}. -	 * @param string the name of the attribute whose validators should be returned. -	 * If this is null, the validators for ALL attributes in the model will be returned. -	 * @return array the validators applicable to the current {@link scenario}. -	 * @since 1.0.1 -	 *  -	 * @TODO Port validators from Yii to Prado? Not used in ActiveRecords -> ignoring this for now... -	 *  -	 */ -	public function getValidators($attribute=null) -	{ -		/*if($this->_validators===null) -			$this->_validators=$this->createValidators(); - -		$validators=array(); -		$scenario=$this->getScenario(); -		foreach($this->_validators as $validator) -		{ -			if($validator->applyTo($scenario)) -			{ -				if($attribute===null || in_array($attribute,$validator->attributes,true)) -					$validators[]=$validator; -			} -		} -		return $validators;*/ -		return array(); -	} - -	/** -	 * Creates validator objects based on the specification in {@link rules}. -	 * This method is mainly used internally. -	 * @return array validators built based on {@link rules()}. -	 * -	 * @TODO Port validators from Yii to Prado? Not used in ActiveRecords -> ignoring this for now... -	 *  -	 */ -	public function createValidators() -	{ -		/*$validators=array(); -		foreach($this->rules() as $rule) -		{ -			if(isset($rule[0],$rule[1]))  // attributes, validator name -				$validators[]=CValidator::createValidator($rule[1],$this,$rule[0],array_slice($rule,2)); -			else -				throw new CException(Yii::t('yii','{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.', -					array('{class}'=>get_class($this)))); -		} -		return $validators;*/ -		return array(); -	} - -	/** -	 * Returns a value indicating whether the attribute is required. -	 * This is determined by checking if the attribute is associated with a -	 * {@link CRequiredValidator} validation rule in the current {@link scenario}. -	 * @param string attribute name -	 * @return boolean whether the attribute is required -	 * @since 1.0.2 -	 * -	 * @TODO Port validators from Yii to Prado? Not used in ActiveRecords -> ignoring this for now... -	 *  -	 */ -	public function isAttributeRequired($attribute) -	{ -		/* -		foreach($this->getValidators($attribute) as $validator) -		{ -			if($validator instanceof CRequiredValidator) -				return true; -		} -		return false; -		*/ -		return true; -	} - -	/** -	 * Returns the text label for the specified attribute. -	 * @param string the attribute name -	 * @return string the attribute label -	 * @see generateAttributeLabel -	 * @see attributeLabels -	 */ -	public function getAttributeLabel($attribute) -	{ -		$labels=$this->attributeLabels(); -		if(isset($labels[$attribute])) -			return $labels[$attribute]; -		else -			return $this->generateAttributeLabel($attribute); -	} - -	/** -	 * Returns a value indicating whether there is any validation error. -	 * @param string attribute name. Use null to check all attributes. -	 * @return boolean whether there is any error. -	 */ -	public function hasErrors($attribute=null) -	{ -		if($attribute===null) -			return $this->_errors!==array(); -		else -			return isset($this->_errors[$attribute]); -	} - -	/** -	 * Returns the errors for all attribute or a single attribute. -	 * @param string attribute name. Use null to retrieve errors for all attributes. -	 * @return array errors for all attributes or the specified attribute. Empty array is returned if no error. -	 */ -	public function getErrors($attribute=null) -	{ -		if($attribute===null) -			return $this->_errors; -		else -			return isset($this->_errors[$attribute]) ? $this->_errors[$attribute] : array(); -	} - -	/** -	 * Returns the first error of the specified attribute. -	 * @param string attribute name. -	 * @return string the error message. Null is returned if no error. -	 * @since 1.0.2 -	 */ -	public function getError($attribute) -	{ -		return isset($this->_errors[$attribute]) ? reset($this->_errors[$attribute]) : null; -	} - -	/** -	 * Adds a new error to the specified attribute. -	 * @param string attribute name -	 * @param string new error message -	 */ -	public function addError($attribute,$error) -	{ -		$this->_errors[$attribute][]=$error; -	} - -	/** -	 * Adds a list of errors. -	 * @param array a list of errors. The array keys must be attribute names. -	 * The array values should be error messages. If an attribute has multiple errors, -	 * these errors must be given in terms of an array. -	 * You may use the result of {@link getErrors} as the value for this parameter. -	 * @since 1.0.5 -	 */ -	public function addErrors($errors) -	{ -		foreach($errors as $attribute=>$error) -		{ -			if(is_array($error)) -			{ -				foreach($error as $e) -					$this->_errors[$attribute][]=$e; -			} -			else -				$this->_errors[$attribute][]=$error; -		} -	} - -	/** -	 * Removes errors for all attributes or a single attribute. -	 * @param string attribute name. Use null to remove errors for all attribute. -	 */ -	public function clearErrors($attribute=null) -	{ -		if($attribute===null) -			$this->_errors=array(); -		else -			unset($this->_errors[$attribute]); -	} - -	/** -	 * Generates a user friendly attribute label. -	 * This is done by replacing underscores or dashes with blanks and -	 * changing the first letter of each word to upper case. -	 * For example, 'department_name' or 'DepartmentName' becomes 'Department Name'. -	 * @param string the column name -	 * @return string the attribute label -	 */ -	public function generateAttributeLabel($name) -	{ -		return ucwords(trim(strtolower(str_replace(array('-','_'),' ',preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $name))))); -	} - -	/** -	 * Returns all attribute values. -	 * @param array list of attributes whose value needs to be returned. -	 * Defaults to null, meaning all attributes as listed in {@link attributeNames} will be returned. -	 * If it is an array, only the attributes in the array will be returned. -	 * @return array attribute values (name=>value). -	 */ -	public function getAttributes($names=null) -	{ -		$values=array(); -		foreach($this->attributeNames() as $name) -			$values[$name]=$this->$name; - -		if(is_array($names)) -		{ -			$values2=array(); -			foreach($names as $name) -				$values2[$name]=isset($values[$name]) ? $values[$name] : null; -			return $values2; -		} -		else -			return $values; -	} - -	/** -	 * Sets the attribute values in a massive way. -	 * @param array attribute values (name=>value) to be set. -	 * @param boolean whether the assignments should only be done to the safe attributes. -	 * A safe attribute is one that is associated with a validation rule in the current {@link scenario}. -	 * @see getSafeAttributeNames -	 * @see attributeNames -	 */ -	public function setAttributes($values,$safeOnly=true) -	{ -		if(!is_array($values)) -			return; -		$attributes=array_flip($safeOnly ? $this->getSafeAttributeNames() : $this->attributeNames()); -		foreach($values as $name=>$value) -		{ -			if(isset($attributes[$name])) -				$this->$name=$value; -		} -	} - -	/** -	 * Returns the scenario that this model is used in. -	 * -	 * Scenario affects how validation is performed and which attributes can -	 * be massively assigned. -	 * -	 * A validation rule will be performed when calling {@link validate()} -	 * if its 'on' option is not set or contains the current scenario value. -	 * -	 * And an attribute can be massively assigned if it is associated with -	 * a validation rule for the current scenario. Note that an exception is -	 * the {@link CUnsafeValidator unsafe} validator which marks the associated -	 * attributes as unsafe and not allowed to be massively assigned. -	 * -	 * @return string the scenario that this model is in. -	 * @since 1.0.4 -	 */ -	public function getScenario() -	{ -		return $this->_scenario; -	} - -	/** -	 * @param string the scenario that this model is in. -	 * @see getScenario -	 * @since 1.0.4 -	 */ -	public function setScenario($value) -	{ -		$this->_scenario=$value; -	} - -	/** -	 * Returns the attribute names that are safe to be massively assigned. -	 * A safe attribute is one that is associated with a validation rule in the current {@link scenario}. -	 * @return array safe attribute names -	 * @since 1.0.2 -	 *  -	 * @TODO Port validators from Yii to Prado? Not used in ActiveRecords -> ignoring this for now... -	 *  -	 */ -	public function getSafeAttributeNames() -	{ -		$attributes=array(); -		$unsafe=array(); -		foreach($this->getValidators() as $validator) -		{ -#			if($validator instanceof CUnsafeValidator) -#			{ -#				foreach($validator->attributes as $name) -#					$unsafe[]=$name; -#			} -#			else -#			{ -				foreach($validator->attributes as $name) -					$attributes[$name]=true; -#			} -		} - -#		foreach($unsafe as $name) -#			unset($attributes[$name]); -		return array_keys($attributes); -	} - -	/** -	 * Returns an iterator for traversing the attributes in the model. -	 * This method is required by the interface IteratorAggregate. -	 * @return CMapIterator an iterator for traversing the items in the list. -	 */ -	public function getIterator() -	{ -		$attributes=$this->getAttributes(); -		return new TMapIterator($attributes); -	} - -	/** -	 * Returns whether there is an element at the specified offset. -	 * This method is required by the interface ArrayAccess. -	 * @param mixed the offset to check on -	 * @return boolean -	 * @since 1.0.2 -	 */ -	public function offsetExists($offset) -	{ -		return property_exists($this,$offset); -	} - -	/** -	 * Returns the element at the specified offset. -	 * This method is required by the interface ArrayAccess. -	 * @param integer the offset to retrieve element. -	 * @return mixed the element at the offset, null if no element is found at the offset -	 * @since 1.0.2 -	 */ -	public function offsetGet($offset) -	{ -		return $this->$offset; -	} - -	/** -	 * Sets the element at the specified offset. -	 * This method is required by the interface ArrayAccess. -	 * @param integer the offset to set element -	 * @param mixed the element value -	 * @since 1.0.2 -	 */ -	public function offsetSet($offset,$item) -	{ -		$this->$offset=$item; -	} - -	/** -	 * Unsets the element at the specified offset. -	 * This method is required by the interface ArrayAccess. -	 * @param mixed the offset to unset element -	 * @since 1.0.2 -	 */ -	public function offsetUnset($offset) -	{ -		unset($this->$offset); -	} -} diff --git a/framework/Base/TModelBehavior.php b/framework/Base/TModelBehavior.php deleted file mode 100644 index 901c9948..00000000 --- a/framework/Base/TModelBehavior.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -/** - * TModelBehavior class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -/** - * TModelBehavior is a base class for behaviors that are attached to a model component. - * The model should extend from {@link CModel} or its child classes. - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TModelBehavior.php 1082 2009-06-01 12:03:00Z qiang.xue $ - * @package system.base - * @since 1.0.2 - */ -  -Prado::using('System.Base.TBehavior'); -  -class TModelBehavior extends TBehavior -{ -	/** -	 * Declares events and the corresponding event handler methods. -	 * The default implementation returns 'onBeforeValidate' and 'onAfterValidate' events and handlers. -	 * If you override this method, make sure you merge the parent result to the return value. -	 * @return array events (array keys) and the corresponding event handler methods (array values). -	 * @see TBehavior::events -	 */ -	public function events() -	{ -		return array( -			'onBeforeValidate'=>'beforeValidate', -			'onAfterValidate'=>'afterValidate', -		); -	} - -	/** -	 * Responds to {@link TModel::onBeforeValidate} event. -	 * Overrides this method if you want to handle the corresponding event of the {@link owner}. -	 * You may set {@link TModelEvent::isValid} to be false if you want to stop the current validation process. -	 * @param TModelEvent event parameter -	 */ -	public function beforeValidate($event) -	{ -	} - -	/** -	 * Responds to {@link TModel::onAfterValidate} event. -	 * Overrides this method if you want to handle the corresponding event of the {@link owner}. -	 * @param TEvent event parameter -	 */ -	public function afterValidate($event) -	{ -	} -} diff --git a/framework/Base/TModelEvent.php b/framework/Base/TModelEvent.php deleted file mode 100644 index c785b997..00000000 --- a/framework/Base/TModelEvent.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** - * TModelEvent class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -Prado::using('System.Base.TEvent'); - -/** - * TModelEvent class. - * - * TModelEvent represents the event parameters needed by events raised by a model. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TModelEvent.php 1093 2009-06-05 13:09:17Z qiang.xue $ - * @package system.base - * @since 1.0 - */ -class TModelEvent extends TEvent -{ -	/** -	 * @var boolean whether the model is valid. Defaults to true. -	 * If this is set false, {@link TModel::validate()} will return false and quit the current validation process. -	 */ -	public $isValid=true; -} diff --git a/framework/TComponent.php b/framework/TComponent.php index ece83636..b29302ec 100644 --- a/framework/TComponent.php +++ b/framework/TComponent.php @@ -79,11 +79,6 @@ class TComponent  	private $_e=array();  	/** -	 * @var array models (ported from Yii) -	 */ -	private $_m=array(); - -	/**  	 * Returns a property value or an event handler list by property or event name.  	 * Do not call this method. This is a PHP magic method that we override  	 * to allow using the following syntax to read a property: @@ -356,7 +351,6 @@ class TComponent  						$method=substr($handler,$pos+1);  						if(method_exists($object,$method))  							$object->$method($sender,$param); -  						else  							throw new TInvalidDataValueException('component_eventhandler_invalid',get_class($this),$name,$handler);  					} @@ -457,133 +451,6 @@ class TComponent  	public function addParsedObject($object)  	{  	} - -	/** -	 * Returns the named behavior object. -	 * The name 'asa' stands for 'as a'. -	 * @param string the behavior name -	 * @return IBehavior the behavior object, or null if the behavior does not exist -	 */ -	public function asa($behavior) -	{ -		return isset($this->_m[$behavior]) ? $this->_m[$behavior] : null; -	} - -	/** -	 * Attaches a list of behaviors to the component. -	 * Each behavior is indexed by its name and should be an instance of -	 * {@link IBehavior}, a string specifying the behavior class, or an -	 * array of the following structure: -	 * <pre> -	 * array( -	 *     'class'=>'path.to.BehaviorClass', -	 *     'property1'=>'value1', -	 *     'property2'=>'value2', -	 * ) -	 * </pre> -	 * @param array list of behaviors to be attached to the component -	 */ -	public function attachBehaviors($behaviors) -	{ -		foreach($behaviors as $name=>$behavior) -			$this->attachBehavior($name,$behavior); -	} - -	/** -	 * Detaches all behaviors from the component. -	 */ -	public function detachBehaviors() -	{ -		if($this->_m!==null) -		{ -			foreach($this->_m as $name=>$behavior) -				$this->detachBehavior($name); -			$this->_m=null; -		} -	} - -	/** -	 * Attaches a behavior to this component. -	 * This method will create the behavior object based on the given -	 * configuration. After that, the behavior object will be initialized -	 * by calling its {@link IBehavior::attach} method. -	 * @param string the behavior's name. It should uniquely identify this behavior. -	 * @param mixed the behavior configuration. This is passed as the first -	 * parameter to {@link PradoBase::createComponent} to create the behavior object. -	 * @return IBehavior the behavior object -	 */ -	public function attachBehavior($name,$behavior) -	{ -		if(!($behavior instanceof IBehavior)) -			$behavior=Prado::createComponent($behavior); -		$behavior->setEnabled(true); -		$behavior->attach($this); -		return $this->_m[$name]=$behavior; -	} - -	/** -	 * Detaches a behavior from the component. -	 * The behavior's {@link IBehavior::detach} method will be invoked. -	 * @param string the behavior's name. It uniquely identifies the behavior. -	 * @return IBehavior the detached behavior. Null if the behavior does not exist. -	 */ -	public function detachBehavior($name) -	{ -		if(isset($this->_m[$name])) -		{ -			$this->_m[$name]->detach($this); -			$behavior=$this->_m[$name]; -			unset($this->_m[$name]); -			return $behavior; -		} -	} - -	/** -	 * Enables all behaviors attached to this component. -	 */ -	public function enableBehaviors() -	{ -		if($this->_m!==null) -		{ -			foreach($this->_m as $behavior) -				$behavior->setEnabled(true); -		} -	} - -	/** -	 * Disables all behaviors attached to this component. -	 */ -	public function disableBehaviors() -	{ -		if($this->_m!==null) -		{ -			foreach($this->_m as $behavior) -				$behavior->setEnabled(false); -		} -	} - -	/** -	 * Enables an attached behavior. -	 * A behavior is only effective when it is enabled. -	 * A behavior is enabled when first attached. -	 * @param string the behavior's name. It uniquely identifies the behavior. -	 */ -	public function enableBehavior($name) -	{ -		if(isset($this->_m[$name])) -			$this->_m[$name]->setEnabled(true); -	} - -	/** -	 * Disables an attached behavior. -	 * A behavior is only effective when it is enabled. -	 * @param string the behavior's name. It uniquely identifies the behavior. -	 */ -	public function disableBehavior($name) -	{ -		if(isset($this->_m[$name])) -			$this->_m[$name]->setEnabled(false); -	}  }  /** diff --git a/framework/Testing/Data/ActiveRecord/Relations/DEPRECATED_COMPATIBILITY_REASONS_ONLY b/framework/Testing/Data/ActiveRecord/Relations/DEPRECATED_COMPATIBILITY_REASONS_ONLY deleted file mode 100644 index 8c7a4073..00000000 --- a/framework/Testing/Data/ActiveRecord/Relations/DEPRECATED_COMPATIBILITY_REASONS_ONLY +++ /dev/null @@ -1,3 +0,0 @@ -Please note that this file is used for old Prado ActiveRecord applications which use $record->withAnotherRecord - syntax. - -You shouln't use that syntax anymore as it's deprecated in this portation of Yii ActiveRecords. diff --git a/framework/Testing/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php b/framework/Testing/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php deleted file mode 100644 index f13043df..00000000 --- a/framework/Testing/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php +++ /dev/null @@ -1,230 +0,0 @@ -<?php
 -/**
 - * TActiveRecordRelationContext class.
 - *
 - * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 - * @link http://www.pradosoft.com/
 - * @copyright Copyright © 2005-2008 PradoSoft - * @license http://www.pradosoft.com/license/
 - * @version $Id$
 - * @package System.Testing.Data.ActiveRecord.Relations
 - */
 -
 -/**
 - * TActiveRecordRelationContext holds information regarding record relationships
 - * such as record relation property name, query criteria and foreign object record
 - * class names.
 - *
 - * This class is use internally by passing a context to the TActiveRecordRelation
 - * constructor.
 - *
 - * @author Wei Zhuo <weizho[at]gmail[dot]com>
 - * @version $Id$
 - * @package System.Testing.Data.ActiveRecord.Relations
 - * @since 3.1
 - */
 -class TActiveRecordRelationContext
 -{
 -	private $_property;
 -	private $_record;
 -	private $_relation; //data from an entry of TActiveRecord::$RELATION
 -	private $_fkeys;
 -
 -	public function __construct($record, $property=null, $relation=null)
 -	{
 -		$this->_record=$record;
 -		$this->_property=$property;
 -		$this->_relation=$relation;
 -	}
 -
 -	/**
 -	 * @return boolean true if the relation is defined in TActiveRecord::$RELATIONS
 -	 * @since 3.1.2
 -	 */
 -	public function hasRecordRelation()
 -	{
 -		return $this->_relation!==null;
 -	}
 -
 -	public function getPropertyValue()
 -	{
 -		$obj = $this->getSourceRecord();
 -		return $obj->getColumnValue($this->getProperty());
 -	}
 -
 -	/**
 -	 * @return string name of the record property that the relationship results will be assigned to.
 -	 */
 -	public function getProperty()
 -	{
 -		return $this->_property;
 -	}
 -
 -	/**
 -	 * @return TActiveRecord the active record instance that queried for its related records.
 -	 */
 -	public function getSourceRecord()
 -	{
 -		return $this->_record;
 -	}
 -
 -	/**
 -	 * @return array foreign key of this relations, the keys is dependent on the
 -	 * relationship type.
 -	 * @since 3.1.2
 -	 */
 -	public function getRelationForeignKeys()
 -	{
 -		if($this->_fkeys===null)
 -			$this->_fkeys=$this->getRelationHandler()->getRelationForeignKeys();
 -		return $this->_fkeys;
 -	}
 -
 -	/**
 -	 * @return string HAS_MANY, HAS_ONE, or BELONGS_TO
 -	 */
 -	public function getRelationType()
 -	{
 -		return $this->_relation[0];
 -	}
 -
 -	/**
 -	 * @return string foreign record class name.
 -	 */
 -	public function getForeignRecordClass()
 -	{
 -		return $this->_relation[1];
 -	}
 -
 -	/**
 -	 * @return string foreign key field names, comma delimited.
 -	 * @since 3.1.2
 -	 */
 -	public function getFkField()
 -	{
 -		return $this->_relation[2];
 -	}
 -
 -	/**
 -	 * @return string the query condition for the relation as specified in RELATIONS
 -	 * @since 3.1.2
 -	 */
 -	public function getCondition()
 -	{
 -		return isset($this->_relation[3])?$this->_relation[3]:null;
 -	}
 -
 -	/**
 -	 * @return array the query parameters for the relation as specified in RELATIONS
 -	 * @since 3.1.2
 -	 */
 -	public function getParameters()
 -	{
 -		return isset($this->_relation[4])?$this->_relation[4]:array();
 -	}
 -
 -	/**
 -	 * @return boolean true if the 3rd element of an TActiveRecord::$RELATION entry is set.
 -	 * @since 3.1.2
 -	 */
 -	public function hasFkField()
 -	{
 -		$notManyToMany = $this->getRelationType() !== TActiveRecord::MANY_TO_MANY;
 -		return $notManyToMany && isset($this->_relation[2]) && !empty($this->_relation[2]);
 -	}
 -
 -	/**
 -	 * @return string the M-N relationship association table name.
 -	 */
 -	public function getAssociationTable()
 -	{
 -		return $this->_relation[2];
 -	}
 -
 -	/**
 -	 * @return boolean true if the relationship is HAS_MANY and requires an association table.
 -	 */
 -	public function hasAssociationTable()
 -	{
 -		$isManyToMany = $this->getRelationType() === TActiveRecord::MANY_TO_MANY;
 -		return $isManyToMany && isset($this->_relation[2]) && !empty($this->_relation[2]);
 -	}
 -
 -	/**
 -	 * @return TActiveRecord corresponding relationship foreign object finder instance.
 -	 */
 -	public function getForeignRecordFinder()
 -	{
 -		return TActiveRecord::finder($this->getForeignRecordClass());
 -	}
 -
 -	/**
 -	 * Creates and return the TActiveRecordRelation handler for specific relationships.
 -	 * An instance of TActiveRecordHasOne, TActiveRecordBelongsTo, TActiveRecordHasMany,
 -	 * or TActiveRecordHasManyAssocation will be returned.
 -	 * @param TActiveRecordCriteria search criteria
 -	 * @return TActiveRecordRelation record relationship handler instnace.
 -	 * @throws TActiveRecordException if property is not defined or missing.
 -	 */
 -	public function getRelationHandler($criteria=null)
 -	{
 -		if(!$this->hasRecordRelation())
 -		{
 -			throw new TActiveRecordException('ar_undefined_relation_prop',
 -				$this->_property, get_class($this->_record), 'RELATIONS');
 -		}
 -		if($criteria===null)
 -			$criteria = new TActiveRecordCriteria($this->getCondition(), $this->getParameters());
 -		switch($this->getRelationType())
 -		{
 -			case TActiveRecord::HAS_MANY:
 -				Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordHasMany');
 -				return new TActiveRecordHasMany($this, $criteria);
 -			case TActiveRecord::MANY_TO_MANY:
 -				Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordHasManyAssociation');
 -				return new TActiveRecordHasManyAssociation($this, $criteria);
 -			case TActiveRecord::HAS_ONE:
 -				Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordHasOne');
 -				return new TActiveRecordHasOne($this, $criteria);
 -			case TActiveRecord::BELONGS_TO:
 -				Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordBelongsTo');
 -				return new TActiveRecordBelongsTo($this, $criteria);
 -			default:
 -				throw new TActiveRecordException('ar_invalid_relationship');
 -		}
 -	}
 -
 -	/**
 -	 * @return TActiveRecordRelationCommand
 -	 */
 -	public function updateAssociatedRecords($updateBelongsTo=false)
 -	{
 -		$success=true;
 -		foreach($this->_record->getRecordRelations() as $data)
 -		{
 -			list($property, $relation) = $data;
 -			$belongsTo = $relation[0]==TActiveRecord::BELONGS_TO;
 -			if(($updateBelongsTo && $belongsTo) || (!$updateBelongsTo && !$belongsTo))
 -			{
 -				$obj = $this->getSourceRecord();
 -				if(!$this->isEmptyFkObject($obj->getColumnValue($property)))
 -				{
 -					$context = new TActiveRecordRelationContext($this->getSourceRecord(),$property,$relation);
 -					$success = $context->getRelationHandler()->updateAssociatedRecords() && $success;
 -				}
 -			}
 -		}
 -		return $success;
 -	}
 -
 -	protected function isEmptyFkObject($obj)
 -	{
 -		if(is_object($obj))
 -			return $obj instanceof TList ? $obj->count() === 0 : false;
 -		else if(is_array($obj))
 -			return count($obj)===0;
 -		else
 -			return empty($obj);
 -	}
 -}
 -
 diff --git a/framework/Testing/Data/ActiveRecord/TActiveFinder.php b/framework/Testing/Data/ActiveRecord/TActiveFinder.php deleted file mode 100644 index d1c35bdf..00000000 --- a/framework/Testing/Data/ActiveRecord/TActiveFinder.php +++ /dev/null @@ -1,1279 +0,0 @@ -<?php -/** - * CActiveRecord class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/CBaseActiveRelation*/ - -/** - * CActiveFinder implements eager loading and lazy loading of related active records. - * - * When used in eager loading, this class provides the same set of find methods as - * {@link CActiveRecord}. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveFinder.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0 - */ -class TActiveFinder extends TComponent -{ -	/** -	 * @var boolean join all tables all at once. Defaults to false. -	 * This property is internally used. -	 * @since 1.0.2 -	 */ -	public $joinAll=false; -	/** -	 * @var boolean whether the base model has limit or offset. -	 * This property is internally used. -	 * @since 1.0.2 -	 */ -	public $baseLimited=false; - -	private $_joinCount=0; -	private $_joinTree; -	private $_builder; -	private $_criteria;  // the criteria generated via named scope - -	/** -	 * Constructor. -	 * A join tree is built up based on the declared relationships between active record classes. -	 * @param CActiveRecord the model that initiates the active finding process -	 * @param mixed the relation names to be actively looked for -	 * @param CDbCriteria the criteria associated with the named scopes (since version 1.0.5) -	 */ -	public function __construct($model,$with,$criteria=null) -	{ -		$this->_criteria=$criteria; -		$this->_builder=$model->getCommandBuilder(); -		$this->_joinTree=new TJoinElement($this,$model); -		$this->buildJoinTree($this->_joinTree,$with); -	} - -	/** -	 * Uses the most aggressive join approach. -	 * By calling this method, even if there is LIMIT/OFFSET option set for -	 * the primary table query, we will still use a single SQL statement. -	 * By default (without calling this method), the primary table will be queried -	 * by itself so that LIMIT/OFFSET can be correctly applied. -	 * @return CActiveFinder the finder object -	 * @since 1.0.2 -	 */ -	public function together() -	{ -		$this->joinAll=true; -		return $this; -	} - -	private function query($criteria,$all=false) -	{ -		if($this->_criteria!==null) -		{ -			$this->_criteria->mergeWith($criteria); -			$criteria=$this->_criteria; -		} - -		$this->_joinTree->find($criteria); -		$this->_joinTree->afterFind(); - -		if($all) -			return array_values($this->_joinTree->records); -		else if(count($this->_joinTree->records)) -			return reset($this->_joinTree->records); -		else -			return null; -	} - -	/** -	 * This is the relational version of {@link CActiveRecord::find()}. -	 */ -	public function find($condition='',$params=array()) -	{ -		Prado::trace(get_class($this->_joinTree->model).'.find() eagerly','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->_builder->createCriteria($condition,$params); -		return $this->query($criteria); -	} - -	/** -	 * This is the relational version of {@link CActiveRecord::findAll()}. -	 */ -	public function findAll($condition='',$params=array()) -	{ -		Prado::trace(get_class($this->_joinTree->model).'.findAll() eagerly','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->_builder->createCriteria($condition,$params); -		return $this->query($criteria,true); -	} - -	/** -	 * This is the relational version of {@link CActiveRecord::findByPk()}. -	 */ -	public function findByPk($pk,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this->_joinTree->model).'.findByPk() eagerly','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->_builder->createPkCriteria($this->_joinTree->model->getTableSchema(),$pk,$condition,$params); -		return $this->query($criteria); -	} - -	/** -	 * This is the relational version of {@link CActiveRecord::findAllByPk()}. -	 */ -	public function findAllByPk($pk,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this->_joinTree->model).'.findAllByPk() eagerly','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->_builder->createPkCriteria($this->_joinTree->model->getTableSchema(),$pk,$condition,$params); -		return $this->query($criteria,true); -	} - -	/** -	 * This is  the relational version of {@link CActiveRecord::findByAttributes()}. -	 */ -	public function findByAttributes($attributes,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this->_joinTree->model).'.findByAttributes() eagerly','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->_builder->createColumnCriteria($this->_joinTree->model->getTableSchema(),$attributes,$condition,$params); -		return $this->query($criteria); -	} - -	/** -	 * This is the relational version of {@link CActiveRecord::findAllByAttributes()}. -	 */ -	public function findAllByAttributes($attributes,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this->_joinTree->model).'.findAllByAttributes() eagerly','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->_builder->createColumnCriteria($this->_joinTree->model->getTableSchema(),$attributes,$condition,$params); -		return $this->query($criteria,true); -	} - -	/** -	 * This is the relational version of {@link CActiveRecord::findBySql()}. -	 */ -	public function findBySql($sql,$params=array()) -	{ -		Prado::trace(get_class($this->_joinTree->model).'.findBySql() eagerly','System.Testing.Data.ActiveRecord.TActiveRecord'); -		if(($row=$this->_builder->createSqlCommand($sql,$params)->queryRow())!==false) -		{ -			$baseRecord=$this->_joinTree->model->populateRecord($row,false); -			$this->_joinTree->findWithBase($baseRecord); -			$this->_joinTree->afterFind(); -			return $baseRecord; -		} -	} - -	/** -	 * This is the relational version of {@link CActiveRecord::findAllBySql()}. -	 */ -	public function findAllBySql($sql,$params=array()) -	{ -		Prado::trace(get_class($this->_joinTree->model).'.findAllBySql() eagerly','System.Testing.Data.ActiveRecord.TActiveRecord'); -		if(($rows=$this->_builder->createSqlCommand($sql,$params)->queryAll())!==array()) -		{ -			$baseRecords=$this->_joinTree->model->populateRecords($rows,false); -			$this->_joinTree->findWithBase($baseRecords); -			$this->_joinTree->afterFind(); -			return $baseRecords; -		} -		else -			return array(); -	} - -	/** -	 * This is the relational version of {@link CActiveRecord::count()}. -	 * @since 1.0.3 -	 */ -	public function count($condition='',$params=array()) -	{ -		Prado::trace(get_class($this->_joinTree->model).'.count() eagerly','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->_builder->createCriteria($condition,$params); -		if($this->_criteria!==null) -		{ -			$this->_criteria->mergeWith($criteria); -			$criteria=$this->_criteria; -		} -		return $this->_joinTree->count($criteria); -	} - -	/** -	 * Finds the related objects for the specified active record. -	 * This method is internally invoked by {@link CActiveRecord} to support lazy loading. -	 * @param CActiveRecord the base record whose related objects are to be loaded -	 */ -	public function lazyFind($baseRecord) -	{ -		$this->_joinTree->lazyFind($baseRecord); -		if(!empty($this->_joinTree->children)) -		{ -			$child=reset($this->_joinTree->children); -			$child->afterFind(); -		} -	} - -	/** -	 * Builds up the join tree representing the relationships involved in this query. -	 * @param CJoinElement the parent tree node -	 * @param mixed the names of the related objects relative to the parent tree node -	 * @param array additional query options to be merged with the relation -	 */ -	private function buildJoinTree($parent,$with,$options=null) -	{ -		if($parent instanceof CStatElement) -			throw new TDbException('The STAT relation "'.($parent->relation->name).'" cannot have child relations.'); - -		if(is_string($with)) -		{ -			if(($pos=strrpos($with,'.'))!==false) -			{ -				$parent=$this->buildJoinTree($parent,substr($with,0,$pos)); -				$with=substr($with,$pos+1); -			} - -			// named scope -			if(($pos=strpos($with,':'))!==false) -			{ -				$scopes=explode(':',substr($with,$pos+1)); -				$with=substr($with,0,$pos); -			} - -			if(isset($parent->children[$with])) -				return $parent->children[$with]; - -			if(($relation=$parent->model->getActiveRelation($with))===null) -				throw new TDbException('Relation "'.$with.'" is not defined in active record class "'.get_class($parent->model).'".'); - -			$relation=clone $relation; -			$model=TActiveRecord::model($relation->className); -			if(($scope=$model->defaultScope())!==array()) -				$relation->mergeWith($scope); -			if(isset($scopes) && !empty($scopes)) -			{ -				$scs=$model->scopes(); -				foreach($scopes as $scope) -				{ -					if(isset($scs[$scope])) -						$relation->mergeWith($scs[$scope]); -					else -						throw new TDbException('Active record class "'.get_class($model).'" does not have a scope named "'.$scope.'".'); -				} -			} - -			// dynamic options -			if($options!==null) -				$relation->mergeWith($options); - -			if($relation instanceof TStatRelation) -				return new TStatElement($this,$relation,$parent); -			else -			{ -				$element=$parent->children[$with]=new TJoinElement($this,$relation,$parent,++$this->_joinCount); -				if(!empty($relation->with)) -					$this->buildJoinTree($element,$relation->with); -				return $element; -			} -		} - -		// $with is an array, keys are relation name, values are relation spec -		foreach($with as $key=>$value) -		{ -			if(is_string($value))  // the value is a relation name -				$this->buildJoinTree($parent,$value); -			else if(is_string($key) && is_array($value)) -				$element=$this->buildJoinTree($parent,$key,$value); -		} -	} -} - - -/** - * CJoinElement represents a tree node in the join tree created by {@link CActiveFinder}. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveFinder.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0 - */ -class TJoinElement -{ -	/** -	 * @var integer the unique ID of this tree node -	 */ -	public $id; -	/** -	 * @var CActiveRelation the relation represented by this tree node -	 */ -	public $relation; -	/** -	 * @var CActiveRecord the model associated with this tree node -	 */ -	public $model; -	/** -	 * @var array list of active records found by the queries. They are indexed by primary key values. -	 */ -	public $records=array(); -	/** -	 * @var array list of child join elements -	 */ -	public $children=array(); -	/** -	 * @var array list of stat elements -	 * @since 1.0.4 -	 */ -	public $stats=array(); -	/** -	 * @var string table alias for this join element -	 */ -	public $tableAlias; - -	private $_finder; -	private $_builder; -	private $_parent; -	private $_pkAlias;  				// string or name=>alias -	private $_columnAliases=array();	// name=>alias -	private $_joined=false; -	private $_table; -	private $_related=array();			// PK, relation name, related PK => true - -	/** -	 * Constructor. -	 * @param CActiveFinder the finder -	 * @param mixed the relation (if the third parameter is not null) -	 * or the model (if the third parameter is null) associated with this tree node. -	 * @param CJoinElement the parent tree node -	 * @param integer the ID of this tree node that is unique among all the tree nodes -	 */ -	public function __construct($finder,$relation,$parent=null,$id=0) -	{ -		$this->_finder=$finder; -		$this->id=$id; -		if($parent!==null) -		{ -			$this->relation=$relation; -			$this->_parent=$parent; -			$this->_builder=$parent->_builder; -			$this->tableAlias=$relation->alias===null?$relation->name:$relation->alias; -			$this->model=TActiveRecord::model($relation->className); -			$this->_table=$this->model->getTableSchema(); -		} -		else  // root element, the first parameter is the model. -		{ -			$this->model=$relation; -			$this->_builder=$relation->getCommandBuilder(); -			$this->_table=$relation->getTableSchema(); -		} - -		// set up column aliases, such as t1_c2 -		$table=$this->_table; -		$prefix='t'.$id.'_c'; -		foreach($table->getColumnNames() as $key=>$name) -		{ -			$alias=$prefix.$key; -			$this->_columnAliases[$name]=$alias; -			if($table->primaryKey===$name) -				$this->_pkAlias=$alias; -			else if(is_array($table->primaryKey) && in_array($name,$table->primaryKey)) -				$this->_pkAlias[$name]=$alias; -		} -	} - -	/** -	 * Performs the recursive finding with the criteria. -	 * @param CDbCriteria the query criteria -	 */ -	public function find($criteria=null) -	{ -		if($this->_parent===null) // root element -		{ -			$query=new TJoinQuery($this,$criteria); -			$this->_finder->baseLimited=($criteria->offset>=0 || $criteria->limit>=0); -			$this->buildQuery($query); -			$this->_finder->baseLimited=false; -			$this->runQuery($query); -		} -		else if(!$this->_joined && !empty($this->_parent->records)) // not joined before -		{ -			$query=new TJoinQuery($this->_parent); -			$this->_joined=true; -			$query->join($this); -			$this->buildQuery($query); -			$this->_parent->runQuery($query); -		} - -		foreach($this->children as $child) // find recursively -			$child->find(); - -		foreach($this->stats as $stat) -			$stat->query(); -	} - -	/** -	 * Performs lazy find with the specified base record. -	 * @param CActiveRecord the active record whose related object is to be fetched. -	 */ -	public function lazyFind($baseRecord) -	{ -		if(is_string($this->_table->primaryKey)) -			$this->records[$baseRecord->{$this->_table->primaryKey}]=$baseRecord; -		else -		{ -			$pk=array(); -			foreach($this->_table->primaryKey as $name) -				$pk[$name]=$baseRecord->$name; -			$this->records[serialize($pk)]=$baseRecord; -		} - -		foreach($this->stats as $stat) -			$stat->query(); - -		if(empty($this->children)) -			return; - -		$child=reset($this->children); -		$query=new TJoinQuery($this); -		$this->_joined=true; -		$child->_joined=true; -		$query->join($child); -		if($child->relation instanceof THasManyRelation) -		{ -			$query->limit=$child->relation->limit; -			$query->offset=$child->relation->offset; -			$this->_finder->baseLimited=($query->offset>=0 || $query->limit>=0); -			$query->groups[]=$child->relation->group; -			$query->havings[]=$child->relation->having; -		} -		$child->buildQuery($query); -		$this->_finder->baseLimited=false; -		$this->runQuery($query); -		foreach($child->children as $c) -			$c->find(); -	} - -	/** -	 * Performs the eager loading with the base records ready. -	 * @param mixed the available base record(s). -	 */ -	public function findWithBase($baseRecords) -	{ -		if(!is_array($baseRecords)) -			$baseRecords=array($baseRecords); -		if(is_string($this->_table->primaryKey)) -		{ -			foreach($baseRecords as $baseRecord) -				$this->records[$baseRecord->{$this->_table->primaryKey}]=$baseRecord; -		} -		else -		{ -			foreach($baseRecords as $baseRecord) -			{ -				$pk=array(); -				foreach($this->_table->primaryKey as $name) -					$pk[$name]=$baseRecord->$name; -				$this->records[serialize($pk)]=$baseRecord; -			} -		} - -		$query=new TJoinQuery($this); -		$this->buildQuery($query); -		if(count($query->joins)>1) -			$this->runQuery($query); -		foreach($this->children as $child) -			$child->find(); - -		foreach($this->stats as $stat) -			$stat->query(); -	} - -	/** -	 * Count the number of primary records returned by the join statement. -	 * @param CDbCriteria the query criteria -	 * @return integer number of primary records. -	 * @since 1.0.3 -	 */ -	public function count($criteria=null) -	{ -		$query=new TJoinQuery($this,$criteria); -		// ensure only one big join statement is used -		$this->_finder->baseLimited=false; -		$this->_finder->joinAll=true; -		$this->buildQuery($query); - -		if(is_string($this->_table->primaryKey)) -		{ -			$prefix=$this->getColumnPrefix(); -			$schema=$this->_builder->getSchema(); -			$column=$prefix.$schema->quoteColumnName($this->_table->primaryKey); -		} -		else if($criteria->select!=='*') -			$column=$criteria->select; -		else -			throw new TDbException('Unable to count records with composite primary keys. Please explicitly specify the SELECT option in the query criteria.'); - -		$query->selects=array("COUNT(DISTINCT $column)"); -		$query->orders=$query->groups=$query->havings=array(); -		$command=$query->createCommand($this->_builder); -		return $command->queryScalar(); -	} - -	/** -	 * Calls {@link CActiveRecord::afterFind} of all the records. -	 * @since 1.0.3 -	 */ -	public function afterFind() -	{ -		foreach($this->records as $record) -			$record->afterFindInternal(); -		foreach($this->children as $child) -			$child->afterFind(); -	} - -	/** -	 * Builds the join query with all descendant HAS_ONE and BELONGS_TO nodes. -	 * @param CJoinQuery the query being built up -	 */ -	public function buildQuery($query) -	{ -		foreach($this->children as $child) -		{ -			if($child->relation instanceof THasOneRelation || $child->relation instanceof TBelongsToRelation -				|| $this->_finder->joinAll || !$this->_finder->baseLimited && $child->relation->together) -			{ -				$child->_joined=true; -				$query->join($child); -				$child->buildQuery($query); -			} -		} -	} - -	/** -	 * Executes the join query and populates the query results. -	 * @param CJoinQuery the query to be executed. -	 */ -	public function runQuery($query) -	{ -		$command=$query->createCommand($this->_builder); -		foreach($command->queryAll() as $row) -			$this->populateRecord($query,$row); -	} - -	/** -	 * Populates the active records with the query data. -	 * @param CJoinQuery the query executed -	 * @param array a row of data -	 * @return CActiveRecord the populated record -	 */ -	private function populateRecord($query,$row) -	{ -		// determine the primary key value -		if(is_string($this->_pkAlias))  // single key -		{ -			if(isset($row[$this->_pkAlias])) -				$pk=$row[$this->_pkAlias]; -			else	// no matching related objects -				return null; -		} -		else // is_array, composite key -		{ -			$pk=array(); -			foreach($this->_pkAlias as $name=>$alias) -			{ -				if(isset($row[$alias])) -					$pk[$name]=$row[$alias]; -				else	// no matching related objects -					return null; -			} -			$pk=serialize($pk); -		} - -		// retrieve or populate the record according to the primary key value -		if(isset($this->records[$pk])) -			$record=$this->records[$pk]; -		else -		{ -			$attributes=array(); -			$aliases=array_flip($this->_columnAliases); -			foreach($row as $alias=>$value) -			{ -				if(isset($aliases[$alias])) -					$attributes[$aliases[$alias]]=$value; -			} -			$record=$this->model->populateRecord($attributes,false); -			foreach($this->children as $child) -				$record->addRelatedRecord($child->relation->name,null,$child->relation instanceof THasManyRelation); -			$this->records[$pk]=$record; -		} - -		// populate child records recursively -		foreach($this->children as $child) -		{ -			if(!isset($query->elements[$child->id])) -				continue; -			$childRecord=$child->populateRecord($query,$row); -			if($child->relation instanceof THasOneRelation || $child->relation instanceof TBelongsToRelation) -				$record->addRelatedRecord($child->relation->name,$childRecord,false); -			else // has_many and many_many -			{ -				// need to double check to avoid adding duplicated related objects -				if($childRecord instanceof TActiveRecord) -					$fpk=serialize($childRecord->getPrimaryKey()); -				else -					$fpk=0; -				if(!isset($this->_related[$pk][$child->relation->name][$fpk])) -				{ -					$record->addRelatedRecord($child->relation->name,$childRecord,true); -					$this->_related[$pk][$child->relation->name][$fpk]=true; -				} -			} -		} - -		return $record; -	} - -	/** -	 * @return string the table name and the table alias (if any). This can be used directly in SQL query without escaping. -	 */ -	public function getTableNameWithAlias() -	{ -		if($this->tableAlias!==null) -			return $this->_table->rawName . ' ' . $this->tableAlias; -		else -			return $this->_table->rawName; -	} - -	/** -	 * Generates the list of columns to be selected. -	 * Columns will be properly aliased and primary keys will be added to selection if they are not specified. -	 * @param mixed columns to be selected. Defaults to '*', indicating all columns. -	 * @return string the column selection -	 */ -	public function getColumnSelect($select='*') -	{ -		$schema=$this->_builder->getSchema(); -		$prefix=$this->getColumnPrefix(); -		$columns=array(); -		if($select==='*') -		{ -			foreach($this->_table->getColumnNames() as $name) -				$columns[]=$prefix.$schema->quoteColumnName($name).' AS '.$schema->quoteColumnName($this->_columnAliases[$name]); -		} -		else -		{ -			if(is_string($select)) -				$select=explode(',',$select); -			$selected=array(); -			foreach($select as $name) -			{ -				$name=trim($name); -				$matches=array(); -				if(($pos=strrpos($name,'.'))!==false) -					$key=substr($name,$pos+1); -				else -					$key=$name; -				if(isset($this->_columnAliases[$key]))  // simple column names -				{ -					$columns[]=$prefix.$schema->quoteColumnName($key).' AS '.$schema->quoteColumnName($this->_columnAliases[$key]); -					$selected[$this->_columnAliases[$key]]=1; -				} -				else if(preg_match('/^(.*?)\s+AS\s+(\w+)$/i',$name,$matches)) // if the column is already aliased -				{ -					$alias=$matches[2]; -					if(!isset($this->_columnAliases[$alias]) || $this->_columnAliases[$alias]!==$alias) -					{ -						$this->_columnAliases[$alias]=$alias; -						$columns[]=$name; -						$selected[$alias]=1; -					} -				} -				else -					throw new TDbException('Active record "'.get_class($this->model).'" is trying to select an invalid column "'.$name.'". Note, the column must exist in the table or be an expression with alias.'); -			} -			// add primary key selection if they are not selected -			if(is_string($this->_pkAlias) && !isset($selected[$this->_pkAlias])) -				$columns[]=$prefix.$schema->quoteColumnName($this->_table->primaryKey).' AS '.$schema->quoteColumnName($this->_pkAlias); -			else if(is_array($this->_pkAlias)) -			{ -				foreach($this->_table->primaryKey as $name) -					if(!isset($selected[$name])) -						$columns[]=$prefix.$schema->quoteColumnName($name).' AS '.$schema->quoteColumnName($this->_pkAlias[$name]); -			} -		} - -		return implode(', ',$columns); -	} - -	/** -	 * @return string the primary key selection -	 */ -	public function getPrimaryKeySelect() -	{ -		$schema=$this->_builder->getSchema(); -		$prefix=$this->getColumnPrefix(); -		$columns=array(); -		if(is_string($this->_pkAlias)) -			$columns[]=$prefix.$schema->quoteColumnName($this->_table->primaryKey).' AS '.$schema->quoteColumnName($this->_pkAlias); -		else if(is_array($this->_pkAlias)) -		{ -			foreach($this->_pkAlias as $name=>$alias) -				$columns[]=$prefix.$schema->quoteColumnName($name).' AS '.$schema->quoteColumnName($alias); -		} -		return implode(', ',$columns); -	} - -	/** -	 * @return string the condition that specifies only the rows with the selected primary key values. -	 */ -	public function getPrimaryKeyRange() -	{ -		if(empty($this->records)) -			return ''; -		$values=array_keys($this->records); -		if(is_array($this->_table->primaryKey)) -		{ -			foreach($values as &$value) -				$value=unserialize($value); -		} -		return $this->_builder->createInCondition($this->_table,$this->_table->primaryKey,$values,$this->getColumnPrefix()); -	} - -	/** -	 * @return string the column prefix for column reference disambiguation -	 */ -	public function getColumnPrefix() -	{ -		if($this->tableAlias!==null) -			return $this->tableAlias.'.'; -		else -			return $this->_table->rawName.'.'; -	} - -	/** -	 * @return string the join statement (this node joins with its parent) -	 */ -	public function getJoinCondition() -	{ -		$parent=$this->_parent; -		$relation=$this->relation; -		if($this->relation instanceof TManyManyRelation) -		{ -			if(!preg_match('/^\s*(.*?)\((.*)\)\s*$/',$this->relation->foreignKey,$matches)) -				throw new TDbException('The relation "'.($this->relation->name).'" in active record class "'.get_class($parent->model).'" is specified with an invalid foreign key. The format of the foreign key must be "joinTable(fk1,fk2,...)".'); - -			$schema=$this->_builder->getSchema(); -			if(($joinTable=$schema->getTable($matches[1]))===null) -				throw new TDbException('The relation "'.($this->relation->name).'" in active record class "'.get_class($parent->model).'" is not specified correctly: the join table "'.($matches[1]).'" given in the foreign key cannot be found in the database.'); -				 -			$fks=preg_split('/[\s,]+/',$matches[2],-1,PREG_SPLIT_NO_EMPTY); - -			return $this->joinManyMany($joinTable,$fks,$parent); -		} -		else -		{ -			$fks=preg_split('/[\s,]+/',$relation->foreignKey,-1,PREG_SPLIT_NO_EMPTY); -			if($this->relation instanceof TBelongsToRelation) -			{ -				$pke=$this; -				$fke=$parent; -			} -			else -			{ -				$pke=$parent; -				$fke=$this; -			} -			return $this->joinOneMany($fke,$fks,$pke,$parent); -		} -	} - -	/** -	 * Generates the join statement for one-many relationship. -	 * This works for HAS_ONE, HAS_MANY and BELONGS_TO. -	 * @param CJoinElement the join element containing foreign keys -	 * @param array the foreign keys -	 * @param CJoinElement the join element containg primary keys -	 * @param CJoinElement the parent join element -	 * @return string the join statement -	 * @throws CDbException if a foreign key is invalid -	 */ -	private function joinOneMany($fke,$fks,$pke,$parent) -	{ -		$schema=$this->_builder->getSchema(); -		$joins=array(); -		foreach($fks as $i=>$fk) -		{ -			if(!isset($fke->_table->columns[$fk])) -				throw new TDbException('The relation "'.($this->relation->name).'" in active record class "'.get_class($parent->model).'" is specified with an invalid foreign key "'.$fk.'". There is no such column in the table "'.($fke->_table->name).'".'); - -			if(isset($fke->_table->foreignKeys[$fk])) -				$pk=$fke->_table->foreignKeys[$fk][1]; -			else  // FK constraints undefined -			{ -				if(is_array($pke->_table->primaryKey)) // composite PK -					$pk=$pke->_table->primaryKey[$i]; -				else -					$pk=$pke->_table->primaryKey; -			} -			$joins[]=$fke->getColumnPrefix().$schema->quoteColumnName($fk) . '=' . $pke->getColumnPrefix().$schema->quoteColumnName($pk); -		} -		if(!empty($this->relation->on)) -			$joins[]=$this->relation->on; -		return $this->relation->joinType . ' ' . $this->getTableNameWithAlias() . ' ON (' . implode(') AND (',$joins).')'; -	} - -	/** -	 * Generates the join statement for many-many relationship. -	 * @param CDbTableSchema the join table -	 * @param array the foreign keys -	 * @param CJoinElement the parent join element -	 * @return string the join statement -	 * @throws CDbException if a foreign key is invalid -	 */ -	private function joinManyMany($joinTable,$fks,$parent) -	{ -		$schema=$this->_builder->getSchema(); -		$joinAlias=$this->relation->name.'_'.$this->tableAlias; -		$parentCondition=array(); -		$childCondition=array(); -		foreach($fks as $i=>$fk) -		{ -			if(!isset($joinTable->columns[$fk])) -				throw new TDbException('The relation "'.($this->relation->name).'" in active record class "'.get_class($parent->model).'" is specified with an invalid foreign key "'.$fk.'". There is no such column in the table "'.($joinTable->name).'".'); - -			if(isset($joinTable->foreignKeys[$fk])) -			{ -				list($tableName,$pk)=$joinTable->foreignKeys[$fk]; -				if(!isset($parentCondition[$pk]) && $schema->compareTableNames($parent->_table->rawName,$tableName)) -					$parentCondition[$pk]=$parent->getColumnPrefix().$schema->quoteColumnName($pk).'='.$joinAlias.'.'.$schema->quoteColumnName($fk); -				else if(!isset($childCondition[$pk]) && $schema->compareTableNames($this->_table->rawName,$tableName)) -					$childCondition[$pk]=$this->getColumnPrefix().$schema->quoteColumnName($pk).'='.$joinAlias.'.'.$schema->quoteColumnName($fk); -				else -					throw new TDbException('The relation "'.($this->relation->name).'" in active record class "'.get_class($parent->model).'" is specified with an invalid foreign key "'.$fk.'". The foreign key does not point to either joining table.'); -			} -			else // FK constraints not defined -			{ -				if($i<count($parent->_table->primaryKey)) -				{ -					$pk=is_array($parent->_table->primaryKey) ? $parent->_table->primaryKey[$i] : $parent->_table->primaryKey; -					$parentCondition[$pk]=$parent->getColumnPrefix().$schema->quoteColumnName($pk).'='.$joinAlias.'.'.$schema->quoteColumnName($fk); -				} -				else -				{ -					$j=$i-count($parent->_table->primaryKey); -					$pk=is_array($this->_table->primaryKey) ? $this->_table->primaryKey[$j] : $this->_table->primaryKey; -					$childCondition[$pk]=$this->getColumnPrefix().$schema->quoteColumnName($pk).'='.$joinAlias.'.'.$schema->quoteColumnName($fk); -				} -			} -		} -		if($parentCondition!==array() && $childCondition!==array()) -		{ -			$join=$this->relation->joinType.' '.$joinTable->rawName.' '.$joinAlias; -			$join.=' ON ('.implode(') AND (',$parentCondition).')'; -			$join.=' '.$this->relation->joinType.' '.$this->getTableNameWithAlias(); -			$join.=' ON ('.implode(') AND (',$childCondition).')'; -			if(!empty($this->relation->on)) -				$join.=' AND ('.$this->relation->on.')'; -			return $join; -		} -		else -			throw new TDbException('The relation "'.($this->relation->name).'" in active record class "'.get_class($parent->model).'" is specified with an incomplete foreign key. The foreign key must consist of columns referencing both joining tables.'); -	} -} - - -/** - * CJoinQuery represents a JOIN SQL statement. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveFinder.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0 - */ -class TJoinQuery -{ -	/** -	 * @var array list of column selections -	 */ -	public $selects=array(); -	/** -	 * @var array list of join statement -	 */ -	public $joins=array(); -	/** -	 * @var array list of WHERE clauses -	 */ -	public $conditions=array(); -	/** -	 * @var array list of ORDER BY clauses -	 */ -	public $orders=array(); -	/** -	 * @var array list of GROUP BY clauses -	 */ -	public $groups=array(); -	/** -	 * @var array list of HAVING clauses -	 */ -	public $havings=array(); -	/** -	 * @var integer row limit -	 */ -	public $limit=-1; -	/** -	 * @var integer row offset -	 */ -	public $offset=-1; -	/** -	 * @var array list of query parameters -	 */ -	public $params=array(); -	/** -	 * @var array list of join element IDs (id=>true) -	 */ -	public $elements=array(); - -	/** -	 * Constructor. -	 * @param CJoinElement The root join tree. -	 * @param CDbCriteria the query criteria -	 */ -	public function __construct($joinElement,$criteria=null) -	{ -		if($criteria!==null) -		{ -			$this->selects[]=$joinElement->getColumnSelect($criteria->select); -			$this->joins[]=$joinElement->getTableNameWithAlias(); -			$this->joins[]=$criteria->join; -			$this->conditions[]=$criteria->condition; -			$this->orders[]=$criteria->order; -			$this->groups[]=$criteria->group; -			$this->havings[]=$criteria->having; -			$this->limit=$criteria->limit; -			$this->offset=$criteria->offset; -			$this->params=$criteria->params; -		} -		else -		{ -			$this->selects[]=$joinElement->getPrimaryKeySelect(); -			$this->joins[]=$joinElement->getTableNameWithAlias(); -			$this->conditions[]=$joinElement->getPrimaryKeyRange(); -		} -		$this->elements[$joinElement->id]=true; -	} - -	/** -	 * Joins with another join element -	 * @param CJoinElement the element to be joined -	 */ -	public function join($element) -	{ -		$this->selects[]=$element->getColumnSelect($element->relation->select); -		$this->conditions[]=$element->relation->condition; -		$this->orders[]=$element->relation->order; -		$this->joins[]=$element->getJoinCondition(); -		$this->groups[]=$element->relation->group; -		$this->havings[]=$element->relation->having; - -		if(is_array($element->relation->params)) -		{ -			if(is_array($this->params)) -				$this->params=array_merge($this->params,$element->relation->params); -			else -				$this->params=$element->relation->params; -		} -		$this->elements[$element->id]=true; -	} - -	/** -	 * Creates the SQL statement. -	 * @param CDbCommandBuilder the command builder -	 * @return string the SQL statement -	 */ -	public function createCommand($builder) -	{ -		$sql='SELECT ' . implode(', ',$this->selects); -		$sql.=' FROM ' . implode(' ',$this->joins); - -		$conditions=array(); -		foreach($this->conditions as $condition) -			if($condition!=='') -				$conditions[]=$condition; -		if($conditions!==array()) -			$sql.=' WHERE (' . implode(') AND (',$conditions).')'; - -		$groups=array(); -		foreach($this->groups as $group) -			if($group!=='') -				$groups[]=$group; -		if($groups!==array()) -			$sql.=' GROUP BY ' . implode(', ',$groups); - -		$havings=array(); -		foreach($this->havings as $having) -			if($having!=='') -				$havings[]=$having; -		if($havings!==array()) -			$sql.=' HAVING (' . implode(') AND (',$havings).')'; - -		$orders=array(); -		foreach($this->orders as $order) -			if($order!=='') -				$orders[]=$order; -		if($orders!==array()) -			$sql.=' ORDER BY ' . implode(', ',$orders); - -		$sql=$builder->applyLimit($sql,$this->limit,$this->offset); -		$command=$builder->getDbConnection()->createCommand($sql); -		$builder->bindValues($command,$this->params); -		return $command; -	} -} - - -/** - * CStatElement represents STAT join element for {@link CActiveFinder}. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveFinder.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0.4 - */ -class TStatElement -{ -	/** -	 * @var CActiveRelation the relation represented by this tree node -	 */ -	public $relation; - -	private $_finder; -	private $_parent; - -	/** -	 * Constructor. -	 * @param CActiveFinder the finder -	 * @param CStatRelation the STAT relation -	 * @param CJoinElement the join element owning this STAT element -	 */ -	public function __construct($finder,$relation,$parent) -	{ -		$this->_finder=$finder; -		$this->_parent=$parent; -		$this->relation=$relation; -		$parent->stats[]=$this; -	} - -	/** -	 * Performs the STAT query. -	 */ -	public function query() -	{ -		if(preg_match('/^\s*(.*?)\((.*)\)\s*$/',$this->relation->foreignKey,$matches)) -			$this->queryManyMany($matches[1],$matches[2]); -		else -			$this->queryOneMany(); -	} - -	private function queryOneMany() -	{ -		$relation=$this->relation; -		$model=TActiveRecord::model($relation->className); -		$builder=$model->getCommandBuilder(); -		$schema=$builder->getSchema(); -		$table=$model->getTableSchema(); -		$pkTable=$this->_parent->model->getTableSchema(); - -		$fks=preg_split('/[\s,]+/',$relation->foreignKey,-1,PREG_SPLIT_NO_EMPTY); -		if(count($fks)!==count($pkTable->primaryKey)) -			throw new TDbException('The relation "'.($relation->name).'" in active record class "'.get_class($parent->model).'" is specified with an invalid foreign key. The columns in the key must match the primary keys of the table "'.($pkTable->name).'".'); - -		// set up mapping between fk and pk columns -		$map=array();  // pk=>fk -		foreach($fks as $i=>$fk) -		{ -			if(!isset($table->columns[$fk])) -				throw new TDbException('The relation "'.($relation->name).'" in active record class "'.get_class($parent->model).'" is specified with an invalid foreign key "'.$fk.'". There is no such column in the table "'.($table->name).'".'); - -			if(isset($table->foreignKeys[$fk])) -			{ -				list($tableName,$pk)=$table->foreignKeys[$fk]; -				if($schema->compareTableNames($pkTable->rawName,$tableName)) -					$map[$pk]=$fk; -				else -					throw new TDbException('The relation "'.($relation->name).'" in active record class "'.get_class($parent->model).'" is specified with a foreign key "'.$fk.'" that does not point to the parent table "'.($pkTable->name).'".'); -			} -			else  // FK constraints undefined -			{ -				if(is_array($table->primaryKey)) // composite PK -					$map[$table->primaryKey[$i]]=$fk; -			} -		} - -		$records=$this->_parent->records; - -		$where=empty($relation->condition)?'' : ' WHERE ('.$relation->condition.')'; -		$group=empty($relation->group)?'' : ', '.$relation->group; -		$having=empty($relation->having)?'' : ' AND ('.$relation->having.')'; -		$order=empty($relation->order)?'' : ' ORDER BY '.$relation->order; - -		$c=$schema->quoteColumnName('c'); -		$s=$schema->quoteColumnName('s'); - -		// generate and perform query -		if(count($fks)===1)  // single column FK -		{ -			$col=$table->columns[$fks[0]]->rawName; -			$sql="SELECT $col AS $c, {$relation->select} AS $s FROM {$table->rawName}" -				.$where -				." GROUP BY $col".$group -				." HAVING ".$builder->createInCondition($table,$fks[0],array_keys($records)) -				.$having.$order; -			$command=$builder->getDbConnection()->createCommand($sql); -			if(is_array($relation->params)) -				$builder->bindValues($command,$relation->params); -			$stats=array(); -			foreach($command->queryAll() as $row) -				$stats[$row['c']]=$row['s']; -		} -		else  // composite FK -		{ -			$keys=array_keys($records); -			foreach($keys as &$key) -			{ -				$key2=unserialize($key); -				$key=array(); -				foreach($pkTable->primaryKey as $pk) -					$key[$map[$pk]]=$key2[$pk]; -			} -			$cols=array(); -			foreach($pkTable->primaryKey as $n=>$pk) -			{ -				$name=$table->columns[$map[$pk]]->rawName; -				$cols[$name]=$name.' AS '.$schema->quoteColumnName('c'.$n); -			} -			$sql='SELECT '.implode(', ',$cols).", {$relation->select} AS $s FROM {$table->rawName}" -				.$where -				.' GROUP BY '.implode(', ',array_keys($cols)).$group -				.' HAVING '.$builder->createInCondition($table,$fks,$keys) -				.$having.$order; -			$command=$builder->getDbConnection()->createCommand($sql); -			if(is_array($relation->params)) -				$builder->bindValues($command,$relation->params); -			$stats=array(); -			foreach($command->queryAll() as $row) -			{ -				$key=array(); -				foreach($pkTable->primaryKey as $n=>$pk) -					$key[$pk]=$row['c'.$n]; -				$stats[serialize($key)]=$row['s']; -			} -		} - -		// populate the results into existing records -		foreach($records as $pk=>$record) -			$record->addRelatedRecord($relation->name,isset($stats[$pk])?$stats[$pk]:$relation->defaultValue,false); -	} - -	private function queryManyMany($joinTableName,$keys) -	{ -		$relation=$this->relation; -		$model=TActiveRecord::model($relation->className); -		$table=$model->getTableSchema(); -		$builder=$model->getCommandBuilder(); -		$schema=$builder->getSchema(); -		$pkTable=$this->_parent->model->getTableSchema(); - -		if(($joinTable=$builder->getSchema()->getTable($joinTableName))===null) -			throw new TDbException('The relation "'.($relation->name).'" in active record class "'.get_class($this->_parent->model).'" is not specified correctly. The join table "'.$joinTableName.'" given in the foreign key cannot be found in the database.'); - -		$fks=preg_split('/[\s,]+/',$keys,-1,PREG_SPLIT_NO_EMPTY); -		if(count($fks)!==count($table->primaryKey)+count($pkTable->primaryKey)) -			throw new TDbException('The relation "'.($relation->name).'" in active record class "'.get_class($this->_parent->model).'" is specified with an incomplete foreign key. The foreign key must consist of columns referencing both joining tables.'); - -		$joinCondition=array(); -		$map=array(); -		foreach($fks as $i=>$fk) -		{ -			if(!isset($joinTable->columns[$fk])) -				throw new TDbException('The relation "'.($relation->name).'" in active record class "'.get_class($this->_parent->model).'" is specified with an invalid foreign key "'.$fk.'". There is no such column in the table "'.($joinTable->name).'".'); - -			if(isset($joinTable->foreignKeys[$fk])) -			{ -				list($tableName,$pk)=$joinTable->foreignKeys[$fk]; -				if(!isset($joinCondition[$pk]) && $schema->compareTableNames($table->rawName,$tableName)) -					$joinCondition[$pk]=$table->rawName.'.'.$schema->quoteColumnName($pk).'='.$joinTable->rawName.'.'.$schema->quoteColumnName($fk); -				else if(!isset($map[$pk]) && $schema->compareTableNames($pkTable->rawName,$tableName)) -					$map[$pk]=$fk; -				else -					throw new TDbException('The relation "'.($relation->name).'" in active record class "'.get_class($this->_parent->model).'" is specified with an invalid foreign key "'.$fk.'". The foreign key does not point to either joining table.'); -			} -			else // FK constraints not defined -			{ -				if($i<count($pkTable->primaryKey)) -				{ -					$pk=is_array($pkTable->primaryKey) ? $pkTable->primaryKey[$i] : $pkTable->primaryKey; -					$map[$pk]=$fk; -				} -				else -				{ -					$j=$i-count($pkTable->primaryKey); -					$pk=is_array($table->primaryKey) ? $table->primaryKey[$j] : $table->primaryKey; -					$joinCondition[$pk]=$table->rawName.'.'.$schema->quoteColumnName($pk).'='.$joinTable->rawName.'.'.$schema->quoteColumnName($fk); -				} -			} -		} - -		if($joinCondition===array() || $map===array()) -			throw new TDbException('The relation "'.($relation->name).'" in active record class "'.get_class($this->_parent->model).'" is specified with an incomplete foreign key. The foreign key must consist of columns referencing both joining tables.'); - -		$records=$this->_parent->records; - -		$cols=array(); -		foreach(is_string($pkTable->primaryKey)?array($pkTable->primaryKey):$pkTable->primaryKey as $n=>$pk) -		{ -			$name=$joinTable->rawName.'.'.$schema->quoteColumnName($map[$pk]); -			$cols[$name]=$name.' AS '.$schema->quoteColumnName('c'.$n); -		} - -		$keys=array_keys($records); -		if(is_array($pkTable->primaryKey)) -		{ -			foreach($keys as &$key) -			{ -				$key2=unserialize($key); -				$key=array(); -				foreach($pkTable->primaryKey as $pk) -					$key[$map[$pk]]=$key2[$pk]; -			} -		} - -		$where=empty($relation->condition)?'' : ' WHERE ('.$relation->condition.')'; -		$group=empty($relation->group)?'' : ', '.$relation->group; -		$having=empty($relation->having)?'' : ' AND ('.$relation->having.')'; -		$order=empty($relation->order)?'' : ' ORDER BY '.$relation->order; - -		$sql='SELECT '.$this->relation->select.' AS '.$schema->quoteColumnName('s').', '.implode(', ',$cols) -			.' FROM '.$table->rawName.' INNER JOIN '.$joinTable->rawName -			.' ON ('.implode(') AND (',$joinCondition).')' -			.$where -			.' GROUP BY '.implode(', ',array_keys($cols)).$group -			.' HAVING ('.$builder->createInCondition($joinTable,$map,$keys).')' -			.$having.$order; - -		$command=$builder->getDbConnection()->createCommand($sql); -		if(is_array($relation->params)) -			$builder->bindValues($command,$relation->params); - -		$stats=array(); -		foreach($command->queryAll() as $row) -		{ -			if(is_array($pkTable->primaryKey)) -			{ -				$key=array(); -				foreach($pkTable->primaryKey as $n=>$k) -					$key[$k]=$row['c'.$n]; -				$stats[serialize($key)]=$row['s']; -			} -			else -				$stats[$row['c0']]=$row['s']; -		} - -		foreach($records as $pk=>$record) -			$record->addRelatedRecord($relation->name,isset($stats[$pk])?$stats[$pk]:$this->relation->defaultValue,false); -	} -} diff --git a/framework/Testing/Data/ActiveRecord/TActiveRecord.php b/framework/Testing/Data/ActiveRecord/TActiveRecord.php deleted file mode 100644 index 8d6c5e10..00000000 --- a/framework/Testing/Data/ActiveRecord/TActiveRecord.php +++ /dev/null @@ -1,1843 +0,0 @@ -<?php -/** - * CActiveRecord class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -/** - * CActiveRecord is the base class for classes representing relational data. - * - * It implements the active record design pattern, a popular Object-Relational Mapping (ORM) technique. - * Please check {@link http://www.yiiframework.com/doc/guide/database.ar the Guide} for more details - * about this class. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveRecord.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0 - */ - -Prado::using('System.Base.TModel'); -Prado::using('System.Testing.Data.*'); -Prado::using('System.Testing.Data.ActiveRecord.*'); -Prado::using('System.Base.TEvent'); -Prado::using('System.Testing.Data.ActiveRecord.TActiveRecordCriteria'); - -abstract class TActiveRecord extends TModel -{ -	const BELONGS_TO='TBelongsToRelation'; -	const HAS_ONE='THasOneRelation'; -	const HAS_MANY='THasManyRelation'; -	const MANY_MANY='TManyManyRelation'; -	const STAT='TStatRelation'; - -	/** -	 * @var CDbConnection the default database connection for all active record classes. -	 * By default, this is the 'db' application component. -	 * @see getDbConnection -	 */ -	public static $db; - -	private static $_models=array();			// class name => model - -	private $_md;								// meta data -	private $_new=false;						// whether this instance is new or not -	private $_attributes=array();				// attribute name => attribute value -	private $_related=array();					// attribute name => related objects -	private $_c;								// query criteria (used by finder only) - -	/** -	 * Returns the instance of a active record finder for a particular class. -	 * The finder objects are static instances for each ActiveRecord class. -	 * This means that event handlers bound to these finder instances are class wide. -	 * Create a new instance of the ActiveRecord class if you wish to bound the -	 * event handlers to object instance. -	 * @param string active record class name. -	 * @return TActiveRecord active record finder instance. -	 */ -  -	/** -	 * Constructor. -	 * @param string scenario name. See {@link CModel::scenario} for more details about this parameter. -	 */ -	public function __construct($scenario='insert') -	{ -		if($scenario===null) // internally used by populateRecord() and model() -			return; - -		$this->setScenario($scenario); -		$this->setIsNewRecord(true); -		$this->_attributes=$this->getMetaData()->attributeDefaults; - -		$this->attachBehaviors($this->behaviors()); -		$this->afterConstruct(); -	} - -	/** -	 * PHP sleep magic method. -	 * This method ensures that the model meta data reference is set to null. -	 */ -	public function __sleep() -	{ -		$this->_md=null; -		return array_keys((array)$this); -	} - -	/** -	 * PHP getter magic method. -	 * This method is overridden so that AR attributes can be accessed like properties. -	 * @param string property name -	 * @return mixed property value -	 * @see getAttribute -	 */ -	public function __get($name) -	{ -		if(isset($this->_attributes[$name])) -			return $this->_attributes[$name]; -		else if(isset($this->getMetaData()->columns[$name])) -			return null; -		else if(isset($this->_related[$name])) -			return $this->_related[$name]; -		else if(isset($this->getMetaData()->relations[$name])) -			return $this->getRelated($name); -		else -			return parent::__get($name); -	} - -	/** -	 * PHP setter magic method. -	 * This method is overridden so that AR attributes can be accessed like properties. -	 * @param string property name -	 * @param mixed property value -	 */ -	public function __set($name,$value) -	{ -		if($this->setAttribute($name,$value)===false) -			parent::__set($name,$value); -	} - -	/** -	 * Checks if a property value is null. -	 * This method overrides the parent implementation by checking -	 * if the named attribute is null or not. -	 * @param string the property name or the event name -	 * @return boolean whether the property value is null -	 * @since 1.0.1 -	 */ -	public function __isset($name) -	{ -		if(isset($this->_attributes[$name])) -			return true; -		else if(isset($this->getMetaData()->columns[$name])) -			return false; -		else if(isset($this->_related[$name])) -			return true; -		else if(isset($this->getMetaData()->relations[$name])) -			return $this->getRelated($name)!==null; -#		else -#			return parent::__isset($name); -	} - -	/** -	 * Sets a component property to be null. -	 * This method overrides the parent implementation by clearing -	 * the specified attribute value. -	 * @param string the property name or the event name -	 * @since 1.0.1 -	 */ -	public function __unset($name) -	{ -		if(isset($this->getMetaData()->columns[$name])) -			unset($this->_attributes[$name]); -		else if(isset($this->getMetaData()->relations[$name])) -			unset($this->_related[$name]); -		else -			parent::__unset($name); -	} - -	/** -	 * Calls the named method which is not a class method. -	 * Do not call this method. This is a PHP magic method that we override -	 * to implement the named scope feature. -	 * @param string the method name -	 * @param array method parameters -	 * @return mixed the method return value -	 * @since 1.0.5 -	 *  -	 * @TODO: implement __call to parent -	 *  -	 */ -	public function __call($name,$parameters) -	{ -		if(isset($this->getMetaData()->relations[$name])) -		{ -			if(empty($parameters)) -				return $this->getRelated($name,false); -			else -				return $this->getRelated($name,false,$parameters[0]); -		} - -		$scopes=$this->scopes(); -		if(isset($scopes[$name])) -		{ -			$this->getDbCriteria()->mergeWith($scopes[$name]); -			return $this; -		} - -# 		return parent::__call($name,$parameters);*/ -	} - -	/** -	 * Returns the related record(s). -	 * This method will return the related record(s) of the current record. -	 * If the relation is HAS_ONE or BELONGS_TO, it will return a single object -	 * or null if the object does not exist. -	 * If the relation is HAS_MANY or MANY_MANY, it will return an array of objects -	 * or an empty array. -	 * @param string the relation name (see {@link relations}) -	 * @param boolean whether to reload the related objects from database. Defaults to false. -	 * @param array additional parameters that customize the query conditions as specified in the relation declaration. -	 * This parameter has been available since version 1.0.5. -	 * @return mixed the related object(s). -	 * @throws CDbException if the relation is not specified in {@link relations}. -	 * @since 1.0.2 -	 */ -	public function getRelated($name,$refresh=false,$params=array()) -	{ -		if(!$refresh && $params===array() && (isset($this->_related[$name]) || array_key_exists($name,$this->_related))) -			return $this->_related[$name]; - -		$md=$this->getMetaData(); -		if(!isset($md->relations[$name])) -			throw new TDbException(get_class($this).' does not have relation "'.$name.'".'); - -		Prado::trace('lazy loading '.get_class($this).'.'.$name,'System.Testing.Data.ActiveRecord.TActiveRecord'); -		$relation=$md->relations[$name]; -		if($this->getIsNewRecord() && ($relation instanceof THasOneRelation || $relation instanceof THasManyRelation)) -			return $relation instanceof THasOneRelation ? null : array(); - -		if($params!==array()) // dynamic query -		{ -			$exists=isset($this->_related[$name]) || array_key_exists($name,$this->_related); -			if($exists) -				$save=$this->_related[$name]; -			unset($this->_related[$name]); -			$r=array($name=>$params); -		} -		else -			$r=$name; - -		$finder=new TActiveFinder($this,$r); -		$finder->lazyFind($this); - -		if(!isset($this->_related[$name])) -		{ -			if($relation instanceof THasManyRelation) -				$this->_related[$name]=array(); -			else if($relation instanceof TStatRelation) -				$this->_related[$name]=$relation->defaultValue; -			else -				$this->_related[$name]=null; -		} - -		if($params!==array()) -		{ -			$results=$this->_related[$name]; -			if($exists) -				$this->_related[$name]=$save; -			else -				unset($this->_related[$name]); -			return $results; -		} -		else -			return $this->_related[$name]; -	} - -	/** -	 * Returns a value indicating whether the named related object(s) has been loaded. -	 * @param string the relation name -	 * @return booolean a value indicating whether the named related object(s) has been loaded. -	 * @since 1.0.3 -	 */ -	public function hasRelated($name) -	{ -		return isset($this->_related[$name]) || array_key_exists($name,$this->_related); -	} - -	/** -	 * Returns the query criteria associated with this model. -	 * @param boolean whether to create a criteria instance if it does not exist. Defaults to true. -	 * @return CDbCriteria the query criteria that is associated with this model. -	 * This criteria is mainly used by {@link scopes named scope} feature to accumulate -	 * different criteria specifications. -	 * @since 1.0.5 -	 */ -	public function getDbCriteria($createIfNull=true) -	{ -		if($this->_c===null) -		{ -			if(($c=$this->defaultScope())!==array() || $createIfNull) -				$this->_c=new TDbCriteria($c); -		} -		return $this->_c; -	} - -	/** -	 * Returns the default named scope that should be applied to all queries implicitly for this model. -	 * The default implementation simply returns an empty array. You may override this method -	 * if the model needs to be queried with some default criteria (e.g. only active records should be returned). -	 * @return array the query criteria. This will be used as the parameter to the constructor -	 * of {@link CDbCriteria}. -	 * @since 1.0.5 -	 */ -	public function defaultScope() -	{ -		return array(); -	} - -	/** -	 * Returns the static model of the specified AR class. -	 * The model returned is a static instance of the AR class. -	 * It is provided for invoking class-level methods (something similar to static class methods.) -	 * -	 * EVERY derived AR class must override this method as follows, -	 * <pre> -	 * public static function model($className=__CLASS__) -	 * { -	 *     return parent::model($className); -	 * } -	 * </pre> -	 * -	 * @param string active record class name. -	 * @return CActiveRecord active record model instance. -	 */ -	public static function model($className=__CLASS__) -	{ -		if(isset(self::$_models[$className])) -			return self::$_models[$className]; -		else -		{ -			$model=self::$_models[$className]=new $className(null); -			$model->attachBehaviors($model->behaviors()); -			$model->_md=new TActiveRecordMetaData($model); -			return $model; -		} -	} - -	/** -	 * @return CActiveRecordMetaData the meta for this AR class. -	 */ -	public function getMetaData() -	{ -		if($this->_md!==null) -			return $this->_md; -		else -			return $this->_md=self::model(get_class($this))->_md; -	} - -	/** -	 * Returns the name of the associated database table. -	 * By default this method returns the class name as the table name. -	 * You may override this method if the table is not named after this convention. -	 * @return string the table name -	 */ -	public function tableName() -	{ -		return get_class($this); -	} - -	/** -	 * Returns the primary key of the associated database table. -	 * This method is meant to be overridden in case when the table is not defined with a primary key -	 * (for some legency database). If the table is already defined with a primary key, -	 * you do not need to override this method. The default implementation simply returns null, -	 * meaning using the primary key defined in the database. -	 * @return mixed the primary key of the associated database table. -	 * If the key is a single column, it should return the column name; -	 * If the key is a composite one consisting of several columns, it should -	 * return the array of the key column names. -	 * @since 1.0.4 -	 */ -	public function primaryKey() -	{ -	} - -	/** -	 * This method should be overridden to declare related objects. -	 * -	 * There are four types of relations that may exist between two active record objects: -	 * <ul> -	 * <li>BELONGS_TO: e.g. a member belongs to a team;</li> -	 * <li>HAS_ONE: e.g. a member has at most one profile;</li> -	 * <li>HAS_MANY: e.g. a team has many members;</li> -	 * <li>MANY_MANY: e.g. a member has many skills and a skill belongs to a member.</li> -	 * </ul> -	 * -	 * By declaring these relations, CActiveRecord can bring back related objects -	 * in either lazy loading or eager loading approach, and you save the effort of -	 * writing complex JOIN SQL statements. -	 * -	 * Each kind of related objects is defined in this method as an array with the following elements: -	 * <pre> -	 * 'varName'=>array('relationType', 'className', 'foreignKey', ...additional options) -	 * </pre> -	 * where 'varName' refers to the name of the variable/property that the related object(s) can -	 * be accessed through; 'relationType' refers to the type of the relation, which can be one of the -	 * following four constants: self::BELONGS_TO, self::HAS_ONE, self::HAS_MANY and self::MANY_MANY; -	 * 'className' refers to the name of the active record class that the related object(s) is of; -	 * and 'foreignKey' states the foreign key that relates the two kinds of active record. -	 * Note, for composite foreign keys, they must be listed together, separating with space or comma; -	 * and for foreign keys used in MANY_MANY relation, the joining table must be declared as well -	 * (e.g. 'joinTable(fk1, fk2)'). -	 * -	 * Additional options may be specified as name-value pairs in the rest array elements: -	 * <ul> -	 * <li>'select': string|array, a list of columns to be selected. Defaults to '*', meaning all columns. -	 *   Column names should be disambiguated if they appear in an expression (e.g. COUNT(??.name) AS name_count).</li> -	 * <li>'condition': string, the WHERE clause. Defaults to empty. Note, column references need to -	 *   be disambiguated with prefix '??.' (e.g. ??.age>20)</li> -	 * <li>'order': string, the ORDER BY clause. Defaults to empty. Note, column references need to -	 *   be disambiguated with prefix '??.' (e.g. ??.age DESC)</li> -	 * <li>'with': string|array, a list of child related objects that should be loaded together with this object. -	 *   Note, this is only honored by lazy loading, not eager loading.</li> -	 * <li>'joinType': type of join. Defaults to 'LEFT OUTER JOIN'.</li> -	 * <li>'alias': the alias for the table associated with this relationship. -	 *   This option has been available since version 1.0.1. It defaults to null, -	 *   meaning the table alias is the same as the relation name.</li> -     * <li>'params': the parameters to be bound to the generated SQL statement. -	 *   This should be given as an array of name-value pairs. This option has been -	 *   available since version 1.0.3.</li> -	 * <li>'on': the ON clause. The condition specified here will be appended -	 *   to the joining condition using the AND operator. This option has been -	 *   available since version 1.0.2.</li> -	 * </ul> -	 * -	 * The following options are available for certain relations when lazy loading: -	 * <ul> -	 * <li>'group': string, the GROUP BY clause. Defaults to empty. Note, column references need to -	 *   be disambiguated with prefix '??.' (e.g. ??.age). This option only applies to HAS_MANY and MANY_MANY relations.</li> -	 * <li>'having': string, the HAVING clause. Defaults to empty. Note, column references need to -	 *   be disambiguated with prefix '??.' (e.g. ??.age). This option only applies to HAS_MANY and MANY_MANY relations.</li> -	 * <li>'limit': limit of the rows to be selected. This option does not apply to BELONGS_TO relation.</li> -	 * <li>'offset': offset of the rows to be selected. This option does not apply to BELONGS_TO relation.</li> -	 * </ul> -	 * -	 * Below is an example declaring related objects for 'Post' active record class: -	 * <pre> -	 * return array( -	 *     'author'=>array(self::BELONGS_TO, 'User', 'authorID'), -	 *     'comments'=>array(self::HAS_MANY, 'Comment', 'postID', 'with'=>'author', 'order'=>'createTime DESC'), -	 *     'tags'=>array(self::MANY_MANY, 'Tag', 'PostTag(postID, tagID)', 'order'=>'name'), -	 * ); -	 * </pre> -	 * -	 * @return array list of related object declarations. Defaults to empty array. -	 */ -	public function relations() -	{ -		return array(); -	} -	 -	/** -	 * Returns the declaration of named scopes. -	 * A named scope represents a query criteria that can be chained together with -	 * other named scopes and applied to a query. This method should be overridden -	 * by child classes to declare named scopes for the particular AR classes. -	 * For example, the following code declares two named scopes: 'recently' and -	 * 'published'. -	 * <pre> -	 * return array( -	 *     'published'=>array( -	 *           'condition'=>'status=1', -	 *     ), -	 *     'recently'=>array( -	 *           'order'=>'createTime DESC', -	 *           'limit'=>5, -	 *     ), -	 * ); -	 * </pre> -	 * If the above scopes are declared in a 'Post' model, we can perform the following -	 * queries: -	 * <pre> -	 * $posts=Post::model()->published()->findAll(); -	 * $posts=Post::model()->published()->recently()->findAll(); -	 * $posts=Post::model()->published()->with('comments')->findAll(); -	 * </pre> -	 * Note that the last query is a relational query. -	 * -	 * @return array the scope definition. The array keys are scope names; the array -	 * values are the corresponding scope definitions. Each scope definition is represented -	 * as an array whose keys must be properties of {@link CDbCriteria}. -	 * @since 1.0.5 -	 */ -	public function scopes() -	{ -		return array(); -	} - -	/** -	 * Returns the list of all attribute names of the model. -	 * This would return all column names of the table associated with this AR class. -	 * @return array list of attribute names. -	 * @since 1.0.1 -	 */ -	public function attributeNames() -	{ -		return array_keys($this->getMetaData()->columns); -	} - -	/** -	 * Returns the database connection used by active record. -	 * By default, the "db" application component is used as the database connection. -	 * You may override this method if you want to use a different database connection. -	 * @return CDbConnection the database connection used by active record. -	 *  -	 * @TODO Get default db connection if theres none set -	 *  -	 */ -	public function getDbConnection() -	{ -		if(self::$db!==null) -			return self::$db; -		else -		{ -			self::$db=Prado::getApplication()->getModule($this->getConnectionId())->getDbConnection(); -			if(self::$db instanceof TDbConnection) -			{ -				self::$db->setActive(true); -				return self::$db; -			} -			else -				throw new TDbException('ActiveRecord requires a db connection.'); -		} -	} - -	/** -	 * Returns connection id (must be overloaded by child classes) -	 * @return string Id of TDbConnection module -	 */ -	abstract public function getConnectionId(); - -	/** -	 * @param string the relation name -	 * @return CActiveRelation the named relation declared for this AR class. Null if the relation does not exist. -	 */ -	public function getActiveRelation($name) -	{ -		return isset($this->getMetaData()->relations[$name]) ? $this->getMetaData()->relations[$name] : null; -	} - -	/** -	 * @return CDbTableSchema the metadata of the table that this AR belongs to -	 */ -	public function getTableSchema() -	{ -		return $this->getMetaData()->tableSchema; -	} - -	/** -	 * @return CDbCommandBuilder the command builder used by this AR -	 */ -	public function getCommandBuilder() -	{ -		return $this->getDbConnection()->getSchema()->getCommandBuilder(); -	} - -	/** -	 * @param string attribute name -	 * @return boolean whether this AR has the named attribute (table column). -	 */ -	public function hasAttribute($name) -	{ -		return isset($this->getMetaData()->columns[$name]); -	} - -	/** -	 * Returns the named attribute value. -	 * If this is a new record and the attribute is not set before, -	 * the default column value will be returned. -	 * If this record is the result of a query and the attribute is not loaded, -	 * null will be returned. -	 * You may also use $this->AttributeName to obtain the attribute value. -	 * @param string the attribute name -	 * @return mixed the attribute value. Null if the attribute is not set or does not exist. -	 * @see hasAttribute -	 */ -	public function getAttribute($name) -	{ -		if(property_exists($this,$name)) -			return $this->$name; -		else if(isset($this->_attributes[$name])) -			return $this->_attributes[$name]; -	} - -	/** -	 * Sets the named attribute value. -	 * You may also use $this->AttributeName to set the attribute value. -	 * @param string the attribute name -	 * @param mixed the attribute value. -	 * @return boolean whether the attribute exists and the assignment is conducted successfully -	 * @see hasAttribute -	 */ -	public function setAttribute($name,$value) -	{ -		if(property_exists($this,$name)) -			$this->$name=$value; -		else if(isset($this->getMetaData()->columns[$name])) -			$this->_attributes[$name]=$value; -		else -			return false; -		return true; -	} - -	/** -	 * Adds a related object to this record. -	 * This method is used internally by {@link CActiveFinder} to populate related objects. -	 * @param string attribute name -	 * @param mixed the related record -	 * @param boolean whether the relation is HAS_MANY/MANY_MANY. -	 */ -	public function addRelatedRecord($name,$record,$multiple) -	{ -		if($multiple) -		{ -			if(!isset($this->_related[$name])) -				$this->_related[$name]=array(); -			if($record instanceof TActiveRecord) -				$this->_related[$name][]=$record; -		} -		else if(!isset($this->_related[$name])) -			$this->_related[$name]=$record; -	} - -	/** -	 * Returns all column attribute values. -	 * Note, related objects are not returned. -	 * @param mixed names of attributes whose value needs to be returned. -	 * If this is true (default), then all attribute values will be returned, including -	 * those that are not loaded from DB (null will be returned for those attributes). -	 * If this is null, all attributes except those that are not loaded from DB will be returned. -	 * @return array attribute values indexed by attribute names. -	 */ -	public function getAttributes($names=true) -	{ -		$attributes=$this->_attributes; -		foreach($this->getMetaData()->columns as $name=>$column) -		{ -			if(property_exists($this,$name)) -				$attributes[$name]=$this->$name; -			else if($names===true && !isset($attributes[$name])) -				$attributes[$name]=null; -		} -		if(is_array($names)) -		{ -			$attrs=array(); -			foreach($names as $name) -				$attrs[$name]=isset($attributes[$name])?$attributes[$name]:null; -			return $attrs; -		} -		else -			return $attributes; -	} - -	/** -	 * Saves the current record. -	 * -	 * The record is inserted as a row into the database table if its {@link isNewRecord} -	 * property is true (usually the case when the record is created using the 'new' -	 * operator). Otherwise, it will be used to update the corresponding row in the table -	 * (usually the case if the record is obtained using one of those 'find' methods.) -	 * -	 * Validation will be performed before saving the record. If the validation fails, -	 * the record will not be saved. You can call {@link getErrors()} to retrieve the -	 * validation errors. -	 * -	 * If the record is saved via insertion, its {@link isNewRecord} property will be -	 * set false, and its {@link scenario} property will be set to be 'update'. -	 * And if its primary key is auto-incremental and is not set before insertion, -	 * the primary key will be populated with the automatically generated key value. -	 * -	 * @param boolean whether to perform validation before saving the record. -	 * If the validation fails, the record will not be saved to database. -	 * @param array list of attributes that need to be saved. Defaults to null, -	 * meaning all attributes that are loaded from DB will be saved. -	 * @return boolean whether the saving succeeds -	 */ -	public function save($runValidation=true,$attributes=null) -	{ -		if(!$runValidation || $this->validate($attributes)) -			return $this->getIsNewRecord() ? $this->insert($attributes) : $this->update($attributes); -		else -			return false; -	} - -	/** -	 * @return boolean whether the record is new and should be inserted when calling {@link save}. -	 * This property is automatically set in constructor and {@link populateRecord}. -	 * Defaults to false, but it will be set to true if the instance is created using -	 * the new operator. -	 */ -	public function getIsNewRecord() -	{ -		return $this->_new; -	} - -	/** -	 * @param boolean whether the record is new and should be inserted when calling {@link save}. -	 * @see getIsNewRecord -	 */ -	public function setIsNewRecord($value) -	{ -		$this->_new=$value; -	} - -	/** -	 * This event is raised before the record is saved. -	 * @param CEvent the event parameter -	 * @since 1.0.2 -	 */ -	public function onBeforeSave($event) -	{ -		$this->raiseEvent('onBeforeSave',$event); -	} - -	/** -	 * This event is raised after the record is saved. -	 * @param CEvent the event parameter -	 * @since 1.0.2 -	 */ -	public function onAfterSave($event) -	{ -		$this->raiseEvent('onAfterSave',$event); -	} - -	/** -	 * This event is raised before the record is deleted. -	 * @param CEvent the event parameter -	 * @since 1.0.2 -	 */ -	public function onBeforeDelete($event) -	{ -		$this->raiseEvent('onBeforeDelete',$event); -	} - -	/** -	 * This event is raised after the record is deleted. -	 * @param CEvent the event parameter -	 * @since 1.0.2 -	 */ -	public function onAfterDelete($event) -	{ -		$this->raiseEvent('onAfterDelete',$event); -	} - -	/** -	 * This event is raised after the record instance is created by new operator. -	 * @param CEvent the event parameter -	 * @since 1.0.2 -	 */ -	public function onAfterConstruct($event) -	{ -		$this->raiseEvent('onAfterConstruct',$event); -	} - -	/** -	 * This event is raised after the record is instantiated by a find method. -	 * @param CEvent the event parameter -	 * @since 1.0.2 -	 */ -	public function onAfterFind($event) -	{ -		$this->raiseEvent('onAfterFind',$event); -	} - -	/** -	 * This method is invoked before saving a record (after validation, if any). -	 * The default implementation raises the {@link onBeforeSave} event. -	 * You may override this method to do any preparation work for record saving. -	 * Use {@link isNewRecord} to determine whether the saving is -	 * for inserting or updating record. -	 * Make sure you call the parent implementation so that the event is raised properly. -	 * @return boolean whether the saving should be executed. Defaults to true. -	 */ -	protected function beforeSave() -	{ -		$this->onBeforeSave(new TEvent($this)); -		return true; -	} - -	/** -	 * This method is invoked after saving a record. -	 * The default implementation raises the {@link onAfterSave} event. -	 * You may override this method to do postprocessing after record saving. -	 * Make sure you call the parent implementation so that the event is raised properly. -	 */ -	protected function afterSave() -	{ -		$this->onAfterSave(new TEvent($this)); -	} - -	/** -	 * This method is invoked before deleting a record. -	 * The default implementation raises the {@link onBeforeDelete} event. -	 * You may override this method to do any preparation work for record deletion. -	 * Make sure you call the parent implementation so that the event is raised properly. -	 * @return boolean whether the record should be deleted. Defaults to true. -	 */ -	protected function beforeDelete() -	{ -		$this->onBeforeDelete(new TEvent($this)); -		return true; -	} - -	/** -	 * This method is invoked after deleting a record. -	 * The default implementation raises the {@link onAfterDelete} event. -	 * You may override this method to do postprocessing after the record is deleted. -	 * Make sure you call the parent implementation so that the event is raised properly. -	 */ -	protected function afterDelete() -	{ -		$this->onAfterDelete(new TEvent($this)); -	} - -	/** -	 * This method is invoked after a record instance is created by new operator. -	 * The default implementation raises the {@link onAfterConstruct} event. -	 * You may override this method to do postprocessing after record creation. -	 * Make sure you call the parent implementation so that the event is raised properly. -	 */ -	protected function afterConstruct() -	{ -		$this->onAfterConstruct(new TEvent($this)); -	} - -	/** -	 * This method is invoked after each record is instantiated by a find method. -	 * The default implementation raises the {@link onAfterFind} event. -	 * You may override this method to do postprocessing after each newly found record is instantiated. -	 * Make sure you call the parent implementation so that the event is raised properly. -	 */ -	protected function afterFind() -	{ -		$this->onAfterFind(new TEvent($this)); -	} - -	/** -	 * Calls {@link afterFind}. -	 * This method is internally used. -	 * @since 1.0.3 -	 */ -	public function afterFindInternal() -	{ -		$this->afterFind(); -	} - -	/** -	 * Inserts a row into the table based on this active record attributes. -	 * If the table's primary key is auto-incremental and is null before insertion, -	 * it will be populated with the actual value after insertion. -	 * Note, validation is not performed in this method. You may call {@link validate} to perform the validation. -	 * After the record is inserted to DB successfully, its {@link isNewRecord} property will be set false, -	 * and its {@link scenario} property will be set to be 'update'. -	 * @param array list of attributes that need to be saved. Defaults to null, -	 * meaning all attributes that are loaded from DB will be saved. -	 * @return boolean whether the attributes are valid and the record is inserted successfully. -	 * @throws CException if the record is not new -	 */ -	public function insert($attributes=null) -	{ -		if(!$this->getIsNewRecord()) -			throw new TDbException('The active record cannot be inserted to database because it is not new.'); -		if($this->beforeSave()) -		{ -			Prado::trace(get_class($this).'.insert()','System.Testing.Data.ActiveRecord.TActiveRecord'); -			$builder=$this->getCommandBuilder(); -			$table=$this->getMetaData()->tableSchema; -			$command=$builder->createInsertCommand($table,$this->getAttributes($attributes)); -			if($command->execute()) -			{ -				$primaryKey=$table->primaryKey; -				if($table->sequenceName!==null) -				{ -					if(is_string($primaryKey) && $this->$primaryKey===null) -						$this->$primaryKey=$builder->getLastInsertID($table); -					else if(is_array($primaryKey)) -					{ -						foreach($primaryKey as $pk) -						{ -							if($this->$pk===null) -							{ -								$this->$pk=$builder->getLastInsertID($table); -								break; -							} -						} -					} -				} -				$this->afterSave(); -				$this->setIsNewRecord(false); -				$this->setScenario('update'); -				return true; -			} -			else -				$this->afterSave(); -		} -		else -			return false; -	} - -	/** -	 * Updates the row represented by this active record. -	 * All loaded attributes will be saved to the database. -	 * Note, validation is not performed in this method. You may call {@link validate} to perform the validation. -	 * @param array list of attributes that need to be saved. Defaults to null, -	 * meaning all attributes that are loaded from DB will be saved. -	 * @return boolean whether the update is successful -	 * @throws CException if the record is new -	 */ -	public function update($attributes=null) -	{ -		if($this->getIsNewRecord()) -			throw new TDbException('The active record cannot be updated because it is new.'); -		if($this->beforeSave()) -		{ -			Prado::trace(get_class($this).'.update()','System.Testing.Data.ActiveRecord.TActiveRecord'); -			$this->updateByPk($this->getPrimaryKey(),$this->getAttributes($attributes)); -			$this->afterSave(); -			return true; -		} -		else -			return false; -	} - -	/** -	 * Saves a selected list of attributes. -	 * Unlike {@link save}, this method only saves the specified attributes -	 * of an existing row dataset. It thus has better performance. -	 * Note, this method does neither attribute filtering nor validation. -	 * So do not use this method with untrusted data (such as user posted data). -	 * You may consider the following alternative if you want to do so: -	 * <pre> -	 * $postRecord=Post::model()->findByPk($postID); -	 * $postRecord->attributes=$_POST['post']; -	 * $postRecord->save(); -	 * </pre> -	 * @param array attributes to be updated. Each element represents an attribute name -	 * or an attribute value indexed by its name. If the latter, the record's -	 * attribute will be changed accordingly before saving. -	 * @return boolean whether the update is successful -	 * @throws CException if the record is new or any database error -	 */ -	public function saveAttributes($attributes) -	{ -		if(!$this->getIsNewRecord()) -		{ -			Prado::trace(get_class($this).'.saveAttributes()','System.Testing.Data.ActiveRecord.TActiveRecord'); -			$values=array(); -			foreach($attributes as $name=>$value) -			{ -				if(is_integer($name)) -					$values[$value]=$this->$value; -				else -					$values[$name]=$this->$name=$value; -			} -			return $this->updateByPk($this->getPrimaryKey(),$values)>0; -		} -		else -			throw new TDbException('The active record cannot be updated because it is new.'); -	} - -	/** -	 * Deletes the row corresponding to this active record. -	 * @return boolean whether the deletion is successful. -	 * @throws CException if the record is new -	 */ -	public function delete() -	{ -		if(!$this->getIsNewRecord()) -		{ -			Prado::trace(get_class($this).'.delete()','System.Testing.Data.ActiveRecord.TActiveRecord'); -			if($this->beforeDelete()) -			{ -				$result=$this->deleteByPk($this->getPrimaryKey())>0; -				$this->afterDelete(); -				return $result; -			} -			else -				return false; -		} -		else -			throw new TDbException('The active record cannot be deleted because it is new.'); -	} - -	/** -	 * Repopulates this active record with the latest data. -	 * @return boolean whether the row still exists in the database. If true, the latest data will be populated to this active record. -	 */ -	public function refresh() -	{ -		Prado::trace(get_class($this).'.refresh()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		if(!$this->getIsNewRecord() && ($record=$this->findByPk($this->getPrimaryKey()))!==null) -		{ -			$this->_attributes=array(); -			$this->_related=array(); -			foreach($this->getMetaData()->columns as $name=>$column) -				$this->$name=$record->$name; -			return true; -		} -		else -			return false; -	} - -	/** -	 * Compares this active record with another one. -	 * The comparison is made by comparing the primary key values of the two active records. -	 * @return boolean whether the two active records refer to the same row in the database table. -	 */ -	public function equals($record) -	{ -		return $this->tableName()===$record->tableName() && $this->getPrimaryKey()===$record->getPrimaryKey(); -	} - -	/** -	 * @return mixed the primary key value. An array (column name=>column value) is returned if the primary key is composite. -	 * If primary key is not defined, null will be returned. -	 */ -	public function getPrimaryKey() -	{ -		$table=$this->getMetaData()->tableSchema; -		if(is_string($table->primaryKey)) -			return $this->{$table->primaryKey}; -		else if(is_array($table->primaryKey)) -		{ -			$values=array(); -			foreach($table->primaryKey as $name) -				$values[$name]=$this->$name; -			return $values; -		} -		else -			return null; -	} - -	private function query($criteria,$all=false) -	{ -		$this->applyScopes($criteria); -		$command=$this->getCommandBuilder()->createFindCommand($this->getTableSchema(),$criteria); -		return $all ? $this->populateRecords($command->queryAll()) : $this->populateRecord($command->queryRow()); -	} - -	private function applyScopes(&$criteria) -	{ -		if(($c=$this->getDbCriteria(false))!==null) -		{ -			$c->mergeWith($criteria); -			$criteria=$c; -			$this->_c=null; -		} -	} - -	/** -	 * Finds a single active record with the specified condition. -	 * @param mixed query condition or criteria. -	 * If a string, it is treated as query condition (the WHERE clause); -	 * If an array, it is treated as the initial values for constructing a {@link CDbCriteria} object; -	 * Otherwise, it should be an instance of {@link CDbCriteria}. -	 * @param array parameters to be bound to an SQL statement. -	 * This is only used when the first parameter is a string (query condition). -	 * In other cases, please use {@link CDbCriteria::params} to set parameters. -	 * @return CActiveRecord the record found. Null if no record is found. -	 */ -	public function find($condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.find()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->getCommandBuilder()->createCriteria($condition,$params); -		$criteria->limit=1; -		return $this->query($criteria); -	} - -	/** -	 * Finds all active records satisfying the specified condition. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return array list of active records satisfying the specified condition. An empty array is returned if none is found. -	 */ -	public function findAll($condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.findAll()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->getCommandBuilder()->createCriteria($condition,$params); -		return $this->query($criteria,true); -	} - -	/** -	 * Finds a single active record with the specified primary key. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * @param mixed primary key value(s). Use array for multiple primary keys. For composite key, each key value must be an array (column name=>column value). -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return CActiveRecord the record found. Null if none is found. -	 */ -	public function findByPk($pk,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.findByPk()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->getCommandBuilder()->createPkCriteria($this->getTableSchema(),$pk,$condition,$params); -		$criteria->limit=1; -		return $this->query($criteria); -	} - -	/** -	 * Finds all active records with the specified primary keys. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * @param mixed primary key value(s). Use array for multiple primary keys. For composite key, each key value must be an array (column name=>column value). -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return array the records found. An empty array is returned if none is found. -	 */ -	public function findAllByPk($pk,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.findAllByPk()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->getCommandBuilder()->createPkCriteria($this->getTableSchema(),$pk,$condition,$params); -		return $this->query($criteria,true); -	} - -	/** -	 * Finds a single active record that has the specified attribute values. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * @param array list of attribute values (indexed by attribute names) that the active records should match. -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return CActiveRecord the record found. Null if none is found. -	 */ -	public function findByAttributes($attributes,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.findByAttributes()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->getCommandBuilder()->createColumnCriteria($this->getTableSchema(),$attributes,$condition,$params); -		$criteria->limit=1; -		return $this->query($criteria); -	} - -	/** -	 * Finds all active records that have the specified attribute values. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * @param array list of attribute values (indexed by attribute names) that the active records should match. -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return array the records found. An empty array is returned if none is found. -	 */ -	public function findAllByAttributes($attributes,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.findAllByAttributes()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$criteria=$this->getCommandBuilder()->createColumnCriteria($this->getTableSchema(),$attributes,$condition,$params); -		return $this->query($criteria,true); -	} - -	/** -	 * Finds a single active record with the specified SQL statement. -	 * @param string the SQL statement -	 * @param array parameters to be bound to the SQL statement -	 * @return CActiveRecord the record found. Null if none is found. -	 */ -	public function findBySql($sql,$params=array()) -	{ -		Prado::trace(get_class($this).'.findBySql()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$command=$this->getCommandBuilder()->createSqlCommand($sql,$params); -		return $this->populateRecord($command->queryRow()); -	} - -	/** -	 * Finds all active records using the specified SQL statement. -	 * @param string the SQL statement -	 * @param array parameters to be bound to the SQL statement -	 * @return array the records found. An empty array is returned if none is found. -	 */ -	public function findAllBySql($sql,$params=array()) -	{ -		Prado::trace(get_class($this).'.findAllBySql()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$command=$this->getCommandBuilder()->createSqlCommand($sql,$params); -		return $this->populateRecords($command->queryAll()); -	} - -	/** -	 * Finds the number of rows satisfying the specified query condition. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return integer the number of rows satisfying the specified query condition. -	 */ -	public function count($condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.count()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$builder=$this->getCommandBuilder(); -		$criteria=$builder->createCriteria($condition,$params); -		$this->applyScopes($criteria); -		return $builder->createCountCommand($this->getTableSchema(),$criteria)->queryScalar(); -	} - -	/** -	 * Finds the number of rows using the given SQL statement. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * @param string the SQL statement -	 * @param array parameters to be bound to the SQL statement -	 * @return integer the number of rows using the given SQL statement. -	 */ -	public function countBySql($sql,$params=array()) -	{ -		Prado::trace(get_class($this).'.countBySql()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		return $this->getCommandBuilder()->createSqlCommand($sql,$params)->queryScalar(); -	} - -	/** -	 * Checks whether there is row satisfying the specified condition. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return boolean whether there is row satisfying the specified condition. -	 */ -	public function exists($condition,$params=array()) -	{ -		Prado::trace(get_class($this).'.exists()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$builder=$this->getCommandBuilder(); -		$criteria=$builder->createCriteria($condition,$params); -		$table=$this->getTableSchema(); -		$criteria->select=reset($table->columns)->rawName; -		$criteria->limit=1; -		$this->applyScopes($criteria); -		return $builder->createFindCommand($table,$criteria)->queryRow()!==false; -	} - -	/** -	 * Specifies which related objects should be eagerly loaded. -	 * This method takes variable number of parameters. Each parameter specifies -	 * the name of a relation or child-relation. For example, -	 * <pre> -	 * // find all posts together with their author and comments -	 * Post::model()->with('author','comments')->findAll(); -	 * // find all posts together with their author and the author's profile -	 * Post::model()->with('author','author.profile')->findAll(); -	 * </pre> -	 * The relations should be declared in {@link relations()}. -	 * -	 * By default, the options specified in {@link relations()} will be used -	 * to do relational query. In order to customize the options on the fly, -	 * we should pass an array parameter to the with() method. The array keys -	 * are relation names, and the array values are the corresponding query options. -	 * For example, -	 * <pre> -	 * Post::model()->with(array( -	 *     'author'=>array('select'=>'id, name'), -	 *     'comments'=>array('condition'=>'approved=1', 'order'=>'createTime'), -	 * ))->findAll(); -	 * </pre> -	 * -	 * This method returns a {@link CActiveFinder} instance that provides -	 * a set of find methods similar to that of CActiveRecord. -	 * -	 * Note, the possible parameters to this method have been changed since version 1.0.2. -	 * Previously, it was not possible to specify on-th-fly query options, -	 * and child-relations were specified as hierarchical arrays. -	 * -	 * @return CActiveFinder the active finder instance. If no parameter is passed in, the object itself will be returned. -	 */ -	public function with() -	{ -		if(func_num_args()>0) -		{ -			$with=func_get_args(); -			if(is_array($with[0]))  // the parameter is given as an array -				$with=$with[0]; -			$finder=new TActiveFinder($this,$with,$this->getDbCriteria(false)); -			$this->_c=null; -			return $finder; -		} -		else -			return $this; -	} - -	/** -	 * Updates records with the specified primary key(s). -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * Note, the attributes are not checked for safety and validation is NOT performed. -	 * @param mixed primary key value(s). Use array for multiple primary keys. For composite key, each key value must be an array (column name=>column value). -	 * @param array list of attributes (name=>$value) to be updated -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return integer the number of rows being updated -	 */ -	public function updateByPk($pk,$attributes,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.updateByPk()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$builder=$this->getCommandBuilder(); -		$table=$this->getTableSchema(); -		$criteria=$builder->createPkCriteria($table,$pk,$condition,$params); -		$this->applyScopes($criteria); -		$command=$builder->createUpdateCommand($table,$attributes,$criteria); -		return $command->execute(); -	} - -	/** -	 * Updates records with the specified condition. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * Note, the attributes are not checked for safety and no validation is done. -	 * @param array list of attributes (name=>$value) to be updated -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return integer the number of rows being updated -	 */ -	public function updateAll($attributes,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.updateAll()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$builder=$this->getCommandBuilder(); -		$criteria=$builder->createCriteria($condition,$params); -		$this->applyScopes($criteria); -		$command=$builder->createUpdateCommand($this->getTableSchema(),$attributes,$criteria); -		return $command->execute(); -	} - -	/** -	 * Updates one or several counter columns. -	 * Note, this updates all rows of data unless a condition or criteria is specified. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * @param array the counters to be updated (column name=>increment value) -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return integer the number of rows being updated -	 */ -	public function updateCounters($counters,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.updateCounters()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$builder=$this->getCommandBuilder(); -		$criteria=$builder->createCriteria($condition,$params); -		$this->applyScopes($criteria); -		$command=$builder->createUpdateCounterCommand($this->getTableSchema(),$counters,$criteria); -		return $command->execute(); -	} - -	/** -	 * Deletes rows with the specified primary key. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * @param mixed primary key value(s). Use array for multiple primary keys. For composite key, each key value must be an array (column name=>column value). -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return integer the number of rows deleted -	 */ -	public function deleteByPk($pk,$condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.deleteByPk()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$builder=$this->getCommandBuilder(); -		$criteria=$builder->createPkCriteria($this->getTableSchema(),$pk,$condition,$params); -		$this->applyScopes($criteria); -		$command=$builder->createDeleteCommand($this->getTableSchema(),$criteria); -		return $command->execute(); -	} - -	/** -	 * Deletes rows with the specified condition. -	 * See {@link find()} for detailed explanation about $condition and $params. -	 * @param mixed query condition or criteria. -	 * @param array parameters to be bound to an SQL statement. -	 * @return integer the number of rows deleted -	 */ -	public function deleteAll($condition='',$params=array()) -	{ -		Prado::trace(get_class($this).'.deleteAll()','System.Testing.Data.ActiveRecord.TActiveRecord'); -		$builder=$this->getCommandBuilder(); -		$criteria=$builder->createCriteria($condition,$params); -		$this->applyScopes($criteria); -		$command=$builder->createDeleteCommand($this->getTableSchema(),$criteria); -		return $command->execute(); -	} - -	/** -	 * Creates an active record with the given attributes. -	 * This method is internally used by the find methods. -	 * @param array attribute values (column name=>column value) -	 * @param boolean whether to call {@link afterFind} after the record is populated. -	 * This parameter is added in version 1.0.3. -	 * @return CActiveRecord the newly created active record. The class of the object is the same as the model class. -	 * Null is returned if the input data is false. -	 */ -	public function populateRecord($attributes,$callAfterFind=true) -	{ -		if($attributes!==false) -		{ -			$record=$this->instantiate($attributes); -			$record->_md=$this->getMetaData(); -			foreach($attributes as $name=>$value) -			{ -				if(property_exists($record,$name)) -					$record->$name=$value; -				else if(isset($record->_md->columns[$name])) -					$record->_attributes[$name]=$value; -			} -			$record->attachBehaviors($record->behaviors()); -			if($callAfterFind) -				$record->afterFind(); -			return $record; -		} -		else -			return null; -	} - -	/** -	 * Creates a list of active records based on the input data. -	 * This method is internally used by the find methods. -	 * @param array list of attribute values for the active records. -	 * @param boolean whether to call {@link afterFind} after each record is populated. -	 * This parameter is added in version 1.0.3. -	 * @return array list of active records. -	 */ -	public function populateRecords($data,$callAfterFind=true) -	{ -		$records=array(); -		$md=$this->getMetaData(); -		$table=$md->tableSchema; -		foreach($data as $attributes) -		{ -			$record=$this->instantiate($attributes); -			$record->_md=$md; -			foreach($attributes as $name=>$value) -			{ -				if(property_exists($record,$name)) -					$record->$name=$value; -				else if(isset($record->_md->columns[$name])) -					$record->_attributes[$name]=$value; -			} -			$record->attachBehaviors($record->behaviors()); -			if($callAfterFind) -				$record->afterFind(); -			$records[]=$record; -		} -		return $records; -	} - -	/** -	 * Creates an active record instance. -	 * This method is called by {@link populateRecord} and {@link populateRecords}. -	 * You may override this method if the instance being created -	 * depends the attributes that are to be populated to the record. -	 * For example, by creating a record based on the value of a column, -	 * you may implement the so-called single-table inheritance mapping. -	 * @param array list of attribute values for the active records. -	 * @return CActiveRecord the active record -	 * @since 1.0.2 -	 */ -	protected function instantiate($attributes) -	{ -		$class=get_class($this); -		$model=new $class(null); -		$model->setScenario('update'); -		return $model; -	} - -	/** -	 * Returns whether there is an element at the specified offset. -	 * This method is required by the interface ArrayAccess. -	 * @param mixed the offset to check on -	 * @return boolean -	 * @since 1.0.2 -	 */ -	public function offsetExists($offset) -	{ -		return isset($this->getMetaData()->columns[$offset]); -	} -} - - -/** - * CBaseActiveRelation is the base class for all active relations. - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveRecord.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0.4 - */ -class TBaseActiveRelation extends TComponent -{ -	/** -	 * @var string name of the related object -	 */ -	public $name; -	/** -	 * @var string name of the related active record class -	 */ -	public $className; -	/** -	 * @var string the foreign key in this relation -	 */ -	public $foreignKey; -	/** -	 * @var mixed list of column names (an array, or a string of names separated by commas) to be selected. -	 * Do not quote or prefix the column names unless they are used in an expression. -	 * In that case, you should prefix the column names with '??.'. -	 */ -	public $select='*'; -	/** -	 * @var string WHERE clause. For {@link CActiveRelation} descendant classes, column names -	 * referenced in the condition should be disambiguated with prefix '??.'. -	 */ -	public $condition=''; -	/** -	 * @var array the parameters that are to be bound to the condition. -	 * The keys are parameter placeholder names, and the values are parameter values. -	 */ -	public $params=array(); -	/** -	 * @var string GROUP BY clause. For {@link CActiveRelation} descendant classes, column names -	 * referenced in this property should be disambiguated with prefix '??.'. -	 */ -	public $group=''; -	/** -	 * @var string HAVING clause. For {@link CActiveRelation} descendant classes, column names -	 * referenced in this property should be disambiguated with prefix '??.'. -	 */ -	public $having=''; -	/** -	 * @var string ORDER BY clause. For {@link CActiveRelation} descendant classes, column names -	 * referenced in this property should be disambiguated with prefix '??.'. -	 */ -	public $order=''; - -	/** -	 * Constructor. -	 * @param string name of the relation -	 * @param string name of the related active record class -	 * @param string foreign key for this relation -	 * @param array additional options (name=>value). The keys must be the property names of this class. -	 */ -	public function __construct($name,$className,$foreignKey,$options=array()) -	{ -		$this->name=$name; -		$this->className=$className; -		$this->foreignKey=$foreignKey; -		foreach($options as $name=>$value) -			$this->$name=$value; -	} - -	/** -	 * Merges this relation with a criteria specified dynamically. -	 * @param array the dynamically specified criteria -	 * @since 1.0.5 -	 */ -	public function mergeWith($criteria) -	{ -		if(isset($criteria['select']) && $this->select!==$criteria['select']) -		{ -			if($this->select==='*') -				$this->select=$criteria['select']; -			else if($criteria['select']!=='*') -			{ -				$select1=is_string($this->select)?preg_split('/\s*,\s*/',trim($this->select),-1,PREG_SPLIT_NO_EMPTY):$this->select; -				$select2=is_string($criteria['select'])?preg_split('/\s*,\s*/',trim($criteria['select']),-1,PREG_SPLIT_NO_EMPTY):$criteria['select']; -				$this->select=array_merge($select1,array_diff($select2,$select1)); -			} -		} - -		if(isset($criteria['condition']) && $this->condition!==$criteria['condition']) -		{ -			if($this->condition==='') -				$this->condition=$criteria['condition']; -			else if($criteria['condition']!=='') -				$this->condition="({$this->condition}) AND ({$criteria['condition']})"; -		} - -		if(isset($criteria['params']) && $this->params!==$criteria['params']) -			$this->params=array_merge($this->params,$criteria['params']); - -		if(isset($criteria['order']) && $this->order!==$criteria['order']) -		{ -			if($this->order==='') -				$this->order=$criteria['order']; -			else if($criteria['order']!=='') -				$this->order.=', '.$criteria['order']; -		} - -		if(isset($criteria['group']) && $this->group!==$criteria['group']) -		{ -			if($this->group==='') -				$this->group=$criteria['group']; -			else if($criteria['group']!=='') -				$this->group.=', '.$criteria['group']; -		} - -		if(isset($criteria['having']) && $this->having!==$criteria['having']) -		{ -			if($this->having==='') -				$this->having=$criteria['having']; -			else if($criteria['having']!=='') -				$this->having="({$this->having}) AND ({$criteria['having']})"; -		} -	} -} - - -/** - * CStatRelation represents a statistical relational query. - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveRecord.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0.4 - */ -class TStatRelation extends TBaseActiveRelation -{ -	/** -	 * @var string the statistical expression. Defaults to 'COUNT(*)', meaning -	 * the count of child objects. -	 */ -	public $select='COUNT(*)'; -	/** -	 * @var mixed the default value to be assigned to those records that do not -	 * receive a statistical query result. Defaults to 0. -	 */ -	public $defaultValue=0; - -	/** -	 * Merges this relation with a criteria specified dynamically. -	 * @param array the dynamically specified criteria -	 * @since 1.0.5 -	 */ -	public function mergeWith($criteria) -	{ -		parent::mergeWith($criteria); - -		if(isset($criteria['defaultValue'])) -			$this->defaultValue=$criteria['defaultValue']; -	} -} - - -/** - * CActiveRelation is the base class for representing active relations that bring back related objects. - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveRecord.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0 - */ -class TActiveRelation extends TBaseActiveRelation -{ -	/** -	 * @var string join type. Defaults to 'LEFT OUTER JOIN'. -	 */ -	public $joinType='LEFT OUTER JOIN'; -	/** -	 * @var string ON clause. The condition specified here will be appended to the joining condition using AND operator. -	 * @since 1.0.2 -	 */ -	public $on=''; -	/** -	 * @var string the alias for the table that this relation refers to. Defaults to null, meaning -	 * the alias will be the same as the relation name. -	 * @since 1.0.1 -	 */ -	public $alias; -	/** -	 * @var string|array specifies which related objects should be eagerly loaded when this related object is lazily loaded. -	 * For more details about this property, see {@link CActiveRecord::with()}. -	 */ -	public $with=array(); - -	/** -	 * Merges this relation with a criteria specified dynamically. -	 * @param array the dynamically specified criteria -	 * @since 1.0.5 -	 */ -	public function mergeWith($criteria) -	{ -		if(isset($criteria['condition']) && $this->on!==$criteria['condition']) -		{ -			if($this->on==='') -				$this->on=$criteria['condition']; -			else if($criteria['condition']!=='') -				$this->on="({$this->on}) AND ({$criteria['condition']})"; -		} -		unset($criteria['condition']); - -		parent::mergeWith($criteria); - -		if(isset($criteria['joinType'])) -			$this->joinType=$criteria['joinType']; - -		if(isset($criteria['on']) && $this->on!==$criteria['on']) -		{ -			if($this->on==='') -				$this->on=$criteria['on']; -			else if($criteria['on']!=='') -				$this->on="({$this->on}) AND ({$criteria['on']})"; -		} - -		if(isset($criteria['with'])) -			$this->with=$criteria['with']; - -		if(isset($criteria['alias'])) -			$this->alias=$criteria['alias']; - -		if(isset($criteria['together'])) -			$this->together=$criteria['together']; -	} -} - - -/** - * CBelongsToRelation represents the parameters specifying a BELONGS_TO relation. - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveRecord.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0 - */ -class TBelongsToRelation extends TActiveRelation -{ -} - - -/** - * CHasOneRelation represents the parameters specifying a HAS_ONE relation. - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveRecord.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0 - */ -class THasOneRelation extends TActiveRelation -{ -} - - -/** - * CHasManyRelation represents the parameters specifying a HAS_MANY relation. - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveRecord.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0 - */ -class THasManyRelation extends TActiveRelation -{ -	/** -	 * @var integer limit of the rows to be selected. It is effective only for lazy loading this related object. Defaults to -1, meaning no limit. -	 */ -	public $limit=-1; -	/** -	 * @var integer offset of the rows to be selected. It is effective only for lazy loading this related object. Defaults to -1, meaning no offset. -	 */ -	public $offset=-1; -	/** -	 * @var boolean whether this table should be joined with the primary table. -	 * When setting this property to be false, the table associated with this relation will -	 * appear in a separate JOIN statement. Defaults to true, meaning the table will be joined -	 * together with the primary table. Note that in version 1.0.x, the default value of this property was false. -	 */ -	public $together=true; - -	/** -	 * Merges this relation with a criteria specified dynamically. -	 * @param array the dynamically specified criteria -	 * @since 1.0.5 -	 */ -	public function mergeWith($criteria) -	{ -		parent::mergeWith($criteria); -		if(isset($criteria['limit']) && $criteria['limit']>0) -			$this->limit=$criteria['limit']; - -		if(isset($criteria['offset']) && $criteria['offset']>=0) -			$this->offset=$criteria['offset']; -	} -} - - -/** - * CManyManyRelation represents the parameters specifying a MANY_MANY relation. - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveRecord.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0 - */ -class TManyManyRelation extends THasManyRelation -{ -} - - -/** - * CActiveRecordMetaData represents the meta-data for an Active Record class. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveRecord.php 1127 2009-06-13 20:26:35Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0 - */ -class TActiveRecordMetaData -{ -	/** -	 * @var CDbTableSchema the table schema information -	 */ -	public $tableSchema; -	/** -	 * @var array table columns -	 */ -	public $columns; -	/** -	 * @var array list of relations -	 */ -	public $relations=array(); -	/** -	 * @var array attribute default values -	 */ -	public $attributeDefaults=array(); - -	private $_model; - -	/** -	 * Constructor. -	 * @param CActiveRecord the model instance -	 */ -	public function __construct($model) -	{ -		$this->_model=$model; - -		$tableName=$model->tableName(); -		if(($table=$model->getDbConnection()->getSchema()->getTable($tableName))===null) -			throw new TDbException('The table "'.$tableName.'" for active record class "'.get_class($model).'" cannot be found in the database.'); -			 -		if($table->primaryKey===null) -			$table->primaryKey=$model->primaryKey(); -		$this->tableSchema=$table; -		$this->columns=$table->columns; - -		foreach($table->columns as $name=>$column) -		{ -			if(!$column->isPrimaryKey && $column->defaultValue!==null) -				$this->attributeDefaults[$name]=$column->defaultValue; -		} - -		foreach($model->relations() as $name=>$config) -		{ -			if(isset($config[0],$config[1],$config[2]))  // relation class, AR class, FK -				$this->relations[$name]=new $config[0]($name,$config[1],$config[2],array_slice($config,3)); -			else -				throw new TDbException('Active record "'.get_class($model).'" has an invalid configuration for relation "'.$name.'". It must specify the relation type, the related active record class and the foreign key.'); -		} -	} -} - -/** - * TActiveRecordInvalidFinderResult class. - * TActiveRecordInvalidFinderResult defines the enumerable type for possible results - * if an invalid {@link TActiveRecord::__call magic-finder} invoked. - * - * The following enumerable values are defined: - * - Null: return null (default) - * - Exception: throws a TActiveRecordException - * - * @author Yves Berkholz <godzilla80@gmx.net> - * @version $Id: TActiveRecord.php 2649 2009-05-11 07:44:55Z godzilla80@gmx.net $ - * @package System.Data.ActiveRecord - * @see TActiveRecordManager::setInvalidFinderResult - * @see TActiveRecordConfig::setInvalidFinderResult - * @see TActiveRecord::setInvalidFinderResult - * @since 3.1.5 - */ -class TActiveRecordInvalidFinderResult extends TEnumerable -{ -	const Null = 'Null'; -	const Exception = 'Exception'; -} diff --git a/framework/Testing/Data/ActiveRecord/TActiveRecordBehavior.php b/framework/Testing/Data/ActiveRecord/TActiveRecordBehavior.php deleted file mode 100644 index cd4d8386..00000000 --- a/framework/Testing/Data/ActiveRecord/TActiveRecordBehavior.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php -/** - * CActiveRecordBehavior class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -/** - * CActiveRecordBehavior is the base class for behaviors that can be attached to {@link CActiveRecord}. - * Compared with {@link CModelBehavior}, CActiveRecordBehavior attaches to more events - * that are only defined by {@link CActiveRecord}. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: CActiveRecordBehavior.php 564 2009-01-21 22:07:10Z qiang.xue $ - * @package System.Testing.Data.ActiveRecord - * @since 1.0.2 - */ -class TActiveRecordBehavior extends TModelBehavior -{ -	/** -	 * Declares events and the corresponding event handler methods. -	 * If you override this method, make sure you merge the parent result to the return value. -	 * @return array events (array keys) and the corresponding event handler methods (array values). -	 * @see CBehavior::events -	 */ -	public function events() -	{ -		return array_merge(parent::events(), array( -			'onBeforeSave'=>'beforeSave', -			'onAfterSave'=>'afterSave', -			'onBeforeDelete'=>'beforeDelete', -			'onAfterDelete'=>'afterDelete', -			'onAfterConstruct'=>'afterConstruct', -			'onAfterFind'=>'afterFind', -		)); -	} - -	/** -	 * Responds to {@link CActiveRecord::onBeforeSave} event. -	 * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. -	 * @param CEvent event parameter -	 */ -	public function beforeSave($event) -	{ -	} - -	/** -	 * Responds to {@link CActiveRecord::onAfterSave} event. -	 * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. -	 * @param CEvent event parameter -	 */ -	public function afterSave($event) -	{ -	} - -	/** -	 * Responds to {@link CActiveRecord::onBeforeDelete} event. -	 * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. -	 * @param CEvent event parameter -	 */ -	public function beforeDelete($event) -	{ -	} - -	/** -	 * Responds to {@link CActiveRecord::onAfterDelete} event. -	 * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. -	 * @param CEvent event parameter -	 */ -	public function afterDelete($event) -	{ -	} - -	/** -	 * Responds to {@link CActiveRecord::onAfterConstruct} event. -	 * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. -	 * @param CEvent event parameter -	 */ -	public function afterConstruct($event) -	{ -	} - -	/** -	 * Responds to {@link CActiveRecord::onAfterFind} event. -	 * Overrides this method if you want to handle the corresponding event of the {@link CBehavior::owner owner}. -	 * @param CEvent event parameter -	 */ -	public function afterFind($event) -	{ -	} -} diff --git a/framework/Testing/Data/ActiveRecord/TActiveRecordCriteria.php b/framework/Testing/Data/ActiveRecord/TActiveRecordCriteria.php deleted file mode 100644 index 46eddaf9..00000000 --- a/framework/Testing/Data/ActiveRecord/TActiveRecordCriteria.php +++ /dev/null @@ -1,254 +0,0 @@ -<?php -/** - * TActiveRecordCriteria class file - * Adapts *deprecated* Prado TActiveRecordCriteria to TDbCriteria (Yii) - * @class TActiveRecordCriteria - * @deprecated - * @author Daniel Mueller <tux@penguinfriends.org> - */ - -Prado::using('System.Testing.Data.Schema.TDbCriteria'); - -class TSqlCriteria extends TDbCriteria -{ -	 -	private $_TDbCriteria = null; - -	public function __construct($condition=null, $parameters=array()) -	{ -		if(!is_array($parameters) && func_num_args() > 1) -			$parameters = array_slice(func_get_args(), 1); - -		$this->_TDbCriteria = $this; -		 -		$this->_TDbCriteria->params = new ArrayObject(); - -		$param = array( -			'condition' => ($condition !== null) ? $condition : '', -			'params' => $parameters -		); -	} - -	public function getCondition() -	{ -		return $this->_TDbCriteria->condition; -	} - -	public function setCondition($value) -	{ -		if(empty($value)) -			return; - -		// supporting the following SELECT-syntax: -		// [ORDER BY {col_name | expr | position} -		//      [ASC | DESC], ...] -		//    [LIMIT {[offset,] row_count | row_count OFFSET offset}] -		// See: http://dev.mysql.com/doc/refman/5.0/en/select.html -				 -				 -		if(preg_match('/ORDER\s+BY\s+(.*?)(?=LIMIT)|ORDER\s+BY\s+(.*?)$/i', $value, $matches) > 0) { -			// condition contains ORDER BY -			$value = str_replace($matches[0], '', $value); -			if(strlen($matches[1]) > 0) { -				$this->_TDbCriteria->setOrdersBy($matches[1]); -			} else if(strlen($matches[2]) > 0) { -				$this->setOrdersBy($matches[2]); -			} -		} -			 -		if(preg_match('/LIMIT\s+([\d\s,]+)/i', $value, $matches) > 0) { -				// condition contains limit -			$value = str_replace($matches[0], '', $value);  -			// remove limit from query -			if(strpos($matches[1], ',')) { // both offset and limit given -				list($offset, $limit) = explode(',', $matches[1]); -				$this->_TDbCriteria->limit = (int)$limit; -				$this->_TDbCriteria->offset = (int)$offset; -			} else { // only limit given -				$this->_TDbCriteria->limit = (int)$matches[1]; -			} -		} - -		if(preg_match('/OFFSET\s+(\d+)/i', $value, $matches) > 0) { -			// condition contains offset -			$value = str_replace($matches[0], '', $value);  -			// remove offset from query -			$this->_TDbCriteria->offset = (int)$matches[1]; // set offset in criteria -		} -		 -		$this->_TDbCriteria->condition = trim($value); -	} - -	public function getParameters() -	{ -		return $this->_TDbCriteria->params; -	} - -	public function setParameters($value) -	{ -		if(is_array($value)) -		{ -			$this->_TDbCriteria->params = $value; -		} -		elseif ($value instanceof ArrayAccess) -		{ -			$this->_TDbCriteria->params = (array)$value; -		} -		else -			throw new TException('Value must be an array or of type ArrayAccess.'); -	} - -	public function getIsNamedParameters() -	{ -		foreach($this->_TDbCriteria->params as $key=>$val) -			return is_string($key); -	} - -	public function getLimit() -	{ -		return ($this->_TDbCriteria->limit != -1) ? $this->_TDbCriteria->limit : null; -	} - -	public function setLimit($value) -	{ -		$this->_TDbCriteria->limit = (int)$value; -	} - -	public function getOffset() -	{ -		return ($this->_TDbCriteria->offset != -1) ? $this->_TDbCriteria->offset : null; -	} - -	public function setOffset($value) -	{ -		$this->_TDbCriteria->offset = (int)$value; -	} -	 -	public function getOrdersBy() -	{ -		if(empty($this->_TDbCriteria->order)) -			return array(); - -		$value=trim(preg_replace('/\s+/',' ', $this->_TDbCriteria->order)); -		$orderBys=array(); -		foreach(explode(',',$value) as $orderBy) -		{ -			$vs=explode(' ',trim($orderBy)); -			 -		$orderBys[$vs[0]]=isset($vs[1])?$vs[1]:'asc'; -		} -		return $orderBys; -	} - -	public function setOrdersBy($value) -	{ -		if(is_string($value)) -			$this->TDbCriteria->order = $value; -		elseif (is_array($value) || $value instanceof Traversable) -		{ -			$str = ''; -			foreach($value as $key => $val) -				$str .= (($str != '') ? ', ': '').$key.' '.$val; -			 -			$this->_TDbCriteria->order = $str; -		} -	}	 - -	public function __toString() -	{ -		$str = ''; -		if(strlen((string)$this->getCondition()) > 0) -			$str .= '"'.(string)$this->getCondition().'"'; -		$params = array(); -		foreach($this->getParameters() as $k=>$v) -			$params[] = "{$k} => ${v}"; -		if(count($params) > 0) -			$str .= ', "'.implode(', ',$params).'"'; -		$orders = array(); -		foreach($this->getOrdersBy() as $k=>$v) -			$orders[] = "{$k} => ${v}"; -		if(count($orders) > 0) -			$str .= ', "'.implode(', ',$orders).'"'; -		if($this->getLimit() !==null) -			$str .= ', '.$this->_limit; -		if($this->getOffset() !== null) -			$str .= ', '.$this->_offset; -		return $str; -	} - -	/** -	 * Returns a property value or an event handler list by property or event name. -	 * Do not call this method. This is a PHP magic method that we override -	 * to allow using the following syntax to read a property: -	 * <code> -	 * $value=$component->PropertyName; -	 * </code> -	 * and to obtain the event handler list for an event, -	 * <code> -	 * $eventHandlerList=$component->EventName; -	 * </code> -	 * @param string the property name or the event name -	 * @return mixed the property value or the event handler list -	 * @throws TInvalidOperationException if the property/event is not defined. -	 */ -	public function __get($name) -	{ -		$getter='get'.$name; -		if(method_exists($this,$getter)) -		{ -			// getting a property -			return $this->$getter(); -		} -		else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name)) -		{ -			// getting an event (handler list) -			$name=strtolower($name); -			if(!isset($this->_e[$name])) -				$this->_e[$name]=new TList; -			return $this->_e[$name]; -		} -		else -		{ -			throw new TInvalidOperationException('component_property_undefined',get_class($this),$name); -		} -	} - -	/** -	 * Sets value of a component property. -	 * Do not call this method. This is a PHP magic method that we override -	 * to allow using the following syntax to set a property or attach an event handler. -	 * <code> -	 * $this->PropertyName=$value; -	 * $this->EventName=$handler; -	 * </code> -	 * @param string the property name or event name -	 * @param mixed the property value or event handler -	 * @throws TInvalidOperationException If the property is not defined or read-only. -	 */ -	public function __set($name,$value) -	{ -		$setter='set'.$name; -		if(method_exists($this,$setter)) -		{ -			$this->$setter($value); -		} -		else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name)) -		{ -			$this->attachEventHandler($name,$value); -		} -		else if(method_exists($this,'get'.$name)) -		{ -			throw new TInvalidOperationException('component_property_readonly',get_class($this),$name); -		} -		else -		{ -			throw new TInvalidOperationException('component_property_undefined',get_class($this),$name); -		} -	} - -} - -class TActiveRecordCriteria extends TSqlCriteria -{ -	 -} diff --git a/framework/Testing/Data/Analysis/TDbStatementAnalysis.php b/framework/Testing/Data/Analysis/TDbStatementAnalysis.php deleted file mode 100644 index 46f9b745..00000000 --- a/framework/Testing/Data/Analysis/TDbStatementAnalysis.php +++ /dev/null @@ -1,238 +0,0 @@ -<?php -/** - * IDbStatementAnalysis, TDbStatementAnalysisParameter, - * TDbStatementAnalysis, TDbStatementClassification file. - * - * @author Yves Berkholz <godzilla80[at]gmx[dot]net> - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2010 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Testing.Data.Analysis - */ - -	/** -	 * IDbStatementAnalysis interface -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @license http://www.pradosoft.com/license/ -	 * @version $Id$ -	 * @package System.Testing.Data.Analysis -	 * @since 4.0 -	 */ -	interface IDbStatementAnalysis -	{ -		/** -		 * @param TDbStatementAnalysisParamete -		 * @return TDbStatementClassification -		 */ -		public static function doClassificationAnalysis(TDbStatementAnalysisParameter $param); - -		/** -		 * @param TDbStatementAnalysisParameter -		 * @return TDbStatementClassification -		 */ -		public function getClassificationAnalysis(TDbStatementAnalysisParameter $param); - -		/** -		 * @param string PDO drivername of connection -		 */ -		public function setDriverName($value); - -		/** -		 * @return string PDO drivername of connection -		 */ -		public function getDriverName(); -	} - -	/** -	 * TDbStatementAnalysisParameter class -	 * -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @license http://www.pradosoft.com/license/ -	 * @version $Id$ -	 * @package System.Testing.Data.Analysis -	 * @since 4.0 -	 */ -	class TDbStatementAnalysisParameter -	{ -		/** -		 * @var string The SQL statement that should be analysed -		 */ -		protected $_statement = null; - -		/** -		 * TDbStatementClassification Defaults to 'UNKNOWN' -		 */ -		protected $_defaultClassification = TDbStatementClassification::UNKNOWN; - -		/** -		 * string|null PDO drivername of connection -		 */ -		protected  $_drivername	= null; - -		/** -		 * @param string The SQL statement that should be analysed -		 * @param TDbStatementClassification -		 * @param string|null PDO drivername of connection -		 */ -		public function __construct($statement='', $defaultClassification=null, $drivername=null) -		{ -			$this->setStatement($statement); -			$this->setDefaultClassification($defaultClassification); -			$this->setDriverName($drivername); -		} - -		/** -		 * @param string The SQL statement that should be analysed -		 */ -		public function setStatement($value) -		{ -			$this->_statement = (string)$value; -		} - -		/** -		 * @return string The SQL statement that should be analysed -		 */ -		public function getStatement() -		{ -			return $this->_statement; -		} - -		/** -		 * @param string|null PDO drivername of connection -		 */ -		public function setDriverName($value) -		{ -			$this->_drivername = ($value===null) ? null : (string)$value; -		} - -		/** -		 * @return string|null PDO drivername of connection -		 */ -		public function getDriverName() -		{ -			return $this->_drivername; -		} - -		/** -		 * @param TDbStatementClassification Defaults to 'UNKNOWN' -		 */ -		public function setDefaultClassification($value) -		{ -			if($value!==null) -				$this->_defaultClassification = (string)$value; -			else -				$this->_defaultClassification = TDbStatementClassification::UNKNOWN; -		} - -		/** -		 * @return TDbStatementClassification -		 */ -		public function getDefaultClassification() -		{ -			return $this->_defaultClassification; -		} -	} - -	/** -	 * TDbStatementAnalysis class -	 * -	 * Basic "dummy" implementation allways return {@link TDbStatementAnalysisParameter::getDefaultClassification DefaultClassification} -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @license http://www.pradosoft.com/license/ -	 * @version $Id$ -	 * @package System.Testing.Data.Analysis -	 * @since 4.0 -	 */ -	class TDbStatementAnalysis implements IDbStatementAnalysis -	{ -		/** -		 * @var string|null PDO drivername of connection -		 */ -		protected $_drivername = null; - -		/** -		 * @param string|null PDO drivername of connection -		 */ -		public function setDriverName($value) -		{ -			$this->_drivername = ($value===null) ? null : (string)$value; -		} - -		/** -		 * @return string|null PDO drivername of connection -		 */ -		public function getDriverName() -		{ -			return $this->_drivername; -		} - -		/** -		 * @param TDbStatementAnalysisParamete -		 * @return TDbStatementClassification -		 */ -		public static function doClassificationAnalysis(TDbStatementAnalysisParameter $param) -		{ -			return $param->getDefaultClassification(); -		} - -		/** -		 * @param TDbStatementAnalysisParameter -		 * @return TDbStatementClassification -		 */ -		public function getClassificationAnalysis(TDbStatementAnalysisParameter $param) -		{ -			return $param->getDefaultClassification(); -		} -	} - -	/** -	 * TDbStatementClassification -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @license http://www.pradosoft.com/license/ -	 * @version $Id$ -	 * @package System.Testing.Data.Analysis -	 * @since 4.0 -	 */ -	class TDbStatementClassification extends TEnumerable -	{ -		/** -		 * Structured Query Language -		 */ -		const SQL = 'SQL'; - -		/** -		 * Data Definition Language -		 */ -		const DDL = 'DDL'; - -		/** -		 * Data Manipulation Language -		 */ -		const DML = 'DML'; - -		/** -		 * Data Control Language -		 */ -		const DCL = 'DCL'; - -		/** -		 * Transaction Control Language -		 */ -		const TCL = 'TCL'; - -		/** -		 * classification depends on subsequent statement(s) -		 */ -		const CONTEXT = 'CONTEXT'; - -		/** -		 * unable to detect real classification or multiple possibilities -		 */ -		const UNKNOWN = 'UNKNOWN'; -	} -?> diff --git a/framework/Testing/Data/Analysis/TSimpleDbStatementAnalysis.php b/framework/Testing/Data/Analysis/TSimpleDbStatementAnalysis.php deleted file mode 100644 index e4ab3391..00000000 --- a/framework/Testing/Data/Analysis/TSimpleDbStatementAnalysis.php +++ /dev/null @@ -1,134 +0,0 @@ -<?php -/** - * TSimpleDbStatementAnalysis file. - * - * @author Yves Berkholz <godzilla80[at]gmx[dot]net> - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2010 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Testing.Data.Analysis - */ - -	Prado::using('System.Testing.Data.Analysis.TDbStatementAnalysis'); - -	/** -	 * TSimpleDbStatementAnalysis class -	 * -	 * IMPORTANT!!! -	 * BETA Version - Use with care and NOT in production environment (only tested with MySql) -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @license http://www.pradosoft.com/license/ -	 * @version $Id$ -	 * @package System.Testing.Data.Analysis -	 * @since 4.0 -	 * @todo SELECT * FOR UPDATE (row lock) -	 * @todo SELECT * INTO [ TEMPORARY | TEMP ] [ TABLE ] new_table (PostgreSQL) -	 * @todo mysql conditional commands in multiline comments e.g. / *! MySQL specific code * / -	 */ -	class TSimpleDbStatementAnalysis extends TDbStatementAnalysis -	{ -		/** -		 * @var array mapping of commands to classification -		 */ -		protected static $mappingClassificationAnalysis = array( -			'CREATE'	=> TDbStatementClassification::DDL, -			'DROP'		=> TDbStatementClassification::DDL, -			'ALTER'		=> TDbStatementClassification::DDL, -			'RENAME'	=> TDbStatementClassification::DDL, - -			'INSERT'	=> TDbStatementClassification::DML, -			'UPDATE'	=> TDbStatementClassification::DML, -			'DELETE'	=> TDbStatementClassification::DML, -			'REPLACE'	=> TDbStatementClassification::DML, -			'TRUNCATE'	=> TDbStatementClassification::DML, -			'LOAD'		=> TDbStatementClassification::DML, - -			'GRANT'		=> TDbStatementClassification::DCL, -			'REVOKE'	=> TDbStatementClassification::DCL, - -			'XA'				=> TDbStatementClassification::TCL, -			'SAVEPOINT'			=> TDbStatementClassification::TCL, -			'CHECKPOINT'		=> TDbStatementClassification::TCL, -			'RELEASE SAVEPOINT'	=> TDbStatementClassification::TCL, -			'START TRANSACTION'	=> TDbStatementClassification::TCL, -			'BEGIN'				=> TDbStatementClassification::TCL, -			'COMMIT'			=> TDbStatementClassification::TCL, -			'ROLLBACK'			=> TDbStatementClassification::TCL, -			'LOCK'				=> TDbStatementClassification::TCL, -			'UNLOCK'			=> TDbStatementClassification::TCL, -			'ABORT'				=> TDbStatementClassification::TCL, -			'END'				=> TDbStatementClassification::TCL, - -			'SELECT'	=> TDbStatementClassification::SQL, - -			'SHOW'		=> TDbStatementClassification::SQL, -			'DESCRIBE'	=> TDbStatementClassification::SQL, -			'EXPLAIN'	=> TDbStatementClassification::SQL, -			'PRAGMA'	=> TDbStatementClassification::SQL, - -			'SET'	=> TDbStatementClassification::CONTEXT, -			'USE'	=> TDbStatementClassification::CONTEXT, - -			'CALL'			=> TDbStatementClassification::UNKNOWN, -			'EXEC'			=> TDbStatementClassification::UNKNOWN, -			'PREPARE'		=> TDbStatementClassification::UNKNOWN, -			'EXECUTE'		=> TDbStatementClassification::UNKNOWN, -			'DEALLOCATE'	=> TDbStatementClassification::UNKNOWN, -		); - -		/** -		 * @var array -		 */ -		protected static $cacheClassificationAnalysis = array(); - -		/** -		 * @var string -		 */ -		protected static $regExpClassificationAnalysis = null; - -		/** -		 * @param TDbStatementAnalysisParamete -		 * @return TDbStatementClassification -		 */ -		public static function doClassificationAnalysis(TDbStatementAnalysisParameter $param) -		{ -			$statement	= $param->getStatement(); -			$default	= $param->getDefaultClassification(); - -			$hash = md5($statement . '-' . $default); -			 -			if( isset(self::$cacheClassificationAnalysis[$hash]) ) -				return self::$cacheClassificationAnalysis[$hash]; -			 -			self::$cacheClassificationAnalysis[$hash] = $default; -				 -			$statement = preg_replace('/(?:--|\\#)[\x20\\t\\S]*\s+|\/\\*[\x20\\t\\n\\r\\S]*?\\*\//Ssmux', '', $statement); -			$statement = preg_replace('/[\s]+/Smu', ' ', $statement); -			$statement = trim($statement); -			 -			if(self::$regExpClassificationAnalysis===null) -				self::$regExpClassificationAnalysis = '/^(' . str_replace(' ', '\x20', implode('|', array_keys(self::$mappingClassificationAnalysis))) . ')+[\s]+.*|\k1/Siu'; -			 -			$cmd = strToUpper(preg_replace(self::$regExpClassificationAnalysis, '\1', $statement)); -			 -			if( isset(self::$mappingClassificationAnalysis[$cmd]) ) -				self::$cacheClassificationAnalysis[$hash] = self::$mappingClassificationAnalysis[$cmd]; - -			return self::$cacheClassificationAnalysis[$hash]; -		} - -		/** -		 * @param TDbStatementAnalysisParameter -		 * @return TDbStatementClassification -		 */ -		public function getClassificationAnalysis(TDbStatementAnalysisParameter $param) -		{ -			if( ($drivername = $this->getDriverName())!== null ) -				$param->setDriverName($drivername); - -			return self::doClassificationAnalysis($param); -		} -	} -?>
\ No newline at end of file diff --git a/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDataSourceConfig.php b/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDataSourceConfig.php deleted file mode 100644 index ee486fe8..00000000 --- a/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDataSourceConfig.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php -/** - * TMasterSlaveDataSourceConfig class file. - * - * @author Yves Berkholz <godzilla80[at]gmx[dot]net> - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2010 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Testing.Data.Distributed.MasterSlave - */ - -	Prado::using('System.Testing.Data.Distributed.TDistributedDataSourceConfig'); -	Prado::using('System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbConnection'); - -	/** -	 * TMasterSlaveDataSourceConfig module class provides <module> configuration for database connections in master/slave senario. -	 * -	 * IMPORTANT!!! -	 * BETA Version - Use with care and NOT in production environment (only tested with MySql) -	 * -	 * Example usage: mysql connection -	 * <code> -	 * <modules> -	 * <module id="db1" class="System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDataSourceConfig" -	 *	ConnectionClass="System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbConnection" -	 *	DistributedConnectionClass="System.Testing.Data.Distributed.MasterSlave.TSlaveDbConnection" -	 *	DbConnection.StatementAnalyserClass="System.Testing.Data.Analysis.TSimpleDbStatementAnalysis"> -	 *		<database ConnectionString="mysql:host=127.0.0.1;port=3306;dbname=mydatabase" Username="dbuser" Password="dbpass" /> -	 * 		<slave ConnectionString="mysql:host=127.0.0.1;port=3307;dbname=mydatabase" Username="dbuser" Password="dbpass" Weight="3" /> -	 * 		<slave ConnectionString="mysql:host=127.0.0.1;port=3308;dbname=mydatabase" Username="dbuser" Password="dbpass" Weight="2" /> -	 * 		<slave ConnectionString="mysql:host=127.0.0.1;port=3309;dbname=mydatabase" Username="dbuser" Password="dbpass" Weight="5" /> -	 *	</module> -	 * </modules> -	 * </code> -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed.MasterSlave -	 * @since 4.0 -	 */ -	class TMasterSlaveDataSourceConfig extends TDistributedDataSourceConfig -	{ -		/** -		 * @var boolean -		 */ -		private $_bMasterInitialized = false; - -		/** -		 * @var boolean -		 */ -		private $_bSlaveInitialized = false; - -		/** -		 * Constructor -		 */ -		public function __construct() -		{ -			$this->setConnectionClass('System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbConnection'); -			$this->setDistributedConnectionClass('System.Testing.Data.Distributed.MasterSlave.TSlaveDbConnection'); -		} - -		/** -		 * Initalize the database connection properties from attributes in slave tag. -		 * @param TXmlDocument xml configuration. -		 */ -		protected function initChildConnectionData($xml) -		{ -			parent::initChildConnectionData($xml, 'slave'); -		} - -		/** -		 * @return IMasterSlaveDbConnection -		 */ -		public function getDbConnection() { -			$id = $this->getID(); -			static $result = array(); - -			if(!isset($result[$id])) -				$result[$id] = parent::getDbConnection(); - -			if(!$this->bInitialized) -				return $result[$id]; - -			if($this->_bMasterInitialized) -				return $result[$id]; - -			$this->_bMasterInitialized = true; - -			if(!$result[$id] instanceof IMasterSlaveDbConnection) -				return $result[$id]; - -			$slave = parent::getDistributedDbConnection(); - -			if($slave instanceof ISlaveDbConnection && $slave->getMasterConnection()===null) -				$slave->setMasterConnection($result[$id]); - -			if($result[$id]->getSlaveConnection()===null) -				$result[$id]->setSlaveConnection($slave); - -			return $result[$id]; -		} - -		/** -		 * @return ISlaveDbConnection -		 */ -		public function getDistributedDbConnection() { -			$id = $this->getID(); -			static $result = array(); - -			if(!isset($result[$id])) -				$result[$id] = parent::getDistributedDbConnection(); - -			if(!$this->bInitialized) -				return $result[$id]; - -			if($this->_bSlaveInitialized) -				return $result[$id]; - -			$this->_bSlaveInitialized = true; - -			if(!$result[$id] instanceof ISlaveDbConnection) -				return $result[$id]; - -			$master = parent::getDbConnection(); - -			if($master instanceof IMasterSlaveDbConnection && ($master->getSlaveConnection()===null)) -				$master->setSlaveConnection($result[$id]); - -			if($result[$id]->getMasterConnection()===null) -				$result[$id]->setMasterConnection($master); - -			return $result[$id]; -		} - -		/** -		 * Alias for getDbConnection(). -		 * @return IMasterSlaveDbConnection database connection. -		 */ -		public function getMasterDbConnection() -		{ -			return $this->getDbConnection(); -		} - -		/** -		 * Alias for getDistributedDbConnection(). -		 * @return ISlaveDbConnection database connection. -		 */ -		public function getSlaveDbConnection() -		{ -			return $this->getDistributedDbConnection(); -		} -	} -?>
\ No newline at end of file diff --git a/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbConnection.php b/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbConnection.php deleted file mode 100644 index e6b71931..00000000 --- a/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbConnection.php +++ /dev/null @@ -1,477 +0,0 @@ -<?php -/** - * IMasterSlaveDbConnection, ISlaveDbConnection inferface, - * TMasterSlaveDbConnection, TSlaveDbConnection class file. - * - * @author Yves Berkholz <godzilla80[at]gmx[dot]net> - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2010 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Testing.Data.Distributed.MasterSlave - * @todo Test with Backport of Yii's DBO - */ - -	Prado::using('System.Data.TDbConnection'); -	Prado::using('System.Testing.Data.Distributed.TDistributedDbConnection'); -	Prado::using('System.Collections.TQueue'); -	Prado::using('System.Collections.TStack'); -	Prado::using('System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbTransaction'); - -	/** -	 * IMasterSlaveDbConnection interface -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed.MasterSlave -	 * @since 4.0 -	 */ -	interface IMasterSlaveDbConnection extends IDistributedDbConnection -	{ -		/** -		 * @return TQueue -		 */ -		public function getStatementQueue(); - -		/** -		 * @return ISlaveDbConnection|null -		 */ -		public function getSlaveConnection(); - -		/** -		 * @param ISlaveDbConnection|null -		 */ -		public function setSlaveConnection($conn); - -		/** -		 * @return TMasterSlaveDbConnectionForceMaster -		 */ -		public function getForceMaster(); - -		/** -		 * @param TMasterSlaveDbConnectionForceMaster -		 */ -		public function setForceMaster($value); - -	} - -	/** -	 * ISlaveDbConnection interface -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed.MasterSlave -	 * @since 4.0 -	 */ -	interface ISlaveDbConnection extends IDistributedDbConnection -	{ -		/** -		 * @return IMasterSlaveDbConnection|null -		 */ -		public function getMasterConnection(); - -		/** -		 * @param IMasterSlaveDbConnection|null -		 */ -		public function setMasterConnection($conn); - -		/** -		 * @return TMasterSlaveDbConnectionForceMaster -		 */ -		public function getForceMaster(); - -		/** -		 * @param TMasterSlaveDbConnectionForceMaster -		 */ -		public function setForceMaster($value); -	} - -	/** -	 * TMasterSlaveDbConnection class -	 * -	 * IMPORTANT!!! -	 * BETA Version - Use with care and NOT in production environment (only tested with MySql) -	 * -	 * TMasterSlaveDbConnection represents a master connection to a database in master/slave senario. -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed.MasterSlave -	 * @since 4.0 -	 */ -	class TMasterSlaveDbConnection extends TDistributedDbConnection implements IMasterSlaveDbConnection -	{ -		/** -		 * @var TSlaveDbConnection|null -		 */ -		private $_connSlave = null; - -		/** -		 * @var TQueue -		 */ -		private $_statementQueue = null; - -		/** -		 * @var integer -		 * @see TMasterSlaveDbConnectionForceMaster -		 */ -		private $_forceMaster = TMasterSlaveDbConnectionForceMaster::OFF_AUTOMATIC; - -		private $_forceMasterStack = null; - -		/** -		 * Constructor. -		 * Note, the DB connection is not established when this connection -		 * instance is created. Set {@link setActive Active} property to true -		 * to establish the connection. -		 * -		 * @param string The Data Source Name, or DSN, contains the information required to connect to the database. -		 * @param string The user name for the DSN string. -		 * @param string The password for the DSN string. -		 * @param string Charset used for DB Connection (MySql & pgsql only). If not set, will use the default charset of your database server -		 * @see http://www.php.net/manual/en/function.PDO-construct.php -		 */ -		public function __construct($dsn='', $username='', $password='', $charset='') -		{ -			parent::__construct($dsn, $username, $password, $charset); -			parent::setTransactionClass('System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbTransaction'); -		} - -		/** -		 * @return TQueue -		 */ -		public function getStatementQueue() -		{ -			if($this->_statementQueue===null) -				$this->_statementQueue = new TQueue(); -			return $this->_statementQueue; -		} - -		/** -		 * @return ISlaveDbConnection|null -		 */ -		public function getSlaveConnection() -		{ -			return $this->_connSlave; -		} - -		/** -		 * @param ISlaveDbConnection|null -		 * @throws TDbConnectionException if the slave connection already exists -		 * @throws TDbConnectionException connection not instance of ISlaveDbConnection -		 */ -		public function setSlaveConnection($conn) -		{ -			if($this->_connSlave !== null) -				throw new TDbConnectionException('masterslavedbconnection_connection_exists', get_class($this), 'SlaveConnection'); - -			if($conn!==null && !$conn instanceof ISlaveDbConnection) -				throw new TDbConnectionException('masterslavedbconnection_interface_required', get_class($this), 'SlaveConnection', 'ISlaveDbConnection'); - -			$this->_connSlave = $conn; - -			if($this->_connSlave===null) return; -			if($this->_connSlave->getMasterConnection()!==null) return; - -			$this->_connSlave->setMasterConnection($this); -		} - -		/** -		 * Creates a command for execution. -		 * @param string SQL statement associated with the new command. -		 * @return TDistributedDbCommand the DB command -		 * @throws TDbException if the connection is not active -		 */ -		public function createCommand($sql) -		{ -			$force = $this->getForceMaster(); -			if($force == TMasterSlaveDbConnectionForceMaster::ON_MANUAL || $force == TMasterSlaveDbConnectionForceMaster::ON_TRANSACTION) -			{ -				Prado::log('ForceMaster: ' . $force, TLogger::DEBUG, 'System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbConnection'); -				return new TDistributedDbCommand($this, $sql, TDbStatementClassification::UNKNOWN); -			} - -			$bEnqueue	= false; -			$bMaster	= true; - -			$classification = $this->getStatementClassification($sql); - -			switch($classification) { -				case TDbStatementClassification::CONTEXT: -					$bEnqueue	= true; -					$bMaster	= true; -				break; -				case TDbStatementClassification::SQL: -					$bMaster = false; -				break; -				case TDbStatementClassification::TCL: -					$this->setForceMaster(TMasterSlaveDbConnectionForceMaster::ON_TCL); -				case TDbStatementClassification::DDL: -				case TDbStatementClassification::DML: -				case TDbStatementClassification::DCL: -				case TDbStatementClassification::UNKNOWN: -				default: -					$bMaster = true; -				break; -			} - -			$bMaster = $bMaster || $this->getForceMaster(); - -			$result = new TDistributedDbCommand(($bMaster ? $this : $this->getSlaveConnection()), $sql, $classification); -			//$result = new TDistributedDbCommand($this, $sql, $classification); - -			if($bEnqueue) -				$this->getStatementQueue()->enqueue($result); - -			return $result; -		} - -		/** -		 * @return TMasterSlaveDbConnectionForceMaster -		 */ -		public function getForceMaster() -		{ -			return $this->_forceMaster; -		} - -		/** -		 * @param TMasterSlaveDbConnectionForceMaster -		 */ -		public function setForceMaster($value) -		{ -			if($this->_forceMasterStack===null) -				$this->_forceMasterStack = new TStack(); - -			if($value) -			{ -				$this->_forceMaster = (integer)$value; -				$this->_forceMasterStack->push((integer)$value); -			} -			elseif($this->_forceMasterStack->count() > 0) -				$this->_forceMaster = $this->_forceMasterStack->pop(); -			else -				$this->_forceMaster = (integer)$value; -		} - -		/** -		 * @return TDbConnectionServerRole -		 */ -		public function getServerRole() -		{ -			return TDbConnectionServerRole::Master; -		} -	} - -	/** -	 * TSlaveDbConnection class -	 * -	 * IMPORTANT!!! -	 * BETA Version - Use with care and NOT in production environment (only tested with MySql) -	 * -	 * TSlaveDbConnection represents a readonly connection to a database in master/slave senario. -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed.MasterSlave -	 * @since 4.0 -	 */ -	class TSlaveDbConnection extends TDbConnection implements ISlaveDbConnection -	{ -		/** -		 * @var TMasterSlaveDbConnection|null -		 */ -		private $_connMaster = null; - -		/** -		 * @return IMasterSlaveDbConnection|null -		 */ -		public function getMasterConnection() -		{ -			return $this->_connMaster; -		} - -		/** -		 * @param IMasterSlaveDbConnection|null -		 * @throws TDbConnectionException if the master connection already exists -		 * @throws TDbConnectionException connection not instance of IMasterSlaveDbConnection -		 */ -		public function setMasterConnection($conn) -		{ -			if($this->_connMaster!==null) -				throw new TDbConnectionException('masterslavedbconnection_connection_exists', get_class($this), 'MasterConnection'); - -			if($conn!==null && !$conn instanceof IMasterSlaveDbConnection) -				throw new TDbConnectionException('masterslavedbconnection_interface_required', get_class($this), 'MasterConnection', 'IMasterSlaveDbConnection'); - -			$this->_connMaster = $conn; -		} - -		/** -		 * Creates a command for execution. -		 * @param string SQL statement associated with the new command. -		 * @return TDistributedDbCommand the DB command -		 * @throws TDbException if the connection is not active -		 */ -		public function createCommand($sql) -		{ -			$force = $this->getForceMaster(); -			if($force == TMasterSlaveDbConnectionForceMaster::ON_MANUAL || $force == TMasterSlaveDbConnectionForceMaster::ON_TRANSACTION) -			{ -				Prado::log('ForceMaster: ' . $force, TLogger::DEBUG, 'System.Testing.Data.Distributed.MasterSlave.TSlaveDbConnection'); -				return new TDistributedDbCommand($this->getMasterConnection(), $sql, TDbStatementClassification::UNKNOWN); -			} - -			$bEnqueue	= false; -			$bMaster	= false; - -			$classification = $this->getStatementClassification($sql); - -			switch($classification) { -				case TDbStatementClassification::SQL: -					$bMaster = false; -				break; -				case TDbStatementClassification::CONTEXT: -					$bEnqueue	= true; -					$bMaster	= true; -				break; -				case TDbStatementClassification::TCL: -					$this->setForceMaster(TMasterSlaveDbConnectionForceMaster::ON_TCL); -				case TDbStatementClassification::DDL: -				case TDbStatementClassification::DML: -				case TDbStatementClassification::DCL: -				case TDbStatementClassification::UNKNOWN: -				default: -					$bMaster = true; -				break; -			} - -			$bMaster = $bMaster || $this->getForceMaster(); - -			$result = new TDistributedDbCommand(($bMaster ? $this->getMasterConnection() : $this), $sql, $classification); - -			if($bEnqueue) -				$this->getMasterConnection()->getStatementQueue()->enqueue($result); - -			return $result; -		} - -		/** -		 * Starts a transaction. -		 * @return TDbTransaction the transaction initiated -		 * @throws TDbException if no master connection exists or the connection is not active -		 */ -		public function beginTransaction() -		{ -			if($this->getMasterConnection() === null) -				throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection'); - -			return $this->getMasterConnection()->beginTransaction(); -		} - -		/** -		 * @return string Transaction class name to be created by calling {@link TDbConnection::beginTransaction}. -		 * @throws TDbException if no master connection exists -		 */ -		public function getTransactionClass() -		{ -			if($this->getMasterConnection() === null) -				throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection'); -			return $this->getMasterConnection()->getTransactionClass(); -		} - -		/** -		 * @param string Transaction class name to be created by calling {@link TDbConnection::beginTransaction}. -		 * @throws TDbException if no master connection exists -		 */ -		public function setTransactionClass($value) -		{ -			if($this->getMasterConnection() === null) -				throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection'); -			$this->getMasterConnection()->setTransactionClass($value); -		} - -		/** -		 * Gets the statement analyser of type given by -		 * {@link setStatementAnalyserClass StatementAnalyserClass }. -		 * @return IDbStatementAnalysis statement analyser. -		 * @throws TDbException if no master connection exists -		 */ -		public function getStatementAnalyser() -		{ -			if($this->getMasterConnection() === null) -				throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection'); -			return $this->getMasterConnection()->getStatementAnalyser(); -		} - -		/** -		 * The statement analyser class name to be created when {@link getStatementAnalyserClass} -		 * method is called. The {@link setStatementAnalyserClass StatementAnalyserClass} -		 * property must be set before calling {@link getStatementAnalyser} if you wish to -		 * create the connection using the  given class name. -		 * @param string Statement analyser class name. -		 * @throws TDbException if no master connection exists -		 */ -		public function setStatementAnalyserClass($value) -		{ -			if($this->getMasterConnection() === null) -				throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection'); -			$this->getMasterConnection()->setStatementAnalyserClass($value); -		} - -		/** -		 * @param string Statement analyser class name to be created. -		 * @throws TDbException if no master connection exists -		 */ -		public function getStatementAnalyserClass() -		{ -			if($this->getMasterConnection() === null) -				throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection'); -			return $this->getMasterConnection()->getStatementAnalyserClass(); -		} - -		/** -		 * @return TMasterSlaveDbConnectionForceMaster -		 * @throws TDbException if no master connection exists -		 */ -		public function getForceMaster() -		{ -			if($this->getMasterConnection() === null) -				throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection'); -			return $this->getMasterConnection()->getForceMaster(); -		} - -		/** -		 * @param TMasterSlaveDbConnectionForceMaster -		 * @throws TDbException if no master connection exists -		 */ -		public function setForceMaster($value) -		{ -			if($this->getMasterConnection() === null) -				throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection'); -			$this->getMasterConnection()->setForceMaster($value); -		} - -		/** -		 * @return TDbConnectionServerRole -		 */ -		public function getServerRole() -		{ -			return TDbConnectionServerRole::Slave; -		} -	} - -	/** -	 * TMasterSlaveDbConnectionForceMaster class -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed.MasterSlave -	 * @since 4.0 -	 */ -	class TMasterSlaveDbConnectionForceMaster extends TEnumerable -	{ -		const OFF_AUTOMATIC		= 0; -		const ON_MANUAL			= 1; -		const ON_TCL			= -1; -		const ON_TRANSACTION	= -2; -	} diff --git a/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbTransaction.php b/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbTransaction.php deleted file mode 100644 index 254afdb5..00000000 --- a/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbTransaction.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php -/** - * TMasterSlaveDbTransaction class file. - * - * @author Yves Berkholz <godzilla80[at]gmx[dot]net> - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2010 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Testing.Data.Distributed.MasterSlave - */ -	Prado::using('System.Data.TDbTransaction'); - -	/** -	 * TMasterSlaveDbTransaction class -	 * -	 * IMPORTANT!!! -	 * BETA Version - Use with care and NOT in production environment (only tested with MySql) -	 * -	 * TMasterSlaveDbTransaction represents a DB transaction in master/slave senario. -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed.MasterSlave -	 * @since 4.0 -	 */ -	class TMasterSlaveDbTransaction extends TDbTransaction -	{ -		/** -		 * @var boolean -		 */ -		private $_compatible = false; - -		/** -		 * Constructor. -		 * @param TDbConnection the connection associated with this transaction -		 * @see TDbConnection::beginTransaction -		 */ -		public function __construct(TDbConnection $connection) -		{ -			if($connection instanceof ISlaveDbConnection) -			{ -				$this->_compatible = true; -				$master = $connection->getMasterConnection(); -				$master->setForceMaster(TMasterSlaveDbConnectionForceMaster::ON_TRANSACTION); -				Prado::log('contstuct, ForceMaster: ON_TRANSACTION', TLogger::DEBUG, 'System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbTransaction'); -				parent::__construct($master); -			} -			else -			{ -				if($connection instanceof IMasterSlaveDbConnection) -				{ -					$this->_compatible = true; -					$connection->setForceMaster(TMasterSlaveDbConnectionForceMaster::ON_TRANSACTION); -					Prado::log('contstuct, ForceMaster: ON_TRANSACTION', TLogger::DEBUG, 'System.TestingData.Distributed.MasterSlave.TMasterSlaveDbTransaction'); -				} -				parent::__construct($connection); -			} -		} - -		/** -		 * Commits a transaction. -		 * @throws TDbException if the transaction or the DB connection is not active. -		 */ -		public function commit() -		{ -			if($this->_compatible) $this->getConnection()->setForceMaster(TMasterSlaveDbConnectionForceMaster::OFF_AUTOMATIC); -			Prado::log('commit, ForceMaster: OFF_AUTOMATIC', TLogger::DEBUG, 'System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbTransaction'); -			parent::commit(); -		} - -		/** -		 * Rolls back a transaction. -		 * @throws TDbException if the transaction or the DB connection is not active. -		 */ -		public function rollback() -		{ -			if($this->_compatible) $this->getConnection()->setForceMaster(TMasterSlaveDbConnectionForceMaster::OFF_AUTOMATIC); -			Prado::log('rollback, ForceMaster: OFF_AUTOMATIC', TLogger::DEBUG, 'System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbTransaction'); -			parent::rollback(); -		} -	} -?>
\ No newline at end of file diff --git a/framework/Testing/Data/Distributed/TDistributedDataSourceConfig.php b/framework/Testing/Data/Distributed/TDistributedDataSourceConfig.php deleted file mode 100644 index b8c4e5a9..00000000 --- a/framework/Testing/Data/Distributed/TDistributedDataSourceConfig.php +++ /dev/null @@ -1,181 +0,0 @@ -<?php -/** - * TDistributedDataSourceConfig class file. - * - * @author Yves Berkholz <godzilla80[at]gmx[dot]net> - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2010 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Testing.Data.Distributed - */ - -	Prado::using('System.Data.TDataSourceConfig'); -	Prado::using('System.Testing.Data.Distributed.TDistributedDbConnection'); - -	/** -	 * IDistributedDataSourceConfig module interface provides <module> configuration for database connections. -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed -	 * @since 4.0 -	 */ -	interface IDistributedDataSourceConfig /*extends IDataSourceConfig*/ { -		/** -		 * @return string Database connection class name to be created for child connection. -		 */ -		public function getDistributedConnectionClass(); - -		/** -		 * @param string Database connection class name to be created for child connection. -		 */ -		public function setDistributedConnectionClass($value); -	} - -	/** -	 * TDistributedDataSourceConfig module class provides <module> configuration for database connections. -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed -	 * @since 4.0 -	 */ -	class TDistributedDataSourceConfig extends TDataSourceConfig implements IDistributedDataSourceConfig -	{ -		/** -		 * @var array -		 */ -		private $_childConnectionAttributes = array(); - -		/** -		 * @var string -		 */ -		private $_connDistributedClass = 'System.Data.TDbConnection'; - -		/** -		 * @var IDistributedDbConnection -		 */ -		private $_connDistributed = null; - -		/** -		 * @var boolean -		 */ -		protected $bInitialized = false; - -		/** -		 * @var boolean -		 */ -		private $_hasDistributedConnectionData = false; - -		/** -		 * Initalize the database connection properties from attributes in <database> tag. -		 * @param TXmlDocument xml configuration. -		 */ -		public function init($xml) -		{ -			parent::init($xml); -			$this->initChildConnectionData($xml); -			$this->bInitialized = true; -		} - -		/** -		 * Initalize the database connection properties from attributes in $tagName tag. -		 * @param TXmlDocument xml configuration. -		 * @param string Tagnames to parse. Defaults to 'child' -		 */ -		protected function initChildConnectionData($xml, $tagName='child') -		{ -			$c = 0; -			foreach($xml->getElementsByTagName($tagName) as $item) -			{ -				++$c; -				$this->_childConnectionAttributes[] = $item->getAttributes(); -			} - -			if($c===0) -				throw new TConfigurationException('distributeddatasource_child_required', get_class($this), $tagName); -		} - -		/** -		 * @return string Database connection class name to be created for child connection. -		 */ -		public function getDistributedConnectionClass() -		{ -			return $this->_connDistributedClass; -		} - -		/** -		 * @param string Database connection class name to be created for child connection. -		 */ -		public function setDistributedConnectionClass($value) -		{ -			$this->_connDistributedClass=$value; -		} - -		/** -		 * @return IDistributedDbConnection -		 */ -		public function getDistributedDbConnection() -		{ -			$this->_hasDistributedConnectionData = false; -			if($this->_connDistributed===null) -				$this->_connDistributed = Prado::createComponent($this->getDistributedConnectionClass()); - -			if($this->_hasDistributedConnectionData) -				return $this->_connDistributed; - -			$attribs = $this->getDistributedDbConnectionAttributes(); - -			if($attribs===null) -				return $this->_connDistributed; - -			foreach($attribs as $name => $value) -				$this->_connDistributed->setSubproperty($name, $value); - -			$this->_hasDistributedConnectionData = true; - -			return $this->_connDistributed; -		} - -		/** -		 * @return TMap -		 */ -		protected function getDistributedDbConnectionAttributes() -		{ -			$index = 0; -			$c = count($this->_childConnectionAttributes); - -			if($c > 1) { -				$aSrc = array(); -				$aTmp = array(); - -				foreach($this->_childConnectionAttributes as $k => $item) -				{ -					$weight = 1; -					if( isset($item['Weight']) ) -						$weight = $item['Weight']; -					$aSrc[$k] = $weight; -				} - -				asort($aSrc); - -				foreach($aSrc as $idx => $weight) -					$aTmp = array_merge($aTmp, array_pad(array(), $weight*5, $idx)); - -				$min	= 0; -				$max	= count($aTmp)-1; -				$factor = array_sum($aSrc) / count($aSrc); -				$wrand	= round($min + (pow(rand(0, $max) / $max, $factor) * ($max - $min))); -				$index	= $aTmp[$wrand]; -			} - -			$result = $this->_childConnectionAttributes[$index]; - -			if( isset($result['Weight']) ) -				unset($result['Weight']); - -			return $result; -		} -	} -?>
\ No newline at end of file diff --git a/framework/Testing/Data/Distributed/TDistributedDbConnection.php b/framework/Testing/Data/Distributed/TDistributedDbConnection.php deleted file mode 100644 index bb105d50..00000000 --- a/framework/Testing/Data/Distributed/TDistributedDbConnection.php +++ /dev/null @@ -1,189 +0,0 @@ -<?php -/** - * IDistributedDbConnection, TDistributedDbConnection inferface/class file. - * - * @author Yves Berkholz <godzilla80[at]gmx[dot]net> - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2010 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Testing.Data.Distributed - */ - -	Prado::using('System.Data.TDbConnection'); -	Prado::using('System.Testing.Data.Analysis.TDbStatementAnalysis'); - -	/** -	 * TDistributedDbConnection interface -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed -	 * @since 4.0 -	 */ -	interface IDistributedDbConnection /*extends IDbConnection*/ -	{ -		/** -		 * Gets the statement analyser of type given by -		 * {@link setStatementAnalyserClass StatementAnalyserClass }. -		 * @return IDbStatementAnalysis statement analyser. -		 */ -		public function getStatementAnalyser(); - -		/** -		 * The statement analyser class name to be created when {@link getStatementAnalyserClass} -		 * method is called. The {@link setStatementAnalyserClass StatementAnalyserClass} -		 * property must be set before calling {@link getStatementAnalyser} if you wish to -		 * create the connection using the  given class name. -		 * @param string Statement analyser class name. -		 */ -		public function setStatementAnalyserClass($value); - -		/** -		 * @param string Statement analyser class name to be created. -		 */ -		public function getStatementAnalyserClass(); - -		/** -		 * @return TDbConnectionServerRole -		 */ -		public function getServerRole(); -	} - -	/** -	 * TDistributedDbConnection class -	 * -	 * TDistributedDbConnection represents a conditional base connection class to a database -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed -	 * @since 4.0 -	 */ -	abstract class TDistributedDbConnection extends TDbConnection implements IDistributedDbConnection -	{ -		/** -		 * @var string -		 */ -		private $_statementAnalyserClass = 'System.Testing.Data.Analysis.TDbStatementAnalysis'; - -		/** -		 * @var IDbStatementAnalysis -		 */ -		private $_statementAnalyser = null; - -		/** -		 * Gets the statement analyser of type given by -		 * {@link setStatementAnalyserClass StatementAnalyserClass }. -		 * @return IDbStatementAnalysis statement analyser. -		 */ -		public function getStatementAnalyser() -		{ -			if($this->_statementAnalyser === null) -			{ -				$this->setActive(true); -				$this->_statementAnalyser = Prado::createComponent($this->getStatementAnalyserClass()); - -				if($this->getActive()) -					$this->_statementAnalyser->setDriverName($this->getDriverName()); -			} -			return $this->_statementAnalyser; -		} - -		/** -		 * The statement analyser class name to be created when {@link getStatementAnalyser} -		 * method is called. The {@link setStatementAnalyserClass StatementAnalyserClass} -		 * property must be set before calling {@link getStatementAnalyser} if you wish to -		 * create the connection using the given class name. -		 * @param string Statement analyser class name. -		 */ -		public function setStatementAnalyserClass($value) -		{ -			if($this->_statementAnalyser === null) -				$this->_statementAnalyserClass = $value; -		} - -		/** -		 * @param string Statement analyser class name to be created. -		 */ -		public function getStatementAnalyserClass() -		{ -			return $this->_statementAnalyserClass; -		} - -		/** -		 * @param string The SQL statement that should be analysed -		 * @param TDbStatementClassification -		 */ -		protected function getStatementClassification($statement='', $defaultClassification=null) { -			return $this->getStatementAnalyser()->getClassificationAnalysis(new TDbStatementAnalysisParameter($statement, $defaultClassification)); -		} -	} - - 	/** -	 * TDistributedDbCommand -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @license http://www.pradosoft.com/license/ -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed -	 * @since 4.0 -	 */ -	class TDistributedDbCommand extends TDbCommand -	{ -		/** -		 * @var TDbStatementClassification -		 */ -		private $_statementClassification; - -		/** -		 * Constructor. -		 * @param TDbConnection the database connection -		 * @param string the SQL statement to be executed -		 * @param TDbStatementClassification Defaults to 'UNKNOWN' -		 */ -		public function __construct(TDbConnection $connection, $text, $classification=TDbStatementClassification::UNKNOWN) -		{ -			$connection->setActive(true); -			parent::__construct($connection, $text); -			$this->_statementClassification = $classification; -			Prado::log($classification . ', ' . $connection->getServerRole() . ': ' . preg_replace('/[\s]+/', ' ', $text), TLogger::DEBUG, 'System.Testing.Data.Distributed.TDistributedDbCommand'); -		} - -		/** -		 * @return TDbStatementClassification -		 */ -		public function getStatementClassification() -		{ -			return $this->_statementClassification; -		} -	} - - - 	/** -	 * TDbConnectionServerRole -	 * -	 * @author Yves Berkholz <godzilla80[at]gmx[dot]net> -	 * @license http://www.pradosoft.com/license/ -	 * @version $Id$ -	 * @package System.Testing.Data.Distributed -	 * @since 4.0 -	 */ -	class TDbConnectionServerRole extends TEnumerable -	{ -		/** -		 * Master Server (Read/Write) -		 */ -		const Master = 'Master'; - -		/** -		 * Slave Server (Read only) -		 */ -		const Slave = 'Slave'; - -		/** -		 * Mirror Server (Read/Write) for further use -		 */ -		//const Mirror = 'Mirror'; -	} -?>
\ No newline at end of file diff --git a/framework/Testing/Data/Schema/TDbColumnSchema.php b/framework/Testing/Data/Schema/TDbColumnSchema.php deleted file mode 100755 index 92b7c0bd..00000000 --- a/framework/Testing/Data/Schema/TDbColumnSchema.php +++ /dev/null @@ -1,145 +0,0 @@ -<?php -/** - * TDbColumnSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbExpression'); - -/** - * TDbColumnSchema class describes the column meta data of a database table. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TDbColumnSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema - * @since 1.0 - */ -class TDbColumnSchema extends TComponent -{ -	/** -	 * @var string name of this column (without quotes). -	 */ -	public $name; -	/** -	 * @var string raw name of this column. This is the quoted name that can be used in SQL queries. -	 */ -	public $rawName; -	/** -	 * @var boolean whether this column can be null. -	 */ -	public $allowNull; -	/** -	 * @var string the DB type of this column. -	 */ -	public $dbType; -	/** -	 * @var string the PHP type of this column. -	 */ -	public $type; -	/** -	 * @var mixed default value of this column -	 */ -	public $defaultValue; -	/** -	 * @var integer size of the column. -	 */ -	public $size; -	/** -	 * @var integer precision of the column data, if it is numeric. -	 */ -	public $precision; -	/** -	 * @var integer scale of the column data, if it is numeric. -	 */ -	public $scale; -	/** -	 * @var boolean whether this column is a primary key -	 */ -	public $isPrimaryKey; -	/** -	 * @var boolean whether this column is a foreign key -	 */ -	public $isForeignKey; - - -	/** -	 * Initializes the column with its DB type and default value. -	 * This sets up the column's PHP type, size, precision, scale as well as default value. -	 * @param string the column's DB type -	 * @param mixed the default value -	 */ -	public function init($dbType, $defaultValue) -	{ -		$this->dbType=$dbType; -		$this->extractType($dbType); -		$this->extractLimit($dbType); -		if($defaultValue!==null) -			$this->extractDefault($defaultValue); -	} - -	/** -	 * Extracts the PHP type from DB type. -	 * @param string DB type -	 */ -	protected function extractType($dbType) -	{ -		if(stripos($dbType,'int')!==false) -			$this->type='integer'; -		else if(stripos($dbType,'bool')!==false) -			$this->type='boolean'; -		else if(preg_match('/(real|floa|doub)/i',$dbType)) -			$this->type='double'; -		else -			$this->type='string'; -	} - -	/** -	 * Extracts size, precision and scale information from column's DB type. -	 * @param string the column's DB type -	 */ -	protected function extractLimit($dbType) -	{ -		if(strpos($dbType,'(') && preg_match('/\((.*)\)/',$dbType,$matches)) -		{ -			$values=explode(',',$matches[1]); -			$this->size=$this->precision=(int)$values[0]; -			if(isset($values[1])) -				$this->scale=(int)$values[1]; -		} -	} - -	/** -	 * Extracts the default value for the column. -	 * The value is typecasted to correct PHP type. -	 * @param mixed the default value obtained from metadata -	 */ -	protected function extractDefault($defaultValue) -	{ -		$this->defaultValue=$this->typecast($defaultValue); -	} - -	/** -	 * Converts the input value to the type that this column is of. -	 * @param mixed input value -	 * @return mixed converted value -	 */ -	public function typecast($value) -	{ -		if(gettype($value)===$this->type || $value===null || $value instanceof TDbExpression) -			return $value; -		if($value==='') -			return $this->type==='string' ? '' : null; -		switch($this->type) -		{ -			case 'integer': return (integer)$value; -			case 'boolean': return (boolean)$value; -			case 'double': return (double)$value; -			case 'string': return (string)$value; -			default: return $value; -		} -	} -} diff --git a/framework/Testing/Data/Schema/TDbCommandBuilder.php b/framework/Testing/Data/Schema/TDbCommandBuilder.php deleted file mode 100755 index 7a196439..00000000 --- a/framework/Testing/Data/Schema/TDbCommandBuilder.php +++ /dev/null @@ -1,656 +0,0 @@ -<?php -/** - * TDbCommandBuilder class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbSchema'); -prado::using('System.Testing.Data.Schema.TDbCriteria'); - -/** - * TDbCommandBuilder provides basic methods to create query commands for tables. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TDbCommandBuilder.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema - * @since 1.0 - */ -class TDbCommandBuilder extends TComponent -{ -	const PARAM_PREFIX=':yp'; - -	private $_schema; -	private $_connection; - -	/** -	 * @param TDbSchema the schema for this command builder -	 */ -	public function __construct($schema) -	{ -		$this->_schema=$schema; -		$this->_connection=$schema->getDbConnection(); -	} - -	/** -	 * @return TDbConnection database connection. -	 */ -	public function getDbConnection() -	{ -		return $this->_connection; -	} - -	/** -	 * @return TDbSchema the schema for this command builder. -	 */ -	public function getSchema() -	{ -		return $this->_schema; -	} - -	/** -	 * Returns the last insertion ID for the specified table. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @return mixed last insertion id. Null is returned if no sequence name. -	 */ -	public function getLastInsertID($table) -	{ -		$this->ensureTable($table); -		if($table->sequenceName!==null) -			return $this->_connection->getLastInsertID($table->sequenceName); -		else -			return null; -	} - -	/** -	 * Creates a SELECT command for a single table. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param TDbCriteria the query criteria -	 * @return TDbCommand query command. -	 */ -	public function createFindCommand($table,$criteria) -	{ -		$this->ensureTable($table); -		$select=is_array($criteria->select) ? implode(', ',$criteria->select) : $criteria->select; -		$sql="SELECT {$select} FROM {$table->rawName}"; -		$sql=$this->applyJoin($sql,$criteria->join); -		$sql=$this->applyCondition($sql,$criteria->condition); -		$sql=$this->applyGroup($sql,$criteria->group); -		$sql=$this->applyHaving($sql,$criteria->having); -		$sql=$this->applyOrder($sql,$criteria->order); -		$sql=$this->applyLimit($sql,$criteria->limit,$criteria->offset); -		$command=$this->_connection->createCommand($sql); -		$this->bindValues($command,$criteria->params); -		return $command; -	} - -	/** -	 * Creates a COUNT(*) command for a single table. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param TDbCriteria the query criteria -	 * @return TDbCommand query command. -	 */ -	public function createCountCommand($table,$criteria) -	{ -		$this->ensureTable($table); -		$criteria->select='COUNT(*)'; -		return $this->createFindCommand($table,$criteria); -	} - -	/** -	 * Creates a DELETE command. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param TDbCriteria the query criteria -	 * @return TDbCommand delete command. -	 */ -	public function createDeleteCommand($table,$criteria) -	{ -		$this->ensureTable($table); -		$sql="DELETE FROM {$table->rawName}"; -		$sql=$this->applyJoin($sql,$criteria->join); -		$sql=$this->applyCondition($sql,$criteria->condition); -		$sql=$this->applyGroup($sql,$criteria->group); -		$sql=$this->applyHaving($sql,$criteria->having); -		$sql=$this->applyOrder($sql,$criteria->order); -		$sql=$this->applyLimit($sql,$criteria->limit,$criteria->offset); -		$command=$this->_connection->createCommand($sql); -		$this->bindValues($command,$criteria->params); -		return $command; -	} - -	/** -	 * Creates an INSERT command. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param array data to be inserted (column name=>column value). If a key is not a valid column name, the corresponding value will be ignored. -	 * @return TDbCommand insert command -	 */ -	public function createInsertCommand($table,$data) -	{ -		$this->ensureTable($table); -		$fields=array(); -		$values=array(); -		$placeholders=array(); -		$i=0; -		foreach($data as $name=>$value) -		{ -			if(($column=$table->getColumn($name))!==null && ($value!==null || $column->allowNull)) -			{ -				$fields[]=$column->rawName; -				if($value instanceof TDbExpression) -					$placeholders[]=(string)$value; -				else -				{ -					$placeholders[]=self::PARAM_PREFIX.$i; -					$values[self::PARAM_PREFIX.$i]=$column->typecast($value); -					$i++; -				} -			} -		} -		$sql="INSERT INTO {$table->rawName} (".implode(', ',$fields).') VALUES ('.implode(', ',$placeholders).')'; -		$command=$this->_connection->createCommand($sql); - -		foreach($values as $name=>$value) -			$command->bindValue($name,$value); - -		return $command; -	} - -	/** -	 * Creates an UPDATE command. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param array list of columns to be updated (name=>value) -	 * @param TDbCriteria the query criteria -	 * @return TDbCommand update command. -	 */ -	public function createUpdateCommand($table,$data,$criteria) -	{ -		$this->ensureTable($table); -		$fields=array(); -		$values=array(); -		$bindByPosition=isset($criteria->params[0]); -		$i=0; -		foreach($data as $name=>$value) -		{ -			if(($column=$table->getColumn($name))!==null) -			{ -				if($value instanceof TDbExpression) -					$fields[]=$column->rawName.'='.(string)$value; -				else if($bindByPosition) -				{ -					$fields[]=$column->rawName.'=?'; -					$values[]=$column->typecast($value); -				} -				else -				{ -					$fields[]=$column->rawName.'='.self::PARAM_PREFIX.$i; -					$values[self::PARAM_PREFIX.$i]=$column->typecast($value); -					$i++; -				} -			} -		} -		if($fields===array()) -			throw new TDbException('No columns are being updated for table "{0}".', -				$table->name); -		$sql="UPDATE {$table->rawName} SET ".implode(', ',$fields); -		$sql=$this->applyJoin($sql,$criteria->join); -		$sql=$this->applyCondition($sql,$criteria->condition); -		$sql=$this->applyOrder($sql,$criteria->order); -		$sql=$this->applyLimit($sql,$criteria->limit,$criteria->offset); - -		$command=$this->_connection->createCommand($sql); -		$this->bindValues($command,array_merge($values,$criteria->params)); - -		return $command; -	} - -	/** -	 * Creates an UPDATE command that increments/decrements certain columns. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param TDbCriteria the query criteria -	 * @param array counters to be updated (counter increments/decrements indexed by column names.) -	 * @return TDbCommand the created command -	 * @throws CException if no counter is specified -	 */ -	public function createUpdateCounterCommand($table,$counters,$criteria) -	{ -		$this->ensureTable($table); -		$fields=array(); -		foreach($counters as $name=>$value) -		{ -			if(($column=$table->getColumn($name))!==null) -			{ -				$value=(int)$value; -				if($value<0) -					$fields[]="{$column->rawName}={$column->rawName}-".(-$value); -				else -					$fields[]="{$column->rawName}={$column->rawName}+".$value; -			} -		} -		if($fields!==array()) -		{ -			$sql="UPDATE {$table->rawName} SET ".implode(', ',$fields); -			$sql=$this->applyJoin($sql,$criteria->join); -			$sql=$this->applyCondition($sql,$criteria->condition); -			$sql=$this->applyOrder($sql,$criteria->order); -			$sql=$this->applyLimit($sql,$criteria->limit,$criteria->offset); -			$command=$this->_connection->createCommand($sql); -			$this->bindValues($command,$criteria->params); -			return $command; -		} -		else -			throw new TDbException('No counter columns are being updated for table "{0}".', -				$table->name); -	} - -	/** -	 * Creates a command based on a given SQL statement. -	 * @param string the explicitly specified SQL statement -	 * @param array parameters that will be bound to the SQL statement -	 * @return TDbCommand the created command -	 */ -	public function createSqlCommand($sql,$params=array()) -	{ -		$command=$this->_connection->createCommand($sql); -		$this->bindValues($command,$params); -		return $command; -	} - -	/** -	 * Alters the SQL to apply JOIN clause. -	 * @param string the SQL statement to be altered -	 * @param string the JOIN clause (starting with join type, such as INNER JOIN) -	 * @return string the altered SQL statement -	 */ -	public function applyJoin($sql,$join) -	{ -		if($join!=='') -			return $sql.' '.$join; -		else -			return $sql; -	} - -	/** -	 * Alters the SQL to apply WHERE clause. -	 * @param string the SQL statement without WHERE clause -	 * @param string the WHERE clause (without WHERE keyword) -	 * @return string the altered SQL statement -	 */ -	public function applyCondition($sql,$condition) -	{ -		if($condition!=='') -			return $sql.' WHERE '.$condition; -		else -			return $sql; -	} - -	/** -	 * Alters the SQL to apply ORDER BY. -	 * @param string SQL statement without ORDER BY. -	 * @param string column ordering -	 * @return string modified SQL applied with ORDER BY. -	 */ -	public function applyOrder($sql,$orderBy) -	{ -		if($orderBy!=='') -			return $sql.' ORDER BY '.$orderBy; -		else -			return $sql; -	} - -	/** -	 * Alters the SQL to apply LIMIT and OFFSET. -	 * Default implementation is applicable for PostgreSQL, MySQL and SQLite. -	 * @param string SQL query string without LIMIT and OFFSET. -	 * @param integer maximum number of rows, -1 to ignore limit. -	 * @param integer row offset, -1 to ignore offset. -	 * @return string SQL with LIMIT and OFFSET -	 */ -	public function applyLimit($sql,$limit,$offset) -	{ -		if($limit>=0) -			$sql.=' LIMIT '.(int)$limit; -		if($offset>0) -			$sql.=' OFFSET '.(int)$offset; -		return $sql; -	} - -	/** -	 * Alters the SQL to apply GROUP BY. -	 * @param string SQL query string without GROUP BY. -	 * @param string GROUP BY -	 * @return string SQL with GROUP BY. -	 */ -	public function applyGroup($sql,$group) -	{ -		if($group!=='') -			return $sql.' GROUP BY '.$group; -		else -			return $sql; -	} - -	/** -	 * Alters the SQL to apply HAVING. -	 * @param string SQL query string without HAVING -	 * @param string HAVING -	 * @return string SQL with HAVING -	 * @since 1.0.1 -	 */ -	public function applyHaving($sql,$having) -	{ -		if($having!=='') -			return $sql.' HAVING '.$having; -		else -			return $sql; -	} - -	/** -	 * Binds parameter values for an SQL command. -	 * @param TDbCommand database command -	 * @param array values for binding (integer-indexed array for question mark placeholders, string-indexed array for named placeholders) -	 */ -	public function bindValues($command, $values) -	{ -		if(($n=count($values))===0) -			return; -		if(isset($values[0])) // question mark placeholders -		{ -			for($i=0;$i<$n;++$i) -				$command->bindValue($i+1,$values[$i]); -		} -		else // named placeholders -		{ -			foreach($values as $name=>$value) -			{ -				if($name[0]!==':') -					$name=':'.$name; -				$command->bindValue($name,$value); -			} -		} -	} - -	/** -	 * Creates a query criteria. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param mixed query condition or criteria. -	 * If a string, it is treated as query condition (the WHERE clause); -	 * If an array, it is treated as the initial values for constructing a {@link TDbCriteria} object; -	 * Otherwise, it should be an instance of {@link TDbCriteria}. -	 * @param array parameters to be bound to an SQL statement. -	 * This is only used when the first parameter is a string (query condition). -	 * In other cases, please use {@link TDbCriteria::params} to set parameters. -	 * @return TDbCriteria the created query criteria -	 * @throws CException if the condition is not string, array and TDbCriteria -	 */ -	public function createCriteria($condition='',$params=array()) -	{ -		if(is_array($condition)) -			$criteria=new TDbCriteria($condition); -		else if($condition instanceof TDbCriteria) -			$criteria=clone $condition; -		else -		{ -			$criteria=new TDbCriteria; -			$criteria->condition=$condition; -			$criteria->params=$params; -		} -		return $criteria; -	} - -	/** -	 * Creates a query criteria with the specified primary key. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param mixed primary key value(s). Use array for multiple primary keys. For composite key, each key value must be an array (column name=>column value). -	 * @param mixed query condition or criteria. -	 * If a string, it is treated as query condition; -	 * If an array, it is treated as the initial values for constructing a {@link TDbCriteria}; -	 * Otherwise, it should be an instance of {@link TDbCriteria}. -	 * @param array parameters to be bound to an SQL statement. -	 * This is only used when the second parameter is a string (query condition). -	 * In other cases, please use {@link TDbCriteria::params} to set parameters. -	 * @return TDbCriteria the created query criteria -	 */ -	public function createPkCriteria($table,$pk,$condition='',$params=array()) -	{ -		$this->ensureTable($table); -		$criteria=$this->createCriteria($condition,$params); -		if(!is_array($pk)) // single key -			$pk=array($pk); -		if(is_array($table->primaryKey) && !isset($pk[0]) && $pk!==array()) // single composite key -			$pk=array($pk); -		$condition=$this->createInCondition($table,$table->primaryKey,$pk); -		if($criteria->condition!=='') -			$criteria->condition=$condition.' AND ('.$criteria->condition.')'; -		else -			$criteria->condition=$condition; - -		return $criteria; -	} - -	/** -	 * Generates the expression for selecting rows of specified primary key values. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param array list of primary key values to be selected within -	 * @param string column prefix (ended with dot). If null, it will be the table name -	 * @return string the expression for selection -	 */ -	public function createPkCondition($table,$values,$prefix=null) -	{ -		$this->ensureTable($table); -		return $this->createInCondition($table,$table->primaryKey,$values,$prefix); -	} - -	/** -	 * Creates a query criteria with the specified column values. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param array column values that should be matched in the query (name=>value) -	 * @param mixed query condition or criteria. -	 * If a string, it is treated as query condition; -	 * If an array, it is treated as the initial values for constructing a {@link TDbCriteria}; -	 * Otherwise, it should be an instance of {@link TDbCriteria}. -	 * @param array parameters to be bound to an SQL statement. -	 * This is only used when the second parameter is a string (query condition). -	 * In other cases, please use {@link TDbCriteria::params} to set parameters. -	 * @return TDbCriteria the created query criteria -	 */ -	public function createColumnCriteria($table,$columns,$condition='',$params=array()) -	{ -		$this->ensureTable($table); -		$criteria=$this->createCriteria($condition,$params); -		$bindByPosition=isset($criteria->params[0]); -		$conditions=array(); -		$values=array(); -		$i=0; -		foreach($columns as $name=>$value) -		{ -			if(($column=$table->getColumn($name))!==null) -			{ -				if($value!==null) -				{ -					if($bindByPosition) -					{ -						$conditions[]=$table->rawName.'.'.$column->rawName.'=?'; -						$values[]=$value; -					} -					else -					{ -						$conditions[]=$table->rawName.'.'.$column->rawName.'='.self::PARAM_PREFIX.$i; -						$values[self::PARAM_PREFIX.$i]=$value; -						$i++; -					} -				} -				else -					$conditions[]=$table->rawName.'.'.$column->rawName.' IS NULL'; -			} -			else -				throw new TDbException('Table "{0}" does not have a column named "{1}".', -					$table->name,$name); -		} -		$criteria->params=array_merge($values,$criteria->params); -		if(isset($conditions[0])) -		{ -			if($criteria->condition!=='') -				$criteria->condition=implode(' AND ',$conditions).' AND ('.$criteria->condition.')'; -			else -				$criteria->condition=implode(' AND ',$conditions); -		} -		return $criteria; -	} - -	/** -	 * Generates the expression for searching the specified keywords within a list of columns. -	 * The search expression is generated using the 'LIKE' SQL syntax. -	 * Every word in the keywords must be present and appear in at least one of the columns. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param array list of column names for potential search condition. -	 * @param mixed search keywords. This can be either a string with space-separated keywords or an array of keywords. -	 * @param string optional column prefix (with dot at the end). If null, the table name will be used as the prefix. -	 * @param boolean whether the search is case-sensitive. Defaults to true. This parameter -	 * has been available since version 1.0.4. -	 * @return string SQL search condition matching on a set of columns. An empty string is returned -	 * if either the column array or the keywords are empty. -	 */ -	public function createSearchCondition($table,$columns,$keywords,$prefix=null,$caseSensitive=true) -	{ -		$this->ensureTable($table); -		if(!is_array($keywords)) -			$keywords=preg_split('/\s+/u',$keywords,-1,PREG_SPLIT_NO_EMPTY); -		if(empty($keywords)) -			return ''; -		if($prefix===null) -			$prefix=$table->rawName.'.'; -		$conditions=array(); -		foreach($columns as $name) -		{ -			if(($column=$table->getColumn($name))===null) -				throw new TDbException('Table "{0}" does not have a column named "{0}".', -					$table->name,$name); -			$condition=array(); -			foreach($keywords as $keyword) -			{ -				if($caseSensitive) -					$condition[]=$prefix.$column->rawName.' LIKE '.$this->_connection->quoteValue('%'.$keyword.'%'); -				else -					$condition[]='LOWER('.$prefix.$column->rawName.') LIKE LOWER('.$this->_connection->quoteValue('%'.$keyword.'%').')'; -			} -			$conditions[]=implode(' AND ',$condition); -		} -		return '('.implode(' OR ',$conditions).')'; -	} - -	/** -	 * Generates the expression for selecting rows of specified primary key values. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param mixed the column name(s). It can be either a string indicating a single column -	 * or an array of column names. If the latter, it stands for a composite key. -	 * @param array list of key values to be selected within -	 * @param string column prefix (ended with dot). If null, it will be the table name -	 * @return string the expression for selection -	 * @since 1.0.4 -	 */ -	public function createInCondition($table,$columnName,$values,$prefix=null) -	{ -		if(($n=count($values))<1) -			return '0=1'; - -		$this->ensureTable($table); - -		if($prefix===null) -			$prefix=$table->rawName.'.'; - -		$db=$this->_connection; - -		if(is_array($columnName) && count($columnName)===1) -			$columnName=reset($columnName); - -		if(is_string($columnName)) // simple key -		{ -			if(!isset($table->columns[$columnName])) -				throw new TDbException('Table "{0}" does not have a column named "{1}".', -				$table->name, $columnName); -			$column=$table->columns[$columnName]; - -			foreach($values as &$value) -			{ -				$value=$column->typecast($value); -				if(is_string($value)) -					$value=$db->quoteValue($value); -			} -			if($n===1) -				return $prefix.$column->rawName.($values[0]===null?' IS NULL':'='.$values[0]); -			else -				return $prefix.$column->rawName.' IN ('.implode(', ',$values).')'; -		} -		else if(is_array($columnName)) // composite key: $values=array(array('pk1'=>'v1','pk2'=>'v2'),array(...)) -		{ -			foreach($columnName as $name) -			{ -				if(!isset($table->columns[$name])) -					throw new TDbException('Table "{0}" does not have a column named "{1}".', -					$table->name, $name); - -				for($i=0;$i<$n;++$i) -				{ -					if(isset($values[$i][$name])) -					{ -						$value=$table->columns[$name]->typecast($values[$i][$name]); -						if(is_string($value)) -							$values[$i][$name]=$db->quoteValue($value); -						else -							$values[$i][$name]=$value; -					} -					else -						throw new TDbException('The value for the column "{1}" is not supplied when querying the table "{0}".', -							$table->name,$name); -				} -			} -			if(count($values)===1) -			{ -				$entries=array(); -				foreach($values[0] as $name=>$value) -					$entries[]=$prefix.$table->columns[$name]->rawName.($value===null?' IS NULL':'='.$value); -				return implode(' AND ',$entries); -			} - -			return $this->createCompositeInCondition($table,$values,$prefix); -		} -		else -			throw new TDbException('Column name must be either a string or an array.'); -	} - -	/** -	 * Generates the expression for selecting rows with specified composite key values. -	 * @param TDbTableSchema the table schema -	 * @param array list of primary key values to be selected within -	 * @param string column prefix (ended with dot) -	 * @return string the expression for selection -	 * @since 1.0.4 -	 */ -	protected function createCompositeInCondition($table,$values,$prefix) -	{ -		$keyNames=array(); -		foreach(array_keys($values[0]) as $name) -			$keyNames[]=$prefix.$table->columns[$name]->rawName; -		$vs=array(); -		foreach($values as $value) -			$vs[]='('.implode(', ',$value).')'; -		return '('.implode(', ',$keyNames).') IN ('.implode(', ',$vs).')'; -	} - -	/** -	 * Checks if the parameter is a valid table schema. -	 * If it is a string, the corresponding table schema will be retrieved. -	 * @param mixed table schema ({@link TDbTableSchema}) or table name (string). -	 * If this refers to a valid table name, this parameter will be returned with the corresponding table schema. -	 * @throws TDbException if the table name is not valid -	 * @since 1.0.4 -	 */ -	protected function ensureTable(&$table) -	{ -		if(is_string($table) && ($table=$this->_schema->getTable($tableName=$table))===null) -			throw new TDbException('Table "{0}" does not exist.', -				$tableName); -	} -} diff --git a/framework/Testing/Data/Schema/TDbCriteria.php b/framework/Testing/Data/Schema/TDbCriteria.php deleted file mode 100755 index 585765e9..00000000 --- a/framework/Testing/Data/Schema/TDbCriteria.php +++ /dev/null @@ -1,166 +0,0 @@ -<?php -/** - * TDbCriteria class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -/** - * TDbCriteria represents a query criteria, such as conditions, ordering by, limit/offset. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TDbCriteria.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.schema - * @since 1.0 - */ -class TDbCriteria -{ -	/** -	 * @var mixed the columns being selected. This refers to the SELECT clause in an SQL -	 * statement. The property can be either a string (column names separated by commas) -	 * or an array of column names. Defaults to '*', meaning all columns. -	 */ -	public $select='*'; -	/** -	 * @var string query condition. This refers to the WHERE clause in an SQL statement. -	 * For example, <code>age>31 AND team=1</code>. -	 */ -	public $condition=''; -	/** -	 * @var array list of query parameter values indexed by parameter placeholders. -	 * For example, <code>array(':name'=>'Dan', ':age'=>31)</code>. -	 */ -	public $params=array(); -	/** -	 * @var integer maximum number of records to be returned. If less than 0, it means no limit. -	 */ -	public $limit=-1; -	/** -	 * @var integer zero-based offset from where the records are to be returned. If less than 0, it means starting from the beginning. -	 */ -	public $offset=-1; -	/** -	 * @var string how to sort the query results. This refers to the ORDER BY clause in an SQL statement. -	 */ -	public $order=''; -	/** -	 * @var string how to group the query results. This refers to the GROUP BY clause in an SQL statement. -	 * For example, <code>'projectID, teamID'</code>. -	 */ -	public $group=''; -	/** -	 * @var string how to join with other tables. This refers to the JOIN clause in an SQL statement. -	 * For example, <code>'LEFT JOIN users ON users.id=authorID'</code>. -	 */ -	public $join=''; -	/** -	 * @var string the condition to be applied with GROUP-BY clause. -	 * For example, <code>'SUM(revenue)<50000'</code>. -	 * @since 1.0.1 -	 */ -	public $having=''; - -	/** -	 * Constructor. -	 * @param array criteria initial property values (indexed by property name) -	 */ -	public function __construct($data=array()) -	{ -		foreach($data as $name=>$value) -			$this->$name=$value; -	} - -	/** -	 * Merges with another criteria. -	 * In general, the merging makes the resulting criteria more restrictive. -	 * For example, if both criterias have conditions, they will be 'AND' together. -	 * Also, the criteria passed as the parameter takes precedence in case -	 * two options cannot be merged (e.g. LIMIT, OFFSET). -	 * @param TDbCriteria the criteria to be merged with. -	 * @param boolean whether to use 'AND' to merge condition and having options. -	 * If false, 'OR' will be used instead. Defaults to 'AND'. This parameter has been -	 * available since version 1.0.6. -	 * @since 1.0.5 -	 */ -	public function mergeWith($criteria,$useAnd=true) -	{ -		$and=$useAnd ? 'AND' : 'OR'; -		if(is_array($criteria)) -			$criteria=new self($criteria); -		if($this->select!==$criteria->select) -		{ -			if($this->select==='*') -				$this->select=$criteria->select; -			else if($criteria->select!=='*') -			{ -				$select1=is_string($this->select)?preg_split('/\s*,\s*/',trim($this->select),-1,PREG_SPLIT_NO_EMPTY):$this->select; -				$select2=is_string($criteria->select)?preg_split('/\s*,\s*/',trim($criteria->select),-1,PREG_SPLIT_NO_EMPTY):$criteria->select; -				$this->select=array_merge($select1,array_diff($select2,$select1)); -			} -		} - -		if($this->condition!==$criteria->condition) -		{ -			if($this->condition==='') -				$this->condition=$criteria->condition; -			else if($criteria->condition!=='') -				$this->condition="({$this->condition}) $and ({$criteria->condition})"; -		} - -		if($this->params!==$criteria->params) -			$this->params=array_merge($this->params,$criteria->params); - -		if($criteria->limit>0) -			$this->limit=$criteria->limit; - -		if($criteria->offset>=0) -			$this->offset=$criteria->offset; - -		if($this->order!==$criteria->order) -		{ -			if($this->order==='') -				$this->order=$criteria->order; -			else if($criteria->order!=='') -				$this->order.=', '.$criteria->order; -		} - -		if($this->group!==$criteria->group) -		{ -			if($this->group==='') -				$this->group=$criteria->group; -			else if($criteria->group!=='') -				$this->group.=', '.$criteria->group; -		} - -		if($this->join!==$criteria->join) -		{ -			if($this->join==='') -				$this->join=$criteria->join; -			else if($criteria->join!=='') -				$this->join.=' '.$criteria->join; -		} - -		if($this->having!==$criteria->having) -		{ -			if($this->having==='') -				$this->having=$criteria->having; -			else if($criteria->having!=='') -				$this->having="({$this->having}) $and ({$criteria->having})"; -		} -	} - -	/** -	 * @return array the array representation of the criteria -	 * @since 1.0.6 -	 */ -	public function toArray() -	{ -		$result=array(); -		foreach(array('select', 'condition', 'params', 'limit', 'offset', 'order', 'group', 'join', 'having') as $name) -			$result[$name]=$this->$name; -		return $result; -	} -} diff --git a/framework/Testing/Data/Schema/TDbExpression.php b/framework/Testing/Data/Schema/TDbExpression.php deleted file mode 100755 index a1819000..00000000 --- a/framework/Testing/Data/Schema/TDbExpression.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php -/** - * TDbExpression class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -/** - * TDbExpression represents a DB expression that does not need escaping. - * TDbExpression is mainly used in {@link CActiveRecord} as attribute values. - * When inserting or updating a {@link CActiveRecord}, attribute values of - * type TDbExpression will be directly put into the corresponding SQL statement - * without escaping. A typical usage is that an attribute is set with 'NOW()' - * expression so that saving the record would fill the corresponding column - * with the current DB server timestamp. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TDbExpression.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema - * @since 1.0.2 - */ -class TDbExpression extends TComponent -{ -	/** -	 * @var string the DB expression -	 */ -	public $expression; - -	/** -	 * Constructor. -	 * @param string the DB expression -	 */ -	public function __construct($expression) -	{ -		$this->expression=$expression; -	} - -	/** -	 * String magic method -	 * @return string the DB expression -	 */ -	public function __toString() -	{ -		return $this->expression; -	} -} diff --git a/framework/Testing/Data/Schema/TDbSchema.php b/framework/Testing/Data/Schema/TDbSchema.php deleted file mode 100755 index 2c568e7e..00000000 --- a/framework/Testing/Data/Schema/TDbSchema.php +++ /dev/null @@ -1,193 +0,0 @@ -<?php -/** - * TDbSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbCommandBuilder'); - -/** - * TDbSchema is the base class for retrieving metadata information. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TDbSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema - * @since 1.0 - */ -abstract class TDbSchema extends TComponent -{ -	private $_tableNames=array(); -	private $_tables=array(); -	private $_connection; -	private $_builder; -	private $_cacheExclude=array(); - -	/** -	 * Creates a table instance representing the metadata for the named table. -	 * @return TDbTableSchema driver dependent table metadata, null if the table does not exist. -	 */ -	abstract protected function createTable($name); - -	/** -	 * Constructor. -	 * @param TDbConnection database connection. -	 */ -	public function __construct($conn) -	{ -		$conn->setActive(true); -		$this->_connection=$conn; -		foreach($conn->schemaCachingExclude as $name) -			$this->_cacheExclude[$name]=true; -	} - -	/** -	 * @return TDbConnection database connection. The connection is active. -	 */ -	public function getDbConnection() -	{ -		return $this->_connection; -	} - -	/** -	 * Obtains the metadata for the named table. -	 * @param string table name -	 * @return TDbTableSchema table metadata. Null if the named table does not exist. -	 */ -	public function getTable($name) -	{ -		if(isset($this->_tables[$name])) -			return $this->_tables[$name]; -		else if(!isset($this->_cacheExclude[$name]) && ($duration=$this->_connection->schemaCachingDuration)>0 && ($cache=prado::getApplication()->getCache())!==null) -		{ -			$key='prado:dbschema'.$this->_connection->connectionString.':'.$this->_connection->username.':'.$name; -			if(($table=$cache->get($key))===false) -			{ -				$table=$this->createTable($name); -				$cache->set($key,$table,$duration); -			} -			return $this->_tables[$name]=$table; -		} -		else -			return $this->_tables[$name]=$this->createTable($name); -	} - -	/** -	 * Returns the metadata for all tables in the database. -	 * @param string the schema of the tables. Defaults to empty string, meaning the current or default schema. -	 * @return array the metadata for all tables in the database. -	 * Each array element is an instance of {@link TDbTableSchema} (or its child class). -	 * The array keys are table names. -	 * @since 1.0.2 -	 */ -	public function getTables($schema='') -	{ -		$tables=array(); -		foreach($this->getTableNames($schema) as $name) -			$tables[$name]=$this->getTable($name); -		return $tables; -	} - -	/** -	 * Returns all table names in the database. -	 * @param string the schema of the tables. Defaults to empty string, meaning the current or default schema. -	 * If not empty, the returned table names will be prefixed with the schema name. -	 * @return array all table names in the database. -	 * @since 1.0.2 -	 */ -	public function getTableNames($schema='') -	{ -		if(!isset($this->_tableNames[$schema])) -			$this->_tableNames[$schema]=$this->findTableNames($schema); -		return $this->_tableNames[$schema]; -	} - -	/** -	 * @return TDbCommandBuilder the SQL command builder for this connection. -	 */ -	public function getCommandBuilder() -	{ -		if($this->_builder!==null) -			return $this->_builder; -		else -			return $this->_builder=$this->createCommandBuilder(); -	} - -	/** -	 * Refreshes the schema. -	 * This method resets the loaded table metadata and command builder -	 * so that they can be recreated to reflect the change of schema. -	 */ -	public function refresh() -	{ -		$this->_tables=array(); -		$this->_builder=null; -	} - -	/** -	 * Quotes a table name for use in a query. -	 * @param string table name -	 * @return string the properly quoted table name -	 */ -	public function quoteTableName($name) -	{ -		return "'".$name."'"; -	} - -	/** -	 * Quotes a column name for use in a query. -	 * @param string column name -	 * @return string the properly quoted column name -	 */ -	public function quoteColumnName($name) -	{ -		return '"'.$name.'"'; -	} - -	/** -	 * Compares two table names. -	 * The table names can be either quoted or unquoted. This method -	 * will consider both cases. -	 * @param string table name 1 -	 * @param string table name 2 -	 * @return boolean whether the two table names refer to the same table. -	 */ -	public function compareTableNames($name1,$name2) -	{ -		$name1=str_replace(array('"','`',"'"),'',$name1); -		$name2=str_replace(array('"','`',"'"),'',$name2); -		if(($pos=strrpos($name1,'.'))!==false) -			$name1=substr($name1,$pos+1); -		if(($pos=strrpos($name2,'.'))!==false) -			$name2=substr($name2,$pos+1); -		return $name1===$name2; -	} - -	/** -	 * Creates a command builder for the database. -	 * This method may be overridden by child classes to create a DBMS-specific command builder. -	 * @return TDbCommandBuilder command builder instance -	 */ -	protected function createCommandBuilder() -	{ -		return new TDbCommandBuilder($this); -	} - -	/** -	 * Returns all table names in the database. -	 * This method should be overridden by child classes in order to support this feature -	 * because the default implemenation simply throws an exception. -	 * @param string the schema of the tables. Defaults to empty string, meaning the current or default schema. -	 * If not empty, the returned table names will be prefixed with the schema name. -	 * @return array all table names in the database. -	 * @since 1.0.2 -	 */ -	protected function findTableNames($schema='') -	{ -		throw new TDbException('{0} does not support fetching all table names.', -			get_class($this)); -	} -} diff --git a/framework/Testing/Data/Schema/TDbTableSchema.php b/framework/Testing/Data/Schema/TDbTableSchema.php deleted file mode 100755 index 8472059b..00000000 --- a/framework/Testing/Data/Schema/TDbTableSchema.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** - * TDbTableSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -/** - * TDbTableSchema is the base class for representing the metadata of a database table. - * - * It may be extended by different DBMS driver to provide DBMS-specific table metadata. - * - * TDbTableSchema provides the following information about a table: - * <ul> - * <li>{@link name}</li> - * <li>{@link rawName}</li> - * <li>{@link columns}</li> - * <li>{@link primaryKey}</li> - * <li>{@link foreignKeys}</li> - * <li>{@link sequenceName}</li> - * </ul> - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TDbTableSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema - * @since 1.0 - */ -class TDbTableSchema extends TComponent -{ -	/** -	 * @var string name of this table. -	 */ -	public $name; -	/** -	 * @var string raw name of this table. This is the quoted version of table name with optional schema name. It can be directly used in SQLs. -	 */ -	public $rawName; -	/** -	 * @var string|array primary key name of this table. If composite key, an array of key names is returned. -	 */ -	public $primaryKey; -	/** -	 * @var string sequence name for the primary key. Null if no sequence. -	 */ -	public $sequenceName; -	/** -	 * @var array foreign keys of this table. The array is indexed by column name. Each value is an array of foreign table name and foreign column name. -	 */ -	public $foreignKeys=array(); -	/** -	 * @var array column metadata of this table. Each array element is a TDbColumnSchema object, indexed by column names. -	 */ -	public $columns=array(); - -	/** -	 * Gets the named column metadata. -	 * This is a convenient method for retrieving a named column even if it does not exist. -	 * @param string column name -	 * @return TDbColumnSchema metadata of the named column. Null if the named column does not exist. -	 */ -	public function getColumn($name) -	{ -		return isset($this->columns[$name]) ? $this->columns[$name] : null; -	} - -	/** -	 * @return array list of column names -	 */ -	public function getColumnNames() -	{ -		return array_keys($this->columns); -	} -} diff --git a/framework/Testing/Data/Schema/mssql/TMssqlColumnSchema.php b/framework/Testing/Data/Schema/mssql/TMssqlColumnSchema.php deleted file mode 100755 index 0123f183..00000000 --- a/framework/Testing/Data/Schema/mssql/TMssqlColumnSchema.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -/** - * TMssqlColumnSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @author Christophe Boulain <Christophe.Boulain@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbColumnSchema'); - -/** - * TMssqlColumnSchema class describes the column meta data of a MSSQL table. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @author Christophe Boulain <Christophe.Boulain@gmail.com> - * @version $Id: TMssqlColumnSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.mssql - * @since 1.0.4 - */ -class TMssqlColumnSchema extends TDbColumnSchema -{ -	/** -	 * Extracts the PHP type from DB type. -	 * @param string DB type -	 */ -	protected function extractType($dbType) -	{ -		if(strpos($dbType,'bigint')!==false || strpos($dbType,'float')!==false || strpos($dbType,'real')!==false) -			$this->type='double'; -		else if(strpos($dbType,'int')!==false || strpos($dbType,'smallint')!==false || strpos($dbType,'tinyint')) -			$this->type='integer'; -		else if(strpos($dbType,'bit')!==false) -			$this->type='boolean'; -		else -			$this->type='string'; -	} - -	protected function extractDefault($defaultValue) -	{ -		if($this->dbType==='timestamp' ) -			$this->defaultValue=null; -		else -			parent::extractDefault(str_replace(array('(',')',"'"), '', $defaultValue)); -	} - -	/** -	 * Extracts size, precision and scale information from column's DB type. -	 * We do nothing here, since sizes and precisions have been computed before. -	 * @param string the column's DB type -	 */ -	protected function extractLimit($dbType) -	{ -	} -} diff --git a/framework/Testing/Data/Schema/mssql/TMssqlCommandBuilder.php b/framework/Testing/Data/Schema/mssql/TMssqlCommandBuilder.php deleted file mode 100755 index 54190f33..00000000 --- a/framework/Testing/Data/Schema/mssql/TMssqlCommandBuilder.php +++ /dev/null @@ -1,304 +0,0 @@ -<?php -/** - * CMsCommandBuilder class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @author Christophe Boulain <Christophe.Boulain@gmail.com> - * @author Wei Zhuo <weizhuo[at]gmail[dot]com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using ('System.Testing.Data.schame.TDbCommandBuilder'); - -/** - * TMssqlCommandBuilder provides basic methods to create query commands for tables for Mssql Servers. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @author Christophe Boulain <Christophe.Boulain@gmail.com> - * @author Wei Zhuo <weizhuo[at]gmail[dot]com> - * @version $Id: TMssqlCommandBuilder.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.schema.mssql - * @since 1.0.4 - */ -class TMssqlCommandBuilder extends TDbCommandBuilder -{ -   	/** -	 * Returns the last insertion ID for the specified table. -	 * Override parent implemantation since PDO mssql driver does not provide this method -	 * @param TDbTableSchema the table metadata -	 * @return mixed last insertion id. Null is returned if no sequence name. -	 */ -	public function getLastInsertID($table) -	{ -		if($table->sequenceName!==null) -			return $this->getDbConnection()->createCommand('SELECT SCOPE_IDENTITY()')->queryScalar(); -		else -			return null; -	} - -	/** -	 * Creates a COUNT(*) command for a single table. -	 * Override parent implementation to remove the order clause of criteria if it exists -	 * @param TDbTableSchema the table metadata -	 * @param TDbCriteria the query criteria -	 * @return TDbCommand query command. -	 */ -	public function createCountCommand($table,$criteria) -	{ -		$criteria->order=''; -		return parent::createCountCommand($table, $criteria); -	} - -	/** -	 * Creates a SELECT command for a single table. -	 * Override parent implementation to check if an orderby clause if specified when querying with an offset -	 * @param TDbTableSchema the table metadata -	 * @param TDbCriteria the query criteria -	 * @return TDbCommand query command. -	 */ -	public function createFindCommand($table,$criteria) -	{ -		$criteria=$this->checkCriteria($table,$criteria); -		return parent::createFindCommand($table,$criteria); - -	} - -	/** -	 * Creates an UPDATE command. -	 * Override parent implementation because mssql don't want to update an identity column -	 * @param TDbTableSchema the table metadata -	 * @param array list of columns to be updated (name=>value) -	 * @param TDbCriteria the query criteria -	 * @return TDbCommand update command. -	 */ -	public function createUpdateCommand($table,$data,$criteria) -	{ -		$criteria=$this->checkCriteria($table,$criteria); -		$fields=array(); -		$values=array(); -		$bindByPosition=isset($criteria->params[0]); -		foreach($data as $name=>$value) -		{ -			if(($column=$table->getColumn($name))!==null) -			{ -				if ($table->sequenceName !== null && $column->isPrimaryKey === true) continue; -				if($value instanceof TDbExpression) -					$fields[]=$column->rawName.'='.(string)$value; -				else if($bindByPosition) -				{ -					$fields[]=$column->rawName.'=?'; -					$values[]=$column->typecast($value); -				} -				else -				{ -					$fields[]=$column->rawName.'=:'.$name; -					$values[':'.$name]=$column->typecast($value); -				} -			} -		} -		if($fields===array()) -			throw new TDbException('No columns are being updated for table "{0}".', -				$table->name); -		$sql="UPDATE {$table->rawName} SET ".implode(', ',$fields); -		$sql=$this->applyJoin($sql,$criteria->join); -		$sql=$this->applyCondition($sql,$criteria->condition); -		$sql=$this->applyOrder($sql,$criteria->order); -		$sql=$this->applyLimit($sql,$criteria->limit,$criteria->offset); - -		$command=$this->getDbConnection()->createCommand($sql); -		$this->bindValues($command,array_merge($values,$criteria->params)); - -		return $command; -	} - -	/** -	 * Creates a DELETE command. -	 * Override parent implementation to check if an orderby clause if specified when querying with an offset -	 * @param TDbTableSchema the table metadata -	 * @param TDbCriteria the query criteria -	 * @return TDbCommand delete command. -	 */ -	public function createDeleteCommand($table,$criteria) -	{ -		$criteria=$this->checkCriteria($table, $criteria); -		return parent::createDeleteCommand($table, $criteria); -	} - -	/** -	 * Creates an UPDATE command that increments/decrements certain columns. -	 * Override parent implementation to check if an orderby clause if specified when querying with an offset -	 * @param TDbTableSchema the table metadata -	 * @param TDbCriteria the query criteria -	 * @param array counters to be updated (counter increments/decrements indexed by column names.) -	 * @return TDbCommand the created command -	 * @throws CException if no counter is specified -	 */ -	public function createUpdateCounterCommand($table,$counters,$criteria) -	{ -		$criteria=$this->checkCriteria($table, $criteria); -		return parent::createUpdateCounterCommand($table, $counters, $criteria); -	} - -	/** -	 * This is a port from Prado Framework. -	 * -	 * Overrides parent implementation. Alters the sql to apply $limit and $offset. -	 * The idea for limit with offset is done by modifying the sql on the fly -	 * with numerous assumptions on the structure of the sql string. -	 * The modification is done with reference to the notes from -	 * http://troels.arvin.dk/db/rdbms/#select-limit-offset -	 * -	 * <code> -	 * SELECT * FROM ( -	 *  SELECT TOP n * FROM ( -	 *    SELECT TOP z columns      -- (z=n+skip) -	 *    FROM tablename -	 *    ORDER BY key ASC -	 *  ) AS FOO ORDER BY key DESC -- ('FOO' may be anything) -	 * ) AS BAR ORDER BY key ASC    -- ('BAR' may be anything) -	 * </code> -	 * -	 * <b>Regular expressions are used to alter the SQL query. The resulting SQL query -	 * may be malformed for complex queries.</b> The following restrictions apply -	 * -	 * <ul> -	 *   <li> -	 * In particular, <b>commas</b> should <b>NOT</b> -	 * be used as part of the ordering expression or identifier. Commas must only be -	 * used for separating the ordering clauses. -	 *  </li> -	 *  <li> -	 * In the ORDER BY clause, the column name should NOT be be qualified -	 * with a table name or view name. Alias the column names or use column index. -	 * </li> -	 * <li> -	 * No clauses should follow the ORDER BY clause, e.g. no COMPUTE or FOR clauses. -	 * </li> -	 * </ul> -	 * -	 * @param string SQL query string. -	 * @param integer maximum number of rows, -1 to ignore limit. -	 * @param integer row offset, -1 to ignore offset. -	 * @return string SQL with limit and offset. -	 * -	 * @author Wei Zhuo <weizhuo[at]gmail[dot]com> -	 */ -	public function applyLimit($sql, $limit, $offset) -	{ -		$limit = $limit!==null ? intval($limit) : -1; -		$offset = $offset!==null ? intval($offset) : -1; -		if ($limit > 0 && $offset <= 0) //just limit -			$sql = preg_replace('/^([\s(])*SELECT( DISTINCT)?(?!\s*TOP\s*\()/i',"\\1SELECT\\2 TOP $limit", $sql); -		else if($limit > 0 && $offset > 0) -			$sql = $this->rewriteLimitOffsetSql($sql, $limit,$offset); -		return $sql; -	} - -	/** -	 * Rewrite sql to apply $limit > and $offset > 0 for MSSQL database. -	 * See http://troels.arvin.dk/db/rdbms/#select-limit-offset -	 * @param string sql query -	 * @param integer $limit > 0 -	 * @param integer $offset > 0 -	 * @return sql modified sql query applied with limit and offset. -	 * -	 * @author Wei Zhuo <weizhuo[at]gmail[dot]com> -	 */ -	protected function rewriteLimitOffsetSql($sql, $limit, $offset) -	{ -		$fetch = $limit+$offset; -		$sql = preg_replace('/^([\s(])*SELECT( DISTINCT)?(?!\s*TOP\s*\()/i',"\\1SELECT\\2 TOP $fetch", $sql); -		$ordering = $this->findOrdering($sql); - -		$orginalOrdering = $this->joinOrdering($ordering); -		$reverseOrdering = $this->joinOrdering($this->reverseDirection($ordering)); -		$sql = "SELECT * FROM (SELECT TOP {$limit} * FROM ($sql) as [__inner top table__] {$reverseOrdering}) as [__outer top table__] {$orginalOrdering}"; -		return $sql; -	} - -	/** -	 * Base on simplified syntax http://msdn2.microsoft.com/en-us/library/aa259187(SQL.80).aspx -	 * -	 * @param string $sql -	 * @return array ordering expression as key and ordering direction as value -	 * -	 * @author Wei Zhuo <weizhuo[at]gmail[dot]com> -	 */ -	protected function findOrdering($sql) -	{ -		if(!preg_match('/ORDER BY/i', $sql)) -			return array(); -		$matches=array(); -		$ordering=array(); -		preg_match_all('/(ORDER BY)[\s"\[](.*)(ASC|DESC)?(?:[\s"\[]|$|COMPUTE|FOR)/i', $sql, $matches); -		if(count($matches)>1 && count($matches[2]) > 0) -		{ -			$parts = explode(',', $matches[2][0]); -			foreach($parts as $part) -			{ -				$subs=array(); -				if(preg_match_all('/(.*)[\s"\]](ASC|DESC)$/i', trim($part), $subs)) -				{ -					if(count($subs) > 1 && count($subs[2]) > 0) -					{ -						$ordering[$subs[1][0]] = $subs[2][0]; -					} -					//else what? -				} -				else -					$ordering[trim($part)] = 'ASC'; -			} -		} -		return $ordering; -	} - -	/** -	 * @param array ordering obtained from findOrdering() -	 * @return string concat the orderings -	 * -	 * @author Wei Zhuo <weizhuo[at]gmail[dot]com> -	 */ -	protected function joinOrdering($orders) -	{ -		if(count($orders)>0) -		{ -			$str=array(); -			foreach($orders as $column => $direction) -				$str[] = $column.' '.$direction; -			return 'ORDER BY '.implode(', ', $str); -		} -	} - -	/** -	 * @param array original ordering -	 * @return array ordering with reversed direction. -	 * -	 * @author Wei Zhuo <weizhuo[at]gmail[dot]com> -	 */ -	protected function reverseDirection($orders) -	{ -		foreach($orders as $column => $direction) -			$orders[$column] = strtolower(trim($direction))==='desc' ? 'ASC' : 'DESC'; -		return $orders; -	} - - -	/** -	 * Checks if the criteria has an order by clause when using offset/limit. -	 * Override parent implementation to check if an orderby clause if specified when querying with an offset -	 * If not, order it by pk. -	 * @param TMssqlTableSchema table schema -	 * @param TDbCriteria criteria -	 * @return TDbCrireria the modified criteria -	 */ -	protected function checkCriteria($table, $criteria) -	{ -		if ($criteria->offset > 0 && $criteria->order==='') -		{ -			$criteria->order=is_array($table->primaryKey)?implode(',',$table->primaryKey):$table->primaryKey; -		} -		return $criteria; -	} -} diff --git a/framework/Testing/Data/Schema/mssql/TMssqlPdoAdapter.php b/framework/Testing/Data/Schema/mssql/TMssqlPdoAdapter.php deleted file mode 100755 index 6f8777dd..00000000 --- a/framework/Testing/Data/Schema/mssql/TMssqlPdoAdapter.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -/** - * TMssqlPdo class file - * - * @author Christophe Boulain <Christophe.Boulain@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -/** - * This is an extension of default PDO class for mssql driver only - * It provides some missing functionalities of pdo driver - * @author Christophe Boulain <Christophe.Boulain@gmail.com> - * @version $Id: TMssqlPdoAdapter.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.schema.mssql - * @since 1.0.4 - */ -class TMssqlPdoAdapter extends PDO -{ -	/** -	 * Get the last inserted id value -	 * MSSQL doesn't support sequence, so, argument is ignored -	 * -	 * @param string sequence name. Defaults to null -	 * @return int last inserted id -	 */ -	public function lastInsertId ($sequence=NULL) -	{ -		return $this->query('SELECT SCOPE_IDENTITY()')->fetchColumn(); -	} - -	/** -	 * Begin a transaction -	 * -	 * Is is necessary to override pdo's method, as mssql pdo drivers -	 * does not support transaction -	 * -	 * @return boolean -	 */ -	public function beginTransaction () -	{ -		$this->exec('BEGIN TRANSACTION'); -		return true; -	} - -	/** -	 * Commit a transaction -	 * -	 * Is is necessary to override pdo's method, as mssql pdo drivers -	 * does not support transaction -	 * -	 * @return boolean -	 */ -	public function commit () -	{ -		$this->exec('COMMIT TRANSACTION'); -		return true; -	} - -	/** -	 * Rollback a transaction -	 * -	 * Is is necessary to override pdo's method, ac mssql pdo drivers -	 * does not support transaction -	 * -	 * @return boolean -	 */ -	public function rollBack () -	{ -		$this->exec('ROLLBACK TRANSACTION'); -		return true; -	} -} diff --git a/framework/Testing/Data/Schema/mssql/TMssqlSchema.php b/framework/Testing/Data/Schema/mssql/TMssqlSchema.php deleted file mode 100755 index d728a6ce..00000000 --- a/framework/Testing/Data/Schema/mssql/TMssqlSchema.php +++ /dev/null @@ -1,313 +0,0 @@ -<?php -/** - * TMssqlSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @author Christophe Boulain <Christophe.Boulain@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbSchema'); -prado::using('System.Testing.Data.Schema.mssql.*'); - -/** - * TMssqlSchema is the class for retrieving metadata information from a MS SQL Server database. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @author Christophe Boulain <Christophe.Boulain@gmail.com> - * @version $Id: TMssqlSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.mssql - * @since 1.0.4 - */ -class TMssqlSchema extends TDbSchema -{ -	const DEFAULT_SCHEMA='dbo'; - - -	/** -	 * Quotes a table name for use in a query. -	 * @param string table name -	 * @return string the properly quoted table name -	 */ -	public function quoteTableName($name) -	{ -		if (strpos($name,'.')===false) -			return '['.$name.']'; -		$names=explode('.',$name); -		foreach ($names as &$n) -			$n = '['.$n.']'; -		return implode('.',$names); -	} - -	/** -	 * Quotes a column name for use in a query. -	 * @param string column name -	 * @return string the properly quoted column name -	 */ -	public function quoteColumnName($name) -	{ -		return '['.$name.']'; -	} - -	/** -	 * Compares two table names. -	 * The table names can be either quoted or unquoted. This method -	 * will consider both cases. -	 * @param string table name 1 -	 * @param string table name 2 -	 * @return boolean whether the two table names refer to the same table. -	 */ -	public function compareTableNames($name1,$name2) -	{ -		$name1=str_replace(array('[',']'),'',$name1); -		$name1=str_replace(array('[',']'),'',$name2); -		return parent::compareTableNames(strtolower($name1),strtolower($name2)); -	} - -	/** -	 * Creates a table instance representing the metadata for the named table. -	 * @return CMysqlTableSchema driver dependent table metadata. Null if the table does not exist. -	 */ -	protected function createTable($name) -	{ -		$table=new TMssqlTableSchema; -		$this->resolveTableNames($table,$name); -		//if (!in_array($table->name, $this->tableNames)) return null; -		$table->primaryKey=$this->findPrimaryKey($table); -		$table->foreignKeys=$this->findForeignKeys($table); -		if($this->findColumns($table)) -		{ -			return $table; -		} -		else -			return null; -	} - -	/** -	 * Generates various kinds of table names. -	 * @param CMysqlTableSchema the table instance -	 * @param string the unquoted table name -	 */ -	protected function resolveTableNames($table,$name) -	{ -		$parts=explode('.',str_replace(array('[',']'),'',$name)); -		if(($c=count($parts))==3) -		{ -			// Catalog name, schema name and table name provided -			$table->catalogName=$parts[0]; -			$table->schemaName=$parts[1]; -			$table->name=$parts[2]; -			$table->rawName=$this->quoteTableName($table->catalogName).'.'.$this->quoteTableName($table->schemaName).'.'.$this->quoteTableName($table->name); -		} -		elseif ($c==2) -		{ -			// Only schema name and table name provided -			$table->name=$parts[1]; -			$table->schemaName=$parts[0]; -			$table->rawName=$this->quoteTableName($table->schemaName).'.'.$this->quoteTableName($table->name); -		} -		else -		{ -			// Only the name given, we need to get at least the schema name -			//if (empty($this->_schemaNames)) $this->findTableNames(); -			$table->name=$parts[0]; -			$table->schemaName=self::DEFAULT_SCHEMA; -			$table->rawName=$this->quoteTableName($table->schemaName).'.'.$this->quoteTableName($table->name); -		} -	} - -	/** -	 * Gets the primary key column(s) details for the given table. -	 * @param TMssqlTableSchema table -	 * @return mixed primary keys (null if no pk, string if only 1 column pk, or array if composite pk) -	 */ -	protected function findPrimaryKey($table) -	{ -		$kcu='INFORMATION_SCHEMA.KEY_COLUMN_USAGE'; -		$tc='INFORMATION_SCHEMA.TABLE_CONSTRAINTS'; -		if (isset($table->catalogName)) -		{ -			$kcu=$table->catalogName.'.'.$kcu; -			$tc=$table->catalogName.'.'.$tc; -		} - -		$sql = <<<EOD -		SELECT k.column_name field_name -			FROM {$this->quoteTableName($kcu)} k -		    LEFT JOIN {$this->quoteTableName($tc)} c -		      ON k.table_name = c.table_name -		     AND k.constraint_name = c.constraint_name -		   WHERE c.constraint_type ='PRIMARY KEY' -		   	    AND k.table_name = :table -				AND k.table_schema = :schema -EOD; -		$command = $this->getDbConnection()->createCommand($sql); -		$command->bindValue(':table', $table->name); -		$command->bindValue(':schema', $table->schemaName); -		$primary=$command->queryColumn(); -		switch (count($primary)) -		{ -			case 0: // No primary key on table -				$primary=null; -				break; -			case 1: // Only 1 primary key -				$primary=$primary[0]; -				break; -		} -		return $primary; -	} - -	/** -	 * Gets foreign relationship constraint keys and table name -	 * @param TMssqlTableSchema table -	 * @return array foreign relationship table name and keys. -	 */ -	protected function findForeignKeys($table) -	{ -		$rc='INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS'; -		$kcu='INFORMATION_SCHEMA.KEY_COLUMN_USAGE'; -		if (isset($table->catalogName)) -		{ -			$kcu=$table->catalogName.'.'.$kcu; -			$rc=$table->catalogName.'.'.$rc; -		} - -		//From http://msdn2.microsoft.com/en-us/library/aa175805(SQL.80).aspx -		$sql = <<<EOD -		SELECT -		     KCU1.CONSTRAINT_NAME AS 'FK_CONSTRAINT_NAME' -		   , KCU1.TABLE_NAME AS 'FK_TABLE_NAME' -		   , KCU1.COLUMN_NAME AS 'FK_COLUMN_NAME' -		   , KCU1.ORDINAL_POSITION AS 'FK_ORDINAL_POSITION' -		   , KCU2.CONSTRAINT_NAME AS 'UQ_CONSTRAINT_NAME' -		   , KCU2.TABLE_NAME AS 'UQ_TABLE_NAME' -		   , KCU2.COLUMN_NAME AS 'UQ_COLUMN_NAME' -		   , KCU2.ORDINAL_POSITION AS 'UQ_ORDINAL_POSITION' -		FROM {$this->quoteTableName($rc)} RC -		JOIN {$this->quoteTableName($kcu)} KCU1 -		ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG -		   AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA -		   AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME -		JOIN {$this->quoteTableName($kcu)} KCU2 -		ON KCU2.CONSTRAINT_CATALOG = -		RC.UNIQUE_CONSTRAINT_CATALOG -		   AND KCU2.CONSTRAINT_SCHEMA = -		RC.UNIQUE_CONSTRAINT_SCHEMA -		   AND KCU2.CONSTRAINT_NAME = -		RC.UNIQUE_CONSTRAINT_NAME -		   AND KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION -		WHERE KCU1.TABLE_NAME = :table -EOD; -		$command = $this->getDbConnection()->createCommand($sql); -		$command->bindValue(':table', $table->name); -		$fkeys=array(); -		foreach($command->queryAll() as $info) -		{ -			$fkeys[$info['FK_COLUMN_NAME']]=array($info['UQ_TABLE_NAME'],$info['UQ_COLUMN_NAME'],); - -		} -		return $fkeys; -	} - - -	/** -	 * Collects the table column metadata. -	 * @param CMysqlTableSchema the table metadata -	 * @return boolean whether the table exists in the database -	 */ -	protected function findColumns($table) -	{ -		$where=array(); -		$where[]="TABLE_NAME='".$table->name."'"; -		if (isset($table->catalogName)) -			$where[]="TABLE_CATALOG='".$table->catalogName."'"; -		if (isset($table->schemaName)) -			$where[]="TABLE_SCHEMA='".$table->schemaName."'"; -		$sql="SELECT *, columnproperty(object_id(table_schema+'.'+table_name), column_name, 'IsIdentity') as IsIdentity ". -			 "FROM INFORMATION_SCHEMA.COLUMNS WHERE ".join(' AND ',$where); -		if (($columns=$this->getDbConnection()->createCommand($sql)->queryAll())===array()) -			return false; - -		foreach($columns as $column) -		{ -			$c=$this->createColumn($column); -			if (is_array($table->primaryKey)) -				$c->isPrimaryKey=in_array($c->name, $table->primaryKey); -			else -				$c->isPrimaryKey=strcasecmp($c->name,$table->primaryKey)===0; - -			$c->isForeignKey=isset($table->foreignKeys[$c->name]); -			$table->columns[$c->name]=$c; -			if ($column['IsIdentity']==1 && $table->sequenceName===null) -				$table->sequenceName=''; - -		} -		return true; -	} - -	/** -	 * Creates a table column. -	 * @param array column metadata -	 * @return TDbColumnSchema normalized column metadata -	 */ -	protected function createColumn($column) -	{ -		$c=new TMssqlColumnSchema; -		$c->name=$column['COLUMN_NAME']; -		$c->rawName=$this->quoteColumnName($c->name); -		$c->allowNull=$column['IS_NULLABLE']=='YES'; -		if ($column['NUMERIC_PRECISION_RADIX']!==null) -		{ -			// We have a numeric datatype -			$c->size=$c->precision=$column['NUMERIC_PRECISION']!==null?(int)$column['NUMERIC_PRECISION']:null; -			$c->scale=$column['NUMERIC_SCALE']!==null?(int)$column['NUMERIC_SCALE']:null; -		} -		elseif ($column['DATA_TYPE']=='image' || $column['DATA_TYPE']=='text') -			$c->size=$c->precision=null; -		else -			$c->size=$c->precision=($column['CHARACTER_MAXIMUM_LENGTH']!== null)?(int)$column['CHARACTER_MAXIMUM_LENGTH']:null; - -		$c->init($column['DATA_TYPE'],$column['COLUMN_DEFAULT']); -		return $c; -	} - -	/** -	 * Returns all table names in the database. -	 * @return array all table names in the database. -	 * @since 1.0.4 -	 */ -	protected function findTableNames($schema='') -	{ -		if($schema==='') -			$schema=self::DEFAULT_SCHEMA; -		$sql=<<<EOD -SELECT TABLE_NAME, TABLE_SCHEMA FROM [INFORMATION_SCHEMA].[TABLES] -WHERE TABLE_TYPE='BASE TABLE' AND TABLE_SCHEMA=:schema -EOD; -		$command=$this->getDbConnection()->createCommand($sql); -		$command->bindParameter(":schema", $schema); -		$rows=$command->queryAll(); -		$names=array(); -		foreach ($rows as $row) -		{ -			if ($schema == self::DEFAULT_SCHEMA) -				$names[]=$row['TABLE_NAME']; -			else -				$names[]=$schema.'.'.$row['TABLE_SCHEMA'].'.'.$row['TABLE_NAME']; -		} - -		return $names; -	} - -	/** -	 * Creates a command builder for the database. -	 * This method overrides parent implementation in order to create a MSSQL specific command builder -	 * @return TDbCommandBuilder command builder instance -	 */ -	protected function createCommandBuilder() -	{ -		return new TMssqlCommandBuilder($this); -	} -} diff --git a/framework/Testing/Data/Schema/mssql/TMssqlTableSchema.php b/framework/Testing/Data/Schema/mssql/TMssqlTableSchema.php deleted file mode 100755 index b6584a32..00000000 --- a/framework/Testing/Data/Schema/mssql/TMssqlTableSchema.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -/** - * TMssqlTableSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @author Christophe Boulain <Christophe.Boulain@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.TDbTableSchema'); - -/** - * TMssqlTableSchema represents the metadata for a MSSQL table. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @author Christophe Boulain <Christophe.Boulain@gmail.com> - * @version $Id: TMssqlTableSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.mssql - * @since 1.0.4 - */ -class TMssqlTableSchema extends TDbTableSchema -{ -	/** -	 * @var string name of the catalog (database) that this table belongs to. -	 * Defaults to null, meaning no schema (or the current database). -	 */ -	public $catalogName; -	/** -	 * @var string name of the schema that this table belongs to. -	 * Defaults to null, meaning no schema (or the current database owner). -	 */ -	public $schemaName; -} diff --git a/framework/Testing/Data/Schema/mysql/TMysqlColumnSchema.php b/framework/Testing/Data/Schema/mysql/TMysqlColumnSchema.php deleted file mode 100755 index 9e82ada5..00000000 --- a/framework/Testing/Data/Schema/mysql/TMysqlColumnSchema.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** - * TMysqlColumnSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbColumnSchema'); - -/** - * TMysqlColumnSchema class describes the column meta data of a MySQL table. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TMysqlColumnSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.mysql - * @since 1.0 - */ -class TMysqlColumnSchema extends TDbColumnSchema -{ -	/** -	 * Extracts the PHP type from DB type. -	 * @param string DB type -	 */ -	protected function extractType($dbType) -	{ -		if(strpos($dbType,'bigint')!==false || strpos($dbType,'float')!==false || strpos($dbType,'double')!==false) -			$this->type='double'; -		else if(strpos($dbType,'bool')!==false || $dbType==='tinyint(1)') -			$this->type='boolean'; -		else if(strpos($dbType,'int')!==false || strpos($dbType,'bit')!==false) -			$this->type='integer'; -		else -			$this->type='string'; -	} - -	protected function extractDefault($defaultValue) -	{ -		if($this->dbType==='timestamp' && $defaultValue==='CURRENT_TIMESTAMP') -			$this->defaultValue=null; -		else -			parent::extractDefault($defaultValue); -	} -} diff --git a/framework/Testing/Data/Schema/mysql/TMysqlSchema.php b/framework/Testing/Data/Schema/mysql/TMysqlSchema.php deleted file mode 100755 index 910bf915..00000000 --- a/framework/Testing/Data/Schema/mysql/TMysqlSchema.php +++ /dev/null @@ -1,205 +0,0 @@ -<?php -/** - * TMysqlSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbSchema'); -prado::using('System.Testing.Data.Schema.mysql.TMysqlTableSchema'); -prado::using('System.Testing.Data.Schema.mysql.TMysqlColumnSchema'); - -/** - * TMysqlSchema is the class for retrieving metadata information from a MySQL database (version 4.1.x and 5.x). - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TMysqlSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.mysql - * @since 1.0 - */ -class TMysqlSchema extends TDbSchema -{ -	private $_tableNames; -	private $_schemaNames; - -	/** -	 * Quotes a table name for use in a query. -	 * @param string table name -	 * @return string the properly quoted table name -	 */ -	public function quoteTableName($name) -	{ -		return '`'.$name.'`'; -	} - -	/** -	 * Quotes a column name for use in a query. -	 * @param string column name -	 * @return string the properly quoted column name -	 */ -	public function quoteColumnName($name) -	{ -		return '`'.$name.'`'; -	} - -	/** -	 * Compares two table names. -	 * The table names can be either quoted or unquoted. This method -	 * will consider both cases. -	 * @param string table name 1 -	 * @param string table name 2 -	 * @return boolean whether the two table names refer to the same table. -	 */ -	public function compareTableNames($name1,$name2) -	{ -		return parent::compareTableNames(strtolower($name1),strtolower($name2)); -	} - -	/** -	 * Creates a table instance representing the metadata for the named table. -	 * @return TMysqlTableSchema driver dependent table metadata. Null if the table does not exist. -	 */ -	protected function createTable($name) -	{ -		$table=new TMysqlTableSchema; -		$this->resolveTableNames($table,$name); - -		if($this->findColumns($table)) -		{ -			$this->findConstraints($table); -			return $table; -		} -		else -			return null; -	} - -	/** -	 * Generates various kinds of table names. -	 * @param TMysqlTableSchema the table instance -	 * @param string the unquoted table name -	 */ -	protected function resolveTableNames($table,$name) -	{ -		$parts=explode('.',str_replace('`','',$name)); -		if(isset($parts[1])) -		{ -			$table->schemaName=$parts[0]; -			$table->name=$parts[1]; -			$table->rawName=$this->quoteTableName($table->schemaName).'.'.$this->quoteTableName($table->name); -		} -		else -		{ -			$table->name=$parts[0]; -			$table->rawName=$this->quoteTableName($table->name); -		} -	} - -	/** -	 * Collects the table column metadata. -	 * @param TMysqlTableSchema the table metadata -	 * @return boolean whether the table exists in the database -	 */ -	protected function findColumns($table) -	{ -		$sql='SHOW COLUMNS FROM '.$table->rawName; -		try -		{ -			$columns=$this->getDbConnection()->createCommand($sql)->queryAll(); -		} -		catch(Exception $e) -		{ -			return false; -		} -		foreach($columns as $column) -		{ -			$c=$this->createColumn($column); -			$table->columns[$c->name]=$c; -			if($c->isPrimaryKey) -			{ -				if($table->primaryKey===null) -					$table->primaryKey=$c->name; -				else if(is_string($table->primaryKey)) -					$table->primaryKey=array($table->primaryKey,$c->name); -				else -					$table->primaryKey[]=$c->name; -				if(strpos(strtolower($column['Extra']),'auto_increment')!==false) -					$table->sequenceName=''; -			} -		} -		return true; -	} - -	/** -	 * Creates a table column. -	 * @param array column metadata -	 * @return TDbColumnSchema normalized column metadata -	 */ -	protected function createColumn($column) -	{ -		$c=new TMysqlColumnSchema; -		$c->name=$column['Field']; -		$c->rawName=$this->quoteColumnName($c->name); -		$c->allowNull=$column['Null']==='YES'; -		$c->isPrimaryKey=strpos($column['Key'],'PRI')!==false; -		$c->isForeignKey=false; -		$c->init($column['Type'],$column['Default']); -		return $c; -	} - -	/** -	 * @return float server version. -	 */ -	protected function getServerVersion() -	{ -		$version=$this->getDbConnection()->getAttribute(PDO::ATTR_SERVER_VERSION); -		$digits=array(); -		preg_match('/(\d+)\.(\d+)\.(\d+)/', $version, $digits); -		return floatval($digits[1].'.'.$digits[2].$digits[3]); -	} - -	/** -	 * Collects the foreign key column details for the given table. -	 * @param TMysqlTableSchema the table metadata -	 */ -	protected function findConstraints($table) -	{ -		$row=$this->getDbConnection()->createCommand('SHOW CREATE TABLE '.$table->rawName)->queryRow(); -		$matches=array(); -		$regexp='/FOREIGN KEY\s+\(([^\)]+)\)\s+REFERENCES\s+([^\(^\s]+)\s*\(([^\)]+)\)/mi'; -		foreach($row as $sql) -		{ -			if(preg_match_all($regexp,$sql,$matches,PREG_SET_ORDER)) -				break; -		} -		$foreign = array(); -		foreach($matches as $match) -		{ -			$keys=array_map('trim',explode(',',str_replace('`','',$match[1]))); -			$fks=array_map('trim',explode(',',str_replace('`','',$match[3]))); -			foreach($keys as $k=>$name) -			{ -				$table->foreignKeys[$name]=array(str_replace('`','',$match[2]),$fks[$k]); -				if(isset($table->columns[$name])) -					$table->columns[$name]->isForeignKey=true; -			} -		} -	} - -	/** -	 * Returns all table names in the database. -	 * @return array all table names in the database. -	 * @since 1.0.2 -	 */ -	protected function findTableNames($schema='') -	{ -		if($schema==='') -			return $this->getDbConnection()->createCommand('SHOW TABLES')->queryColumn(); -		$names=$this->getDbConnection()->createCommand('SHOW TABLES FROM '.$this->quoteTableName($schema))->queryColumn(); -		foreach($names as &$name) -			$name=$schema.'.'.$name; -		return $names; -	} -} diff --git a/framework/Testing/Data/Schema/mysql/TMysqlTableSchema.php b/framework/Testing/Data/Schema/mysql/TMysqlTableSchema.php deleted file mode 100755 index 87f5eefd..00000000 --- a/framework/Testing/Data/Schema/mysql/TMysqlTableSchema.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php -/** - * TMysqlTableSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ -prado::using('System.Testing.Data.Schema.TDbTableSchema'); -/** - * TMysqlTableSchema represents the metadata for a MySQL table. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TMysqlTableSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.mysql - * @since 1.0 - */ -class TMysqlTableSchema extends TDbTableSchema -{ -	/** -	 * @var string name of the schema (database) that this table belongs to. -	 * Defaults to null, meaning no schema (or the current database). -	 */ -	public $schemaName; -} diff --git a/framework/Testing/Data/Schema/oci/TOciColumnSchema.php b/framework/Testing/Data/Schema/oci/TOciColumnSchema.php deleted file mode 100755 index d8c77e16..00000000 --- a/framework/Testing/Data/Schema/oci/TOciColumnSchema.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -/** - * TOciColumnSchema class file. - * - * @author Ricardo Grana <rickgrana@yahoo.com.br> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbColumnSchema'); - -/** - * TOciColumnSchema class describes the column meta data of a Oracle table. - * - * @author Ricardo Grana <rickgrana@yahoo.com.br> - * @version $Id: TOciColumnSchema.php - * @package System.Testing.Data.Schema.oci - * @since 1.0.5 - */ -class TOciColumnSchema extends TDbColumnSchema -{ -	/** -	 * Extracts the PHP type from DB type. -	 * @param string DB type -	 */ -	protected function extractOraType($dbType){ -		if(strpos($dbType,'FLOAT')!==false) return 'double'; - -		if ((strpos($dbType,'NUMBER')!==false) or -			(strpos($dbType,'INTEGER')!==false)) -		{ -			if(strpos($dbType,'(') && preg_match('/\((.*)\)/',$dbType,$matches)) -			{ -				$values=explode(',',$matches[1]); -				if(isset($values[1]) and (((int)$values[1]) > 0)) -					return 'double'; -				else return 'integer'; -			} -		}else{ -			return 'string'; -		} -	} -	protected function extractType($dbType) -	{ -		$this->type=$this->extractOraType($dbType); -	} - -	protected function extractDefault($defaultValue) -	{ -		if(strpos($dbType,'timestamp')!==false) -			$this->defaultValue=null; -		else -			parent::extractDefault($defaultValue); -	} -} diff --git a/framework/Testing/Data/Schema/oci/TOciCommandBuilder.php b/framework/Testing/Data/Schema/oci/TOciCommandBuilder.php deleted file mode 100755 index ed3e8c3b..00000000 --- a/framework/Testing/Data/Schema/oci/TOciCommandBuilder.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php -/** - * TOciCommandBuilder class file. - * - * @author Ricardo Grana <rickgrana@yahoo.com.br> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbCommandBuilder'); - -/** - * TOciCommandBuilder provides basic methods to create query commands for tables. - * - * @author Ricardo Grana <rickgrana@yahoo.com.br> - * @version $Id: TOciCommandBuilder.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.oci - * @since 1.0.5 - */ -class TOciCommandBuilder extends TDbCommandBuilder -{ -	/** -	 * @var integer the last insertion ID -	 */ -	public $returnID; - -	/** -	 * Returns the last insertion ID for the specified table. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @return mixed last insertion id. Null is returned if no sequence name. -	 */ -	public function getLastInsertID($table) -	{ -		return $this->returnID; -	} - -	/** -	 * Alters the SQL to apply LIMIT and OFFSET. -	 * Default implementation is applicable for PostgreSQL, MySQL and SQLite. -	 * @param string SQL query string without LIMIT and OFFSET. -	 * @param integer maximum number of rows, -1 to ignore limit. -	 * @param integer row offset, -1 to ignore offset. -	 * @return string SQL with LIMIT and OFFSET -	 */ -	public function applyLimit($sql,$limit,$offset) -	{ -		if (($limit < 0) and ($offset < 0)) return $sql; - -		$filters = array(); -		if($offset>0){ -			$filters[] = 'rowNumId >= '.(int)$offset; -		} - -		if($limit>=0){ -			$filters[]= 'rownum <= '.(int)$limit; -		} - -		if (count($filters) > 0){ -			$filter = implode(' and ', $filters); -			$filter= " WHERE ".$filter; -		}else{ -			$filter = ''; -		} - - -		$sql = <<<EOD -				WITH USER_SQL AS ({$sql}), -				   PAGINATION AS (SELECT USER_SQL.*, rownum as rowNumId FROM USER_SQL) -				SELECT * -				FROM PAGINATION -				{$filter} -EOD; - -		return $sql; -	} - -	/** -	 * Creates an INSERT command. -	 * @param mixed the table schema ({@link TDbTableSchema}) or the table name (string). -	 * @param array data to be inserted (column name=>column value). If a key is not a valid column name, the corresponding value will be ignored. -	 * @return TDbCommand insert command -	 */ -	public function createInsertCommand($table,$data) -	{ -		$this->ensureTable($table); -		$fields=array(); -		$values=array(); -		$placeholders=array(); -		foreach($data as $name=>$value) -		{ -			if(($column=$table->getColumn($name))!==null && ($value!==null || $column->allowNull)) -			{ -				$fields[]=$column->rawName; -				if($value instanceof TDbExpression) -					$placeholders[]=(string)$value; -				else -				{ -					$placeholders[]=':'.$name; -					$values[':'.$name]=$column->typecast($value); -				} -			} -		} - -		$sql="INSERT INTO {$table->rawName} (".implode(', ',$fields).') VALUES ('.implode(', ',$placeholders).')'; - -		if(is_string($table->primaryKey)) -		{ -			$sql.=" RETURNING ".$table->primaryKey." INTO :RETURN_ID"; -			$command=$this->getDbConnection()->createCommand($sql); -			$command->bindParam(':RETURN_ID', $this->returnID, PDO::PARAM_INT, 12); -			$table->sequenceName='RETURN_ID'; -		} -		else -			$command=$this->getDbConnection()->createCommand($sql); - -		foreach($values as $name=>$value) -			$command->bindValue($name,$value); - -		return $command; -	} -} diff --git a/framework/Testing/Data/Schema/oci/TOciSchema.php b/framework/Testing/Data/Schema/oci/TOciSchema.php deleted file mode 100755 index 1253dac6..00000000 --- a/framework/Testing/Data/Schema/oci/TOciSchema.php +++ /dev/null @@ -1,278 +0,0 @@ -<?php -/** - * TOciSchema class file. - * - * @author Ricardo Grana <rickgrana@yahoo.com.br> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbSchema'); - -/** - * TOciSchema is the class for retrieving metadata information from a PostgreSQL database. - * - * @author Ricardo Grana <qiang.xue@gmail.com> - * @version $Id: TOciSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.oci - * @since 1.0.5 - */ -class TOciSchema extends TDbSchema -{ -	private $_defaultSchema = ''; -	private $_sequences=array(); - -	/** -	 * Quotes a table name for use in a query. -	 * @param string table name -	 * @return string the properly quoted table name -	 */ -	public function quoteTableName($name) -	{ -		return $name; -	} - -	/** -	 * Quotes a column name for use in a query. -	 * @param string column name -	 * @return string the properly quoted column name -	 */ -	public function quoteColumnName($name) -	{ -		return $name; -	} - -	/** -	 * Creates a command builder for the database. -	 * This method may be overridden by child classes to create a DBMS-specific command builder. -	 * @return TDbCommandBuilder command builder instance -	 */ -	protected function createCommandBuilder() -	{ -		return new TOciCommandBuilder($this); -	} - -	/** -     * @param string default schema. -     */ -    public function setDefaultSchema($schema) -    { -		$this->_defaultSchema=$schema; -    } - -    /** -     * @return string default schema. -     */ -    public function getDefaultSchema() -    { -		if (!strlen($this->_defaultSchema)) -		{ -			$this->setDefaultSchema(strtoupper($this->getDbConnection()->username)); -		} - -		return $this->_defaultSchema; -    } - -    /** -     * @param string table name with optional schema name prefix, uses default schema name prefix is not provided. -     * @return array tuple as ($schemaName,$tableName) -     */ -    protected function getSchemaTableName($table) -    { -		$table = strtoupper($table); -		if(count($parts= explode('.', str_replace('"','',$table))) > 1) -			return array($parts[0], $parts[1]); -		else -			return array($this->getDefaultSchema(),$parts[0]); -    } - -	/** -	 * Creates a table instance representing the metadata for the named table. -	 * @return TDbTableSchema driver dependent table metadata. -	 */ -	protected function createTable($name) -	{ -		$table=new TOciTableSchema; -		$this->resolveTableNames($table,$name); - -		if(!$this->findColumns($table)) -			return null; -		$this->findConstraints($table); - -		return $table; -	} - -	/** -	 * Generates various kinds of table names. -	 * @param TOciTableSchema the table instance -	 * @param string the unquoted table name -	 */ -	protected function resolveTableNames($table,$name) -	{ -		$parts=explode('.',str_replace('"','',$name)); -		if(isset($parts[1])) -		{ -			$schemaName=$parts[0]; -			$tableName=$parts[1]; -		} -		else -		{ -			$schemaName=$this->getDefaultSchema(); -			$tableName=$parts[0]; -		} - -		$table->name=$tableName; -		$table->schemaName=$schemaName; -		if($schemaName===$this->getDefaultSchema()) -			$table->rawName=$this->quoteTableName($tableName); -		else -			$table->rawName=$this->quoteTableName($schemaName).'.'.$this->quoteTableName($tableName); -	} - -	/** -	 * Collects the table column metadata. -	 * @param TOciTableSchema the table metadata -	 * @return boolean whether the table exists in the database -	 */ -	protected function findColumns($table) -	{ -		list($schemaName,$tableName) = $this->getSchemaTableName($table->name); - -		$sql=<<<EOD -SELECT a.column_name, a.data_type || -    case -        when data_precision is not null -            then '(' || a.data_precision || -                    case when a.data_scale > 0 then ',' || a.data_scale else '' end -                || ')' -        when data_type = 'DATE' then '' -        else '(' || to_char(a.data_length) || ')' -    end as data_type, -    a.nullable, a.data_default, -    (   SELECT D.constraint_type -        FROM ALL_CONS_COLUMNS C -        inner join ALL_constraints D on D.OWNER = C.OWNER and D.constraint_name = C.constraint_name -        WHERE C.OWNER = B.OWNER -           and C.table_name = B.object_name -           and C.column_name = A.column_name -           and D.constraint_type = 'P') as Key -FROM ALL_TAB_COLUMNS A -inner join ALL_OBJECTS B ON b.owner = a.owner and ltrim(B.OBJECT_NAME) = ltrim(A.TABLE_NAME) -WHERE -    a.owner = '{$schemaName}' -	and b.object_type = 'TABLE' -	and b.object_name = '{$tableName}' -ORDER by a.column_id -EOD; - -		$command=$this->getDbConnection()->createCommand($sql); - -		if(($columns=$command->queryAll())===array()){ -			return false; -		} - -		foreach($columns as $column) -		{ -			$c=$this->createColumn($column); - -			$table->columns[$c->name]=$c; -			if($c->isPrimaryKey) -			{ -				if($table->primaryKey===null) -					$table->primaryKey=$c->name; -				else if(is_string($table->primaryKey)) -					$table->primaryKey=array($table->primaryKey,$c->name); -				else -					$table->primaryKey[]=$c->name; -			} -		} -		return true; -	} - -	/** -	 * Creates a table column. -	 * @param array column metadata -	 * @return TDbColumnSchema normalized column metadata -	 */ -	protected function createColumn($column) -	{ -		$c=new TOciColumnSchema; -		$c->name=$column['COLUMN_NAME']; -		$c->rawName=$this->quoteColumnName($c->name); -		$c->allowNull=$column['NULLABLE']==='Y'; -		$c->isPrimaryKey=strpos($column['KEY'],'P')!==false; -		$c->isForeignKey=false; -		$c->init($column['DATA_TYPE'],$column['DATA_DEFAULT']); - -		return $c; -	} - -	/** -	 * Collects the primary and foreign key column details for the given table. -	 * @param TOciTableSchema the table metadata -	 */ -	protected function findConstraints($table) -	{ -		$sql=<<<EOD -		SELECT D.constraint_type, C.COLUMN_NAME, C.position, D.r_constraint_name, -                E.table_name as table_ref, f.column_name as column_ref -        FROM ALL_CONS_COLUMNS C -        inner join ALL_constraints D on D.OWNER = C.OWNER and D.constraint_name = C.constraint_name -        left join ALL_constraints E on E.OWNER = D.r_OWNER and E.constraint_name = D.r_constraint_name -        left join ALL_cons_columns F on F.OWNER = E.OWNER and F.constraint_name = E.constraint_name and F.position = c.position -        WHERE C.OWNER = '{$table->schemaName}' -           and C.table_name = '{$table->name}' -           and D.constraint_type <> 'P' -        order by d.constraint_name, c.position -EOD; -		$command=$this->getDbConnection()->createCommand($sql); -		foreach($command->queryAll() as $row) -		{ -			if($row['constraint_type']==='R')   // foreign key -			{ -				$name = $row["COLUMN_NAME"]; -				$table->foreignKeys[$name]=array($row["TABLE_REF"], array($row["COLUMN_REF"])); -				if(isset($table->columns[$name])) -					$table->columns[$name]->isForeignKey=true; -			} - -		} -	} - - -	/** -	 * Returns all table names in the database. -	 * @return array all table names in the database. -	 */ -	protected function findTableNames($schema='') -	{ -		if($schema==='') -		{ -			$sql=<<<EOD -SELECT table_name, '{$schema}' as table_schema FROM user_tables -EOD; -			$command=$this->getDbConnection()->createCommand($sql); -		} -		else -		{ -			$sql=<<<EOD -SELECT object_name as table_name, owner as table_schema FROM all_objects -WHERE object_type = 'TABLE' AND owner=:schema -EOD; -			$command=$this->getDbConnection()->createCommand($sql); -			$command->bindParam(':schema',$schema); -		} - -		$rows=$command->queryAll(); -		$names=array(); -		foreach($rows as $row) -		{ -			if($schema===$this->getDefaultSchema()) -				$names[]=$row['table_name']; -			else -				$names[]=$row['schema_name'].'.'.$row['table_name']; -		} -		return $names; -	} -} diff --git a/framework/Testing/Data/Schema/oci/TOciTableSchema.php b/framework/Testing/Data/Schema/oci/TOciTableSchema.php deleted file mode 100755 index 4376c528..00000000 --- a/framework/Testing/Data/Schema/oci/TOciTableSchema.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php -/** - * TOciTableSchema class file. - * - * @author Ricardo Grana <rickgrana@yahoo.com.br> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbTableSchame'); - -/** - * TOciTableSchema represents the metadata for a Ora table. - * - * @author Ricardo Grana <rickgrana@yahoo.com.br> - * @version $Id: TOciTableSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.oci - * @since 1.0.5 - */ -class TOciTableSchema extends TDbTableSchema -{ -	/** -	 * @var string name of the schema (database) that this table belongs to. -	 * Defaults to null, meaning no schema (or the current database). -	 */ -	public $schemaName; -} diff --git a/framework/Testing/Data/Schema/pgsql/TPgsqlColumnSchema.php b/framework/Testing/Data/Schema/pgsql/TPgsqlColumnSchema.php deleted file mode 100755 index 7872dd4a..00000000 --- a/framework/Testing/Data/Schema/pgsql/TPgsqlColumnSchema.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/** - * TPgsqlColumnSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbColumnSchema'); - -/** - * TPgsqlColumnSchema class describes the column meta data of a PostgreSQL table. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TPgsqlColumnSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.pgsql - * @since 1.0 - */ -class TPgsqlColumnSchema extends TDbColumnSchema -{ -	/** -	 * Extracts the PHP type from DB type. -	 * @param string DB type -	 */ -	protected function extractType($dbType) -	{ -		if(strpos($dbType,'integer')!==false || strpos($dbType,'oid')===0) -			$this->type='integer'; -		else if(strpos($dbType,'bool')!==false) -			$this->type='boolean'; -		else if(preg_match('/(real|float|double)/',$dbType)) -			$this->type='double'; -		else -			$this->type='string'; -	} - -	/** -	 * Extracts the default value for the column. -	 * The value is typecasted to correct PHP type. -	 * @param mixed the default value obtained from metadata -	 */ -	protected function extractDefault($defaultValue) -	{ -		if($defaultValue==='true') -			$this->defaultValue=true; -		else if($defaultValue==='false') -			$this->defaultValue=false; -		else if(strpos($defaultValue,'nextval')===0) -			$this->defaultValue=null; -		else if(preg_match('/\'(.*)\'::/',$defaultValue,$matches)) -			$this->defaultValue=$this->typecast(str_replace("''","'",$matches[1])); -		else if(preg_match('/^-?\d+(\.\d*)?$/',$defaultValue,$matches)) -			$this->defaultValue=$this->typecast($defaultValue); -		// else is null -	} -} diff --git a/framework/Testing/Data/Schema/pgsql/TPgsqlSchema.php b/framework/Testing/Data/Schema/pgsql/TPgsqlSchema.php deleted file mode 100755 index 05e0fbfa..00000000 --- a/framework/Testing/Data/Schema/pgsql/TPgsqlSchema.php +++ /dev/null @@ -1,284 +0,0 @@ -<?php -/** - * TPgsqlSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbSchema'); - -/** - * TPgsqlSchema is the class for retrieving metadata information from a PostgreSQL database. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TPgsqlSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.pgsql - * @since 1.0 - */ -class TPgsqlSchema extends TDbSchema -{ -	const DEFAULT_SCHEMA='public'; -	private $_sequences=array(); - -	/** -	 * Quotes a table name for use in a query. -	 * @param string table name -	 * @return string the properly quoted table name -	 */ -	public function quoteTableName($name) -	{ -		return '"'.$name.'"'; -	} - -	/** -	 * Creates a table instance representing the metadata for the named table. -	 * @return TDbTableSchema driver dependent table metadata. -	 */ -	protected function createTable($name) -	{ -		$table=new TPgsqlTableSchema; -		$this->resolveTableNames($table,$name); -		if(!$this->findColumns($table)) -			return null; -		$this->findConstraints($table); - -		if(is_string($table->primaryKey) && isset($this->_sequences[$table->primaryKey])) -			$table->sequenceName=$this->_sequences[$table->primaryKey]; - -		return $table; -	} - -	/** -	 * Generates various kinds of table names. -	 * @param TPgsqlTableSchema the table instance -	 * @param string the unquoted table name -	 */ -	protected function resolveTableNames($table,$name) -	{ -		$parts=explode('.',str_replace('"','',$name)); -		if(isset($parts[1])) -		{ -			$schemaName=$parts[0]; -			$tableName=$parts[1]; -		} -		else -		{ -			$schemaName=self::DEFAULT_SCHEMA; -			$tableName=$parts[0]; -		} - -		$table->name=$tableName; -		$table->schemaName=$schemaName; -		if($schemaName===self::DEFAULT_SCHEMA) -			$table->rawName=$this->quoteTableName($tableName); -		else -			$table->rawName=$this->quoteTableName($schemaName).'.'.$this->quoteTableName($tableName); -	} - -	/** -	 * Collects the table column metadata. -	 * @param TPgsqlTableSchema the table metadata -	 * @return boolean whether the table exists in the database -	 */ -	protected function findColumns($table) -	{ -		$sql=<<<EOD -SELECT a.attname, LOWER(format_type(a.atttypid, a.atttypmod)) AS type, d.adsrc, a.attnotnull, a.atthasdef -FROM pg_attribute a LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum -WHERE a.attnum > 0 AND NOT a.attisdropped -	AND a.attrelid = (SELECT oid FROM pg_catalog.pg_class WHERE relname=:table -		AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = :schema)) -ORDER BY a.attnum -EOD; -		$command=$this->getDbConnection()->createCommand($sql); -		$command->bindValue(':table',$table->name); -		$command->bindValue(':schema',$table->schemaName); - -		if(($columns=$command->queryAll())===array()) -			return false; - -		foreach($columns as $column) -		{ -			$c=$this->createColumn($column); -			$table->columns[$c->name]=$c; - -			if(stripos($column['adsrc'],'nextval')===0 && preg_match('/nextval\([^\']*\'([^\']+)\'[^\)]*\)/i',$column['adsrc'],$matches)) -			{ -				if(strpos($matches[1],'.')!==false || $table->schemaName===self::DEFAULT_SCHEMA) -					$this->_sequences[$c->name]=$matches[1]; -				else -					$this->_sequences[$c->name]=$table->schemaName.'.'.$matches[1]; -			} -		} -		return true; -	} - -	/** -	 * Creates a table column. -	 * @param array column metadata -	 * @return TDbColumnSchema normalized column metadata -	 */ -	protected function createColumn($column) -	{ -		$c=new TPgsqlColumnSchema; -		$c->name=$column['attname']; -		$c->rawName=$this->quoteColumnName($c->name); -		$c->allowNull=!$column['attnotnull']; -		$c->isPrimaryKey=false; -		$c->isForeignKey=false; - -		$c->init($column['type'],$column['atthasdef'] ? $column['adsrc'] : null); - -		return $c; -	} - -	/** -	 * Collects the primary and foreign key column details for the given table. -	 * @param TPgsqlTableSchema the table metadata -	 */ -	protected function findConstraints($table) -	{ -		$sql=<<<EOD -SELECT conname, consrc, contype, indkey FROM ( -	SELECT -		conname, -		CASE WHEN contype='f' THEN -			pg_catalog.pg_get_constraintdef(oid) -		ELSE -			'CHECK (' || consrc || ')' -		END AS consrc, -		contype, -		conrelid AS relid, -		NULL AS indkey -	FROM -		pg_catalog.pg_constraint -	WHERE -		contype IN ('f', 'c') -	UNION ALL -	SELECT -		pc.relname, -		NULL, -		CASE WHEN indisprimary THEN -				'p' -		ELSE -				'u' -		END, -		pi.indrelid, -		indkey -	FROM -		pg_catalog.pg_class pc, -		pg_catalog.pg_index pi -	WHERE -		pc.oid=pi.indexrelid -		AND EXISTS ( -			SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c -			ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) -			WHERE d.classid = pc.tableoid AND d.objid = pc.oid AND d.deptype = 'i' AND c.contype IN ('u', 'p') -	) -) AS sub -WHERE relid = (SELECT oid FROM pg_catalog.pg_class WHERE relname=:table -	AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace -	WHERE nspname=:schema)) -EOD; -		$command=$this->getDbConnection()->createCommand($sql); -		$command->bindValue(':table',$table->name); -		$command->bindValue(':schema',$table->schemaName); -		foreach($command->queryAll() as $row) -		{ -			if($row['contype']==='p') // primary key -				$this->findPrimaryKey($table,$row['indkey']); -			else if($row['contype']==='f') // foreign key -				$this->findForeignKey($table,$row['consrc']); -		} -	} - -	/** -	 * Collects primary key information. -	 * @param TPgsqlTableSchema the table metadata -	 * @param string pgsql primary key index list -	 */ -	protected function findPrimaryKey($table,$indices) -	{ -		$indices=implode(', ',preg_split('/\s+/',$indices)); -		$sql=<<<EOD -SELECT attnum, attname FROM pg_catalog.pg_attribute WHERE -	attrelid=( -		SELECT oid FROM pg_catalog.pg_class WHERE relname=:table AND relnamespace=( -			SELECT oid FROM pg_catalog.pg_namespace WHERE nspname=:schema -		) -	) -    AND attnum IN ({$indices}) -EOD; -		$command=$this->getDbConnection()->createCommand($sql); -		$command->bindValue(':table',$table->name); -		$command->bindValue(':schema',$table->schemaName); -		foreach($command->queryAll() as $row) -		{ -			$name=$row['attname']; -			if(isset($table->columns[$name])) -			{ -				$table->columns[$name]->isPrimaryKey=true; -				if($table->primaryKey===null) -					$table->primaryKey=$name; -				else if(is_string($table->primaryKey)) -					$table->primaryKey=array($table->primaryKey,$name); -				else -					$table->primaryKey[]=$name; -			} -		} -	} - -	/** -	 * Collects foreign key information. -	 * @param TPgsqlTableSchema the table metadata -	 * @param string pgsql foreign key definition -	 */ -	protected function findForeignKey($table,$src) -	{ -		$matches=array(); -		$brackets='\(([^\)]+)\)'; -		$pattern="/FOREIGN\s+KEY\s+{$brackets}\s+REFERENCES\s+([^\(]+){$brackets}/i"; -		if(preg_match($pattern,str_replace('"','',$src),$matches)) -		{ -			$keys=preg_split('/,\s+/', $matches[1]); -			$tableName=$matches[2]; -			$fkeys=preg_split('/,\s+/', $matches[3]); -			foreach($keys as $i=>$key) -			{ -				$table->foreignKeys[$key]=array($tableName,$fkeys[$i]); -				if(isset($table->columns[$key])) -					$table->columns[$key]->isForeignKey=true; -			} -		} -	} - -	/** -	 * Returns all table names in the database. -	 * @return array all table names in the database. -	 * @since 1.0.2 -	 */ -	protected function findTableNames($schema='') -	{ -		if($schema==='') -			$schema=self::DEFAULT_SCHEMA; -		$sql=<<<EOD -SELECT table_name, table_schema FROM information_schema.tables -WHERE table_schema=:schema -EOD; -		$command=$this->getDbConnection()->createCommand($sql); -		$command->bindParam(':schema',$schema); -		$rows=$command->queryAll(); -		$names=array(); -		foreach($rows as $row) -		{ -			if($schema===self::DEFAULT_SCHEMA) -				$names[]=$row['table_name']; -			else -				$names[]=$row['schema_name'].'.'.$row['table_name']; -		} -		return $names; -	} -} diff --git a/framework/Testing/Data/Schema/pgsql/TPgsqlTableSchema.php b/framework/Testing/Data/Schema/pgsql/TPgsqlTableSchema.php deleted file mode 100755 index 5e79b6f0..00000000 --- a/framework/Testing/Data/Schema/pgsql/TPgsqlTableSchema.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php -/** - * TPgsqlTable class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbTableSchema'); - -/** - * TPgsqlTable represents the metadata for a PostgreSQL table. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TPgsqlTableSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.pgsql - * @since 1.0 - */ -class TPgsqlTableSchema extends TDbTableSchema -{ -	/** -	 * @var string name of the schema that this table belongs to. -	 */ -	public $schemaName; -} diff --git a/framework/Testing/Data/Schema/sqlite/TSqliteColumnSchema.php b/framework/Testing/Data/Schema/sqlite/TSqliteColumnSchema.php deleted file mode 100755 index 9926e852..00000000 --- a/framework/Testing/Data/Schema/sqlite/TSqliteColumnSchema.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -/** - * TSqliteColumnSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbColumnSchema'); - -/** - * TSqliteColumnSchema class describes the column meta data of a SQLite table. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TSqliteColumnSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.sqlite - * @since 1.0 - */ -class TSqliteColumnSchema extends TDbColumnSchema -{ -	/** -	 * Extracts the default value for the column. -	 * The value is typecasted to correct PHP type. -	 * @param mixed the default value obtained from metadata -	 */ -	protected function extractDefault($defaultValue) -	{ -		if($this->type==='string') // PHP 5.2.6 adds single quotes while 5.2.0 doesn't -			$this->defaultValue=trim($defaultValue,"'\""); -		else -			$this->defaultValue=$this->typecast($defaultValue); -	} -} diff --git a/framework/Testing/Data/Schema/sqlite/TSqliteCommandBuilder.php b/framework/Testing/Data/Schema/sqlite/TSqliteCommandBuilder.php deleted file mode 100755 index fa79b890..00000000 --- a/framework/Testing/Data/Schema/sqlite/TSqliteCommandBuilder.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php -/** - * TSqliteCommandBuilder class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbCommandBuilder'); - -/** - * TSqliteCommandBuilder provides basic methods to create query commands for SQLite tables. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TSqliteCommandBuilder.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.sqlite - * @since 1.0 - */ -class TSqliteCommandBuilder extends TDbCommandBuilder -{ -	/** -	 * Generates the expression for selecting rows with specified composite key values. -	 * This method is overridden because SQLite does not support the default -	 * IN expression with composite columns. -	 * @param TDbTableSchema the table schema -	 * @param array list of primary key values to be selected within -	 * @param string column prefix (ended with dot) -	 * @return string the expression for selection -	 * @since 1.0.4 -	 */ -	protected function createCompositeInCondition($table,$values,$prefix) -	{ -		$keyNames=array(); -		foreach(array_keys($values[0]) as $name) -			$keyNames[]=$prefix.$table->columns[$name]->rawName; -		$vs=array(); -		foreach($values as $value) -			$vs[]=implode("||','||",$value); -		return implode("||','||",$keyNames).' IN ('.implode(', ',$vs).')'; -	} -} diff --git a/framework/Testing/Data/Schema/sqlite/TSqliteSchema.php b/framework/Testing/Data/Schema/sqlite/TSqliteSchema.php deleted file mode 100755 index dd3e73af..00000000 --- a/framework/Testing/Data/Schema/sqlite/TSqliteSchema.php +++ /dev/null @@ -1,134 +0,0 @@ -<?php -/** - * TSqliteSchema class file. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using('System.Testing.Data.Schema.TDbSchema'); -prado::using('System.Testing.Data.Schema.TDbTableSchema'); -prado::using('System.Testing.Data.Schema.sqlite.TSqliteColumnSchema'); -prado::using('System.Testing.Data.Schema.sqlite.TSqliteCommandBuilder'); - -/** - * TSqliteSchema is the class for retrieving metadata information from a SQLite (2/3) database. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id: TSqliteSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ - * @package System.Testing.Data.Schema.sqlite - * @since 1.0 - */ -class TSqliteSchema extends TDbSchema -{ -	/** -	 * Returns all table names in the database. -	 * @param string the schema of the tables. This is not used for sqlite database. -	 * @return array all table names in the database. -	 * @since 1.0.2 -	 */ -	protected function findTableNames($schema='') -	{ -		$sql="SELECT DISTINCT tbl_name FROM sqlite_master WHERE tbl_name<>'sqlite_sequence'"; -		return $this->getDbConnection()->createCommand($sql)->queryColumn(); -	} - -	/** -	 * Creates a command builder for the database. -	 * @return TSqliteCommandBuilder command builder instance -	 */ -	protected function createCommandBuilder() -	{ -		return new TSqliteCommandBuilder($this); -	} - -	/** -	 * Creates a table instance representing the metadata for the named table. -	 * @return TDbTableSchema driver dependent table metadata. Null if the table does not exist. -	 */ -	protected function createTable($name) -	{ -		$db=$this->getDbConnection(); - -		$table=new TDbTableSchema; -		$table->name=$name; -		$table->rawName=$this->quoteTableName($name); - -		if($this->findColumns($table)) -		{ -			$this->findConstraints($table); -			return $table; -		} -		else -			return null; -	} - -	/** -	 * Collects the table column metadata. -	 * @param TDbTableSchema the table metadata -	 * @return boolean whether the table exists in the database -	 */ -	protected function findColumns($table) -	{ -		$sql="PRAGMA table_info({$table->rawName})"; -		$columns=$this->getDbConnection()->createCommand($sql)->queryAll(); -		if(empty($columns)) -			return false; - -		foreach($columns as $column) -		{ -			$c=$this->createColumn($column); -			$table->columns[$c->name]=$c; -			if($c->isPrimaryKey) -			{ -				if($table->primaryKey===null) -					$table->primaryKey=$c->name; -				else if(is_string($table->primaryKey)) -					$table->primaryKey=array($table->primaryKey,$c->name); -				else -					$table->primaryKey[]=$c->name; -			} -		} -		if(is_string($table->primaryKey) && !strncasecmp($table->columns[$table->primaryKey]->dbType,'int',3)) -			$table->sequenceName=''; - -		return true; -	} - -	/** -	 * Collects the foreign key column details for the given table. -	 * @param TDbTableSchema the table metadata -	 */ -	protected function findConstraints($table) -	{ -		$foreignKeys=array(); -		$sql="PRAGMA foreign_key_list({$table->rawName})"; -		$keys=$this->getDbConnection()->createCommand($sql)->queryAll(); -		foreach($keys as $key) -		{ -			$column=$table->columns[$key['from']]; -			$column->isForeignKey=true; -			$foreignKeys[$key['from']]=array($key['table'],$key['to']); -		} -		$table->foreignKeys=$foreignKeys; -	} - -	/** -	 * Creates a table column. -	 * @param array column metadata -	 * @return TDbColumnSchema normalized column metadata -	 */ -	protected function createColumn($column) -	{ -		$c=new TSqliteColumnSchema; -		$c->name=$column['name']; -		$c->rawName=$this->quoteColumnName($c->name); -		$c->allowNull=!$column['notnull']; -		$c->isPrimaryKey=$column['pk']!=0; -		$c->isForeignKey=false; -		$c->init(strtolower($column['type']),$column['dflt_value']); -		return $c; -	} -} diff --git a/framework/Testing/Data/TDataSourceConfig.php b/framework/Testing/Data/TDataSourceConfig.php deleted file mode 100755 index 356e7f17..00000000 --- a/framework/Testing/Data/TDataSourceConfig.php +++ /dev/null @@ -1,168 +0,0 @@ -<?php -/** - * TDataSourceConfig class file. - * - * @author Wei Zhuo <weizhuo[at]gmail[dot]com> - * @author Christophe Boulain <Christophe.Boulain@gmail.com - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2009 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Testing.Data - */ - -Prado::using('System.Testing.Data.TDbConnection'); - -/** - * TDataSourceConfig module class provides <module> configuration for database connections. - * - * Example usage: mysql connection - * <code> - * <modules> - * 	<module id="db1"> - * 		<database ConnectionString="mysqli:host=localhost;dbname=test" - * 			username="dbuser" password="dbpass" /> - * 	</module> - * </modules> - * </code> - * - * Usage in php: - * <code> - * class Home extends TPage - * { - * 		function onLoad($param) - * 		{ - * 			$db = $this->Application->Modules['db1']->DbConnection; - * 			$db->createCommand('...'); //... - * 		} - * } - * </code> - * - * The properties of <connection> are those of the class TDbConnection. - * Set {@link setConnectionClass} attribute for a custom database connection class - * that extends the TDbConnection class. - * - * @author Wei Zhuo <weizho[at]gmail[dot]com> - * @version $Id$ - * @package System.Testing.Data - * @since 3.1 - */ -class TDataSourceConfig extends TModule -{ -	private $_connID=''; -	private $_conn; -	private $_connClass='System.Testing.Data.TDbConnection'; - -	/** -	 * Initalize the database connection properties from attributes in <database> tag. -	 * @param TXmlDocument xml configuration. -	 */ -	public function init($xml) -	{ -		if($this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP) -		{ -			if(isset($xml['database']) && is_array($xml['database'])) -			{ -				$db=$this->getDbConnection(); -				foreach($xml['database'] as $name=>$value) -					$db->setSubProperty($name,$value); -			} -		} -		else -		{ -			if($prop=$xml->getElementByTagName('database')) -			{ -				$db=$this->getDbConnection(); -				foreach($prop->getAttributes() as $name=>$value) -					$db->setSubproperty($name,$value); -			} -		} -	} - -	/** -	 * The module ID of another TDataSourceConfig. The {@link getDbConnection DbConnection} -	 * property of this configuration will equal to {@link getDbConnection DbConnection} -	 * of the given TDataSourceConfig module. -	 * @param string module ID. -	 */ -	public function setConnectionID($value) -	{ -		$this->_connID=$value; -	} - -	/** -	 * @return string connection module ID. -	 */ -	public function getConnectionID() -	{ -		return $this->_connID; -	} - -	/** -	 * Gets the TDbConnection from another module if {@link setConnectionID ConnectionID} -	 * is supplied and valid. Otherwise, a connection of type given by -	 * {@link setConnectionClass ConnectionClass} is created. -	 * @return TDbConnection database connection. -	 */ -	public function getDbConnection() -	{ -		if($this->_conn===null) -		{ -			if($this->_connID!=='') -				$this->_conn = $this->findConnectionByID($this->getConnectionID()); -			else -				$this->_conn = Prado::createComponent($this->getConnectionClass()); -		} -		return $this->_conn; -	} - -	/** -	 * Alias for getDbConnection(). -	 * @return TDbConnection database connection. -	 */ -	public function getDatabase() -	{ -		return $this->getDbConnection(); -	} - -	/** -	 * @param string Database connection class name to be created. -	 */ -	public function getConnectionClass() -	{ -		return $this->_connClass; -	} - -	/** -	 * The database connection class name to be created when {@link getDbConnection} -	 * method is called <b>and</b> {@link setConnectionID ConnectionID} is null. The -	 * {@link setConnectionClass ConnectionClass} property must be set before -	 * calling {@link getDbConnection} if you wish to create the connection using the -	 * given class name. -	 * @param string Database connection class name. -	 * @throws TConfigurationException when database connection is already established. -	 */ -	public function setConnectionClass($value) -	{ -		if($this->_conn!==null) -			throw new TConfigurationException('datasource_dbconnection_exists', $value); -		$this->_connClass=$value; -	} - -	/** -	 * Finds the database connection instance from the Application modules. -	 * @param string Database connection module ID. -	 * @return TDbConnection database connection. -	 * @throws TConfigurationException when module is not of TDbConnection or TDataSourceConfig. -	 */ -	protected function findConnectionByID($id) -	{ -		$conn = $this->getApplication()->getModule($id); -		if($conn instanceof TDbConnection) -			return $conn; -		else if($conn instanceof TDataSourceConfig) -			return $conn->getDbConnection(); -		else -			throw new TConfigurationException('datasource_dbconnection_invalid',$id); -	} -} diff --git a/framework/Testing/Data/TDbCommand.php b/framework/Testing/Data/TDbCommand.php deleted file mode 100755 index dd3a9fe6..00000000 --- a/framework/Testing/Data/TDbCommand.php +++ /dev/null @@ -1,344 +0,0 @@ -<?php -/** - * This file contains the TDbCommand class. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -/** - * TDbCommand represents an SQL statement to execute against a database. - * - * It is usually created by calling {@link TDbConnection::createCommand}. - * The SQL statement to be executed may be set via {@link setText Text}. - * - * To execute a non-query SQL (such as insert, delete, update), call - * {@link execute}. To execute an SQL statement that returns result data set - * (such as SELECT), use {@link query} or its convenient versions {@link queryRow}, - * {@link queryColumn}, or {@link queryScalar}. - * - * If an SQL statement returns results (such as a SELECT SQL), the results - * can be accessed via the returned {@link TDbDataReader}. - * - * TDbCommand supports SQL statment preparation and parameter binding. - * Call {@link bindParam} to bind a PHP variable to a parameter in SQL. - * Call {@link bindValue} to bind a value to an SQL parameter. - * When binding a parameter, the SQL statement is automatically prepared. - * You may also call {@link prepare} to explicitly prepare an SQL statement. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id$ - * @package System.Testing.Data - * @since 1.0 - */ -class TDbCommand extends TComponent -{ -	private $_connection; -	private $_text=''; -	private $_statement=null; -	private $_params; - -	/** -	 * Constructor. -	 * @param TDbConnection the database connection -	 * @param string the SQL statement to be executed -	 */ -	public function __construct(TDbConnection $connection,$text) -	{ -		$this->_connection=$connection; -		$this->setText($text); -	} - -	/** -	 * Set the statement to null when serializing. -	 */ -	public function __sleep() -	{ -		$this->_statement=null; -		return array_keys(get_object_vars($this)); -	} - -	/** -	 * @return string the SQL statement to be executed -	 */ -	public function getText() -	{ -		return $this->_text; -	} - -	/** -	 * Specifies the SQL statement to be executed. -	 * Any previous execution will be terminated or cancel. -	 * @param string the SQL statement to be executed -	 */ -	public function setText($value) -	{ -		$this->_text=$value; -		$this->cancel(); -	} - -	/** -	 * @return TDbConnection the connection associated with this command -	 */ -	public function getConnection() -	{ -		return $this->_connection; -	} - -	/** -	 * @return PDOStatement the underlying PDOStatement for this command -	 * It could be null if the statement is not prepared yet. -	 */ -	public function getPdoStatement() -	{ -		return $this->_statement; -	} - -	/** -	 * Prepares the SQL statement to be executed. -	 * For complex SQL statement that is to be executed multiple times, -	 * this may improve performance. -	 * For SQL statement with binding parameters, this method is invoked -	 * automatically. -	 */ -	public function prepare() -	{ -		if($this->_statement==null) -		{ -			try -			{ -				$this->_statement=$this->getConnection()->getPdoInstance()->prepare($this->getText()); -				$this->_params=array(); -			} -			catch(Exception $e) -			{ -				Prado::log('Error in preparing SQL: '.$this->getText(),TLogger::ERROR,'System.Testing.Data.TDbCommand'); -				throw new TDbException('TDbCommand failed to prepare the SQL statement: {0}', -					$e->getMessage()); -			} -		} -	} - -	/** -	 * Cancels the execution of the SQL statement. -	 */ -	public function cancel() -	{ -		$this->_statement=null; -	} - -	/** -	 * Binds a parameter to the SQL statement to be executed. -	 * @param mixed Parameter identifier. For a prepared statement -	 * using named placeholders, this will be a parameter name of -	 * the form :name. For a prepared statement using question mark -	 * placeholders, this will be the 1-indexed position of the parameter. -	 * @param mixed Name of the PHP variable to bind to the SQL statement parameter -	 * @param int SQL data type of the parameter. If null, the type is determined by the PHP type of the value. -	 * @param int length of the data type -	 * @see http://www.php.net/manual/en/function.PDOStatement-bindParam.php -	 */ -	public function bindParameter($name, &$value, $dataType=null, $length=null) -	{ -		$this->prepare(); -		if($dataType===null) -			$this->_statement->bindParam($name,$value,$this->_connection->getPdoType(gettype($value))); -		else if($length===null) -			$this->_statement->bindParam($name,$value,$dataType); -		else -			$this->_statement->bindParam($name,$value,$dataType,$length); -		if($this->_connection->enableParamLogging) -			$this->_params[]=$name.'=['.gettype($value).']'; -	} - - -	/** -	 * Binds a value to a parameter. -	 * @param mixed Parameter identifier. For a prepared statement -	 * using named placeholders, this will be a parameter name of -	 * the form :name. For a prepared statement using question mark -	 * placeholders, this will be the 1-indexed position of the parameter. -	 * @param mixed The value to bind to the parameter -	 * @param int SQL data type of the parameter. If null, the type is determined by the PHP type of the value. -	 * @see http://www.php.net/manual/en/function.PDOStatement-bindValue.php -	 */ -	public function bindValue($name, $value, $dataType=null) -	{ -		$this->prepare(); -		if($dataType===null) -			$this->_statement->bindValue($name,$value,$this->_connection->getPdoType(gettype($value))); -		else -			$this->_statement->bindValue($name,$value,$dataType); -		if($this->_connection->enableParamLogging) -			$this->_params[]=$name.'='.var_export($value,true); -	} - -	/** -	 * Executes the SQL statement. -	 * This method is meant only for executing non-query SQL statement. -	 * No result set will be returned. -	 * @return integer number of rows affected by the execution. -	 * @throws CException execution failed -	 */ -	public function execute() -	{ -		$params=$this->_connection->enableParamLogging && !empty($this->_params) ? '. Bind with parameter ' . implode(', ',$this->_params) : ''; -		Prado::trace('Executing SQL: '.$this->getText().$params,'System.Testing.Data.TDbCommand'); -		try -		{ -			/* -			if($this->_connection->enableProfiling) -				Prado::beginProfile('System.Testing.Data.TDbCommand.execute('.$this->getText().')','System.Testing.Data.TDbCommand.execute'); -			*/ -			if($this->_statement instanceof PDOStatement) -			{ -				$this->_statement->execute(); -				$n=$this->_statement->rowCount(); -			} -			else -				$n=$this->getConnection()->getPdoInstance()->exec($this->getText()); -			/* -			if($this->_connection->enableProfiling) -				Prado::endProfile('System.Testing.Data.TDbCommand.execute('.$this->getText().')','System.Testing.Data.TDbCommand.execute'); -			*/ -			return $n; -		} -		catch(Exception $e) -		{ -			/* -			if($this->_connection->enableProfiling) -				Prado::endProfile('System.Testing.Data.TDbCommand.execute('.$this->getText().')','System.Testing.Data.TDbCommand.execute'); -			*/ -			Prado::log('Error in executing SQL: '.$this->getText().$params,TLogger::ERROR,'System.Testing.Data.TDbCommand'); -			throw new TDbException('TDbCommand failed to execute the SQL statement: {0}', -				$e->getMessage()); -		} -	} - -	/** -	 * @return String prepared SQL text for debugging purposes. -	 */ -	public function getDebugStatementText() -	{ -		if(Prado::getApplication()->getMode() === TApplicationMode::Debug) -		{ -			$params=$this->_connection->enableParamLogging && !empty($this->_params) ? '. Bind with parameter ' . implode(', ',$this->_params) : ''; -			return $this->_statement instanceof PDOStatement ? -				$this->_statement->queryString.$params -				: $this->getText().$params; - -		} -	} - -	/** -	 * Executes the SQL statement and returns query result. -	 * This method is for executing an SQL query that returns result set. -	 * @return TDbDataReader the reader object for fetching the query result -	 * @throws CException execution failed -	 */ -	public function query() -	{ -		return $this->queryInternal('',0); -	} - -	/** -	 * Executes the SQL statement and returns all rows. -	 * @param boolean whether each row should be returned as an associated array with -	 * column names as the keys or the array keys are column indexes (0-based). -	 * @return array all rows of the query result. Each array element is an array representing a row. -	 * An empty array is returned if the query results in nothing. -	 * @throws CException execution failed -	 */ -	public function queryAll($fetchAssociative=true) -	{ -		return $this->queryInternal('fetchAll',$fetchAssociative ? PDO::FETCH_ASSOC : PDO::FETCH_NUM); -	} - -	/** -	 * Executes the SQL statement and returns the first row of the result. -	 * This is a convenient method of {@link query} when only the first row of data is needed. -	 * @param boolean whether the row should be returned as an associated array with -	 * column names as the keys or the array keys are column indexes (0-based). -	 * @return array the first row of the query result, false if no result. -	 * @throws CException execution failed -	 */ -	public function queryRow($fetchAssociative=true) -	{ -		return $this->queryInternal('fetch',$fetchAssociative ? PDO::FETCH_ASSOC : PDO::FETCH_NUM); -	} - -	/** -	 * Executes the SQL statement and returns the value of the first column in the first row of data. -	 * This is a convenient method of {@link query} when only a single scalar -	 * value is needed (e.g. obtaining the count of the records). -	 * @return mixed the value of the first column in the first row of the query result. False is returned if there is no value. -	 * @throws CException execution failed -	 */ -	public function queryScalar() -	{ -		$result=$this->queryInternal('fetchColumn',0); -		if(is_resource($result) && get_resource_type($result)==='stream') -			return stream_get_contents($result); -		else -			return $result; -	} - -	/** -	 * Executes the SQL statement and returns the first column of the result. -	 * This is a convenient method of {@link query} when only the first column of data is needed. -	 * Note, the column returned will contain the first element in each row of result. -	 * @return array the first column of the query result. Empty array if no result. -	 * @throws CException execution failed -	 */ -	public function queryColumn() -	{ -		return $this->queryInternal('fetchAll',PDO::FETCH_COLUMN); -	} - -	/** -	 * @param string method of PDOStatement to be called -	 * @param mixed the first parameter to be passed to the method -	 * @return mixed the method execution result -	 */ -	private function queryInternal($method,$mode) -	{ -		$params=$this->_connection->enableParamLogging && !empty($this->_params) ? '. Bind with parameter ' . implode(', ',$this->_params) : ''; -		Prado::trace('Querying SQL: '.$this->getText().$params,'System.Testing.Data.TDbCommand'); -		try -		{ -			/* -			if($this->_connection->enableProfiling) -				Prado::beginProfile('System.Testing.Data.TDbCommand.query('.$this->getText().')','System.Testing.Data.TDbCommand.query'); -			*/ -			if($this->_statement instanceof PDOStatement) -				$this->_statement->execute(); -			else -				$this->_statement=$this->getConnection()->getPdoInstance()->query($this->getText()); -			 -			if($method==='') -				$result=new TDbDataReader($this); -			else -			{ -				$result=$this->_statement->{$method}($mode); -				$this->_statement->closeCursor(); -			} -			/* -			if($this->_connection->enableProfiling) -				Prado::endProfile('System.Testing.Data.TDbCommand.query('.$this->getText().')','System.Testing.Data.TDbCommand.query'); -			*/ -			return $result; -		} -		catch(Exception $e) -		{ -			/* -			if($this->_connection->enableProfiling) -				prado::endProfile('System.Testing.Data.TDbCommand.query('.$this->getText().')','System.Testing.Data.TDbCommand.query'); -			*/ -			Prado::log('Error in querying SQL: '.$this->getText().$params,TLogger::ERROR,'System.Testing.Data..TDbCommand'); -			throw new TDbException('TDbCommand failed to execute the SQL statement: {0}', -				$e->getMessage()); -		} -	} -} diff --git a/framework/Testing/Data/TDbConnection.php b/framework/Testing/Data/TDbConnection.php deleted file mode 100755 index d2d268de..00000000 --- a/framework/Testing/Data/TDbConnection.php +++ /dev/null @@ -1,773 +0,0 @@ -<?php -/** - * TDbConnection class file - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @author Christophe Boulain <Christophe.Boulain@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -prado::using ('System.Testing.Data.TDbCommand'); -prado::using ('System.Testing.Data.TDbTransaction'); - -/** - * TDbConnection represents a connection to a database. - * - * This is a port of {@link http://www.yiiframework.com Yii} {@link http://www.yiiframework.com/ CDbConnection} - * - * TDbConnection works together with {@link TDbCommand}, {@link TDbDataReader} - * and {@link TDbTransaction} to provide data access to various DBMS - * in a common set of APIs. They are a thin wrapper of the {@link http://www.php.net/manual/en/ref.pdo.php PDO} - * PHP extension. - * - * To establish a connection, set {@link setActive active} to true after - * specifying {@link connectionString}, {@link username} and {@link password}. - * - * The following example shows how to create a TDbConnection instance and establish - * the actual connection: - * <pre> - * $connection=new TDbConnection($dsn,$username,$password); - * $connection->active=true; - * </pre> - * - * After the DB connection is established, one can execute an SQL statement like the following: - * <pre> - * $command=$connection->createCommand($sqlStatement); - * $command->execute();   // a non-query SQL statement execution - * // or execute an SQL query and fetch the result set - * $reader=$command->query(); - * - * // each $row is an array representing a row of data - * foreach($reader as $row) ... - * </pre> - * - * One can do prepared SQL execution and bind parameters to the prepared SQL: - * <pre> - * $command=$connection->createCommand($sqlStatement); - * $command->bindParam($name1,$value1); - * $command->bindParam($name2,$value2); - * $command->execute(); - * </pre> - * - * To use transaction, do like the following: - * <pre> - * $transaction=$connection->beginTransaction(); - * try - * { - *    $connection->createCommand($sql1)->execute(); - *    $connection->createCommand($sql2)->execute(); - *    //.... other SQL executions - *    $transaction->commit(); - * } - * catch(Exception $e) - * { - *    $transaction->rollBack(); - * } - * </pre> - * - * TDbConnection also provides a set of methods to support setting and querying - * of certain DBMS attributes, such as {@link getNullConversion nullConversion}. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @author Christophe.Boulain <Christophe.Boulain@gmail.com> - * @version $Id$ - * @package System.Testing.Data - * @since 3.2 - */ -class TDbConnection extends TComponent -{ -	/** -	 * @var string The Data Source Name, or DSN, contains the information required to connect to the database. -	 * @see http://www.php.net/manual/en/function.PDO-construct.php -	 */ -	public $connectionString; -	/** -	 * @var string the username for establishing DB connection. Defaults to empty string. -	 */ -	public $username=''; -	/** -	 * @var string the password for establishing DB connection. Defaults to empty string. -	 */ -	public $password=''; -	/** -	 * @var integer number of seconds that table metadata can remain valid in cache. -	 * Use 0 or negative value to indicate not caching schema. -	 * If greater than 0 and the primary cache is enabled, the table metadata will be cached. -	 * @see schemaCachingExclude -	 */ -	public $schemaCachingDuration=0; -	/** -	 * @var array list of tables whose metadata should NOT be cached. Defaults to empty array. -	 * @see schemaCachingDuration -	 */ -	public $schemaCachingExclude=array(); -	/** -	 * @var boolean whether the database connection should be automatically established -	 * the component is being initialized. Defaults to true. Note, this property is only -	 * effective when the TDbConnection object is used as an application component. -	 */ -	public $autoConnect=true; -	/** -	 * @var string the charset used for database connection. The property is only used -	 * for MySQL and PostgreSQL databases. Defaults to null, meaning using default charset -	 * as specified by the database. -	 */ -	public $charset; -	/** -	 * @var boolean whether to turn on prepare emulation. Defaults to false, meaning PDO -	 * will use the native prepare support if available. For some databases (such as MySQL), -	 * this may need to be set true so that PDO can emulate the prepare support to bypass -	 * the buggy native prepare support. Note, this property is only effective for PHP 5.1.3 or above. -	 */ -	public $emulatePrepare=false; -	/** -	 * @var boolean whether to log the values that are bound to a prepare SQL statement. -	 * Defaults to false. During development, you may consider setting this property to true -	 * so that parameter values bound to SQL statements are logged for debugging purpose. -	 * You should be aware that logging parameter values could be expensive and have significant -	 * impact on the performance of your application. -	 */ -	public $enableParamLogging=false; -	/** -	 * @var boolean whether to enable profiling the SQL statements being executed. -	 * Defaults to false. This should be mainly enabled and used during development -	 * to find out the bottleneck of SQL executions. -	 */ -	public $enableProfiling=false; - -	private $_attributes=array(); -	private $_active=false; -	private $_pdo; -	private $_transaction; -	private $_schema; - - -	/** -	 * Constructor. -	 * Note, the DB connection is not established when this connection -	 * instance is created. Set {@link setActive active} property to true -	 * to establish the connection. -	 * @param string The Data Source Name, or DSN, contains the information required to connect to the database. -	 * @param string The user name for the DSN string. -	 * @param string The password for the DSN string. -	 * @see http://www.php.net/manual/en/function.PDO-construct.php -	 */ -	public function __construct($dsn='',$username='',$password='') -	{ -		$this->connectionString=$dsn; -		$this->username=$username; -		$this->password=$password; -	} - -	/** -	 * Close the connection when serializing. -	 */ -	public function __sleep() -	{ -		$this->close(); -		return array_keys(get_object_vars($this)); -	} - -	/** -	 * @return array list of available PDO drivers -	 * @see http://www.php.net/manual/en/function.PDO-getAvailableDrivers.php -	 */ -	public static function getAvailableDrivers() -	{ -		return PDO::getAvailableDrivers(); -	} - -	/** -	 * Initializes the component. -	 * This method is required by {@link IApplicationComponent} and is invoked by application -	 * when the TDbConnection is used as an application component. -	 * If you override this method, make sure to call the parent implementation -	 * so that the component can be marked as initialized. -	 */ -	public function init() -	{ -		if($this->autoConnect) -			$this->setActive(true); -	} - -	/** -	 * @return boolean whether the DB connection is established -	 */ -	public function getActive() -	{ -		return $this->_active; -	} - -	/** -	 * Open or close the DB connection. -	 * @param boolean whether to open or close DB connection -	 * @throws CException if connection fails -	 */ -	public function setActive($value) -	{ -		if($value!=$this->_active) -		{ -			if($value) -				$this->open(); -			else -				$this->close(); -		} -	} - -	/** -	 * Opens DB connection if it is currently not -	 * @throws CException if connection fails -	 */ -	protected function open() -	{ -		if($this->_pdo===null) -		{ -			if(empty($this->connectionString)) -				throw new TDbException('TDbConnection.connectionString cannot be empty.'); -			try -			{ -				Prado::trace('Opening DB connection','System.Testing.Data.TDbConnection'); -				$this->_pdo=$this->createPdoInstance(); -				$this->initConnection($this->_pdo); -				$this->_active=true; -			} -			catch(PDOException $e) -			{ -				throw new TDbException('TDbConnection failed to open the DB connection: {0}',$e->getMessage()); -			} -		} -	} - -	/** -	 * Closes the currently active DB connection. -	 * It does nothing if the connection is already closed. -	 */ -	protected function close() -	{ -		Prado::trace('Closing DB connection','System.Testing.Data.TDbConnection'); -		$this->_pdo=null; -		$this->_active=false; -		$this->_schema=null; -	} - -	/** -	 * Creates the PDO instance. -	 * When some functionalities are missing in the pdo driver, we may use -	 * an adapter class to provides them. -	 * @return PDO the pdo instance -	 * @since 1.0.4 -	 */ -	protected function createPdoInstance() -	{ -		$pdoClass='PDO'; -		if(($pos=strpos($this->connectionString,':'))!==false) -		{ -			$driver=strtolower(substr($this->connectionString,0,$pos)); -			if($driver==='mssql' || $driver==='dblib') -			{ -				prado::using('System.Testing.Data.Schema.mssql.TMssqlPdoAdapter'); -				$pdoClass='TMssqlPdoAdapter'; -			} -		} -		return new $pdoClass($this->connectionString,$this->username, -									$this->password,$this->_attributes); -	} - -	/** -	 * Initializes the open db connection. -	 * This method is invoked right after the db connection is established. -	 * The default implementation is to set the charset for MySQL and PostgreSQL database connections. -	 * @param PDO the PDO instance -	 */ -	protected function initConnection($pdo) -	{ -		$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); -		if($this->emulatePrepare && constant('PDO::ATTR_EMULATE_PREPARES')) -			$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,true); -		if($this->charset!==null) -		{ -			switch (($driver=$pdo->getAttribute(PDO::ATTR_DRIVER_NAME))) -			{ -				case 'mysql': -				case 'sqlite': -					$stmt = $pdo->prepare('SET NAMES ?'); -				break; -				case 'pgsql': -					$stmt = $pdo->prepare('SET client_encoding TO ?'); -				break; -				default: -					throw new TDbException('dbconnection_unsupported_driver_charset', $driver); -			} -			$stmt->execute(array($this->charset)); -		} -	} - -	/** -	 * @return PDO the PDO instance, null if the connection is not established yet -	 */ -	public function getPdoInstance() -	{ -		return $this->_pdo; -	} - -	/** -	 * Creates a command for execution. -	 * @param string SQL statement associated with the new command. -	 * @return TDbCommand the DB command -	 * @throws CException if the connection is not active -	 */ -	public function createCommand($sql) -	{ -		if($this->getActive()) -			return new TDbCommand($this,$sql); -		else -			throw new TDbException('TDbConnection is inactive and cannot perform any DB operations.'); -	} - -	/** -	 * @return TDbTransaction the currently active transaction. Null if no active transaction. -	 */ -	public function getCurrentTransaction() -	{ -		if($this->_transaction!==null) -		{ -			if($this->_transaction->getActive()) -				return $this->_transaction; -		} -		return null; -	} - -	/** -	 * Starts a transaction. -	 * @return TDbTransaction the transaction initiated -	 * @throws CException if the connection is not active -	 */ -	public function beginTransaction() -	{ -		if($this->getActive()) -		{ -			$this->_pdo->beginTransaction(); -			return $this->_transaction=new TDbTransaction($this); -		} -		else -			throw new TDbException('TDbConnection is inactive and cannot perform any DB operations.'); -	} - -	/** -	 * @return TDbSchema the database schema for the current connection -	 * @throws CException if the connection is not active yet -	 */ -	public function getSchema() -	{ -		if($this->_schema!==null) -			return $this->_schema; -		else -		{ -			if(!$this->getActive()) -				throw new TDbException('TDbConnection is inactive and cannot perform any DB operations.'); -			$driver=$this->getDriverName(); -			switch(strtolower($driver)) -			{ -				case 'pgsql':  // PostgreSQL -					prado::using('System.Testing.Data.Schema.pgsql.TPgsqlSchema'); -					return $this->_schema=new TPgsqlSchema($this); -				case 'mysqli': // MySQL -				case 'mysql': -					prado::using('System.Testing.Data.Schema.mysql.TMysqlSchema'); -					return $this->_schema=new TMysqlSchema($this); -				case 'sqlite': // sqlite 3 -				case 'sqlite2': // sqlite 2 -					prado::using('System.Testing.Data.Schema.sqlite.TSqliteSchema'); -					return $this->_schema=new TSqliteSchema($this); -				case 'mssql': // Mssql driver on windows hosts -				case 'dblib': // dblib drivers on linux (and maybe others os) hosts -					prado::using('System.Testing.Data.Schema.mssql.TMssqlSchema'); -					return $this->_schema=new TMssqlSchema($this); -				case 'oci':  // Oracle driver -					prado::using('System.Testing.Data.Schema.oci.TOciSchema'); -					return $this->_schema=new TOciSchema($this); -				case 'ibm': -				default: -					throw new TDbException('TDbConnection does not support reading schema for {0} database.', -						$driver); -			} -		} -	} - -	/** -	 * Returns the SQL command builder for the current DB connection. -	 * @return TDbCommandBuilder the command builder -	 */ -	public function getCommandBuilder() -	{ -		return $this->getSchema()->getCommandBuilder(); -	} - -	/** -	 * Returns the ID of the last inserted row or sequence value. -	 * @param string name of the sequence object (required by some DBMS) -	 * @return string the row ID of the last row inserted, or the last value retrieved from the sequence object -	 * @see http://www.php.net/manual/en/function.PDO-lastInsertId.php -	 */ -	public function getLastInsertID($sequenceName='') -	{ -		if($this->getActive()) -			return $this->_pdo->lastInsertId($sequenceName); -		else -			throw new TDbException('TDbConnection is inactive and cannot perform any DB operations.'); -	} - -	/** -	 * Quotes a string value for use in a query. -	 * @param string string to be quoted -	 * @return string the properly quoted string -	 * @see http://www.php.net/manual/en/function.PDO-quote.php -	 */ -	public function quoteValue($str) -	{ -		if($this->getActive()) -			return $this->_pdo->quote($str); -		else -			throw new TDbException('TDbConnection is inactive and cannot perform any DB operations.'); -	} - -	/** -	 * -	 * Prado 3.1 compatibility method. -	 * -	 * @see quoteValue -	 * -	 * @param string $str -	 * @return string -	 */ -	public function quoteString($str) -	{ -		return $this->quoteValue($str); -	} - -	/** -	 * Quotes a table name for use in a query. -	 * @param string table name -	 * @return string the properly quoted table name -	 */ -	public function quoteTableName($name) -	{ -		return $this->getSchema()->quoteTableName($name); -	} - -	/** -	 * Quotes a column name for use in a query. -	 * @param string column name -	 * @return string the properly quoted column name -	 */ -	public function quoteColumnName($name) -	{ -		return $this->getSchema()->quoteColumnName($name); -	} - -	/** -	 * Determines the PDO type for the specified PHP type. -	 * @param string The PHP type (obtained by gettype() call). -	 * @return integer the corresponding PDO type -	 */ -	public function getPdoType($type) -	{ -		static $map=array -		( -			'boolean'=>PDO::PARAM_BOOL, -			'integer'=>PDO::PARAM_INT, -			'string'=>PDO::PARAM_STR, -			'NULL'=>PDO::PARAM_NULL, -		); -		return isset($map[$type]) ? $map[$type] : PDO::PARAM_STR; -	} - -	/** -	 * @return TDbColumnCaseMode the case of the column names -	 */ -	public function getColumnCase() -	{ -		switch($this->getAttribute(PDO::ATTR_CASE)) -		{ -			case PDO::CASE_NATURAL: -				return TDbColumnCaseMode::Preserved; -			case PDO::CASE_LOWER: -				return TDbColumnCaseMode::LowerCase; -			case PDO::CASE_UPPER: -				return TDbColumnCaseMode::UpperCase; -		} -	} - -	/** -	 * @param TDbColumnCaseMode the case of the column names -	 */ -	public function setColumnCase($value) -	{ -		switch(TPropertyValue::ensureEnum($value,'TDbColumnCaseMode')) -		{ -			case TDbColumnCaseMode::Preserved: -				$value=PDO::CASE_NATURAL; -				break; -			case TDbColumnCaseMode::LowerCase: -				$value=PDO::CASE_LOWER; -				break; -			case TDbColumnCaseMode::UpperCase: -				$value=PDO::CASE_UPPER; -				break; -		} -		$this->setAttribute(PDO::ATTR_CASE,$value); -	} -	/** -	 * @return TDbNullConversionMode how the null and empty strings are converted -	 */ -	public function getNullConversion() -	{ -		switch($this->getAttribute(PDO::ATTR_ORACLE_NULLS)) -		{ -			case PDO::NULL_NATURAL: -				return TDbNullConversionMode::Preserved; -			case PDO::NULL_EMPTY_STRING: -				return TDbNullConversionMode::EmptyStringToNull; -			case PDO::NULL_TO_STRING: -				return TDbNullConversionMode::NullToEmptyString; -		} -	} - -	/** -	 * @param TDbNullConversionMode how the null and empty strings are converted -	 */ -	public function setNullConversion($value) -	{ -		switch(TPropertyValue::ensureEnum($value,'TDbNullConversionMode')) -		{ -			case TDbNullConversionMode::Preserved: -				$value=PDO::NULL_NATURAL; -				break; -			case TDbNullConversionMode::EmptyStringToNull: -				$value=PDO::NULL_EMPTY_STRING; -				break; -			case TDbNullConversionMode::NullToEmptyString: -				$value=PDO::NULL_TO_STRING; -				break; -		} -		$this->setAttribute(PDO::ATTR_ORACLE_NULLS,$value); -	} - -	/** -	 * @return boolean whether creating or updating a DB record will be automatically committed. -	 * Some DBMS (such as sqlite) may not support this feature. -	 */ -	public function getAutoCommit() -	{ -		return $this->getAttribute(PDO::ATTR_AUTOCOMMIT); -	} - -	/** -	 * @param boolean whether creating or updating a DB record will be automatically committed. -	 * Some DBMS (such as sqlite) may not support this feature. -	 */ -	public function setAutoCommit($value) -	{ -		$this->setAttribute(PDO::ATTR_AUTOCOMMIT,$value); -	} - -	/** -	 * @return boolean whether the connection is persistent or not -	 * Some DBMS (such as sqlite) may not support this feature. -	 */ -	public function getPersistent() -	{ -		return $this->getAttribute(PDO::ATTR_PERSISTENT); -	} - -	/** -	 * @param boolean whether the connection is persistent or not -	 * Some DBMS (such as sqlite) may not support this feature. -	 */ -	public function setPersistent($value) -	{ -		return $this->setAttribute(PDO::ATTR_PERSISTENT,$value); -	} - -	/** -	 * @return string name of the DB driver -	 */ -	public function getDriverName() -	{ -		return $this->getAttribute(PDO::ATTR_DRIVER_NAME); -	} - -	/** -	 * @return string the version information of the DB driver -	 */ -	public function getClientVersion() -	{ -		return $this->getAttribute(PDO::ATTR_CLIENT_VERSION); -	} - -	/** -	 * @return string the status of the connection -	 * Some DBMS (such as sqlite) may not support this feature. -	 */ -	public function getConnectionStatus() -	{ -		return $this->getAttribute(PDO::ATTR_CONNECTION_STATUS); -	} - -	/** -	 * @return boolean whether the connection performs data prefetching -	 */ -	public function getPrefetch() -	{ -		return $this->getAttribute(PDO::ATTR_PREFETCH); -	} - -	/** -	 * @return string the information of DBMS server -	 */ -	public function getServerInfo() -	{ -		return $this->getAttribute(PDO::ATTR_SERVER_INFO); -	} - -	/** -	 * @return string the version information of DBMS server -	 */ -	public function getServerVersion() -	{ -		return $this->getAttribute(PDO::ATTR_SERVER_VERSION); -	} - -	/** -	 * @return int timeout settings for the connection -	 */ -	public function getTimeout() -	{ -		return $this->getAttribute(PDO::ATTR_TIMEOUT); -	} - -	/** -	 * Obtains a specific DB connection attribute information. -	 * @param int the attribute to be queried -	 * @return mixed the corresponding attribute information -	 * @see http://www.php.net/manual/en/function.PDO-getAttribute.php -	 */ -	public function getAttribute($name) -	{ -		if($this->getActive()) -			return $this->_pdo->getAttribute($name); -		else -			throw new TDbException('TDbConnection is inactive and cannot perform any DB operations.'); -	} - -	/** -	 * Sets an attribute on the database connection. -	 * @param int the attribute to be set -	 * @param mixed the attribute value -	 * @see http://www.php.net/manual/en/function.PDO-setAttribute.php -	 */ -	public function setAttribute($name,$value) -	{ -		if($this->_pdo instanceof PDO) -			$this->_pdo->setAttribute($name,$value); -		else -			$this->_attributes[$name]=$value; -	} - -	/** -	 * Returns the statistical results of SQL executions. -	 * The results returned include the number of SQL statements executed and -	 * the total time spent. -	 * In order to use this method, {@link enableProfiling} has to be set true. -	 * @return array the first element indicates the number of SQL statements executed, -	 * and the second element the total time spent in SQL execution. -	 * @since 1.0.6 -	 */ -	public function getStats() -	{ -		/*$logger=Yii::getLogger(); -		$timings=$logger->getProfilingResults(null,'System.Testing.Data.TDbCommand.query'); -		$count=count($timings); -		$time=array_sum($timings); -		$timings=$logger->getProfilingResults(null,'System.Testing.Data.TDbCommand.execute'); -		$count+=count($timings); -		$time+=array_sum($timings); -		return array($count,$time);*/ -	} - -	/** -	 * Getters & Setters to provide BC with prado-3.1 -	 */ -	public function getConnectionString() { return $this->connectionString;	} -	public function getUsername () { return $this->username; } -	public function getPassword () { return $this->password; } -	public function getCharset () { return $this->charset; } -	public function getSchemaCachingDuration() { return $this->schemaCachingDuration; } -	public function getSchemaCachingExclude () { return $this->schemaCachingExclude; } -	public function getAutoConnect () { return $this->autoConnect; } -	public function getEmulatePrepare () { return $this->emulatePrepare; } -	public function getEnableParamLogging () { return $this->enableParamLogging; } -	public function getEnableProfiling () { return $this->enableProfiling; } - -	public function setConnectionString($value) { $this->connectionString=TPropertyValue::ensureString($value);	} -	public function setUsername ($value) { $this->username=TPropertyValue::ensureString($value); } -	public function setPassword ($value) { $this->password=TPropertyValue::ensureString($value); } -	public function setCharset ($value) { $this->charset=TPropertyValue::ensureString($value); } -	public function setSchemaCachingDuration ($value) { $this->schemaCachingDuration=TPropertyValue::ensureInteger($value); } -	public function setSchemaCachingExclude ($value) { $this->username=TPropertyValue::ensureArray($value); } -	public function setAutoConnect ($value) { $this->autoConnect = TPropertyValue::ensureBoolean($value); } -	public function setEnablePrepare ($value) { $this->emulatePrepare = TPropertyValue::ensureBoolean($value); } -	public function setEnableParamLogging ($value) { $this->enableParamLogging = TPropertyValue::ensureBoolean($value); } -	public function setEnableProfiling ($value) { $this->enableProfiling = TPropertyValue::ensureBoolean ($value) ; } -} - - -/** - * TDbColumnCaseMode - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id$ - * @package System.Testing.Data - * @since 3.0 - */ -class TDbColumnCaseMode extends TEnumerable -{ -	/** -	 * Column name cases are kept as is from the database -	 */ -	const Preserved='Preserved'; -	/** -	 * Column names are converted to lower case -	 */ -	const LowerCase='LowerCase'; -	/** -	 * Column names are converted to upper case -	 */ -	const UpperCase='UpperCase'; -} - -/** - * TDbNullConversionMode - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id$ - * @package System.Testing.Data - * @since 3.0 - */ -class TDbNullConversionMode extends TEnumerable -{ -	/** -	 * No conversion is performed for null and empty values. -	 */ -	const Preserved='Preserved'; -	/** -	 * NULL is converted to empty string -	 */ -	const NullToEmptyString='NullToEmptyString'; -	/** -	 * Empty string is converted to NULL -	 */ -	const EmptyStringToNull='EmptyStringToNull'; -} diff --git a/framework/Testing/Data/TDbDataReader.php b/framework/Testing/Data/TDbDataReader.php deleted file mode 100755 index 6014ff04..00000000 --- a/framework/Testing/Data/TDbDataReader.php +++ /dev/null @@ -1,221 +0,0 @@ -<?php -/** - * TDbDataReader class file - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -/** - * TDbDataReader represents a forward-only stream of rows from a query result set. - * - * To read the current row of data, call {@link read}. The method {@link readAll} - * returns all the rows in a single array. - * - * One can also retrieve the rows of data in TDbDataReader by using foreach: - * <pre> - * foreach($reader as $row) - *     // $row represents a row of data - * </pre> - * Since TDbDataReader is a forward-only stream, you can only traverse it once. - * - * It is possible to use a specific mode of data fetching by setting - * {@link setFetchMode FetchMode}. See {@link http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php} - * for more details. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id$ - * @package System.Testing.Data - * @since 1.0 - */ -class TDbDataReader extends TComponent implements Iterator -{ -	private $_statement; -	private $_closed=false; -	private $_row; -	private $_index=-1; - -	/** -	 * Constructor. -	 * @param TDbCommand the command generating the query result -	 */ -	public function __construct(TDbCommand $command) -	{ -		$this->_statement=$command->getPdoStatement(); -		$this->_statement->setFetchMode(PDO::FETCH_ASSOC); -	} - -	/** -	 * Binds a column to a PHP variable. -	 * When rows of data are being fetched, the corresponding column value -	 * will be set in the variable. Note, the fetch mode must include PDO::FETCH_BOUND. -	 * @param mixed Number of the column (1-indexed) or name of the column -	 * in the result set. If using the column name, be aware that the name -	 * should match the case of the column, as returned by the driver. -	 * @param mixed Name of the PHP variable to which the column will be bound. -	 * @param int Data type of the parameter -	 * @see http://www.php.net/manual/en/function.PDOStatement-bindColumn.php -	 */ -	public function bindColumn($column, &$value, $dataType=null) -	{ -		if($dataType===null) -			$this->_statement->bindColumn($column,$value); -		else -			$this->_statement->bindColumn($column,$value,$dataType); -	} - -	/** -	 * @see http://www.php.net/manual/en/function.PDOStatement-setFetchMode.php -	 */ -	public function setFetchMode($mode) -	{ -		$params=func_get_args(); -		call_user_func_array(array($this->_statement,'setFetchMode'),$params); -	} - -	/** -	 * Advances the reader to the next row in a result set. -	 * @return array|false the current row, false if no more row available -	 */ -	public function read() -	{ -		return $this->_statement->fetch(); -	} - -	/** -	 * Returns a single column from the next row of a result set. -	 * @param int zero-based column index -	 * @return mixed|false the column of the current row, false if no more row available -	 */ -	public function readColumn($columnIndex) -	{ -		return $this->_statement->fetchColumn($columnIndex); -	} - -	/** -	 * Returns an object populated with the next row of data. -	 * @param string class name of the object to be created and populated -	 * @param array Elements of this array are passed to the constructor -	 * @return mixed|false the populated object, false if no more row of data available -	 */ -	public function readObject($className,$fields) -	{ -		return $this->_statement->fetchObject($className,$fields); -	} - -	/** -	 * Reads the whole result set into an array. -	 * @return array the result set (each array element represents a row of data). -	 * An empty array will be returned if the result contains no row. -	 */ -	public function readAll() -	{ -		return $this->_statement->fetchAll(); -	} - -	/** -	 * Advances the reader to the next result when reading the results of a batch of statements. -	 * This method is only useful when there are multiple result sets -	 * returned by the query. Not all DBMS support this feature. -	 */ -	public function nextResult() -	{ -		return $this->_statement->nextRowset(); -	} - -	/** -	 * Closes the reader. -	 * This frees up the resources allocated for executing this SQL statement. -	 * Read attemps after this method call are unpredictable. -	 */ -	public function close() -	{ -		$this->_statement->closeCursor(); -		$this->_closed=true; -	} - -	/** -	 * @return boolean whether the reader is closed or not. -	 */ -	public function getIsClosed() -	{ -		return $this->_closed; -	} - -	/** -	 * @return int number of rows contained in the result. -	 * Note, most DBMS may not give a meaningful count. -	 * In this case, use "SELECT COUNT(*) FROM tableName" to obtain the number of rows. -	 */ -	public function getRowCount() -	{ -		return $this->_statement->rowCount(); -	} - -	/** -	 * @return int the number of columns in the result set. -	 * Note, even there's no row in the reader, this still gives correct column number. -	 */ -	public function getColumnCount() -	{ -		return $this->_statement->columnCount(); -	} - -	/** -	 * Resets the iterator to the initial state. -	 * This method is required by the interface Iterator. -	 * @throws CException if this method is invoked twice -	 */ -	public function rewind() -	{ -		if($this->_index<0) -		{ -			$this->_row=$this->_statement->fetch(); -			$this->_index=0; -		} -		else -			throw new TDbException('dbdatareader_rewind_invalid'); -	} - -	/** -	 * Returns the index of the current row. -	 * This method is required by the interface Iterator. -	 * @return integer the index of the current row. -	 */ -	public function key() -	{ -		return $this->_index; -	} - -	/** -	 * Returns the current row. -	 * This method is required by the interface Iterator. -	 * @return mixed the current row. -	 */ -	public function current() -	{ -		return $this->_row; -	} - -	/** -	 * Moves the internal pointer to the next row. -	 * This method is required by the interface Iterator. -	 */ -	public function next() -	{ -		$this->_row=$this->_statement->fetch(); -		$this->_index++; -	} - -	/** -	 * Returns whether there is a row of data at current position. -	 * This method is required by the interface Iterator. -	 * @return boolean whether there is a row of data at current position. -	 */ -	public function valid() -	{ -		return $this->_row!==false; -	} -} diff --git a/framework/Testing/Data/TDbTransaction.php b/framework/Testing/Data/TDbTransaction.php deleted file mode 100755 index 41a2c1f9..00000000 --- a/framework/Testing/Data/TDbTransaction.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php -/** - * TDbTransaction class file - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2009 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -Prado::using('System.Testing.Data.TDbDataReader'); - - -/** - * TDbTransaction represents a DB transaction. - * - * It is usually created by calling {@link TDbConnection::beginTransaction}. - * - * The following code is a common scenario of using transactions: - * <pre> - * $transaction=$connection->beginTransaction(); - * try - * { - *    $connection->createCommand($sql1)->execute(); - *    $connection->createCommand($sql2)->execute(); - *    //.... other SQL executions - *    $transaction->commit(); - * } - * catch(Exception $e) - * { - *    $transaction->rollBack(); - * } - * </pre> - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id$ - * @package System.Testing.Data - * @since 1.0 - */ -class TDbTransaction extends TComponent -{ -	private $_connection=null; -	private $_active; - -	/** -	 * Constructor. -	 * @param TDbConnection the connection associated with this transaction -	 * @see TDbConnection::beginTransaction -	 */ -	public function __construct(TDbConnection $connection) -	{ -		$this->_connection=$connection; -		$this->setActive(true); -	} - -	/** -	 * Commits a transaction. -	 * @throws CException if the transaction or the DB connection is not active. -	 */ -	public function commit() -	{ -		if($this->_active && $this->_connection->getActive()) -		{ -			Prado::trace('Committing transaction','System.Testing.Data.TDbTransaction'); -			$this->_connection->getPdoInstance()->commit(); -			$this->_active=false; -		} -		else -			throw new TDbException('dbtransaction_transaction_inactive'); -	} - -	/** -	 * Rolls back a transaction. -	 * @throws CException if the transaction or the DB connection is not active. -	 */ -	public function rollback() -	{ -		if($this->_active && $this->_connection->getActive()) -		{ -			Prado::trace('Rolling back transaction','System.Testing.Data.TDbTransaction'); -			$this->_connection->getPdoInstance()->rollBack(); -			$this->_active=false; -		} -		else -			throw new TDbException('dbtransaction_transaction_inactive'); -	} - -	/** -	 * @return TDbConnection the DB connection for this transaction -	 */ -	public function getConnection() -	{ -		return $this->_connection; -	} - -	/** -	 * @return boolean whether this transaction is active -	 */ -	public function getActive() -	{ -		return $this->_active; -	} - -	/** -	 * @param boolean whether this transaction is active -	 */ -	protected function setActive($value) -	{ -		$this->_active=TPropertyValue::ensureBoolean($value); -	} -} | 
