diff options
Diffstat (limited to 'framework/Data/SqlMap')
32 files changed, 6497 insertions, 6497 deletions
diff --git a/framework/Data/SqlMap/Configuration/TDiscriminator.php b/framework/Data/SqlMap/Configuration/TDiscriminator.php index cbc05612..f0c9187b 100644 --- a/framework/Data/SqlMap/Configuration/TDiscriminator.php +++ b/framework/Data/SqlMap/Configuration/TDiscriminator.php @@ -1,232 +1,232 @@ -<?php
-/**
- * TDiscriminator and TSubMap classes file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TDiscriminator and TSubMap classes file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- */
-
-/**
- * The TDiscriminator corresponds to the <discriminator> tag within a <resultMap>.
- *
- * TDiscriminator allows inheritance logic in SqlMap result mappings.
- * SqlMap compares the data found in the discriminator column to the different
- * <submap> values using the column value's string equivalence. When the string values
- * matches a particular <submap>, SqlMap will use the <resultMap> defined by
- * {@link resultMapping TSubMap::setResultMapping()} property for loading
- * the object data.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TDiscriminator extends TComponent
-{
- private $_column;
- private $_type;
- private $_typeHandler=null;
- private $_columnIndex;
- private $_nullValue;
- private $_mapping;
- private $_resultMaps=array();
- private $_subMaps=array();
-
- /**
- * @return string the name of the column in the result set from which the
- * value will be used to populate the property.
- */
- public function getColumn()
- {
- return $this->_column;
- }
-
- /**
- * @param string the name of the column in the result set from which the
- * value will be used to populate the property.
- */
- public function setColumn($value)
- {
- $this->_column = $value;
- }
-
- /**
- * @param string property type of the parameter to be set.
- */
- public function getType()
- {
- return $this->_type;
- }
-
- /**
- * The type attribute is used to explicitly specify the property type of the
- * parameter to be set. If the attribute type is not set and the framework
- * cannot otherwise determine the type, the type is assumed from the default
- * value of the property.
- * @return string property type of the parameter to be set.
- */
- public function setType($value)
- {
- $this->_type = $value;
- }
-
- /**
- * @return string custom type handler class name (may use namespace).
- */
- public function getTypeHandler()
- {
- return $this->_typeHandler;
- }
-
- /**
- * @param string custom type handler class name (may use namespace).
- */
- public function setTypeHandler($value)
- {
- $this->_typeHandler = $value;
- }
-
- /**
- * @return int index of the column in the ResultSet
- */
- public function getColumnIndex()
- {
- return $this->_columnIndex;
- }
-
- /**
- * The columnIndex attribute value is the index of the column in the
- * ResultSet from which the value will be used to populate the object property.
- * @param int index of the column in the ResultSet
- */
- public function setColumnIndex($value)
- {
- $this->_columnIndex = TPropertyValue::ensureInteger($value);
- }
-
- /**
- * @return mixed outgoing null value replacement.
- */
- public function getNullValue()
- {
- return $this->_nullValue;
- }
-
- /**
- * @param mixed outgoing null value replacement.
- */
- public function setNullValue($value)
- {
- $this->_nullValue = $value;
- }
-
- /**
- * @return TResultProperty result property for the discriminator column.
- */
- public function getMapping()
- {
- return $this->_mapping;
- }
-
- /**
- * @param TSubMap add new sub mapping.
- */
- public function addSubMap($subMap)
- {
- $this->_subMaps[] = $subMap;
- }
-
- /**
- * @param string database value
- * @return TResultMap result mapping.
- */
- public function getSubMap($value)
- {
- if(isset($this->_resultMaps[$value]))
- return $this->_resultMaps[$value];
- }
-
- /**
- * Copies the discriminator properties to a new TResultProperty.
- * @param TResultMap result map holding the discriminator.
- */
- public function initMapping($resultMap)
- {
- $this->_mapping = new TResultProperty($resultMap);
- $this->_mapping->setColumn($this->getColumn());
- $this->_mapping->setColumnIndex($this->getColumnIndex());
- $this->_mapping->setType($this->getType());
- $this->_mapping->setTypeHandler($this->getTypeHandler());
- $this->_mapping->setNullValue($this->getNullValue());
- }
-
- /**
- * Set the result maps for particular sub-mapping values.
- * @param TSqlMapManager sql map manager instance.
- */
- public function initialize($manager)
- {
- foreach($this->_subMaps as $subMap)
- {
- $this->_resultMaps[$subMap->getValue()] =
- $manager->getResultMap($subMap->getResultMapping());
- }
- }
-}
-
-/**
- * TSubMap class defines a submapping value and the corresponding <resultMap>
- *
- * The {@link Value setValue()} property is used for comparison with the
- * discriminator column value. When the {@link Value setValue()} matches
- * that of the discriminator column value, the corresponding {@link ResultMapping setResultMapping}
- * is used inplace of the current result map.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSubMap extends TComponent
-{
- private $_value;
- private $_resultMapping;
-
- /**
- * @return string value for comparison with discriminator column value.
- */
- public function getValue()
- {
- return $this->_value;
- }
-
- /**
- * @param string value for comparison with discriminator column value.
- */
- public function setValue($value)
- {
- $this->_value = $value;
- }
-
- /**
- * The result map to use when the Value matches the discriminator column value.
- * @return string ID of a result map
- */
- public function getResultMapping()
- {
- return $this->_resultMapping;
- }
-
- /**
- * @param string ID of a result map
- */
- public function setResultMapping($value)
- {
- $this->_resultMapping = $value;
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * The TDiscriminator corresponds to the <discriminator> tag within a <resultMap>. + * + * TDiscriminator allows inheritance logic in SqlMap result mappings. + * SqlMap compares the data found in the discriminator column to the different + * <submap> values using the column value's string equivalence. When the string values + * matches a particular <submap>, SqlMap will use the <resultMap> defined by + * {@link resultMapping TSubMap::setResultMapping()} property for loading + * the object data. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TDiscriminator extends TComponent +{ + private $_column; + private $_type; + private $_typeHandler=null; + private $_columnIndex; + private $_nullValue; + private $_mapping; + private $_resultMaps=array(); + private $_subMaps=array(); + + /** + * @return string the name of the column in the result set from which the + * value will be used to populate the property. + */ + public function getColumn() + { + return $this->_column; + } + + /** + * @param string the name of the column in the result set from which the + * value will be used to populate the property. + */ + public function setColumn($value) + { + $this->_column = $value; + } + + /** + * @param string property type of the parameter to be set. + */ + public function getType() + { + return $this->_type; + } + + /** + * The type attribute is used to explicitly specify the property type of the + * parameter to be set. If the attribute type is not set and the framework + * cannot otherwise determine the type, the type is assumed from the default + * value of the property. + * @return string property type of the parameter to be set. + */ + public function setType($value) + { + $this->_type = $value; + } + + /** + * @return string custom type handler class name (may use namespace). + */ + public function getTypeHandler() + { + return $this->_typeHandler; + } + + /** + * @param string custom type handler class name (may use namespace). + */ + public function setTypeHandler($value) + { + $this->_typeHandler = $value; + } + + /** + * @return int index of the column in the ResultSet + */ + public function getColumnIndex() + { + return $this->_columnIndex; + } + + /** + * The columnIndex attribute value is the index of the column in the + * ResultSet from which the value will be used to populate the object property. + * @param int index of the column in the ResultSet + */ + public function setColumnIndex($value) + { + $this->_columnIndex = TPropertyValue::ensureInteger($value); + } + + /** + * @return mixed outgoing null value replacement. + */ + public function getNullValue() + { + return $this->_nullValue; + } + + /** + * @param mixed outgoing null value replacement. + */ + public function setNullValue($value) + { + $this->_nullValue = $value; + } + + /** + * @return TResultProperty result property for the discriminator column. + */ + public function getMapping() + { + return $this->_mapping; + } + + /** + * @param TSubMap add new sub mapping. + */ + public function addSubMap($subMap) + { + $this->_subMaps[] = $subMap; + } + + /** + * @param string database value + * @return TResultMap result mapping. + */ + public function getSubMap($value) + { + if(isset($this->_resultMaps[$value])) + return $this->_resultMaps[$value]; + } + + /** + * Copies the discriminator properties to a new TResultProperty. + * @param TResultMap result map holding the discriminator. + */ + public function initMapping($resultMap) + { + $this->_mapping = new TResultProperty($resultMap); + $this->_mapping->setColumn($this->getColumn()); + $this->_mapping->setColumnIndex($this->getColumnIndex()); + $this->_mapping->setType($this->getType()); + $this->_mapping->setTypeHandler($this->getTypeHandler()); + $this->_mapping->setNullValue($this->getNullValue()); + } + + /** + * Set the result maps for particular sub-mapping values. + * @param TSqlMapManager sql map manager instance. + */ + public function initialize($manager) + { + foreach($this->_subMaps as $subMap) + { + $this->_resultMaps[$subMap->getValue()] = + $manager->getResultMap($subMap->getResultMapping()); + } + } +} + +/** + * TSubMap class defines a submapping value and the corresponding <resultMap> + * + * The {@link Value setValue()} property is used for comparison with the + * discriminator column value. When the {@link Value setValue()} matches + * that of the discriminator column value, the corresponding {@link ResultMapping setResultMapping} + * is used inplace of the current result map. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSubMap extends TComponent +{ + private $_value; + private $_resultMapping; + + /** + * @return string value for comparison with discriminator column value. + */ + public function getValue() + { + return $this->_value; + } + + /** + * @param string value for comparison with discriminator column value. + */ + public function setValue($value) + { + $this->_value = $value; + } + + /** + * The result map to use when the Value matches the discriminator column value. + * @return string ID of a result map + */ + public function getResultMapping() + { + return $this->_resultMapping; + } + + /** + * @param string ID of a result map + */ + public function setResultMapping($value) + { + $this->_resultMapping = $value; + } +} + diff --git a/framework/Data/SqlMap/Configuration/TInlineParameterMapParser.php b/framework/Data/SqlMap/Configuration/TInlineParameterMapParser.php index b78a235c..914d7eb7 100644 --- a/framework/Data/SqlMap/Configuration/TInlineParameterMapParser.php +++ b/framework/Data/SqlMap/Configuration/TInlineParameterMapParser.php @@ -1,79 +1,79 @@ -<?php
-/**
- * TInlineParameterMapParser class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TInlineParameterMapParser class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- */
-
-/**
- * TInlineParameterMapParser class.
- *
- * The inline parameter map syntax lets you embed the property name,
- * the property type, the column type, and a null value replacement into a
- * parametrized SQL statement.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TInlineParameterMapParser
-{
- /**
- * Regular expression for parsing inline parameter maps.
- */
- const PARAMETER_TOKEN_REGEXP = '/#([^#]+)#/';
-
- /**
- * Parse the sql text for inline parameters.
- * @param string sql text
- * @param array file and node details for exception message.
- * @return array 'sql' and 'parameters' name value pairs.
- */
- public function parse($sqlText, $scope)
- {
- $matches = array();
- $mappings = array();
- preg_match_all(self::PARAMETER_TOKEN_REGEXP, $sqlText, $matches);
-
- for($i = 0, $k=count($matches[1]); $i<$k; $i++)
- {
- $mappings[] = $this->parseMapping($matches[1][$i], $scope);
- $sqlText = str_replace($matches[0][$i], '?', $sqlText);
- }
- return array('sql'=>$sqlText, 'parameters'=>$mappings);
- }
-
- /**
- * Parse inline parameter with syntax as
- * #propertyName,type=string,dbype=Varchar,nullValue=N/A,handler=string#
- * @param string parameter token
- * @param array file and node details for exception message.
- */
- protected function parseMapping($token, $scope)
- {
- $mapping = new TParameterProperty;
- $properties = explode(',', $token);
- $mapping->setProperty(trim(array_shift($properties)));
- foreach($properties as $property)
- {
- $prop = explode('=',$property);
- $name = trim($prop[0]); $value=trim($prop[1]);
- if($mapping->canSetProperty($name))
- $mapping->{'set'.$name}($value);
- else
- {
- throw new TSqlMapUndefinedException(
- 'sqlmap_undefined_property_inline_map',
- $name, $scope['file'], $scope['node'], $token);
- }
- }
- return $mapping;
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TInlineParameterMapParser class. + * + * The inline parameter map syntax lets you embed the property name, + * the property type, the column type, and a null value replacement into a + * parametrized SQL statement. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TInlineParameterMapParser +{ + /** + * Regular expression for parsing inline parameter maps. + */ + const PARAMETER_TOKEN_REGEXP = '/#([^#]+)#/'; + + /** + * Parse the sql text for inline parameters. + * @param string sql text + * @param array file and node details for exception message. + * @return array 'sql' and 'parameters' name value pairs. + */ + public function parse($sqlText, $scope) + { + $matches = array(); + $mappings = array(); + preg_match_all(self::PARAMETER_TOKEN_REGEXP, $sqlText, $matches); + + for($i = 0, $k=count($matches[1]); $i<$k; $i++) + { + $mappings[] = $this->parseMapping($matches[1][$i], $scope); + $sqlText = str_replace($matches[0][$i], '?', $sqlText); + } + return array('sql'=>$sqlText, 'parameters'=>$mappings); + } + + /** + * Parse inline parameter with syntax as + * #propertyName,type=string,dbype=Varchar,nullValue=N/A,handler=string# + * @param string parameter token + * @param array file and node details for exception message. + */ + protected function parseMapping($token, $scope) + { + $mapping = new TParameterProperty; + $properties = explode(',', $token); + $mapping->setProperty(trim(array_shift($properties))); + foreach($properties as $property) + { + $prop = explode('=',$property); + $name = trim($prop[0]); $value=trim($prop[1]); + if($mapping->canSetProperty($name)) + $mapping->{'set'.$name}($value); + else + { + throw new TSqlMapUndefinedException( + 'sqlmap_undefined_property_inline_map', + $name, $scope['file'], $scope['node'], $token); + } + } + return $mapping; + } +} + diff --git a/framework/Data/SqlMap/Configuration/TParameterMap.php b/framework/Data/SqlMap/Configuration/TParameterMap.php index d7cc5eb6..ee740fdb 100644 --- a/framework/Data/SqlMap/Configuration/TParameterMap.php +++ b/framework/Data/SqlMap/Configuration/TParameterMap.php @@ -1,210 +1,210 @@ -<?php
-/**
- * TParameterMap class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- */
-
-/**
- * TParameterMap corresponds to the <parameterMap> element.
- *
- * TParameterMap holds one or more parameter child elements that map object
- * properties to placeholders in a SQL statement.
- *
- * A TParameterMap defines an ordered list of values that match up with the
- * placeholders of a parameterized query statement. While the attributes
- * specified by the map still need to be in the correct order, each parameter
- * is named. You can populate the underlying class in any order, and the
- * TParameterMap ensures each value is passed in the correct order.
- *
- * Parameter Maps can be provided as an external element and inline.
- * The <parameterMap> element accepts two attributes: id (required) and extends (optional).
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TParameterMap extends TComponent
-{
- private $_extend;
- private $_properties;
- private $_propertyMap;
- private $_extendMap;
- private $_ID;
-
- /**
- * Initialize the properties and property map collections.
- */
- public function __construct()
- {
- $this->_properties = new TList;
- $this->_propertyMap = new TMap;
- }
-
- /**
- * @return string a unique identifier for the <parameterMap>.
- */
- public function getID()
- {
- return $this->_ID;
- }
-
- /**
- * @param string a unique identifier for the <parameterMap>.
- */
- public function setID($value)
- {
- $this->_ID=$value;
- }
-
- /**
- * @return TParameterProperty[] list of properties for the parameter map.
- */
- public function getProperties()
- {
- return $this->_properties;
- }
-
- /**
- * @return string name of another <parameterMap> upon which to base this TParameterMap.
- */
- public function getExtends()
- {
- return $this->_extend;
- }
-
- /**
- * @param string name of another <parameterMap> upon which to base this TParameterMap.
- */
- public function setExtends($value)
- {
- $this->_extend = $value;
- }
-
- /**
- * @param string name of a parameter property.
- * @return TParameterProperty parameter property.
- * @throws TSqlMapException if index is not string nor integer.
- */
- public function getProperty($index)
- {
- if(is_string($index))
- return $this->_propertyMap->itemAt($index);
- else if(is_int($index))
- return $this->_properties->itemAt($index);
- else
- throw new TSqlMapException('sqlmap_index_must_be_string_or_int', $index);
- }
-
- /**
- * @param TParameterProperty new parameter property
- */
- public function addProperty(TParameterProperty $property)
- {
- $this->_propertyMap->add($property->getProperty(), $property);
- $this->_properties->add($property);
- }
-
- /**
- * @param int parameter property index
- * @param TParameterProperty new parameter property.
- */
- public function insertProperty($index, TParameterProperty $property)
- {
- $this->_propertyMap->add($property->getProperty(), $property);
- $this->_properties->insertAt($index, $property);
- }
-
- /**
- * @return array list of property names.
- */
- public function getPropertyNames()
- {
- return $this->_propertyMap->getKeys();
- }
-
- /**
- * Get the value of a property from the the parameter object.
- * @param TSqlMapTypeHandlerRegistry type handler registry.
- * @param TParameterProperty parameter proproperty.
- * @param mixed parameter object to get the value from.
- * @return unknown
- */
- public function getPropertyValue($registry, $property, $parameterValue)
- {
- $value = $this->getObjectValue($parameterValue,$property);
-
- if(($handler=$this->createTypeHandler($property, $registry))!==null)
- $value = $handler->getParameter($value);
-
- $value = $this->nullifyDefaultValue($property,$value);
-
- if(($type = $property->getType())!==null)
- $value = $registry->convertToType($type, $value);
-
- return $value;
- }
-
-
- /**
- * Create type handler from {@link Type setType()} or {@link TypeHandler setTypeHandler}.
- * @param TParameterProperty parameter property
- * @param TSqlMapTypeHandlerRegistry type handler registry
- * @return TSqlMapTypeHandler type handler.
- */
- protected function createTypeHandler($property, $registry)
- {
- $type=$property->getTypeHandler() ? $property->getTypeHandler() : $property->getType();
- $handler=$registry->getTypeHandler($type);
- if($handler===null && $property->getTypeHandler())
- $handler = Prado::createComponent($type);
- return $handler;
- }
-
-
- /**
- * @param mixed object to obtain the property from.
- * @param TParameterProperty parameter property.
- * @return mixed property value.
- * @throws TSqlMapException if property access is invalid.
- */
- protected function getObjectValue($object,$property)
- {
- try
- {
- return TPropertyAccess::get($object, $property->getProperty());
- }
- catch (TInvalidPropertyException $e)
- {
- throw new TSqlMapException(
- 'sqlmap_unable_to_get_property_for_parameter',
- $this->getID(),
- $property->getProperty(),
- (is_object($object) ? get_class($object) : gettype($object))
- );
- }
- }
-
- /**
- * When the actual value matches the {@link NullValue TParameterProperty::setNullValue()},
- * set the current value to null.
- * @param TParameterProperty parameter property.
- * @param mixed current property value
- * @return mixed null if NullValue matches currrent value.
- */
- protected function nullifyDefaultValue($property,$value)
- {
- if(($nullValue = $property->getNullValue())!==null)
- {
- if($nullValue === $value)
- $value = null;
- }
- return $value;
- }
-}
+<?php +/** + * TParameterMap class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TParameterMap corresponds to the <parameterMap> element. + * + * TParameterMap holds one or more parameter child elements that map object + * properties to placeholders in a SQL statement. + * + * A TParameterMap defines an ordered list of values that match up with the + * placeholders of a parameterized query statement. While the attributes + * specified by the map still need to be in the correct order, each parameter + * is named. You can populate the underlying class in any order, and the + * TParameterMap ensures each value is passed in the correct order. + * + * Parameter Maps can be provided as an external element and inline. + * The <parameterMap> element accepts two attributes: id (required) and extends (optional). + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TParameterMap extends TComponent +{ + private $_extend; + private $_properties; + private $_propertyMap; + private $_extendMap; + private $_ID; + + /** + * Initialize the properties and property map collections. + */ + public function __construct() + { + $this->_properties = new TList; + $this->_propertyMap = new TMap; + } + + /** + * @return string a unique identifier for the <parameterMap>. + */ + public function getID() + { + return $this->_ID; + } + + /** + * @param string a unique identifier for the <parameterMap>. + */ + public function setID($value) + { + $this->_ID=$value; + } + + /** + * @return TParameterProperty[] list of properties for the parameter map. + */ + public function getProperties() + { + return $this->_properties; + } + + /** + * @return string name of another <parameterMap> upon which to base this TParameterMap. + */ + public function getExtends() + { + return $this->_extend; + } + + /** + * @param string name of another <parameterMap> upon which to base this TParameterMap. + */ + public function setExtends($value) + { + $this->_extend = $value; + } + + /** + * @param string name of a parameter property. + * @return TParameterProperty parameter property. + * @throws TSqlMapException if index is not string nor integer. + */ + public function getProperty($index) + { + if(is_string($index)) + return $this->_propertyMap->itemAt($index); + else if(is_int($index)) + return $this->_properties->itemAt($index); + else + throw new TSqlMapException('sqlmap_index_must_be_string_or_int', $index); + } + + /** + * @param TParameterProperty new parameter property + */ + public function addProperty(TParameterProperty $property) + { + $this->_propertyMap->add($property->getProperty(), $property); + $this->_properties->add($property); + } + + /** + * @param int parameter property index + * @param TParameterProperty new parameter property. + */ + public function insertProperty($index, TParameterProperty $property) + { + $this->_propertyMap->add($property->getProperty(), $property); + $this->_properties->insertAt($index, $property); + } + + /** + * @return array list of property names. + */ + public function getPropertyNames() + { + return $this->_propertyMap->getKeys(); + } + + /** + * Get the value of a property from the the parameter object. + * @param TSqlMapTypeHandlerRegistry type handler registry. + * @param TParameterProperty parameter proproperty. + * @param mixed parameter object to get the value from. + * @return unknown + */ + public function getPropertyValue($registry, $property, $parameterValue) + { + $value = $this->getObjectValue($parameterValue,$property); + + if(($handler=$this->createTypeHandler($property, $registry))!==null) + $value = $handler->getParameter($value); + + $value = $this->nullifyDefaultValue($property,$value); + + if(($type = $property->getType())!==null) + $value = $registry->convertToType($type, $value); + + return $value; + } + + + /** + * Create type handler from {@link Type setType()} or {@link TypeHandler setTypeHandler}. + * @param TParameterProperty parameter property + * @param TSqlMapTypeHandlerRegistry type handler registry + * @return TSqlMapTypeHandler type handler. + */ + protected function createTypeHandler($property, $registry) + { + $type=$property->getTypeHandler() ? $property->getTypeHandler() : $property->getType(); + $handler=$registry->getTypeHandler($type); + if($handler===null && $property->getTypeHandler()) + $handler = Prado::createComponent($type); + return $handler; + } + + + /** + * @param mixed object to obtain the property from. + * @param TParameterProperty parameter property. + * @return mixed property value. + * @throws TSqlMapException if property access is invalid. + */ + protected function getObjectValue($object,$property) + { + try + { + return TPropertyAccess::get($object, $property->getProperty()); + } + catch (TInvalidPropertyException $e) + { + throw new TSqlMapException( + 'sqlmap_unable_to_get_property_for_parameter', + $this->getID(), + $property->getProperty(), + (is_object($object) ? get_class($object) : gettype($object)) + ); + } + } + + /** + * When the actual value matches the {@link NullValue TParameterProperty::setNullValue()}, + * set the current value to null. + * @param TParameterProperty parameter property. + * @param mixed current property value + * @return mixed null if NullValue matches currrent value. + */ + protected function nullifyDefaultValue($property,$value) + { + if(($nullValue = $property->getNullValue())!==null) + { + if($nullValue === $value) + $value = null; + } + return $value; + } +} diff --git a/framework/Data/SqlMap/Configuration/TParameterProperty.php b/framework/Data/SqlMap/Configuration/TParameterProperty.php index d941ca18..a79af7f2 100644 --- a/framework/Data/SqlMap/Configuration/TParameterProperty.php +++ b/framework/Data/SqlMap/Configuration/TParameterProperty.php @@ -1,150 +1,150 @@ -<?php
-/**
- * TParameterPropert class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TParameterPropert class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- */
-
-/**
- * TParameterProperty corresponds to the <property> tag and defines
- * one object property for the <parameterMap>
- *
- * The {@link NullValue setNullValue()} attribute can be set to any valid
- * value (based on property type). The {@link NullValue setNullValue()} attribute
- * is used to specify an inbound null value replacement. What this means is
- * that when the value is detected in the object property, a NULL will be written
- * to the database (the opposite behavior of an inbound null value replacement).
- * This allows you to use a magic null number in your application for types that
- * do not support null values (such as int, double, float). When these types of
- * properties contain a matching null value (for example, say, -9999), a NULL
- * will be written to the database instead of the value.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TParameterProperty extends TComponent
-{
- private $_typeHandler;
- private $_type;
- private $_column;
- private $_dbType;
- private $_property;
- private $_nullValue;
-
- /**
- * @return string class name of a custom type handler.
- */
- public function getTypeHandler()
- {
- return $this->_typeHandler;
- }
-
- /**
- * @param string class name of a custom type handler.
- */
- public function setTypeHandler($value)
- {
- $this->_typeHandler = $value;
- }
-
- /**
- * @return string type of the parameter's property
- */
- public function getType()
- {
- return $this->_type;
- }
-
- /**
- * @param string type of the parameter's property
- */
- public function setType($value)
- {
- $this->_type = $value;
- }
-
- /**
- * @return string name of a parameter to be used in the SQL statement.
- */
- public function getColumn()
- {
- return $this->_column;
- }
-
- /**
- * @param string name of a parameter to be used in the SQL statement.
- */
- public function setColumn($value)
- {
- $this->_column = $value;
- }
-
- /**
- * @return string the database column type of the parameter to be set by this property.
- */
- public function getDbType()
- {
- return $this->_dbType;
- }
-
- /**
- * @param string the database column type of the parameter to be set by this property.
- */
- public function setDbType($value)
- {
- $this->_dbType = $value;
- }
-
- /**
- * @return string name of a property of the parameter object.
- */
- public function getProperty()
- {
- return $this->_property;
- }
-
- /**
- * @param string name of a property of the parameter object.
- */
- public function setProperty($value)
- {
- $this->_property = $value;
- }
-
- /**
- * @return mixed null value replacement
- */
- public function getNullValue()
- {
- return $this->_nullValue;
- }
-
- /**
- * The nullValue attribute is used to specify an outgoing null value replacement.
- * @param mixed null value replacement.
- */
- public function setNullValue($value)
- {
- $this->_nullValue = $value;
- }
-
- public function __sleep()
- {
- $exprops = array(); $cn = 'TParameterProperty';
- if ($this->_typeHandler===null) $exprops[] = "\0$cn\0_typeHandler";
- if ($this->_type===null) $exprops[] = "\0$cn\0_type";
- if ($this->_column===null) $exprops[] = "\0$cn\0_column";
- if ($this->_dbType===null) $exprops[] = "\0$cn\0_dbType";
- if ($this->_property===null) $exprops[] = "\0$cn\0_property";
- if ($this->_nullValue===null) $exprops[] = "\0$cn\0_nullValue";
- return array_diff(parent::__sleep(),$exprops);
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TParameterProperty corresponds to the <property> tag and defines + * one object property for the <parameterMap> + * + * The {@link NullValue setNullValue()} attribute can be set to any valid + * value (based on property type). The {@link NullValue setNullValue()} attribute + * is used to specify an inbound null value replacement. What this means is + * that when the value is detected in the object property, a NULL will be written + * to the database (the opposite behavior of an inbound null value replacement). + * This allows you to use a magic null number in your application for types that + * do not support null values (such as int, double, float). When these types of + * properties contain a matching null value (for example, say, -9999), a NULL + * will be written to the database instead of the value. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TParameterProperty extends TComponent +{ + private $_typeHandler; + private $_type; + private $_column; + private $_dbType; + private $_property; + private $_nullValue; + + /** + * @return string class name of a custom type handler. + */ + public function getTypeHandler() + { + return $this->_typeHandler; + } + + /** + * @param string class name of a custom type handler. + */ + public function setTypeHandler($value) + { + $this->_typeHandler = $value; + } + + /** + * @return string type of the parameter's property + */ + public function getType() + { + return $this->_type; + } + + /** + * @param string type of the parameter's property + */ + public function setType($value) + { + $this->_type = $value; + } + + /** + * @return string name of a parameter to be used in the SQL statement. + */ + public function getColumn() + { + return $this->_column; + } + + /** + * @param string name of a parameter to be used in the SQL statement. + */ + public function setColumn($value) + { + $this->_column = $value; + } + + /** + * @return string the database column type of the parameter to be set by this property. + */ + public function getDbType() + { + return $this->_dbType; + } + + /** + * @param string the database column type of the parameter to be set by this property. + */ + public function setDbType($value) + { + $this->_dbType = $value; + } + + /** + * @return string name of a property of the parameter object. + */ + public function getProperty() + { + return $this->_property; + } + + /** + * @param string name of a property of the parameter object. + */ + public function setProperty($value) + { + $this->_property = $value; + } + + /** + * @return mixed null value replacement + */ + public function getNullValue() + { + return $this->_nullValue; + } + + /** + * The nullValue attribute is used to specify an outgoing null value replacement. + * @param mixed null value replacement. + */ + public function setNullValue($value) + { + $this->_nullValue = $value; + } + + public function __sleep() + { + $exprops = array(); $cn = 'TParameterProperty'; + if ($this->_typeHandler===null) $exprops[] = "\0$cn\0_typeHandler"; + if ($this->_type===null) $exprops[] = "\0$cn\0_type"; + if ($this->_column===null) $exprops[] = "\0$cn\0_column"; + if ($this->_dbType===null) $exprops[] = "\0$cn\0_dbType"; + if ($this->_property===null) $exprops[] = "\0$cn\0_property"; + if ($this->_nullValue===null) $exprops[] = "\0$cn\0_nullValue"; + return array_diff(parent::__sleep(),$exprops); + } +} + diff --git a/framework/Data/SqlMap/Configuration/TResultMap.php b/framework/Data/SqlMap/Configuration/TResultMap.php index e05c4c47..77b5f0b2 100644 --- a/framework/Data/SqlMap/Configuration/TResultMap.php +++ b/framework/Data/SqlMap/Configuration/TResultMap.php @@ -1,200 +1,200 @@ -<?php
-/**
- * TResultMap class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- */
-
-/**
- * TResultMap corresponds to <resultMap> mapping tag.
- *
- * A TResultMap lets you control how data is extracted from the result of a
- * query, and how the columns are mapped to object properties. A TResultMap
- * can describe the column type, a null value replacement, and complex property
- * mappings including Collections.
- *
- * The <resultMap> can contain any number of property mappings that map object
- * properties to the columns of a result element. The property mappings are
- * applied, and the columns are read, in the order that they are defined.
- * Maintaining the element order ensures consistent results between different
- * drivers and providers.
- *
- * The {@link Class setClass()} property must be a PHP class object or array instance.
- *
- * The optional {@link Extends setExtends()} attribute can be set to the ID of
- * another <resultMap> upon which to base this <resultMap>. All properties of the
- * "parent" <resultMap> will be included as part of this <resultMap>, and values
- * from the "parent" <resultMap> are set before any values specified by this <resultMap>.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TResultMap extends TComponent
-{
- private $_columns;
- private $_class;
- private $_extends;
- private $_groupBy;
- private $_discriminator;
- private $_typeHandlers;
- private $_ID;
-
- /**
- * Initialize the columns collection.
- */
- public function __construct()
- {
- $this->_columns=new TMap;
- }
-
- /**
- * @return string a unique identifier for the <resultMap>.
- */
- public function getID()
- {
- return $this->_ID;
- }
-
- /**
- * @param string a unique identifier for the <resultMap>.
- */
- public function setID($value)
- {
- $this->_ID=$value;
- }
-
- /**
- * @return string result class name.
- */
- public function getClass()
- {
- return $this->_class;
- }
-
- /**
- * @param string result class name.
- */
- public function setClass($value)
- {
- $this->_class = $value;
- }
-
- /**
- * @return TMap result columns.
- */
- public function getColumns()
- {
- return $this->_columns;
- }
-
- /**
- * @return string result map extends another result map.
- */
- public function getExtends()
- {
- return $this->_extends;
- }
-
- /**
- * @param string result map extends another result map.
- */
- public function setExtends($value)
- {
- $this->_extends = $value;
- }
-
- /**
- * @return string result map groups by.
- */
- public function getGroupBy()
- {
- return $this->_groupBy;
- }
-
- /**
- * @param string result map group by
- */
- public function setGroupBy($value)
- {
- $this->_groupBy = $value;
- }
-
- /**
- * @return TDiscriminator result class discriminator.
- */
- public function getDiscriminator()
- {
- return $this->_discriminator;
- }
-
- /**
- * @param TDiscriminator result class discriminator.
- */
- public function setDiscriminator(TDiscriminator $value)
- {
- $this->_discriminator = $value;
- }
-
- /**
- * Add a TResultProperty to result mapping.
- * @param TResultProperty result property.
- */
- public function addResultProperty(TResultProperty $property)
- {
- $this->_columns[$property->getProperty()] = $property;
- }
-
- /**
- * Create a new instance of the class of this result map.
- * @param TSqlMapTypeHandlerRegistry type handler registry.
- * @return mixed new result object.
- * @throws TSqlMapException
- */
- public function createInstanceOfResult($registry)
- {
- $handler = $registry->getTypeHandler($this->getClass());
- try
- {
- if($handler!==null)
- return $handler->createNewInstance();
- else
- return $registry->createInstanceOf($this->getClass());
- }
- catch (TSqlMapException $e)
- {
- throw new TSqlMapException(
- 'sqlmap_unable_to_create_new_instance',
- $this->getClass(), get_class($handler), $this->getID());
- }
- }
-
- /**
- * Result sub-mappings using the discriminiator column.
- * @param TSqlMapTypeHandlerRegistry type handler registry
- * @param array row data.
- * @return TResultMap result sub-map.
- */
- public function resolveSubMap($registry,$row)
- {
- $subMap = $this;
- if(($disc = $this->getDiscriminator())!==null)
- {
- $value = $disc->getMapping()->getPropertyValue($registry,$row);
- $subMap = $disc->getSubMap((string)$value);
-
- if($subMap===null)
- $subMap = $this;
- else if($subMap !== $this)
- $subMap = $subMap->resolveSubMap($registry,$row);
- }
- return $subMap;
- }
-}
-
+<?php +/** + * TResultMap class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TResultMap corresponds to <resultMap> mapping tag. + * + * A TResultMap lets you control how data is extracted from the result of a + * query, and how the columns are mapped to object properties. A TResultMap + * can describe the column type, a null value replacement, and complex property + * mappings including Collections. + * + * The <resultMap> can contain any number of property mappings that map object + * properties to the columns of a result element. The property mappings are + * applied, and the columns are read, in the order that they are defined. + * Maintaining the element order ensures consistent results between different + * drivers and providers. + * + * The {@link Class setClass()} property must be a PHP class object or array instance. + * + * The optional {@link Extends setExtends()} attribute can be set to the ID of + * another <resultMap> upon which to base this <resultMap>. All properties of the + * "parent" <resultMap> will be included as part of this <resultMap>, and values + * from the "parent" <resultMap> are set before any values specified by this <resultMap>. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TResultMap extends TComponent +{ + private $_columns; + private $_class; + private $_extends; + private $_groupBy; + private $_discriminator; + private $_typeHandlers; + private $_ID; + + /** + * Initialize the columns collection. + */ + public function __construct() + { + $this->_columns=new TMap; + } + + /** + * @return string a unique identifier for the <resultMap>. + */ + public function getID() + { + return $this->_ID; + } + + /** + * @param string a unique identifier for the <resultMap>. + */ + public function setID($value) + { + $this->_ID=$value; + } + + /** + * @return string result class name. + */ + public function getClass() + { + return $this->_class; + } + + /** + * @param string result class name. + */ + public function setClass($value) + { + $this->_class = $value; + } + + /** + * @return TMap result columns. + */ + public function getColumns() + { + return $this->_columns; + } + + /** + * @return string result map extends another result map. + */ + public function getExtends() + { + return $this->_extends; + } + + /** + * @param string result map extends another result map. + */ + public function setExtends($value) + { + $this->_extends = $value; + } + + /** + * @return string result map groups by. + */ + public function getGroupBy() + { + return $this->_groupBy; + } + + /** + * @param string result map group by + */ + public function setGroupBy($value) + { + $this->_groupBy = $value; + } + + /** + * @return TDiscriminator result class discriminator. + */ + public function getDiscriminator() + { + return $this->_discriminator; + } + + /** + * @param TDiscriminator result class discriminator. + */ + public function setDiscriminator(TDiscriminator $value) + { + $this->_discriminator = $value; + } + + /** + * Add a TResultProperty to result mapping. + * @param TResultProperty result property. + */ + public function addResultProperty(TResultProperty $property) + { + $this->_columns[$property->getProperty()] = $property; + } + + /** + * Create a new instance of the class of this result map. + * @param TSqlMapTypeHandlerRegistry type handler registry. + * @return mixed new result object. + * @throws TSqlMapException + */ + public function createInstanceOfResult($registry) + { + $handler = $registry->getTypeHandler($this->getClass()); + try + { + if($handler!==null) + return $handler->createNewInstance(); + else + return $registry->createInstanceOf($this->getClass()); + } + catch (TSqlMapException $e) + { + throw new TSqlMapException( + 'sqlmap_unable_to_create_new_instance', + $this->getClass(), get_class($handler), $this->getID()); + } + } + + /** + * Result sub-mappings using the discriminiator column. + * @param TSqlMapTypeHandlerRegistry type handler registry + * @param array row data. + * @return TResultMap result sub-map. + */ + public function resolveSubMap($registry,$row) + { + $subMap = $this; + if(($disc = $this->getDiscriminator())!==null) + { + $value = $disc->getMapping()->getPropertyValue($registry,$row); + $subMap = $disc->getSubMap((string)$value); + + if($subMap===null) + $subMap = $this; + else if($subMap !== $this) + $subMap = $subMap->resolveSubMap($registry,$row); + } + return $subMap; + } +} + diff --git a/framework/Data/SqlMap/Configuration/TResultProperty.php b/framework/Data/SqlMap/Configuration/TResultProperty.php index 0a016350..8447d400 100644 --- a/framework/Data/SqlMap/Configuration/TResultProperty.php +++ b/framework/Data/SqlMap/Configuration/TResultProperty.php @@ -1,344 +1,344 @@ -<?php
-/**
- * TResultProperty class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- */
-
-/**
- * TResultProperty corresponds a <property> tags inside a <resultMap> tag.
- *
- * The {@link NullValue setNullValue()} attribute can be set to any valid
- * value (based on property type). The {@link NullValue setNullValue()} attribute
- * is used to specify an outgoing null value replacement. What this means is
- * that when a null value is detected in the result, the corresponding value of
- * the {@link NullValue getNullValue()} will be used instead.
- *
- * The {@link Select setSelect()} property is used to describe a relationship
- * between objects and to automatically load complex (i.e. user defined)
- * property types. The value of the {@link Select setSelect()} property must be
- * the name of another mapped statement. The value of the database
- * {@link Column setColumn()} that is defined in the same property element as
- * this statement attribute will be passed to the related mapped statement as
- * the parameter. The {@link LazyLoad setLayLoad()} attribute can be specified
- * with the {@link Select setSelect()} .
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TResultProperty extends TComponent
-{
- private $_nullValue;
- private $_propertyName;
- private $_columnName;
- private $_columnIndex=-1;
- private $_nestedResultMapName;
- private $_nestedResultMap;
- private $_valueType;
- private $_typeHandler;
- private $_isLazyLoad=false;
- private $_select;
-
- private $_hostResultMapID='inplicit internal mapping';
-
- const LIST_TYPE = 0;
- const ARRAY_TYPE = 1;
-
- /**
- * Gets the containing result map ID.
- * @param TResultMap containing result map.
- */
- public function __construct($resultMap=null)
- {
- if($resultMap instanceof TResultMap)
- $this->_hostResultMapID = $resultMap->getID();
- }
-
- /**
- * @return mixed null value replacement.
- */
- public function getNullValue()
- {
- return $this->_nullValue;
- }
-
- /**
- * @param mixed null value replacement.
- */
- public function setNullValue($value)
- {
- $this->_nullValue = $value;
- }
-
- /**
- * @return string name of a property of the result object that will be set to.
- */
- public function getProperty()
- {
- return $this->_propertyName;
- }
-
- /**
- * @param string name of a property of the result object that will be set to.
- */
- public function setProperty($value)
- {
- $this->_propertyName = $value;
- }
-
- /**
- * @return string name of the column in the result set from which the value
- * will be used to populate the property.
- */
- public function getColumn()
- {
- return $this->_columnName;
- }
-
- /**
- * @param string name of the column in the result set from which the value
- * will be used to populate the property.
- */
- public function setColumn($value)
- {
- $this->_columnName = $value;
- }
-
- /**
- * @return int index of the column in the ResultSet from which the value will
- * be used to populate the object property
- */
- public function getColumnIndex()
- {
- return $this->_columnIndex;
- }
-
- /**
- * @param int index of the column in the ResultSet from which the value will
- * be used to populate the object property
- */
- public function setColumnIndex($value)
- {
- $this->_columnIndex = TPropertyValue::ensureInteger($value);
- }
-
- /**
- * @return string ID of another <resultMap> used to fill the property.
- */
- public function getResultMapping()
- {
- return $this->_nestedResultMapName;
- }
-
- /**
- * @param string ID of another <resultMap> used to fill the property.
- */
- public function setResultMapping($value)
- {
- $this->_nestedResultMapName = $value;
- }
-
- /**
- * @return TResultMap nested result map.
- */
- public function getNestedResultMap()
- {
- return $this->_nestedResultMap;
- }
-
- /**
- * @param TResult nested result map.
- */
- public function setNestedResultMap($value)
- {
- $this->_nestedResultMap = $value;
- }
-
- /**
- * @return string property type of the object property to be set.
- */
- public function getType()
- {
- return $this->_valueType;
- }
-
- /**
- * @param string property type of the object property to be set.
- */
- public function setType($value)
- {
- $this->_valueType = $value;
- }
-
- /**
- * @return string custom type handler class name (may use namespace).
- */
- public function getTypeHandler()
- {
- return $this->_typeHandler;
- }
-
- /**
- * @param string custom type handler class name (may use namespace).
- */
- public function setTypeHandler($value)
- {
- $this->_typeHandler = $value;
- }
-
- /**
- * @return string name of another mapped statement
- */
- public function getSelect()
- {
- return $this->_select;
- }
-
- /**
- * The select property is used to describe a relationship between objects
- * and to automatically load complex (i.e. user defined) property types.
- * @param string name of another mapped statement.
- */
- public function setSelect($value)
- {
- $this->_select = $value;
- }
-
- /**
- * @return boolean indicate whether or not the select statement's results should be lazy loaded
- */
- public function getLazyLoad()
- {
- return $this->_isLazyLoad;
- }
-
- /**
- * @param boolean indicate whether or not the select statement's results should be lazy loaded
- */
- public function setLazyLoad($value)
- {
- $this->_isLazyLoad = TPropertyValue::ensureBoolean($value,false);
- }
-
- /**
- * Gets the value for the current property, converts to applicable type if necessary.
- * @param TSqlMapTypeHandlerRegistry type handler registry
- * @param array result row
- * @return mixed property value.
- */
- public function getPropertyValue($registry,$row)
- {
- $value = null;
- $index = $this->getColumnIndex();
- $name = $this->getColumn();
- if($index > 0 && isset($row[$index]))
- $value = $this->getTypedValue($registry,$row[$index]);
- else if(isset($row[$name]))
- $value = $this->getTypedValue($registry,$row[$name]);
- if(($value===null) && ($this->getNullValue()!==null))
- $value = $this->getTypedValue($registry,$this->getNullValue());
- return $value;
- }
-
- /**
- * @param TSqlMapTypeHandlerRegistry type handler registry
- * @param mixed raw property value
- * @return mixed property value casted to specific type.
- */
- protected function getTypedValue($registry,$value)
- {
- if(($handler = $this->createTypeHandler($registry))!==null)
- return $handler->getResult($value);
- else
- return $registry->convertToType($this->getType(), $value);
- }
-
- /**
- * Create type handler from {@link Type setType()} or {@link TypeHandler setTypeHandler}.
- * @param TSqlMapTypeHandlerRegistry type handler registry
- * @return TSqlMapTypeHandler type handler.
- */
- protected function createTypeHandler($registry)
- {
- $type=$this->getTypeHandler() ? $this->getTypeHandler() : $this->getType();
- $handler=$registry->getTypeHandler($type);
- if($handler===null && $this->getTypeHandler())
- $handler = Prado::createComponent($type);
- return $handler;
- }
-
- /**
- * Determines if the type is an instance of ArrayAccess, TList or an array.
- * @return int TResultProperty::LIST_TYPE or TResultProperty::ARRAY_TYPE
- */
- protected function getPropertyValueType()
- {
- if(class_exists($type = $this->getType(), false)) //NO force autoloading
- {
- if($type==='TList')
- return self::LIST_TYPE;
- $class = new ReflectionClass($type);
- if($class->isSubclassOf('TList'))
- return self::LIST_TYPE;
- if($class->implementsInterface('ArrayAccess'))
- return self::ARRAY_TYPE;
- }
- if(strtolower($type) == 'array')
- return self::ARRAY_TYPE;
- }
-
- /**
- * Returns true if the result property {@link Type getType()} is of TList type
- * or that the actual result object is an instance of TList.
- * @param object result object
- * @return boolean true if the result object is an instance of TList
- */
- public function instanceOfListType($target)
- {
- if($this->getType()===null)
- return TPropertyAccess::get($target,$this->getProperty()) instanceof TList;
- return $this->getPropertyValueType() == self::LIST_TYPE;
- }
-
- /**
- * Returns true if the result property {@link Type getType()} is of ArrayAccess
- * or that the actual result object is an array or implements ArrayAccess
- * @param object result object
- * @return boolean true if the result object is an instance of ArrayAccess or is an array.
- */
- public function instanceOfArrayType($target)
- {
- if($this->getType()===null)
- {
- $prop = TPropertyAccess::get($target,$this->getProperty());
- if(is_object($prop))
- return $prop instanceof ArrayAccess;
- return is_array($prop);
- }
- return $this->getPropertyValueType() == self::ARRAY_TYPE;
- }
-
- public function __sleep()
- {
- $exprops = array(); $cn = 'TResultProperty';
- if ($this->_nullValue===null) $exprops[] = "\0$cn\0_nullValue";
- if ($this->_propertyName===null) $exprops[] = "\0$cn\0_propertyNama";
- if ($this->_columnName===null) $exprops[] = "\0$cn\0_columnName";
- if ($this->_columnIndex==-1) $exprops[] = "\0$cn\0_columnIndex";
- if ($this->_nestedResultMapName===null) $exprops[] = "\0$cn\0_nestedResultMapName";
- if ($this->_nestedResultMap===null) $exprops[] = "\0$cn\0_nestedResultMap";
- if ($this->_valueType===null) $exprops[] = "\0$cn\0_valueType";
- if ($this->_typeHandler===null) $exprops[] = "\0$cn\0_typeHandler";
- if ($this->_isLazyLoad===false) $exprops[] = "\0$cn\0_isLazyLoad";
- if ($this->_select===null) $exprops[] = "\0$cn\0_select";
- return array_diff(parent::__sleep(),$exprops);
- }
-}
-
+<?php +/** + * TResultProperty class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TResultProperty corresponds a <property> tags inside a <resultMap> tag. + * + * The {@link NullValue setNullValue()} attribute can be set to any valid + * value (based on property type). The {@link NullValue setNullValue()} attribute + * is used to specify an outgoing null value replacement. What this means is + * that when a null value is detected in the result, the corresponding value of + * the {@link NullValue getNullValue()} will be used instead. + * + * The {@link Select setSelect()} property is used to describe a relationship + * between objects and to automatically load complex (i.e. user defined) + * property types. The value of the {@link Select setSelect()} property must be + * the name of another mapped statement. The value of the database + * {@link Column setColumn()} that is defined in the same property element as + * this statement attribute will be passed to the related mapped statement as + * the parameter. The {@link LazyLoad setLayLoad()} attribute can be specified + * with the {@link Select setSelect()} . + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TResultProperty extends TComponent +{ + private $_nullValue; + private $_propertyName; + private $_columnName; + private $_columnIndex=-1; + private $_nestedResultMapName; + private $_nestedResultMap; + private $_valueType; + private $_typeHandler; + private $_isLazyLoad=false; + private $_select; + + private $_hostResultMapID='inplicit internal mapping'; + + const LIST_TYPE = 0; + const ARRAY_TYPE = 1; + + /** + * Gets the containing result map ID. + * @param TResultMap containing result map. + */ + public function __construct($resultMap=null) + { + if($resultMap instanceof TResultMap) + $this->_hostResultMapID = $resultMap->getID(); + } + + /** + * @return mixed null value replacement. + */ + public function getNullValue() + { + return $this->_nullValue; + } + + /** + * @param mixed null value replacement. + */ + public function setNullValue($value) + { + $this->_nullValue = $value; + } + + /** + * @return string name of a property of the result object that will be set to. + */ + public function getProperty() + { + return $this->_propertyName; + } + + /** + * @param string name of a property of the result object that will be set to. + */ + public function setProperty($value) + { + $this->_propertyName = $value; + } + + /** + * @return string name of the column in the result set from which the value + * will be used to populate the property. + */ + public function getColumn() + { + return $this->_columnName; + } + + /** + * @param string name of the column in the result set from which the value + * will be used to populate the property. + */ + public function setColumn($value) + { + $this->_columnName = $value; + } + + /** + * @return int index of the column in the ResultSet from which the value will + * be used to populate the object property + */ + public function getColumnIndex() + { + return $this->_columnIndex; + } + + /** + * @param int index of the column in the ResultSet from which the value will + * be used to populate the object property + */ + public function setColumnIndex($value) + { + $this->_columnIndex = TPropertyValue::ensureInteger($value); + } + + /** + * @return string ID of another <resultMap> used to fill the property. + */ + public function getResultMapping() + { + return $this->_nestedResultMapName; + } + + /** + * @param string ID of another <resultMap> used to fill the property. + */ + public function setResultMapping($value) + { + $this->_nestedResultMapName = $value; + } + + /** + * @return TResultMap nested result map. + */ + public function getNestedResultMap() + { + return $this->_nestedResultMap; + } + + /** + * @param TResult nested result map. + */ + public function setNestedResultMap($value) + { + $this->_nestedResultMap = $value; + } + + /** + * @return string property type of the object property to be set. + */ + public function getType() + { + return $this->_valueType; + } + + /** + * @param string property type of the object property to be set. + */ + public function setType($value) + { + $this->_valueType = $value; + } + + /** + * @return string custom type handler class name (may use namespace). + */ + public function getTypeHandler() + { + return $this->_typeHandler; + } + + /** + * @param string custom type handler class name (may use namespace). + */ + public function setTypeHandler($value) + { + $this->_typeHandler = $value; + } + + /** + * @return string name of another mapped statement + */ + public function getSelect() + { + return $this->_select; + } + + /** + * The select property is used to describe a relationship between objects + * and to automatically load complex (i.e. user defined) property types. + * @param string name of another mapped statement. + */ + public function setSelect($value) + { + $this->_select = $value; + } + + /** + * @return boolean indicate whether or not the select statement's results should be lazy loaded + */ + public function getLazyLoad() + { + return $this->_isLazyLoad; + } + + /** + * @param boolean indicate whether or not the select statement's results should be lazy loaded + */ + public function setLazyLoad($value) + { + $this->_isLazyLoad = TPropertyValue::ensureBoolean($value,false); + } + + /** + * Gets the value for the current property, converts to applicable type if necessary. + * @param TSqlMapTypeHandlerRegistry type handler registry + * @param array result row + * @return mixed property value. + */ + public function getPropertyValue($registry,$row) + { + $value = null; + $index = $this->getColumnIndex(); + $name = $this->getColumn(); + if($index > 0 && isset($row[$index])) + $value = $this->getTypedValue($registry,$row[$index]); + else if(isset($row[$name])) + $value = $this->getTypedValue($registry,$row[$name]); + if(($value===null) && ($this->getNullValue()!==null)) + $value = $this->getTypedValue($registry,$this->getNullValue()); + return $value; + } + + /** + * @param TSqlMapTypeHandlerRegistry type handler registry + * @param mixed raw property value + * @return mixed property value casted to specific type. + */ + protected function getTypedValue($registry,$value) + { + if(($handler = $this->createTypeHandler($registry))!==null) + return $handler->getResult($value); + else + return $registry->convertToType($this->getType(), $value); + } + + /** + * Create type handler from {@link Type setType()} or {@link TypeHandler setTypeHandler}. + * @param TSqlMapTypeHandlerRegistry type handler registry + * @return TSqlMapTypeHandler type handler. + */ + protected function createTypeHandler($registry) + { + $type=$this->getTypeHandler() ? $this->getTypeHandler() : $this->getType(); + $handler=$registry->getTypeHandler($type); + if($handler===null && $this->getTypeHandler()) + $handler = Prado::createComponent($type); + return $handler; + } + + /** + * Determines if the type is an instance of ArrayAccess, TList or an array. + * @return int TResultProperty::LIST_TYPE or TResultProperty::ARRAY_TYPE + */ + protected function getPropertyValueType() + { + if(class_exists($type = $this->getType(), false)) //NO force autoloading + { + if($type==='TList') + return self::LIST_TYPE; + $class = new ReflectionClass($type); + if($class->isSubclassOf('TList')) + return self::LIST_TYPE; + if($class->implementsInterface('ArrayAccess')) + return self::ARRAY_TYPE; + } + if(strtolower($type) == 'array') + return self::ARRAY_TYPE; + } + + /** + * Returns true if the result property {@link Type getType()} is of TList type + * or that the actual result object is an instance of TList. + * @param object result object + * @return boolean true if the result object is an instance of TList + */ + public function instanceOfListType($target) + { + if($this->getType()===null) + return TPropertyAccess::get($target,$this->getProperty()) instanceof TList; + return $this->getPropertyValueType() == self::LIST_TYPE; + } + + /** + * Returns true if the result property {@link Type getType()} is of ArrayAccess + * or that the actual result object is an array or implements ArrayAccess + * @param object result object + * @return boolean true if the result object is an instance of ArrayAccess or is an array. + */ + public function instanceOfArrayType($target) + { + if($this->getType()===null) + { + $prop = TPropertyAccess::get($target,$this->getProperty()); + if(is_object($prop)) + return $prop instanceof ArrayAccess; + return is_array($prop); + } + return $this->getPropertyValueType() == self::ARRAY_TYPE; + } + + public function __sleep() + { + $exprops = array(); $cn = 'TResultProperty'; + if ($this->_nullValue===null) $exprops[] = "\0$cn\0_nullValue"; + if ($this->_propertyName===null) $exprops[] = "\0$cn\0_propertyNama"; + if ($this->_columnName===null) $exprops[] = "\0$cn\0_columnName"; + if ($this->_columnIndex==-1) $exprops[] = "\0$cn\0_columnIndex"; + if ($this->_nestedResultMapName===null) $exprops[] = "\0$cn\0_nestedResultMapName"; + if ($this->_nestedResultMap===null) $exprops[] = "\0$cn\0_nestedResultMap"; + if ($this->_valueType===null) $exprops[] = "\0$cn\0_valueType"; + if ($this->_typeHandler===null) $exprops[] = "\0$cn\0_typeHandler"; + if ($this->_isLazyLoad===false) $exprops[] = "\0$cn\0_isLazyLoad"; + if ($this->_select===null) $exprops[] = "\0$cn\0_select"; + return array_diff(parent::__sleep(),$exprops); + } +} + diff --git a/framework/Data/SqlMap/Configuration/TSimpleDynamicParser.php b/framework/Data/SqlMap/Configuration/TSimpleDynamicParser.php index 1ceba9eb..a70e6b3f 100644 --- a/framework/Data/SqlMap/Configuration/TSimpleDynamicParser.php +++ b/framework/Data/SqlMap/Configuration/TSimpleDynamicParser.php @@ -1,45 +1,45 @@ -<?php
-/**
- * TSimpleDynamicParser class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TSimpleDynamicParser class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- */
-
-/**
- * TSimpleDynamicParser finds place holders $name$ in the sql text and replaces
- * it with a TSimpleDynamicParser::DYNAMIC_TOKEN.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSimpleDynamicParser
-{
- const PARAMETER_TOKEN_REGEXP = '/\$([^\$]+)\$/';
- const DYNAMIC_TOKEN = '`!`';
-
- /**
- * Parse the sql text for dynamic place holders of the form $name$.
- * @param string Sql text.
- * @return array name value pairs 'sql' and 'parameters'.
- */
- public function parse($sqlText)
- {
- $matches = array();
- $mappings = array();
- preg_match_all(self::PARAMETER_TOKEN_REGEXP, $sqlText, $matches);
- for($i = 0, $k=count($matches[1]); $i<$k; $i++)
- {
- $mappings[] = $matches[1][$i];
- $sqlText = str_replace($matches[0][$i], self::DYNAMIC_TOKEN, $sqlText);
- }
- return array('sql'=>$sqlText, 'parameters'=>$mappings);
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TSimpleDynamicParser finds place holders $name$ in the sql text and replaces + * it with a TSimpleDynamicParser::DYNAMIC_TOKEN. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSimpleDynamicParser +{ + const PARAMETER_TOKEN_REGEXP = '/\$([^\$]+)\$/'; + const DYNAMIC_TOKEN = '`!`'; + + /** + * Parse the sql text for dynamic place holders of the form $name$. + * @param string Sql text. + * @return array name value pairs 'sql' and 'parameters'. + */ + public function parse($sqlText) + { + $matches = array(); + $mappings = array(); + preg_match_all(self::PARAMETER_TOKEN_REGEXP, $sqlText, $matches); + for($i = 0, $k=count($matches[1]); $i<$k; $i++) + { + $mappings[] = $matches[1][$i]; + $sqlText = str_replace($matches[0][$i], self::DYNAMIC_TOKEN, $sqlText); + } + return array('sql'=>$sqlText, 'parameters'=>$mappings); + } +} + diff --git a/framework/Data/SqlMap/Configuration/TSqlMapCacheModel.php b/framework/Data/SqlMap/Configuration/TSqlMapCacheModel.php index 4b985e51..0dc5d821 100644 --- a/framework/Data/SqlMap/Configuration/TSqlMapCacheModel.php +++ b/framework/Data/SqlMap/Configuration/TSqlMapCacheModel.php @@ -1,246 +1,246 @@ -<?php
-/**
- * TSqlMapCacheModel, TSqlMapCacheTypes and TSqlMapCacheKey classes file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- */
-
-/**
- * TSqlMapCacheModel corresponds to the <cacheModel> sql mapping configuration tag.
- *
- * The results from a query Mapped Statement can be cached simply by specifying
- * the {@link CacheModel TSqlMapStatement::setCacheModel()} property in <statement> tag.
- * A cache model is a configured cache that is defined within the sql map
- * configuration file. Cache models are configured using the <cacheModel> element.
- *
- * The cache model uses a pluggable framework for supporting different types of
- * caches. The choice of cache is specified by the {@link Implementation setImplementation()}
- * property. The class name specified must be one of {@link TSqlMapCacheTypes}.
- *
- * The cache implementations, LRU and FIFO cache below do not persist across
- * requests. That is, once the request is complete, all cache data is lost.
- * These caches are useful queries that results in the same repeated data during
- * the current request.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSqlMapCacheModel extends TComponent
-{
- private $_cache;
- private $_hits = 0;
- private $_requests = 0;
- private $_id;
- private $_implementation=TSqlMapCacheTypes::Basic;
- private $_properties = array();
- private $_flushInterval = 0;
-
- private static $_cacheTypes = array();
-
- public static function registerCacheType($type, $className)
- {
- self::$_cacheTypes[$type] = $className;
- }
-
- /**
- * @return string unique cache model identifier.
- */
- public function getID()
- {
- return $this->_id;
- }
-
- /**
- * @param string unique cache model identifier.
- */
- public function setID($value)
- {
- $this->_id = $value;
- }
-
- /**
- * @return string cache implements of TSqlMapCacheTypes, either 'Basic', 'LRU' or 'FIFO'.
- */
- public function getImplementation()
- {
- return $this->_implementation;
- }
-
- /**
- * @param string cache implements of TSqlMapCacheTypes, either 'Basic', 'LRU' or 'FIFO'.
- */
- public function setImplementation($value)
- {
- if (isset(self::$_cacheTypes[$value]))
- $this->_implementation = $value;
- else
- $this->_implementation = TPropertyValue::ensureEnum($value,'TSqlMapCacheTypes');
- }
-
- /**
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- */
- public function setFlushInterval($value)
- {
- $this->_flushInterval=TPropertyValue::ensureInteger($value);
- }
-
- /**
- * @return integer cache duration.
- */
- public function getFlushInterval()
- {
- return $this->_flushInterval;
- }
-
- /**
- * Initialize the cache implementation, sets the actual cache contain if supplied.
- * @param ISqLMapCache cache implementation instance.
- */
- public function initialize($cache=null)
- {
- if($cache===null)
- $this->_cache= Prado::createComponent($this->getImplementationClass(), $this);
- else
- $this->_cache=$cache;
- }
-
- /**
- * @return string cache implementation class name.
- */
- public function getImplementationClass()
- {
- $implementation = $this->_implementation;
- if (isset(self::$_cacheTypes[$implementation])) return self::$_cacheTypes[$implementation];
-
- switch(TPropertyValue::ensureEnum($implementation,'TSqlMapCacheTypes'))
- {
- case TSqlMapCacheTypes::FIFO: return 'TSqlMapFifoCache';
- case TSqlMapCacheTypes::LRU : return 'TSqlMapLruCache';
- case TSqlMapCacheTypes::Basic : return 'TSqlMapApplicationCache';
- }
- }
-
- /**
- * Register a mapped statement that will trigger a cache flush.
- * @param TMappedStatement mapped statement that may flush the cache.
- */
- public function registerTriggerStatement($mappedStatement)
- {
- $mappedStatement->attachEventHandler('OnExecuteQuery',array($this, 'flush'));
- }
-
- /**
- * Clears the cache.
- */
- public function flush()
- {
- $this->_cache->flush();
- }
-
- /**
- * @param TSqlMapCacheKey|string cache key
- * @return mixed cached value.
- */
- public function get($key)
- {
- if($key instanceof TSqlMapCacheKey)
- $key = $key->getHash();
-
- //if flush ?
- $value = $this->_cache->get($key);
- $this->_requests++;
- if($value!==null)
- $this->_hits++;
- return $value;
- }
-
- /**
- * @param TSqlMapCacheKey|string cache key
- * @param mixed value to be cached.
- */
- public function set($key, $value)
- {
- if($key instanceof TSqlMapCacheKey)
- $key = $key->getHash();
-
- if($value!==null)
- $this->_cache->set($key, $value, $this->_flushInterval);
- }
-
- /**
- * @return float cache hit ratio.
- */
- public function getHitRatio()
- {
- if($this->_requests != 0)
- return $this->_hits / $this->_requests;
- else
- return 0;
- }
-}
-
-/**
- * TSqlMapCacheTypes enumerable class.
- *
- * Implemented cache are 'Basic', 'FIFO' and 'LRU'.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSqlMapCacheTypes extends TEnumerable
-{
- const Basic='Basic';
- const FIFO='FIFO';
- const LRU='LRU';
-}
-
-/**
- * TSqlMapCacheKey class.
- *
- * Provides a hash of the object to be cached.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSqlMapCacheKey
-{
- private $_key;
-
- /**
- * @param mixed object to be cached.
- */
- public function __construct($object)
- {
- $this->_key = $this->generateKey(serialize($object));
- }
-
- /**
- * @param string serialized object
- * @return string crc32 hash of the serialized object.
- */
- protected function generateKey($string)
- {
- return sprintf('%x',crc32($string));
- }
-
- /**
- * @return string object hash.
- */
- public function getHash()
- {
- return $this->_key;
- }
-}
-
+<?php +/** + * TSqlMapCacheModel, TSqlMapCacheTypes and TSqlMapCacheKey classes file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TSqlMapCacheModel corresponds to the <cacheModel> sql mapping configuration tag. + * + * The results from a query Mapped Statement can be cached simply by specifying + * the {@link CacheModel TSqlMapStatement::setCacheModel()} property in <statement> tag. + * A cache model is a configured cache that is defined within the sql map + * configuration file. Cache models are configured using the <cacheModel> element. + * + * The cache model uses a pluggable framework for supporting different types of + * caches. The choice of cache is specified by the {@link Implementation setImplementation()} + * property. The class name specified must be one of {@link TSqlMapCacheTypes}. + * + * The cache implementations, LRU and FIFO cache below do not persist across + * requests. That is, once the request is complete, all cache data is lost. + * These caches are useful queries that results in the same repeated data during + * the current request. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapCacheModel extends TComponent +{ + private $_cache; + private $_hits = 0; + private $_requests = 0; + private $_id; + private $_implementation=TSqlMapCacheTypes::Basic; + private $_properties = array(); + private $_flushInterval = 0; + + private static $_cacheTypes = array(); + + public static function registerCacheType($type, $className) + { + self::$_cacheTypes[$type] = $className; + } + + /** + * @return string unique cache model identifier. + */ + public function getID() + { + return $this->_id; + } + + /** + * @param string unique cache model identifier. + */ + public function setID($value) + { + $this->_id = $value; + } + + /** + * @return string cache implements of TSqlMapCacheTypes, either 'Basic', 'LRU' or 'FIFO'. + */ + public function getImplementation() + { + return $this->_implementation; + } + + /** + * @param string cache implements of TSqlMapCacheTypes, either 'Basic', 'LRU' or 'FIFO'. + */ + public function setImplementation($value) + { + if (isset(self::$_cacheTypes[$value])) + $this->_implementation = $value; + else + $this->_implementation = TPropertyValue::ensureEnum($value,'TSqlMapCacheTypes'); + } + + /** + * @param integer the number of seconds in which the cached value will expire. 0 means never expire. + */ + public function setFlushInterval($value) + { + $this->_flushInterval=TPropertyValue::ensureInteger($value); + } + + /** + * @return integer cache duration. + */ + public function getFlushInterval() + { + return $this->_flushInterval; + } + + /** + * Initialize the cache implementation, sets the actual cache contain if supplied. + * @param ISqLMapCache cache implementation instance. + */ + public function initialize($cache=null) + { + if($cache===null) + $this->_cache= Prado::createComponent($this->getImplementationClass(), $this); + else + $this->_cache=$cache; + } + + /** + * @return string cache implementation class name. + */ + public function getImplementationClass() + { + $implementation = $this->_implementation; + if (isset(self::$_cacheTypes[$implementation])) return self::$_cacheTypes[$implementation]; + + switch(TPropertyValue::ensureEnum($implementation,'TSqlMapCacheTypes')) + { + case TSqlMapCacheTypes::FIFO: return 'TSqlMapFifoCache'; + case TSqlMapCacheTypes::LRU : return 'TSqlMapLruCache'; + case TSqlMapCacheTypes::Basic : return 'TSqlMapApplicationCache'; + } + } + + /** + * Register a mapped statement that will trigger a cache flush. + * @param TMappedStatement mapped statement that may flush the cache. + */ + public function registerTriggerStatement($mappedStatement) + { + $mappedStatement->attachEventHandler('OnExecuteQuery',array($this, 'flush')); + } + + /** + * Clears the cache. + */ + public function flush() + { + $this->_cache->flush(); + } + + /** + * @param TSqlMapCacheKey|string cache key + * @return mixed cached value. + */ + public function get($key) + { + if($key instanceof TSqlMapCacheKey) + $key = $key->getHash(); + + //if flush ? + $value = $this->_cache->get($key); + $this->_requests++; + if($value!==null) + $this->_hits++; + return $value; + } + + /** + * @param TSqlMapCacheKey|string cache key + * @param mixed value to be cached. + */ + public function set($key, $value) + { + if($key instanceof TSqlMapCacheKey) + $key = $key->getHash(); + + if($value!==null) + $this->_cache->set($key, $value, $this->_flushInterval); + } + + /** + * @return float cache hit ratio. + */ + public function getHitRatio() + { + if($this->_requests != 0) + return $this->_hits / $this->_requests; + else + return 0; + } +} + +/** + * TSqlMapCacheTypes enumerable class. + * + * Implemented cache are 'Basic', 'FIFO' and 'LRU'. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapCacheTypes extends TEnumerable +{ + const Basic='Basic'; + const FIFO='FIFO'; + const LRU='LRU'; +} + +/** + * TSqlMapCacheKey class. + * + * Provides a hash of the object to be cached. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapCacheKey +{ + private $_key; + + /** + * @param mixed object to be cached. + */ + public function __construct($object) + { + $this->_key = $this->generateKey(serialize($object)); + } + + /** + * @param string serialized object + * @return string crc32 hash of the serialized object. + */ + protected function generateKey($string) + { + return sprintf('%x',crc32($string)); + } + + /** + * @return string object hash. + */ + public function getHash() + { + return $this->_key; + } +} + diff --git a/framework/Data/SqlMap/Configuration/TSqlMapStatement.php b/framework/Data/SqlMap/Configuration/TSqlMapStatement.php index 1d90d4b1..8f2ca5cc 100644 --- a/framework/Data/SqlMap/Configuration/TSqlMapStatement.php +++ b/framework/Data/SqlMap/Configuration/TSqlMapStatement.php @@ -1,451 +1,451 @@ -<?php
-/**
- * TSqlMapStatement, TSqlMapInsert, TSqlMapUpdate, TSqlMapDelete,
- * TSqlMapSelect and TSqlMapSelectKey classes file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- */
-
-/**
- * TSqlMapStatement class corresponds to <statement> element.
- *
- * Mapped Statements can hold any SQL statement and can use Parameter Maps
- * and Result Maps for input and output.
- *
- * The <statement> element is a general "catch all" element that can be used
- * for any type of SQL statement. Generally it is a good idea to use one of the
- * more specific statement-type elements. The more specific elements provided
- * better error-checking and even more functionality. (For example, the insert
- * statement can return a database-generated key.)
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSqlMapStatement extends TComponent
-{
- private $_parameterMapName;
- private $_parameterMap;
- private $_parameterClassName;
- private $_resultMapName;
- private $_resultMap;
- private $_resultClassName;
- private $_cacheModelName;
- private $_SQL;
- private $_listClass;
- private $_typeHandler;
- private $_extendStatement;
- private $_cache;
- private $_ID;
-
- /**
- * @return string name for this statement, unique to each sql map manager.
- */
- public function getID()
- {
- return $this->_ID;
- }
-
- /**
- * @param string name for this statement, which must be unique for each sql map manager.
- */
- public function setID($value)
- {
- $this->_ID=$value;
- }
-
- /**
- * @return string name of a parameter map.
- */
- public function getParameterMap()
- {
- return $this->_parameterMapName;
- }
-
- /**
- * A Parameter Map defines an ordered list of values that match up with
- * the "?" placeholders of a standard, parameterized query statement.
- * @param string parameter map name.
- */
- public function setParameterMap($value)
- {
- $this->_parameterMapName = $value;
- }
-
- /**
- * @return string parameter class name.
- */
- public function getParameterClass()
- {
- return $this->_parameterClassName;
- }
-
- /**
- * If a {@link ParameterMap setParameterMap()} property is not specified,
- * you may specify a ParameterClass instead and use inline parameters.
- * The value of the parameterClass attribute can be any existing PHP class name.
- * @param string parameter class name.
- */
- public function setParameterClass($value)
- {
- $this->_parameterClassName = $value;
- }
-
- /**
- * @return string result map name.
- */
- public function getResultMap()
- {
- return $this->_resultMapName;
- }
-
- /**
- * A Result Map lets you control how data is extracted from the result of a
- * query, and how the columns are mapped to object properties.
- * @param string result map name.
- */
- public function setResultMap($value)
- {
- $this->_resultMapName = $value;
- }
-
- /**
- * @return string result class name.
- */
- public function getResultClass()
- {
- return $this->_resultClassName;
- }
-
- /**
- * If a {@link ResultMap setResultMap()} is not specified, you may specify a
- * ResultClass instead. The value of the ResultClass property can be the
- * name of a PHP class or primitives like integer, string, or array. The
- * class specified will be automatically mapped to the columns in the
- * result, based on the result metadata.
- * @param string result class name.
- */
- public function setResultClass($value)
- {
- $this->_resultClassName = $value;
- }
-
- /**
- * @return string cache mode name.
- */
- public function getCacheModel()
- {
- return $this->_cacheModelName;
- }
-
- /**
- * @param string cache mode name.
- */
- public function setCacheModel($value)
- {
- $this->_cacheModelName = $value;
- }
-
- /**
- * @return TSqlMapCacheModel cache implementation instance for this statement.
- */
- public function getCache()
- {
- return $this->_cache;
- }
-
- /**
- * @param TSqlMapCacheModel cache implementation instance for this statement.
- */
- public function setCache($value)
- {
- $this->_cache = $value;
- }
-
- /**
- * @return TStaticSql sql text container.
- */
- public function getSqlText()
- {
- return $this->_SQL;
- }
-
- /**
- * @param TStaticSql sql text container.
- */
- public function setSqlText($value)
- {
- $this->_SQL = $value;
- }
-
- /**
- * @return string name of a PHP class that implements ArrayAccess.
- */
- public function getListClass()
- {
- return $this->_listClass;
- }
-
- /**
- * An ArrayAccess class can be specified to handle the type of objects in the collection.
- * @param string name of a PHP class that implements ArrayAccess.
- */
- public function setListClass($value)
- {
- $this->_listClass = $value;
- }
-
- /**
- * @return string another statement element name.
- */
- public function getExtends()
- {
- return $this->_extendStatement;
- }
-
- /**
- * @param string name of another statement element to extend.
- */
- public function setExtends($value)
- {
- $this->_extendStatement = $value;
- }
-
- /**
- * @return TResultMap the result map corresponding to the
- * {@link ResultMap getResultMap()} property.
- */
- public function resultMap()
- {
- return $this->_resultMap;
- }
-
- /**
- * @return TParameterMap the parameter map corresponding to the
- * {@link ParameterMap getParameterMap()} property.
- */
- public function parameterMap()
- {
- return $this->_parameterMap;
- }
-
- /**
- * @param TInlineParameterMap parameter extracted from the sql text.
- */
- public function setInlineParameterMap($map)
- {
- $this->_parameterMap = $map;
- }
-
- /**
- * @param TSqlMapManager initialize the statement, sets the result and parameter maps.
- */
- public function initialize($manager)
- {
- if(strlen($this->_resultMapName) > 0)
- $this->_resultMap = $manager->getResultMap($this->_resultMapName);
- if(strlen($this->_parameterMapName) > 0)
- $this->_parameterMap = $manager->getParameterMap($this->_parameterMapName);
- }
-
- /**
- * @param TSqlMapTypeHandlerRegistry type handler registry
- * @return ArrayAccess new instance of list class.
- */
- public function createInstanceOfListClass($registry)
- {
- if(strlen($type = $this->getListClass()) > 0)
- return $this->createInstanceOf($registry,$type);
- return array();
- }
-
- /**
- * Create a new instance of a given type.
- * @param TSqlMapTypeHandlerRegistry type handler registry
- * @param string result class name.
- * @param array result data.
- * @return mixed result object.
- */
- protected function createInstanceOf($registry,$type,$row=null)
- {
- $handler = $registry->getTypeHandler($type);
- if($handler!==null)
- return $handler->createNewInstance($row);
- else
- return $registry->createInstanceOf($type);
- }
-
- /**
- * Create a new instance of result class.
- * @param TSqlMapTypeHandlerRegistry type handler registry
- * @param array result data.
- * @return mixed result object.
- */
- public function createInstanceOfResultClass($registry,$row)
- {
- if(strlen($type= $this->getResultClass()) > 0)
- return $this->createInstanceOf($registry,$type,$row);
- }
-
- public function __sleep()
- {
- $cn = __CLASS__;
- $exprops = array("\0$cn\0_resultMap");
- if (!$this->_parameterMapName) $exprops[] = "\0$cn\0_parameterMapName";
- if (!$this->_parameterMap) $exprops[] = "\0$cn\0_parameterMap";
- if (!$this->_parameterClassName) $exprops[] = "\0$cn\0_parameterClassName";
- if (!$this->_resultMapName) $exprops[] = "\0$cn\0_resultMapName";
- if (!$this->_resultMap) $exprops[] = "\0$cn\0_resultMap";
- if (!$this->_resultClassName) $exprops[] = "\0$cn\0_resultClassName";
- if (!$this->_cacheModelName) $exprops[] = "\0$cn\0_cacheModelName";
- if (!$this->_SQL) $exprops[] = "\0$cn\0_SQL";
- if (!$this->_listClass) $exprops[] = "\0$cn\0_listClass";
- if (!$this->_typeHandler) $exprops[] = "\0$cn\0_typeHandler";
- if (!$this->_extendStatement) $exprops[] = "\0$cn\0_extendStatement";
- if (!$this->_cache) $exprops[] = "\0$cn\0_cache";
-
- return array_diff(parent::__sleep(),$exprops);
- }
-
-}
-
-/**
- * TSqlMapSelect class file.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TSqlMapSelect extends TSqlMapStatement
-{
- private $_generate;
-
- public function getGenerate(){ return $this->_generate; }
- public function setGenerate($value){ $this->_generate = $value; }
-}
-
-/**
- * TSqlMapInsert class corresponds to the <insert> element.
- *
- * The <insert> element allows <selectKey> child elements that can be used
- * to generate a key to be used for the insert command.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSqlMapInsert extends TSqlMapStatement
-{
- private $_selectKey=null;
-
- /**
- * @return TSqlMapSelectKey select key element.
- */
- public function getSelectKey()
- {
- return $this->_selectKey;
- }
-
- /**
- * @param TSqlMapSelectKey select key.
- */
- public function setSelectKey($value)
- {
- $this->_selectKey = $value;
- }
-}
-
-/**
- * TSqlMapUpdate class corresponds to <update> element.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSqlMapUpdate extends TSqlMapStatement
-{
-}
-
-/**
- * TSqlMapDelete class corresponds to the <delete> element.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSqlMapDelete extends TSqlMapUpdate
-{
-}
-
-/**
- * TSqlMapSelect corresponds to the <selectKey> element.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSqlMapSelectKey extends TSqlMapStatement
-{
- private $_type = 'post';
- private $_property;
-
- /**
- * @return string select generated key type, 'post' or 'pre'.
- */
- public function getType()
- {
- return $this->_type;
- }
-
- /**
- * @param string select generated key type, 'post' or 'pre'.
- */
- public function setType($value)
- {
- $this->_type = strtolower($value) == 'post' ? 'post' : 'pre';
- }
-
- /**
- * @return string property name for the generated key.
- */
- public function getProperty()
- {
- return $this->_property;
- }
-
- /**
- * @param string property name for the generated key.
- */
- public function setProperty($value)
- {
- $this->_property = $value;
- }
-
- /**
- * @throws TSqlMapConfigurationException extends is unsupported.
- */
- public function setExtends($value)
- {
- throw new TSqlMapConfigurationException('sqlmap_can_not_extend_select_key');
- }
-
- /**
- * @return boolean true if key is generated after insert command, false otherwise.
- */
- public function getIsAfter()
- {
- return $this->_type == 'post';
- }
-}
-
+<?php +/** + * TSqlMapStatement, TSqlMapInsert, TSqlMapUpdate, TSqlMapDelete, + * TSqlMapSelect and TSqlMapSelectKey classes file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TSqlMapStatement class corresponds to <statement> element. + * + * Mapped Statements can hold any SQL statement and can use Parameter Maps + * and Result Maps for input and output. + * + * The <statement> element is a general "catch all" element that can be used + * for any type of SQL statement. Generally it is a good idea to use one of the + * more specific statement-type elements. The more specific elements provided + * better error-checking and even more functionality. (For example, the insert + * statement can return a database-generated key.) + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapStatement extends TComponent +{ + private $_parameterMapName; + private $_parameterMap; + private $_parameterClassName; + private $_resultMapName; + private $_resultMap; + private $_resultClassName; + private $_cacheModelName; + private $_SQL; + private $_listClass; + private $_typeHandler; + private $_extendStatement; + private $_cache; + private $_ID; + + /** + * @return string name for this statement, unique to each sql map manager. + */ + public function getID() + { + return $this->_ID; + } + + /** + * @param string name for this statement, which must be unique for each sql map manager. + */ + public function setID($value) + { + $this->_ID=$value; + } + + /** + * @return string name of a parameter map. + */ + public function getParameterMap() + { + return $this->_parameterMapName; + } + + /** + * A Parameter Map defines an ordered list of values that match up with + * the "?" placeholders of a standard, parameterized query statement. + * @param string parameter map name. + */ + public function setParameterMap($value) + { + $this->_parameterMapName = $value; + } + + /** + * @return string parameter class name. + */ + public function getParameterClass() + { + return $this->_parameterClassName; + } + + /** + * If a {@link ParameterMap setParameterMap()} property is not specified, + * you may specify a ParameterClass instead and use inline parameters. + * The value of the parameterClass attribute can be any existing PHP class name. + * @param string parameter class name. + */ + public function setParameterClass($value) + { + $this->_parameterClassName = $value; + } + + /** + * @return string result map name. + */ + public function getResultMap() + { + return $this->_resultMapName; + } + + /** + * A Result Map lets you control how data is extracted from the result of a + * query, and how the columns are mapped to object properties. + * @param string result map name. + */ + public function setResultMap($value) + { + $this->_resultMapName = $value; + } + + /** + * @return string result class name. + */ + public function getResultClass() + { + return $this->_resultClassName; + } + + /** + * If a {@link ResultMap setResultMap()} is not specified, you may specify a + * ResultClass instead. The value of the ResultClass property can be the + * name of a PHP class or primitives like integer, string, or array. The + * class specified will be automatically mapped to the columns in the + * result, based on the result metadata. + * @param string result class name. + */ + public function setResultClass($value) + { + $this->_resultClassName = $value; + } + + /** + * @return string cache mode name. + */ + public function getCacheModel() + { + return $this->_cacheModelName; + } + + /** + * @param string cache mode name. + */ + public function setCacheModel($value) + { + $this->_cacheModelName = $value; + } + + /** + * @return TSqlMapCacheModel cache implementation instance for this statement. + */ + public function getCache() + { + return $this->_cache; + } + + /** + * @param TSqlMapCacheModel cache implementation instance for this statement. + */ + public function setCache($value) + { + $this->_cache = $value; + } + + /** + * @return TStaticSql sql text container. + */ + public function getSqlText() + { + return $this->_SQL; + } + + /** + * @param TStaticSql sql text container. + */ + public function setSqlText($value) + { + $this->_SQL = $value; + } + + /** + * @return string name of a PHP class that implements ArrayAccess. + */ + public function getListClass() + { + return $this->_listClass; + } + + /** + * An ArrayAccess class can be specified to handle the type of objects in the collection. + * @param string name of a PHP class that implements ArrayAccess. + */ + public function setListClass($value) + { + $this->_listClass = $value; + } + + /** + * @return string another statement element name. + */ + public function getExtends() + { + return $this->_extendStatement; + } + + /** + * @param string name of another statement element to extend. + */ + public function setExtends($value) + { + $this->_extendStatement = $value; + } + + /** + * @return TResultMap the result map corresponding to the + * {@link ResultMap getResultMap()} property. + */ + public function resultMap() + { + return $this->_resultMap; + } + + /** + * @return TParameterMap the parameter map corresponding to the + * {@link ParameterMap getParameterMap()} property. + */ + public function parameterMap() + { + return $this->_parameterMap; + } + + /** + * @param TInlineParameterMap parameter extracted from the sql text. + */ + public function setInlineParameterMap($map) + { + $this->_parameterMap = $map; + } + + /** + * @param TSqlMapManager initialize the statement, sets the result and parameter maps. + */ + public function initialize($manager) + { + if(strlen($this->_resultMapName) > 0) + $this->_resultMap = $manager->getResultMap($this->_resultMapName); + if(strlen($this->_parameterMapName) > 0) + $this->_parameterMap = $manager->getParameterMap($this->_parameterMapName); + } + + /** + * @param TSqlMapTypeHandlerRegistry type handler registry + * @return ArrayAccess new instance of list class. + */ + public function createInstanceOfListClass($registry) + { + if(strlen($type = $this->getListClass()) > 0) + return $this->createInstanceOf($registry,$type); + return array(); + } + + /** + * Create a new instance of a given type. + * @param TSqlMapTypeHandlerRegistry type handler registry + * @param string result class name. + * @param array result data. + * @return mixed result object. + */ + protected function createInstanceOf($registry,$type,$row=null) + { + $handler = $registry->getTypeHandler($type); + if($handler!==null) + return $handler->createNewInstance($row); + else + return $registry->createInstanceOf($type); + } + + /** + * Create a new instance of result class. + * @param TSqlMapTypeHandlerRegistry type handler registry + * @param array result data. + * @return mixed result object. + */ + public function createInstanceOfResultClass($registry,$row) + { + if(strlen($type= $this->getResultClass()) > 0) + return $this->createInstanceOf($registry,$type,$row); + } + + public function __sleep() + { + $cn = __CLASS__; + $exprops = array("\0$cn\0_resultMap"); + if (!$this->_parameterMapName) $exprops[] = "\0$cn\0_parameterMapName"; + if (!$this->_parameterMap) $exprops[] = "\0$cn\0_parameterMap"; + if (!$this->_parameterClassName) $exprops[] = "\0$cn\0_parameterClassName"; + if (!$this->_resultMapName) $exprops[] = "\0$cn\0_resultMapName"; + if (!$this->_resultMap) $exprops[] = "\0$cn\0_resultMap"; + if (!$this->_resultClassName) $exprops[] = "\0$cn\0_resultClassName"; + if (!$this->_cacheModelName) $exprops[] = "\0$cn\0_cacheModelName"; + if (!$this->_SQL) $exprops[] = "\0$cn\0_SQL"; + if (!$this->_listClass) $exprops[] = "\0$cn\0_listClass"; + if (!$this->_typeHandler) $exprops[] = "\0$cn\0_typeHandler"; + if (!$this->_extendStatement) $exprops[] = "\0$cn\0_extendStatement"; + if (!$this->_cache) $exprops[] = "\0$cn\0_cache"; + + return array_diff(parent::__sleep(),$exprops); + } + +} + +/** + * TSqlMapSelect class file. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TSqlMapSelect extends TSqlMapStatement +{ + private $_generate; + + public function getGenerate(){ return $this->_generate; } + public function setGenerate($value){ $this->_generate = $value; } +} + +/** + * TSqlMapInsert class corresponds to the <insert> element. + * + * The <insert> element allows <selectKey> child elements that can be used + * to generate a key to be used for the insert command. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapInsert extends TSqlMapStatement +{ + private $_selectKey=null; + + /** + * @return TSqlMapSelectKey select key element. + */ + public function getSelectKey() + { + return $this->_selectKey; + } + + /** + * @param TSqlMapSelectKey select key. + */ + public function setSelectKey($value) + { + $this->_selectKey = $value; + } +} + +/** + * TSqlMapUpdate class corresponds to <update> element. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapUpdate extends TSqlMapStatement +{ +} + +/** + * TSqlMapDelete class corresponds to the <delete> element. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapDelete extends TSqlMapUpdate +{ +} + +/** + * TSqlMapSelect corresponds to the <selectKey> element. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapSelectKey extends TSqlMapStatement +{ + private $_type = 'post'; + private $_property; + + /** + * @return string select generated key type, 'post' or 'pre'. + */ + public function getType() + { + return $this->_type; + } + + /** + * @param string select generated key type, 'post' or 'pre'. + */ + public function setType($value) + { + $this->_type = strtolower($value) == 'post' ? 'post' : 'pre'; + } + + /** + * @return string property name for the generated key. + */ + public function getProperty() + { + return $this->_property; + } + + /** + * @param string property name for the generated key. + */ + public function setProperty($value) + { + $this->_property = $value; + } + + /** + * @throws TSqlMapConfigurationException extends is unsupported. + */ + public function setExtends($value) + { + throw new TSqlMapConfigurationException('sqlmap_can_not_extend_select_key'); + } + + /** + * @return boolean true if key is generated after insert command, false otherwise. + */ + public function getIsAfter() + { + return $this->_type == 'post'; + } +} + diff --git a/framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php b/framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php index a60827fe..988d00db 100644 --- a/framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php +++ b/framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php @@ -1,805 +1,805 @@ -<?php
-/**
- * TSqlMapXmlConfigBuilder, TSqlMapXmlConfiguration, TSqlMapXmlMappingConfiguration classes file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- */
-
-Prado::using('System.Data.SqlMap.Configuration.TSqlMapStatement');
-
-/**
- * TSqlMapXmlConfig class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- */
-abstract class TSqlMapXmlConfigBuilder
-{
- /**
- * Create an instance of an object give by the attribute named 'class' in the
- * node and set the properties on the object given by attribute names and values.
- * @param SimpleXmlNode property node
- * @return Object new instance of class with class name given by 'class' attribute value.
- */
- protected function createObjectFromNode($node)
- {
- if(isset($node['class']))
- {
- $obj = Prado::createComponent((string)$node['class']);
- $this->setObjectPropFromNode($obj,$node,array('class'));
- return $obj;
- }
- throw new TSqlMapConfigurationException(
- 'sqlmap_node_class_undef', $node, $this->getConfigFile());
- }
-
- /**
- * For each attributes (excluding attribute named in $except) set the
- * property of the $obj given by the name of the attribute with the value
- * of the attribute.
- * @param Object object instance
- * @param SimpleXmlNode property node
- * @param array exception property name
- */
- protected function setObjectPropFromNode($obj,$node,$except=array())
- {
- foreach($node->attributes() as $name=>$value)
- {
- if(!in_array($name,$except))
- {
- if($obj->canSetProperty($name))
- $obj->{$name} = (string)$value;
- else
- throw new TSqlMapConfigurationException(
- 'sqlmap_invalid_property', $name, get_class($obj),
- $node, $this->getConfigFile());
- }
- }
- }
-
- /**
- * Gets the filename relative to the basefile.
- * @param string base filename
- * @param string relative filename
- * @return string absolute filename.
- */
- protected function getAbsoluteFilePath($basefile,$resource)
- {
- $basedir = dirname($basefile);
- $file = realpath($basedir.DIRECTORY_SEPARATOR.$resource);
- if(!is_string($file) || !is_file($file))
- $file = realpath($resource);
- if(is_string($file) && is_file($file))
- return $file;
- else
- throw new TSqlMapConfigurationException(
- 'sqlmap_unable_to_find_resource', $resource);
- }
-
- /**
- * Load document using simple xml.
- * @param string filename.
- * @return SimpleXmlElement xml document.
- */
- protected function loadXmlDocument($filename,TSqlMapXmlConfiguration $config)
- {
- if( strpos($filename, '${') !== false)
- $filename = $config->replaceProperties($filename);
-
- if(!is_file($filename))
- throw new TSqlMapConfigurationException(
- 'sqlmap_unable_to_find_config', $filename);
- return simplexml_load_string($config->replaceProperties(file_get_contents($filename)));
- }
-
- /**
- * Get element node by ID value (try for attribute name ID as case insensitive).
- * @param SimpleXmlDocument $document
- * @param string tag name.
- * @param string id value.
- * @return SimpleXmlElement node if found, null otherwise.
- */
- protected function getElementByIdValue($document, $tag, $value)
- {
- //hack to allow upper case and lower case attribute names.
- foreach(array('id','ID','Id', 'iD') as $id)
- {
- $xpath = "//{$tag}[@{$id}='{$value}']";
- foreach($document->xpath($xpath) as $node)
- return $node;
- }
- }
-
- /**
- * @return string configuration file.
- */
- protected abstract function getConfigFile();
-}
-
-/**
- * TSqlMapXmlConfig class.
- *
- * Configures the TSqlMapManager using xml configuration file.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSqlMapXmlConfiguration extends TSqlMapXmlConfigBuilder
-{
- /**
- * @var TSqlMapManager manager
- */
- private $_manager;
- /**
- * @var string configuration file.
- */
- private $_configFile;
- /**
- * @var array global properties.
- */
- private $_properties=array();
-
- /**
- * @param TSqlMapManager manager instance.
- */
- public function __construct($manager)
- {
- $this->_manager=$manager;
- }
-
- public function getManager()
- {
- return $this->_manager;
- }
-
- protected function getConfigFile()
- {
- return $this->_configFile;
- }
-
- /**
- * Configure the TSqlMapManager using the given xml file.
- * @param string SqlMap configuration xml file.
- */
- public function configure($filename=null)
- {
- $this->_configFile=$filename;
- $document = $this->loadXmlDocument($filename,$this);
-
- foreach($document->xpath('//property') as $property)
- $this->loadGlobalProperty($property);
-
- foreach($document->xpath('//typeHandler') as $handler)
- $this->loadTypeHandler($handler);
-
- foreach($document->xpath('//connection[last()]') as $conn)
- $this->loadDatabaseConnection($conn);
-
- //try to load configuration in the current config file.
- $mapping = new TSqlMapXmlMappingConfiguration($this);
- $mapping->configure($filename);
-
- foreach($document->xpath('//sqlMap') as $sqlmap)
- $this->loadSqlMappingFiles($sqlmap);
-
- $this->resolveResultMapping();
- $this->attachCacheModels();
- }
-
- /**
- * Load global replacement property.
- * @param SimpleXmlElement property node.
- */
- protected function loadGlobalProperty($node)
- {
- $this->_properties[(string)$node['name']] = (string)$node['value'];
- }
-
- /**
- * Load the type handler configurations.
- * @param SimpleXmlElement type handler node
- */
- protected function loadTypeHandler($node)
- {
- $handler = $this->createObjectFromNode($node);
- $this->_manager->getTypeHandlers()->registerTypeHandler($handler);
- }
-
- /**
- * Load the database connection tag.
- * @param SimpleXmlElement connection node.
- */
- protected function loadDatabaseConnection($node)
- {
- $conn = $this->createObjectFromNode($node);
- $this->_manager->setDbConnection($conn);
- }
-
- /**
- * Load SqlMap mapping configuration.
- * @param unknown_type $node
- */
- protected function loadSqlMappingFiles($node)
- {
- if(strlen($resource = (string)$node['resource']) > 0)
- {
- if( strpos($resource, '${') !== false)
- $resource = $this->replaceProperties($resource);
-
- $mapping = new TSqlMapXmlMappingConfiguration($this);
- $filename = $this->getAbsoluteFilePath($this->_configFile, $resource);
- $mapping->configure($filename);
- }
- }
-
- /**
- * Resolve nest result mappings.
- */
- protected function resolveResultMapping()
- {
- $maps = $this->_manager->getResultMaps();
- foreach($maps as $entry)
- {
- foreach($entry->getColumns() as $item)
- {
- $resultMap = $item->getResultMapping();
- if(strlen($resultMap) > 0)
- {
- if($maps->contains($resultMap))
- $item->setNestedResultMap($maps[$resultMap]);
- else
- throw new TSqlMapConfigurationException(
- 'sqlmap_unable_to_find_result_mapping',
- $resultMap, $this->_configFile, $entry->getID());
- }
- }
- if($entry->getDiscriminator()!==null)
- $entry->getDiscriminator()->initialize($this->_manager);
- }
- }
-
- /**
- * Set the cache for each statement having a cache model property.
- */
- protected function attachCacheModels()
- {
- foreach($this->_manager->getMappedStatements() as $mappedStatement)
- {
- if(strlen($model = $mappedStatement->getStatement()->getCacheModel()) > 0)
- {
- $cache = $this->_manager->getCacheModel($model);
- $mappedStatement->getStatement()->setCache($cache);
- }
- }
- }
-
- /**
- * Replace the place holders ${name} in text with properties the
- * corresponding global property value.
- * @param string original string.
- * @return string string with global property replacement.
- */
- public function replaceProperties($string)
- {
- foreach($this->_properties as $find => $replace)
- $string = str_replace('${'.$find.'}', $replace, $string);
- return $string;
- }
-}
-
-/**
- * Loads the statements, result maps, parameters maps from xml configuration.
- *
- * description
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Configuration
- * @since 3.1
- */
-class TSqlMapXmlMappingConfiguration extends TSqlMapXmlConfigBuilder
-{
- private $_xmlConfig;
- private $_configFile;
- private $_manager;
-
- private $_document;
-
- private $_FlushOnExecuteStatements=array();
-
- /**
- * Regular expressions for escaping simple/inline parameter symbols
- */
- const SIMPLE_MARK='$';
- const INLINE_SYMBOL='#';
- const ESCAPED_SIMPLE_MARK_REGEXP='/\$\$/';
- const ESCAPED_INLINE_SYMBOL_REGEXP='/\#\#/';
- const SIMPLE_PLACEHOLDER='`!!`';
- const INLINE_PLACEHOLDER='`!!!`';
-
- /**
- * @param TSqlMapXmlConfiguration parent xml configuration.
- */
- public function __construct(TSqlMapXmlConfiguration $xmlConfig)
- {
- $this->_xmlConfig=$xmlConfig;
- $this->_manager=$xmlConfig->getManager();
- }
-
- protected function getConfigFile()
- {
- return $this->_configFile;
- }
-
- /**
- * Configure an XML mapping.
- * @param string xml mapping filename.
- */
- public function configure($filename)
- {
- $this->_configFile=$filename;
- $document = $this->loadXmlDocument($filename,$this->_xmlConfig);
- $this->_document=$document;
-
- static $bCacheDependencies;
- if($bCacheDependencies === null)
- $bCacheDependencies = Prado::getApplication()->getMode() !== TApplicationMode::Performance;
-
- if($bCacheDependencies)
- $this->_manager->getCacheDependencies()
- ->getDependencies()
- ->add(new TFileCacheDependency($filename));
-
- foreach($document->xpath('//resultMap') as $node)
- $this->loadResultMap($node);
-
- foreach($document->xpath('//parameterMap') as $node)
- $this->loadParameterMap($node);
-
- foreach($document->xpath('//statement') as $node)
- $this->loadStatementTag($node);
-
- foreach($document->xpath('//select') as $node)
- $this->loadSelectTag($node);
-
- foreach($document->xpath('//insert') as $node)
- $this->loadInsertTag($node);
-
- foreach($document->xpath('//update') as $node)
- $this->loadUpdateTag($node);
-
- foreach($document->xpath('//delete') as $node)
- $this->loadDeleteTag($node);
-
- foreach($document->xpath('//procedure') as $node)
- $this->loadProcedureTag($node);
-
- foreach($document->xpath('//cacheModel') as $node)
- $this->loadCacheModel($node);
-
- $this->registerCacheTriggers();
- }
-
- /**
- * Load the result maps.
- * @param SimpleXmlElement result map node.
- */
- protected function loadResultMap($node)
- {
- $resultMap = $this->createResultMap($node);
-
- //find extended result map.
- if(strlen($extendMap = $resultMap->getExtends()) > 0)
- {
- if(!$this->_manager->getResultMaps()->contains($extendMap))
- {
- $extendNode=$this->getElementByIdValue($this->_document,'resultMap',$extendMap);
- if($extendNode!==null)
- $this->loadResultMap($extendNode);
- }
-
- if(!$this->_manager->getResultMaps()->contains($extendMap))
- throw new TSqlMapConfigurationException(
- 'sqlmap_unable_to_find_parent_result_map', $node, $this->_configFile, $extendMap);
-
- $superMap = $this->_manager->getResultMap($extendMap);
- $resultMap->getColumns()->mergeWith($superMap->getColumns());
- }
-
- //add the result map
- if(!$this->_manager->getResultMaps()->contains($resultMap->getID()))
- $this->_manager->addResultMap($resultMap);
- }
-
- /**
- * Create a new result map and its associated result properties,
- * disciminiator and sub maps.
- * @param SimpleXmlElement result map node
- * @return TResultMap SqlMap result mapping.
- */
- protected function createResultMap($node)
- {
- $resultMap = new TResultMap();
- $this->setObjectPropFromNode($resultMap,$node);
-
- //result nodes
- foreach($node->result as $result)
- {
- $property = new TResultProperty($resultMap);
- $this->setObjectPropFromNode($property,$result);
- $resultMap->addResultProperty($property);
- }
-
- //create the discriminator
- $discriminator = null;
- if(isset($node->discriminator))
- {
- $discriminator = new TDiscriminator();
- $this->setObjectPropFromNode($discriminator, $node->discriminator);
- $discriminator->initMapping($resultMap);
- }
-
- foreach($node->xpath('subMap') as $subMapNode)
- {
- if($discriminator===null)
- throw new TSqlMapConfigurationException(
- 'sqlmap_undefined_discriminator', $node, $this->_configFile,$subMapNode);
- $subMap = new TSubMap;
- $this->setObjectPropFromNode($subMap,$subMapNode);
- $discriminator->addSubMap($subMap);
- }
-
- if($discriminator!==null)
- $resultMap->setDiscriminator($discriminator);
-
- return $resultMap;
- }
-
- /**
- * Load parameter map from xml.
- *
- * @param SimpleXmlElement parameter map node.
- */
- protected function loadParameterMap($node)
- {
- $parameterMap = $this->createParameterMap($node);
-
- if(strlen($extendMap = $parameterMap->getExtends()) > 0)
- {
- if(!$this->_manager->getParameterMaps()->contains($extendMap))
- {
- $extendNode=$this->getElementByIdValue($this->_document,'parameterMap',$extendMap);
- if($extendNode!==null)
- $this->loadParameterMap($extendNode);
- }
-
- if(!$this->_manager->getParameterMaps()->contains($extendMap))
- throw new TSqlMapConfigurationException(
- 'sqlmap_unable_to_find_parent_parameter_map', $node, $this->_configFile,$extendMap);
- $superMap = $this->_manager->getParameterMap($extendMap);
- $index = 0;
- foreach($superMap->getPropertyNames() as $propertyName)
- $parameterMap->insertProperty($index++,$superMap->getProperty($propertyName));
- }
- $this->_manager->addParameterMap($parameterMap);
- }
-
- /**
- * Create a new parameter map from xml node.
- * @param SimpleXmlElement parameter map node.
- * @return TParameterMap new parameter mapping.
- */
- protected function createParameterMap($node)
- {
- $parameterMap = new TParameterMap();
- $this->setObjectPropFromNode($parameterMap,$node);
- foreach($node->parameter as $parameter)
- {
- $property = new TParameterProperty();
- $this->setObjectPropFromNode($property,$parameter);
- $parameterMap->addProperty($property);
- }
- return $parameterMap;
- }
-
- /**
- * Load statement mapping from xml configuration file.
- * @param SimpleXmlElement statement node.
- */
- protected function loadStatementTag($node)
- {
- $statement = new TSqlMapStatement();
- $this->setObjectPropFromNode($statement,$node);
- $this->processSqlStatement($statement, $node);
- $mappedStatement = new TMappedStatement($this->_manager, $statement);
- $this->_manager->addMappedStatement($mappedStatement);
- }
-
- /**
- * Load extended SQL statements if application. Replaces global properties
- * in the sql text. Extracts inline parameter maps.
- * @param TSqlMapStatement mapped statement.
- * @param SimpleXmlElement statement node.
- */
- protected function processSqlStatement($statement, $node)
- {
- $commandText = (string)$node;
- if(strlen($extend = $statement->getExtends()) > 0)
- {
- $superNode = $this->getElementByIdValue($this->_document,'*',$extend);
- if($superNode!==null)
- $commandText = (string)$superNode . $commandText;
- else
- throw new TSqlMapConfigurationException(
- 'sqlmap_unable_to_find_parent_sql', $extend, $this->_configFile,$node);
- }
- //$commandText = $this->_xmlConfig->replaceProperties($commandText);
- $statement->initialize($this->_manager);
- $this->applyInlineParameterMap($statement, $commandText, $node);
- }
-
- /**
- * Extract inline parameter maps.
- * @param TSqlMapStatement statement object.
- * @param string sql text
- * @param SimpleXmlElement statement node.
- */
- protected function applyInlineParameterMap($statement, $sqlStatement, $node)
- {
- $scope['file'] = $this->_configFile;
- $scope['node'] = $node;
-
- $sqlStatement=preg_replace(self::ESCAPED_INLINE_SYMBOL_REGEXP,self::INLINE_PLACEHOLDER,$sqlStatement);
- if($statement->parameterMap() === null)
- {
- // Build a Parametermap with the inline parameters.
- // if they exist. Then delete inline infos from sqltext.
- $parameterParser = new TInlineParameterMapParser;
- $sqlText = $parameterParser->parse($sqlStatement, $scope);
- if(count($sqlText['parameters']) > 0)
- {
- $map = new TParameterMap();
- $map->setID($statement->getID().'-InLineParameterMap');
- $statement->setInlineParameterMap($map);
- foreach($sqlText['parameters'] as $property)
- $map->addProperty($property);
- }
- $sqlStatement = $sqlText['sql'];
- }
- $sqlStatement=preg_replace('/'.self::INLINE_PLACEHOLDER.'/',self::INLINE_SYMBOL,$sqlStatement);
-
- $this->prepareSql($statement, $sqlStatement, $node);
- }
-
- /**
- * Prepare the sql text (may extend to dynamic sql).
- * @param TSqlMapStatement mapped statement.
- * @param string sql text.
- * @param SimpleXmlElement statement node.
- * @todo Extend to dynamic sql.
- */
- protected function prepareSql($statement,$sqlStatement, $node)
- {
- $simpleDynamic = new TSimpleDynamicParser;
- $sqlStatement=preg_replace(self::ESCAPED_SIMPLE_MARK_REGEXP,self::SIMPLE_PLACEHOLDER,$sqlStatement);
- $dynamics = $simpleDynamic->parse($sqlStatement);
- if(count($dynamics['parameters']) > 0)
- {
- $sql = new TSimpleDynamicSql($dynamics['parameters']);
- $sqlStatement = $dynamics['sql'];
- }
- else
- $sql = new TStaticSql();
- $sqlStatement=preg_replace('/'.self::SIMPLE_PLACEHOLDER.'/',self::SIMPLE_MARK,$sqlStatement);
- $sql->buildPreparedStatement($statement, $sqlStatement);
- $statement->setSqlText($sql);
- }
-
- /**
- * Load select statement from xml mapping.
- * @param SimpleXmlElement select node.
- */
- protected function loadSelectTag($node)
- {
- $select = new TSqlMapSelect;
- $this->setObjectPropFromNode($select,$node);
- $this->processSqlStatement($select,$node);
- $mappedStatement = new TMappedStatement($this->_manager, $select);
- if(strlen($select->getCacheModel()) > 0)
- $mappedStatement = new TCachingStatement($mappedStatement);
-
- $this->_manager->addMappedStatement($mappedStatement);
- }
-
- /**
- * Load insert statement from xml mapping.
- * @param SimpleXmlElement insert node.
- */
- protected function loadInsertTag($node)
- {
- $insert = $this->createInsertStatement($node);
- $this->processSqlStatement($insert, $node);
- $mappedStatement = new TInsertMappedStatement($this->_manager, $insert);
- $this->_manager->addMappedStatement($mappedStatement);
- }
-
- /**
- * Create new insert statement from xml node.
- * @param SimpleXmlElement insert node.
- * @return TSqlMapInsert insert statement.
- */
- protected function createInsertStatement($node)
- {
- $insert = new TSqlMapInsert;
- $this->setObjectPropFromNode($insert,$node);
- if(isset($node->selectKey))
- $this->loadSelectKeyTag($insert,$node->selectKey);
- return $insert;
- }
-
- /**
- * Load the selectKey statement from xml mapping.
- * @param SimpleXmlElement selectkey node
- */
- protected function loadSelectKeyTag($insert, $node)
- {
- $selectKey = new TSqlMapSelectKey;
- $this->setObjectPropFromNode($selectKey,$node);
- $selectKey->setID($insert->getID());
- $selectKey->setID($insert->getID().'.SelectKey');
- $this->processSqlStatement($selectKey,$node);
- $insert->setSelectKey($selectKey);
- $mappedStatement = new TMappedStatement($this->_manager, $selectKey);
- $this->_manager->addMappedStatement($mappedStatement);
- }
-
- /**
- * Load update statement from xml mapping.
- * @param SimpleXmlElement update node.
- */
- protected function loadUpdateTag($node)
- {
- $update = new TSqlMapUpdate;
- $this->setObjectPropFromNode($update,$node);
- $this->processSqlStatement($update, $node);
- $mappedStatement = new TUpdateMappedStatement($this->_manager, $update);
- $this->_manager->addMappedStatement($mappedStatement);
- }
-
- /**
- * Load delete statement from xml mapping.
- * @param SimpleXmlElement delete node.
- */
- protected function loadDeleteTag($node)
- {
- $delete = new TSqlMapDelete;
- $this->setObjectPropFromNode($delete,$node);
- $this->processSqlStatement($delete, $node);
- $mappedStatement = new TDeleteMappedStatement($this->_manager, $delete);
- $this->_manager->addMappedStatement($mappedStatement);
- }
-
- /**
- * Load procedure statement from xml mapping.
- * @todo Implement loading procedure
- * @param SimpleXmlElement procedure node
- */
- protected function loadProcedureTag($node)
- {
- //var_dump('todo: add load procedure');
- }
-
- /**
- * Load cache models from xml mapping.
- * @param SimpleXmlElement cache node.
- */
- protected function loadCacheModel($node)
- {
- $cacheModel = new TSqlMapCacheModel;
- $properties = array('id','implementation');
- foreach($node->attributes() as $name=>$value)
- {
- if(in_array(strtolower($name), $properties))
- $cacheModel->{'set'.$name}((string)$value);
- }
- $cache = Prado::createComponent($cacheModel->getImplementationClass(), $cacheModel);
- $this->setObjectPropFromNode($cache,$node,$properties);
-
- foreach($node->xpath('property') as $propertyNode)
- {
- $name = $propertyNode->attributes()->name;
- if($name===null || $name==='') continue;
-
- $value = $propertyNode->attributes()->value;
- if($value===null || $value==='') continue;
-
- if( !TPropertyAccess::has($cache, $name) ) continue;
-
- TPropertyAccess::set($cache, $name, $value);
- }
-
- $this->loadFlushInterval($cacheModel,$node);
-
- $cacheModel->initialize($cache);
- $this->_manager->addCacheModel($cacheModel);
- foreach($node->xpath('flushOnExecute') as $flush)
- $this->loadFlushOnCache($cacheModel,$node,$flush);
- }
-
- /**
- * Load the flush interval
- * @param TSqlMapCacheModel cache model
- * @param SimpleXmlElement cache node
- */
- protected function loadFlushInterval($cacheModel, $node)
- {
- $flushInterval = $node->xpath('flushInterval');
- if($flushInterval === null || count($flushInterval) === 0) return;
- $duration = 0;
- foreach($flushInterval[0]->attributes() as $name=>$value)
- {
- switch(strToLower($name))
- {
- case 'seconds':
- $duration += (integer)$value;
- break;
- case 'minutes':
- $duration += 60 * (integer)$value;
- break;
- case 'hours':
- $duration += 3600 * (integer)$value;
- break;
- case 'days':
- $duration += 86400 * (integer)$value;
- break;
- case 'duration':
- $duration = (integer)$value;
- break 2; // switch, foreach
- }
- }
- $cacheModel->setFlushInterval($duration);
- }
-
- /**
- * Load the flush on cache properties.
- * @param TSqlMapCacheModel cache model
- * @param SimpleXmlElement parent node.
- * @param SimpleXmlElement flush node.
- */
- protected function loadFlushOnCache($cacheModel,$parent,$node)
- {
- $id = $cacheModel->getID();
- if(!isset($this->_FlushOnExecuteStatements[$id]))
- $this->_FlushOnExecuteStatements[$id] = array();
- foreach($node->attributes() as $name=>$value)
- {
- if(strtolower($name)==='statement')
- $this->_FlushOnExecuteStatements[$id][] = (string)$value;
- }
- }
-
- /**
- * Attach CacheModel to statement and register trigger statements for cache models
- */
- protected function registerCacheTriggers()
- {
- foreach($this->_FlushOnExecuteStatements as $cacheID => $statementIDs)
- {
- $cacheModel = $this->_manager->getCacheModel($cacheID);
- foreach($statementIDs as $statementID)
- {
- $statement = $this->_manager->getMappedStatement($statementID);
- $cacheModel->registerTriggerStatement($statement);
- }
- }
- }
-}
-
+<?php +/** + * TSqlMapXmlConfigBuilder, TSqlMapXmlConfiguration, TSqlMapXmlMappingConfiguration classes file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +Prado::using('System.Data.SqlMap.Configuration.TSqlMapStatement'); + +/** + * TSqlMapXmlConfig class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ +abstract class TSqlMapXmlConfigBuilder +{ + /** + * Create an instance of an object give by the attribute named 'class' in the + * node and set the properties on the object given by attribute names and values. + * @param SimpleXmlNode property node + * @return Object new instance of class with class name given by 'class' attribute value. + */ + protected function createObjectFromNode($node) + { + if(isset($node['class'])) + { + $obj = Prado::createComponent((string)$node['class']); + $this->setObjectPropFromNode($obj,$node,array('class')); + return $obj; + } + throw new TSqlMapConfigurationException( + 'sqlmap_node_class_undef', $node, $this->getConfigFile()); + } + + /** + * For each attributes (excluding attribute named in $except) set the + * property of the $obj given by the name of the attribute with the value + * of the attribute. + * @param Object object instance + * @param SimpleXmlNode property node + * @param array exception property name + */ + protected function setObjectPropFromNode($obj,$node,$except=array()) + { + foreach($node->attributes() as $name=>$value) + { + if(!in_array($name,$except)) + { + if($obj->canSetProperty($name)) + $obj->{$name} = (string)$value; + else + throw new TSqlMapConfigurationException( + 'sqlmap_invalid_property', $name, get_class($obj), + $node, $this->getConfigFile()); + } + } + } + + /** + * Gets the filename relative to the basefile. + * @param string base filename + * @param string relative filename + * @return string absolute filename. + */ + protected function getAbsoluteFilePath($basefile,$resource) + { + $basedir = dirname($basefile); + $file = realpath($basedir.DIRECTORY_SEPARATOR.$resource); + if(!is_string($file) || !is_file($file)) + $file = realpath($resource); + if(is_string($file) && is_file($file)) + return $file; + else + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_resource', $resource); + } + + /** + * Load document using simple xml. + * @param string filename. + * @return SimpleXmlElement xml document. + */ + protected function loadXmlDocument($filename,TSqlMapXmlConfiguration $config) + { + if( strpos($filename, '${') !== false) + $filename = $config->replaceProperties($filename); + + if(!is_file($filename)) + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_config', $filename); + return simplexml_load_string($config->replaceProperties(file_get_contents($filename))); + } + + /** + * Get element node by ID value (try for attribute name ID as case insensitive). + * @param SimpleXmlDocument $document + * @param string tag name. + * @param string id value. + * @return SimpleXmlElement node if found, null otherwise. + */ + protected function getElementByIdValue($document, $tag, $value) + { + //hack to allow upper case and lower case attribute names. + foreach(array('id','ID','Id', 'iD') as $id) + { + $xpath = "//{$tag}[@{$id}='{$value}']"; + foreach($document->xpath($xpath) as $node) + return $node; + } + } + + /** + * @return string configuration file. + */ + protected abstract function getConfigFile(); +} + +/** + * TSqlMapXmlConfig class. + * + * Configures the TSqlMapManager using xml configuration file. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapXmlConfiguration extends TSqlMapXmlConfigBuilder +{ + /** + * @var TSqlMapManager manager + */ + private $_manager; + /** + * @var string configuration file. + */ + private $_configFile; + /** + * @var array global properties. + */ + private $_properties=array(); + + /** + * @param TSqlMapManager manager instance. + */ + public function __construct($manager) + { + $this->_manager=$manager; + } + + public function getManager() + { + return $this->_manager; + } + + protected function getConfigFile() + { + return $this->_configFile; + } + + /** + * Configure the TSqlMapManager using the given xml file. + * @param string SqlMap configuration xml file. + */ + public function configure($filename=null) + { + $this->_configFile=$filename; + $document = $this->loadXmlDocument($filename,$this); + + foreach($document->xpath('//property') as $property) + $this->loadGlobalProperty($property); + + foreach($document->xpath('//typeHandler') as $handler) + $this->loadTypeHandler($handler); + + foreach($document->xpath('//connection[last()]') as $conn) + $this->loadDatabaseConnection($conn); + + //try to load configuration in the current config file. + $mapping = new TSqlMapXmlMappingConfiguration($this); + $mapping->configure($filename); + + foreach($document->xpath('//sqlMap') as $sqlmap) + $this->loadSqlMappingFiles($sqlmap); + + $this->resolveResultMapping(); + $this->attachCacheModels(); + } + + /** + * Load global replacement property. + * @param SimpleXmlElement property node. + */ + protected function loadGlobalProperty($node) + { + $this->_properties[(string)$node['name']] = (string)$node['value']; + } + + /** + * Load the type handler configurations. + * @param SimpleXmlElement type handler node + */ + protected function loadTypeHandler($node) + { + $handler = $this->createObjectFromNode($node); + $this->_manager->getTypeHandlers()->registerTypeHandler($handler); + } + + /** + * Load the database connection tag. + * @param SimpleXmlElement connection node. + */ + protected function loadDatabaseConnection($node) + { + $conn = $this->createObjectFromNode($node); + $this->_manager->setDbConnection($conn); + } + + /** + * Load SqlMap mapping configuration. + * @param unknown_type $node + */ + protected function loadSqlMappingFiles($node) + { + if(strlen($resource = (string)$node['resource']) > 0) + { + if( strpos($resource, '${') !== false) + $resource = $this->replaceProperties($resource); + + $mapping = new TSqlMapXmlMappingConfiguration($this); + $filename = $this->getAbsoluteFilePath($this->_configFile, $resource); + $mapping->configure($filename); + } + } + + /** + * Resolve nest result mappings. + */ + protected function resolveResultMapping() + { + $maps = $this->_manager->getResultMaps(); + foreach($maps as $entry) + { + foreach($entry->getColumns() as $item) + { + $resultMap = $item->getResultMapping(); + if(strlen($resultMap) > 0) + { + if($maps->contains($resultMap)) + $item->setNestedResultMap($maps[$resultMap]); + else + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_result_mapping', + $resultMap, $this->_configFile, $entry->getID()); + } + } + if($entry->getDiscriminator()!==null) + $entry->getDiscriminator()->initialize($this->_manager); + } + } + + /** + * Set the cache for each statement having a cache model property. + */ + protected function attachCacheModels() + { + foreach($this->_manager->getMappedStatements() as $mappedStatement) + { + if(strlen($model = $mappedStatement->getStatement()->getCacheModel()) > 0) + { + $cache = $this->_manager->getCacheModel($model); + $mappedStatement->getStatement()->setCache($cache); + } + } + } + + /** + * Replace the place holders ${name} in text with properties the + * corresponding global property value. + * @param string original string. + * @return string string with global property replacement. + */ + public function replaceProperties($string) + { + foreach($this->_properties as $find => $replace) + $string = str_replace('${'.$find.'}', $replace, $string); + return $string; + } +} + +/** + * Loads the statements, result maps, parameters maps from xml configuration. + * + * description + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapXmlMappingConfiguration extends TSqlMapXmlConfigBuilder +{ + private $_xmlConfig; + private $_configFile; + private $_manager; + + private $_document; + + private $_FlushOnExecuteStatements=array(); + + /** + * Regular expressions for escaping simple/inline parameter symbols + */ + const SIMPLE_MARK='$'; + const INLINE_SYMBOL='#'; + const ESCAPED_SIMPLE_MARK_REGEXP='/\$\$/'; + const ESCAPED_INLINE_SYMBOL_REGEXP='/\#\#/'; + const SIMPLE_PLACEHOLDER='`!!`'; + const INLINE_PLACEHOLDER='`!!!`'; + + /** + * @param TSqlMapXmlConfiguration parent xml configuration. + */ + public function __construct(TSqlMapXmlConfiguration $xmlConfig) + { + $this->_xmlConfig=$xmlConfig; + $this->_manager=$xmlConfig->getManager(); + } + + protected function getConfigFile() + { + return $this->_configFile; + } + + /** + * Configure an XML mapping. + * @param string xml mapping filename. + */ + public function configure($filename) + { + $this->_configFile=$filename; + $document = $this->loadXmlDocument($filename,$this->_xmlConfig); + $this->_document=$document; + + static $bCacheDependencies; + if($bCacheDependencies === null) + $bCacheDependencies = Prado::getApplication()->getMode() !== TApplicationMode::Performance; + + if($bCacheDependencies) + $this->_manager->getCacheDependencies() + ->getDependencies() + ->add(new TFileCacheDependency($filename)); + + foreach($document->xpath('//resultMap') as $node) + $this->loadResultMap($node); + + foreach($document->xpath('//parameterMap') as $node) + $this->loadParameterMap($node); + + foreach($document->xpath('//statement') as $node) + $this->loadStatementTag($node); + + foreach($document->xpath('//select') as $node) + $this->loadSelectTag($node); + + foreach($document->xpath('//insert') as $node) + $this->loadInsertTag($node); + + foreach($document->xpath('//update') as $node) + $this->loadUpdateTag($node); + + foreach($document->xpath('//delete') as $node) + $this->loadDeleteTag($node); + + foreach($document->xpath('//procedure') as $node) + $this->loadProcedureTag($node); + + foreach($document->xpath('//cacheModel') as $node) + $this->loadCacheModel($node); + + $this->registerCacheTriggers(); + } + + /** + * Load the result maps. + * @param SimpleXmlElement result map node. + */ + protected function loadResultMap($node) + { + $resultMap = $this->createResultMap($node); + + //find extended result map. + if(strlen($extendMap = $resultMap->getExtends()) > 0) + { + if(!$this->_manager->getResultMaps()->contains($extendMap)) + { + $extendNode=$this->getElementByIdValue($this->_document,'resultMap',$extendMap); + if($extendNode!==null) + $this->loadResultMap($extendNode); + } + + if(!$this->_manager->getResultMaps()->contains($extendMap)) + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_parent_result_map', $node, $this->_configFile, $extendMap); + + $superMap = $this->_manager->getResultMap($extendMap); + $resultMap->getColumns()->mergeWith($superMap->getColumns()); + } + + //add the result map + if(!$this->_manager->getResultMaps()->contains($resultMap->getID())) + $this->_manager->addResultMap($resultMap); + } + + /** + * Create a new result map and its associated result properties, + * disciminiator and sub maps. + * @param SimpleXmlElement result map node + * @return TResultMap SqlMap result mapping. + */ + protected function createResultMap($node) + { + $resultMap = new TResultMap(); + $this->setObjectPropFromNode($resultMap,$node); + + //result nodes + foreach($node->result as $result) + { + $property = new TResultProperty($resultMap); + $this->setObjectPropFromNode($property,$result); + $resultMap->addResultProperty($property); + } + + //create the discriminator + $discriminator = null; + if(isset($node->discriminator)) + { + $discriminator = new TDiscriminator(); + $this->setObjectPropFromNode($discriminator, $node->discriminator); + $discriminator->initMapping($resultMap); + } + + foreach($node->xpath('subMap') as $subMapNode) + { + if($discriminator===null) + throw new TSqlMapConfigurationException( + 'sqlmap_undefined_discriminator', $node, $this->_configFile,$subMapNode); + $subMap = new TSubMap; + $this->setObjectPropFromNode($subMap,$subMapNode); + $discriminator->addSubMap($subMap); + } + + if($discriminator!==null) + $resultMap->setDiscriminator($discriminator); + + return $resultMap; + } + + /** + * Load parameter map from xml. + * + * @param SimpleXmlElement parameter map node. + */ + protected function loadParameterMap($node) + { + $parameterMap = $this->createParameterMap($node); + + if(strlen($extendMap = $parameterMap->getExtends()) > 0) + { + if(!$this->_manager->getParameterMaps()->contains($extendMap)) + { + $extendNode=$this->getElementByIdValue($this->_document,'parameterMap',$extendMap); + if($extendNode!==null) + $this->loadParameterMap($extendNode); + } + + if(!$this->_manager->getParameterMaps()->contains($extendMap)) + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_parent_parameter_map', $node, $this->_configFile,$extendMap); + $superMap = $this->_manager->getParameterMap($extendMap); + $index = 0; + foreach($superMap->getPropertyNames() as $propertyName) + $parameterMap->insertProperty($index++,$superMap->getProperty($propertyName)); + } + $this->_manager->addParameterMap($parameterMap); + } + + /** + * Create a new parameter map from xml node. + * @param SimpleXmlElement parameter map node. + * @return TParameterMap new parameter mapping. + */ + protected function createParameterMap($node) + { + $parameterMap = new TParameterMap(); + $this->setObjectPropFromNode($parameterMap,$node); + foreach($node->parameter as $parameter) + { + $property = new TParameterProperty(); + $this->setObjectPropFromNode($property,$parameter); + $parameterMap->addProperty($property); + } + return $parameterMap; + } + + /** + * Load statement mapping from xml configuration file. + * @param SimpleXmlElement statement node. + */ + protected function loadStatementTag($node) + { + $statement = new TSqlMapStatement(); + $this->setObjectPropFromNode($statement,$node); + $this->processSqlStatement($statement, $node); + $mappedStatement = new TMappedStatement($this->_manager, $statement); + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Load extended SQL statements if application. Replaces global properties + * in the sql text. Extracts inline parameter maps. + * @param TSqlMapStatement mapped statement. + * @param SimpleXmlElement statement node. + */ + protected function processSqlStatement($statement, $node) + { + $commandText = (string)$node; + if(strlen($extend = $statement->getExtends()) > 0) + { + $superNode = $this->getElementByIdValue($this->_document,'*',$extend); + if($superNode!==null) + $commandText = (string)$superNode . $commandText; + else + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_parent_sql', $extend, $this->_configFile,$node); + } + //$commandText = $this->_xmlConfig->replaceProperties($commandText); + $statement->initialize($this->_manager); + $this->applyInlineParameterMap($statement, $commandText, $node); + } + + /** + * Extract inline parameter maps. + * @param TSqlMapStatement statement object. + * @param string sql text + * @param SimpleXmlElement statement node. + */ + protected function applyInlineParameterMap($statement, $sqlStatement, $node) + { + $scope['file'] = $this->_configFile; + $scope['node'] = $node; + + $sqlStatement=preg_replace(self::ESCAPED_INLINE_SYMBOL_REGEXP,self::INLINE_PLACEHOLDER,$sqlStatement); + if($statement->parameterMap() === null) + { + // Build a Parametermap with the inline parameters. + // if they exist. Then delete inline infos from sqltext. + $parameterParser = new TInlineParameterMapParser; + $sqlText = $parameterParser->parse($sqlStatement, $scope); + if(count($sqlText['parameters']) > 0) + { + $map = new TParameterMap(); + $map->setID($statement->getID().'-InLineParameterMap'); + $statement->setInlineParameterMap($map); + foreach($sqlText['parameters'] as $property) + $map->addProperty($property); + } + $sqlStatement = $sqlText['sql']; + } + $sqlStatement=preg_replace('/'.self::INLINE_PLACEHOLDER.'/',self::INLINE_SYMBOL,$sqlStatement); + + $this->prepareSql($statement, $sqlStatement, $node); + } + + /** + * Prepare the sql text (may extend to dynamic sql). + * @param TSqlMapStatement mapped statement. + * @param string sql text. + * @param SimpleXmlElement statement node. + * @todo Extend to dynamic sql. + */ + protected function prepareSql($statement,$sqlStatement, $node) + { + $simpleDynamic = new TSimpleDynamicParser; + $sqlStatement=preg_replace(self::ESCAPED_SIMPLE_MARK_REGEXP,self::SIMPLE_PLACEHOLDER,$sqlStatement); + $dynamics = $simpleDynamic->parse($sqlStatement); + if(count($dynamics['parameters']) > 0) + { + $sql = new TSimpleDynamicSql($dynamics['parameters']); + $sqlStatement = $dynamics['sql']; + } + else + $sql = new TStaticSql(); + $sqlStatement=preg_replace('/'.self::SIMPLE_PLACEHOLDER.'/',self::SIMPLE_MARK,$sqlStatement); + $sql->buildPreparedStatement($statement, $sqlStatement); + $statement->setSqlText($sql); + } + + /** + * Load select statement from xml mapping. + * @param SimpleXmlElement select node. + */ + protected function loadSelectTag($node) + { + $select = new TSqlMapSelect; + $this->setObjectPropFromNode($select,$node); + $this->processSqlStatement($select,$node); + $mappedStatement = new TMappedStatement($this->_manager, $select); + if(strlen($select->getCacheModel()) > 0) + $mappedStatement = new TCachingStatement($mappedStatement); + + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Load insert statement from xml mapping. + * @param SimpleXmlElement insert node. + */ + protected function loadInsertTag($node) + { + $insert = $this->createInsertStatement($node); + $this->processSqlStatement($insert, $node); + $mappedStatement = new TInsertMappedStatement($this->_manager, $insert); + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Create new insert statement from xml node. + * @param SimpleXmlElement insert node. + * @return TSqlMapInsert insert statement. + */ + protected function createInsertStatement($node) + { + $insert = new TSqlMapInsert; + $this->setObjectPropFromNode($insert,$node); + if(isset($node->selectKey)) + $this->loadSelectKeyTag($insert,$node->selectKey); + return $insert; + } + + /** + * Load the selectKey statement from xml mapping. + * @param SimpleXmlElement selectkey node + */ + protected function loadSelectKeyTag($insert, $node) + { + $selectKey = new TSqlMapSelectKey; + $this->setObjectPropFromNode($selectKey,$node); + $selectKey->setID($insert->getID()); + $selectKey->setID($insert->getID().'.SelectKey'); + $this->processSqlStatement($selectKey,$node); + $insert->setSelectKey($selectKey); + $mappedStatement = new TMappedStatement($this->_manager, $selectKey); + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Load update statement from xml mapping. + * @param SimpleXmlElement update node. + */ + protected function loadUpdateTag($node) + { + $update = new TSqlMapUpdate; + $this->setObjectPropFromNode($update,$node); + $this->processSqlStatement($update, $node); + $mappedStatement = new TUpdateMappedStatement($this->_manager, $update); + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Load delete statement from xml mapping. + * @param SimpleXmlElement delete node. + */ + protected function loadDeleteTag($node) + { + $delete = new TSqlMapDelete; + $this->setObjectPropFromNode($delete,$node); + $this->processSqlStatement($delete, $node); + $mappedStatement = new TDeleteMappedStatement($this->_manager, $delete); + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Load procedure statement from xml mapping. + * @todo Implement loading procedure + * @param SimpleXmlElement procedure node + */ + protected function loadProcedureTag($node) + { + //var_dump('todo: add load procedure'); + } + + /** + * Load cache models from xml mapping. + * @param SimpleXmlElement cache node. + */ + protected function loadCacheModel($node) + { + $cacheModel = new TSqlMapCacheModel; + $properties = array('id','implementation'); + foreach($node->attributes() as $name=>$value) + { + if(in_array(strtolower($name), $properties)) + $cacheModel->{'set'.$name}((string)$value); + } + $cache = Prado::createComponent($cacheModel->getImplementationClass(), $cacheModel); + $this->setObjectPropFromNode($cache,$node,$properties); + + foreach($node->xpath('property') as $propertyNode) + { + $name = $propertyNode->attributes()->name; + if($name===null || $name==='') continue; + + $value = $propertyNode->attributes()->value; + if($value===null || $value==='') continue; + + if( !TPropertyAccess::has($cache, $name) ) continue; + + TPropertyAccess::set($cache, $name, $value); + } + + $this->loadFlushInterval($cacheModel,$node); + + $cacheModel->initialize($cache); + $this->_manager->addCacheModel($cacheModel); + foreach($node->xpath('flushOnExecute') as $flush) + $this->loadFlushOnCache($cacheModel,$node,$flush); + } + + /** + * Load the flush interval + * @param TSqlMapCacheModel cache model + * @param SimpleXmlElement cache node + */ + protected function loadFlushInterval($cacheModel, $node) + { + $flushInterval = $node->xpath('flushInterval'); + if($flushInterval === null || count($flushInterval) === 0) return; + $duration = 0; + foreach($flushInterval[0]->attributes() as $name=>$value) + { + switch(strToLower($name)) + { + case 'seconds': + $duration += (integer)$value; + break; + case 'minutes': + $duration += 60 * (integer)$value; + break; + case 'hours': + $duration += 3600 * (integer)$value; + break; + case 'days': + $duration += 86400 * (integer)$value; + break; + case 'duration': + $duration = (integer)$value; + break 2; // switch, foreach + } + } + $cacheModel->setFlushInterval($duration); + } + + /** + * Load the flush on cache properties. + * @param TSqlMapCacheModel cache model + * @param SimpleXmlElement parent node. + * @param SimpleXmlElement flush node. + */ + protected function loadFlushOnCache($cacheModel,$parent,$node) + { + $id = $cacheModel->getID(); + if(!isset($this->_FlushOnExecuteStatements[$id])) + $this->_FlushOnExecuteStatements[$id] = array(); + foreach($node->attributes() as $name=>$value) + { + if(strtolower($name)==='statement') + $this->_FlushOnExecuteStatements[$id][] = (string)$value; + } + } + + /** + * Attach CacheModel to statement and register trigger statements for cache models + */ + protected function registerCacheTriggers() + { + foreach($this->_FlushOnExecuteStatements as $cacheID => $statementIDs) + { + $cacheModel = $this->_manager->getCacheModel($cacheID); + foreach($statementIDs as $statementID) + { + $statement = $this->_manager->getMappedStatement($statementID); + $cacheModel->registerTriggerStatement($statement); + } + } + } +} + diff --git a/framework/Data/SqlMap/DataMapper/TFastSqlMapApplicationCache.php b/framework/Data/SqlMap/DataMapper/TFastSqlMapApplicationCache.php index d780b413..e85c54cf 100644 --- a/framework/Data/SqlMap/DataMapper/TFastSqlMapApplicationCache.php +++ b/framework/Data/SqlMap/DataMapper/TFastSqlMapApplicationCache.php @@ -1,89 +1,89 @@ -<?php
-/**
- * TFastSqlMapApplicationCache class file contains Fast SqlMap cache implementation.
- *
- * @author Berczi Gabor <gabor.berczi@devworx.hu>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id: TFastSqlMapApplicationCache.php 2996 2011-06-20 15:24:57Z ctrlaltca@gmail.com $
- * @package System.Data.SqlMap
- */
-
-/**
- * TFastSqlMapApplicationCache class file
- *
- * Fast SqlMap result cache class with minimal-concurrency get/set and atomic flush operations
- *
- * @author Berczi Gabor <gabor.berczi@devworx.hu>
- * @version $Id: TFastSqlMapApplicationCache.php 2996 2011-06-20 15:24:57Z ctrlaltca@gmail.com $
- * @package System.Data.SqlMap
- * @since 3.2
- */
-
-class TFastSqlMapApplicationCache implements ICache
-{
- protected $_cacheModel=null;
- protected $_cache=null;
-
- public function __construct($cacheModel=null)
- {
- $this->_cacheModel = $cacheModel;
- }
-
- protected function getBaseKeyKeyName()
- {
- return 'SqlMapCacheBaseKey::'.$this->_cacheModel->getId();
- }
-
- protected function getBaseKey()
- {
- $cache = $this->getCache();
- $keyname = $this->getBaseKeyKeyName();
- $basekey = $cache->get($keyname);
- if (!$basekey)
- {
- $basekey = DxUtil::generateRandomHash(8);
- $cache->set($keyname,$basekey);
- }
- return $basekey;
- }
-
- protected function getCacheKey($key)
- {
- return $this->getBaseKey().'###'.$key;
- }
-
- public function delete($key)
- {
- $this->getCache()->delete($this->getCacheKey($key));
- }
-
- public function flush()
- {
- $this->getCache()->delete($this->getBaseKeyKeyName());
- }
-
- public function get($key)
- {
- $result = $this->getCache()->get($this->getCacheKey($key));
- return $result === false ? null : $result;
- }
-
- public function set($key, $value,$expire=0,$dependency=null)
- {
- $this->getCache()->set($this->getCacheKey($key), $value, $expire,$dependency);
- }
-
- protected function getCache()
- {
- if (!$this->_cache)
- $this->_cache = Prado::getApplication()->getCache();
- return $this->_cache;
- }
-
- public function add($id,$value,$expire=0,$dependency=null)
- {
- throw new TSqlMapException('sqlmap_use_set_to_store_cache');
- }
-}
+<?php +/** + * TFastSqlMapApplicationCache class file contains Fast SqlMap cache implementation. + * + * @author Berczi Gabor <gabor.berczi@devworx.hu> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id: TFastSqlMapApplicationCache.php 2996 2011-06-20 15:24:57Z ctrlaltca@gmail.com $ + * @package System.Data.SqlMap + */ + +/** + * TFastSqlMapApplicationCache class file + * + * Fast SqlMap result cache class with minimal-concurrency get/set and atomic flush operations + * + * @author Berczi Gabor <gabor.berczi@devworx.hu> + * @version $Id: TFastSqlMapApplicationCache.php 2996 2011-06-20 15:24:57Z ctrlaltca@gmail.com $ + * @package System.Data.SqlMap + * @since 3.2 + */ + +class TFastSqlMapApplicationCache implements ICache +{ + protected $_cacheModel=null; + protected $_cache=null; + + public function __construct($cacheModel=null) + { + $this->_cacheModel = $cacheModel; + } + + protected function getBaseKeyKeyName() + { + return 'SqlMapCacheBaseKey::'.$this->_cacheModel->getId(); + } + + protected function getBaseKey() + { + $cache = $this->getCache(); + $keyname = $this->getBaseKeyKeyName(); + $basekey = $cache->get($keyname); + if (!$basekey) + { + $basekey = DxUtil::generateRandomHash(8); + $cache->set($keyname,$basekey); + } + return $basekey; + } + + protected function getCacheKey($key) + { + return $this->getBaseKey().'###'.$key; + } + + public function delete($key) + { + $this->getCache()->delete($this->getCacheKey($key)); + } + + public function flush() + { + $this->getCache()->delete($this->getBaseKeyKeyName()); + } + + public function get($key) + { + $result = $this->getCache()->get($this->getCacheKey($key)); + return $result === false ? null : $result; + } + + public function set($key, $value,$expire=0,$dependency=null) + { + $this->getCache()->set($this->getCacheKey($key), $value, $expire,$dependency); + } + + protected function getCache() + { + if (!$this->_cache) + $this->_cache = Prado::getApplication()->getCache(); + return $this->_cache; + } + + public function add($id,$value,$expire=0,$dependency=null) + { + throw new TSqlMapException('sqlmap_use_set_to_store_cache'); + } +} diff --git a/framework/Data/SqlMap/DataMapper/TLazyLoadList.php b/framework/Data/SqlMap/DataMapper/TLazyLoadList.php index 9b163960..8e5d8d85 100644 --- a/framework/Data/SqlMap/DataMapper/TLazyLoadList.php +++ b/framework/Data/SqlMap/DataMapper/TLazyLoadList.php @@ -1,144 +1,144 @@ -<?php
-/**
- * TLazyLoadList, TObjectProxy classes file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TLazyLoadList, TObjectProxy classes file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap
- */
-
-/**
- * TLazyLoadList executes mapped statements when the proxy collection is first accessed.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TLazyLoadList
-{
- private $_param;
- private $_target;
- private $_propertyName='';
- private $_statement='';
- private $_loaded=false;
- private $_innerList;
- private $_connection;
-
- /**
- * Create a new proxy list that will execute the mapped statement when any
- * of the list's method are accessed for the first time.
- * @param TMappedStatement statement to be executed to load the data.
- * @param mixed parameter value for the statement.
- * @param object result object that contains the lazy collection.
- * @param string property of the result object to set the loaded collection.
- */
- protected function __construct($mappedStatement, $param, $target, $propertyName)
- {
- $this->_param = $param;
- $this->_target = $target;
- $this->_statement = $mappedStatement;
- $this->_connection=$mappedStatement->getManager()->getDbConnection();
- $this->_propertyName = $propertyName;
- }
-
- /**
- * Create a new instance of a lazy collection.
- * @param TMappedStatement statement to be executed to load the data.
- * @param mixed parameter value for the statement.
- * @param object result object that contains the lazy collection.
- * @param string property of the result object to set the loaded collection.
- * @return TObjectProxy proxied collection object.
- */
- public static function newInstance($mappedStatement, $param, $target, $propertyName)
- {
- $handler = new self($mappedStatement, $param, $target, $propertyName);
- $statement = $mappedStatement->getStatement();
- $registry=$mappedStatement->getManager()->getTypeHandlers();
- $list = $statement->createInstanceOfListClass($registry);
- if(!is_object($list))
- throw new TSqlMapExecutionException('sqlmap_invalid_lazyload_list',$statement->getID());
- return new TObjectProxy($handler, $list);
- }
-
- /**
- * Relay the method call to the underlying collection.
- * @param string method name.
- * @param array method parameters.
- */
- public function intercept($method, $arguments)
- {
- return call_user_func_array(array($this->_innerList, $method), $arguments);
- }
-
- /**
- * Load the data by executing the mapped statement.
- */
- protected function fetchListData()
- {
- if($this->_loaded == false)
- {
- $this->_innerList = $this->_statement->executeQueryForList($this->_connection,$this->_param);
- $this->_loaded = true;
- //replace the target property with real list
- TPropertyAccess::set($this->_target, $this->_propertyName, $this->_innerList);
- }
- }
-
- /**
- * Try to fetch the data when any of the proxy collection method is called.
- * @param string method name.
- * @return boolean true if the underlying collection has the corresponding method name.
- */
- public function hasMethod($method)
- {
- $this->fetchListData();
- if(is_object($this->_innerList))
- return in_array($method, get_class_methods($this->_innerList));
- return false;
- }
-}
-
-/**
- * TObjectProxy sets up a simple object that intercepts method calls to a
- * particular object and relays the call to handler object.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TObjectProxy
-{
- private $_object;
- private $_handler;
-
- /**
- * @param object handler to method calls.
- * @param object the object to by proxied.
- */
- public function __construct($handler, $object)
- {
- $this->_handler = $handler;
- $this->_object = $object;
- }
-
- /**
- * Relay the method call to the handler object (if able to be handled), otherwise
- * it calls the proxied object's method.
- * @param string method name called
- * @param array method arguments
- * @return mixed method return value.
- */
- public function __call($method,$params)
- {
- if($this->_handler->hasMethod($method))
- return $this->_handler->intercept($method, $params);
- else
- return call_user_func_array(array($this->_object, $method), $params);
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap + */ + +/** + * TLazyLoadList executes mapped statements when the proxy collection is first accessed. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TLazyLoadList +{ + private $_param; + private $_target; + private $_propertyName=''; + private $_statement=''; + private $_loaded=false; + private $_innerList; + private $_connection; + + /** + * Create a new proxy list that will execute the mapped statement when any + * of the list's method are accessed for the first time. + * @param TMappedStatement statement to be executed to load the data. + * @param mixed parameter value for the statement. + * @param object result object that contains the lazy collection. + * @param string property of the result object to set the loaded collection. + */ + protected function __construct($mappedStatement, $param, $target, $propertyName) + { + $this->_param = $param; + $this->_target = $target; + $this->_statement = $mappedStatement; + $this->_connection=$mappedStatement->getManager()->getDbConnection(); + $this->_propertyName = $propertyName; + } + + /** + * Create a new instance of a lazy collection. + * @param TMappedStatement statement to be executed to load the data. + * @param mixed parameter value for the statement. + * @param object result object that contains the lazy collection. + * @param string property of the result object to set the loaded collection. + * @return TObjectProxy proxied collection object. + */ + public static function newInstance($mappedStatement, $param, $target, $propertyName) + { + $handler = new self($mappedStatement, $param, $target, $propertyName); + $statement = $mappedStatement->getStatement(); + $registry=$mappedStatement->getManager()->getTypeHandlers(); + $list = $statement->createInstanceOfListClass($registry); + if(!is_object($list)) + throw new TSqlMapExecutionException('sqlmap_invalid_lazyload_list',$statement->getID()); + return new TObjectProxy($handler, $list); + } + + /** + * Relay the method call to the underlying collection. + * @param string method name. + * @param array method parameters. + */ + public function intercept($method, $arguments) + { + return call_user_func_array(array($this->_innerList, $method), $arguments); + } + + /** + * Load the data by executing the mapped statement. + */ + protected function fetchListData() + { + if($this->_loaded == false) + { + $this->_innerList = $this->_statement->executeQueryForList($this->_connection,$this->_param); + $this->_loaded = true; + //replace the target property with real list + TPropertyAccess::set($this->_target, $this->_propertyName, $this->_innerList); + } + } + + /** + * Try to fetch the data when any of the proxy collection method is called. + * @param string method name. + * @return boolean true if the underlying collection has the corresponding method name. + */ + public function hasMethod($method) + { + $this->fetchListData(); + if(is_object($this->_innerList)) + return in_array($method, get_class_methods($this->_innerList)); + return false; + } +} + +/** + * TObjectProxy sets up a simple object that intercepts method calls to a + * particular object and relays the call to handler object. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TObjectProxy +{ + private $_object; + private $_handler; + + /** + * @param object handler to method calls. + * @param object the object to by proxied. + */ + public function __construct($handler, $object) + { + $this->_handler = $handler; + $this->_object = $object; + } + + /** + * Relay the method call to the handler object (if able to be handled), otherwise + * it calls the proxied object's method. + * @param string method name called + * @param array method arguments + * @return mixed method return value. + */ + public function __call($method,$params) + { + if($this->_handler->hasMethod($method)) + return $this->_handler->intercept($method, $params); + else + return call_user_func_array(array($this->_object, $method), $params); + } +} + diff --git a/framework/Data/SqlMap/DataMapper/TPropertyAccess.php b/framework/Data/SqlMap/DataMapper/TPropertyAccess.php index 7445e9d8..a6a2c451 100644 --- a/framework/Data/SqlMap/DataMapper/TPropertyAccess.php +++ b/framework/Data/SqlMap/DataMapper/TPropertyAccess.php @@ -1,156 +1,156 @@ -<?php
-/**
- * TPropertyAccess class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap
- */
-
-/**
- * TPropertyAccess class provides dot notation stype property access and setting.
- *
- * Access object's properties (and subproperties) using dot path notation.
- * The following are equivalent.
- * <code>
- * echo $obj->property1;
- * echo $obj->getProperty1();
- * echo $obj['property1']; //$obj may be an array or object
- * echo TPropertyAccess($obj, 'property1');
- * </code>
- *
- * Setting a property value.
- * <code>
- * $obj1->propert1 = 'hello';
- * $obj->setProperty('hello');
- * $obj['property1'] = 'hello'; //$obj may be an array or object
- * TPropertyAccess($obj, 'property1', 'hello');
- * </code>
- *
- * Subproperties are supported using the dot notation. E.g.
- * <code>
- * echo $obj->property1->property2->property3
- * echo TPropertyAccess::get($obj, 'property1.property2.property3');
- * </code>
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TPropertyAccess
-{
- /**
- * Gets the property value.
- * @param mixed object or path.
- * @param string property path.
- * @return mixed property value.
- * @throws TInvalidDataValueException if property path is invalid.
- */
- public static function get($object,$path)
- {
- if(!is_array($object) && !is_object($object))
- return $object;
- $properties = explode('.', $path);
- foreach($properties as $prop)
- {
- if(is_array($object) || $object instanceof ArrayAccess)
- {
- if(array_key_exists($prop, $object))
- $object = $object[$prop];
- else
- throw new TInvalidPropertyException('sqlmap_invalid_property',$path);
- }
- else if(is_object($object))
- {
- $getter = 'get'.$prop;
- if(method_exists($object, $getter) && is_callable(array($object, $getter)))
- $object = $object->{$getter}();
- else if(in_array($prop, array_keys(get_object_vars($object))))
- $object = $object->{$prop};
- elseif(method_exists($object, '__get') && is_callable(array($object, '__get')))
- $object = $object->{$prop};
- else
- throw new TInvalidPropertyException('sqlmap_invalid_property',$path);
- }
- else
- throw new TInvalidPropertyException('sqlmap_invalid_property',$path);
- }
- return $object;
- }
-
- /**
- * @param mixed object or array
- * @param string property path.
- * @return boolean true if property path is valid
- */
- public static function has($object, $path)
- {
- if(!is_array($object) && !is_object($object))
- return false;
- $properties = explode('.', $path);
- foreach($properties as $prop)
- {
- if(is_array($object) || $object instanceof ArrayAccess)
- {
- if(array_key_exists($prop, $object))
- $object = $object[$prop];
- else
- return false;
- }
- else if(is_object($object))
- {
- $getter = 'get'.$prop;
- if(method_exists($object, $getter) && is_callable(array($object, $getter)))
- $object = $object->{$getter}();
- else if(in_array($prop, array_keys(get_object_vars($object))))
- $object = $object->{$prop};
- elseif(method_exists($object, '__get') && is_callable(array($object, '__get')))
- $object = $object->{$prop};
- else
- return false;
- }
- else
- return false;
- }
- return true;
- }
-
- /**
- * Sets the property value.
- * @param mixed object or array
- * @param string property path.
- * @param mixed new property value.
- * @throws TInvalidDataValueException if property path is invalid.
- */
- public static function set(&$originalObject, $path, $value)
- {
- $properties = explode('.', $path);
- $prop = array_pop($properties);
- if(count($properties) > 0)
- $object = self::get($originalObject, implode('.',$properties));
- else
- $object = &$originalObject;
-
- if(is_array($object) || $object instanceof ArrayAccess)
- {
- $object[$prop] = $value;
- }
- else if(is_object($object))
- {
- $setter = 'set'.$prop;
- if (method_exists($object, $setter) && is_callable(array($object, $setter)))
- $object->{$setter}($value);
- else
- $object->{$prop} = $value;
- }
- else
- throw new TInvalidPropertyException('sqlmap_invalid_property_type',$path);
- }
-
-}
-
-?>
+<?php +/** + * TPropertyAccess class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap + */ + +/** + * TPropertyAccess class provides dot notation stype property access and setting. + * + * Access object's properties (and subproperties) using dot path notation. + * The following are equivalent. + * <code> + * echo $obj->property1; + * echo $obj->getProperty1(); + * echo $obj['property1']; //$obj may be an array or object + * echo TPropertyAccess($obj, 'property1'); + * </code> + * + * Setting a property value. + * <code> + * $obj1->propert1 = 'hello'; + * $obj->setProperty('hello'); + * $obj['property1'] = 'hello'; //$obj may be an array or object + * TPropertyAccess($obj, 'property1', 'hello'); + * </code> + * + * Subproperties are supported using the dot notation. E.g. + * <code> + * echo $obj->property1->property2->property3 + * echo TPropertyAccess::get($obj, 'property1.property2.property3'); + * </code> + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TPropertyAccess +{ + /** + * Gets the property value. + * @param mixed object or path. + * @param string property path. + * @return mixed property value. + * @throws TInvalidDataValueException if property path is invalid. + */ + public static function get($object,$path) + { + if(!is_array($object) && !is_object($object)) + return $object; + $properties = explode('.', $path); + foreach($properties as $prop) + { + if(is_array($object) || $object instanceof ArrayAccess) + { + if(array_key_exists($prop, $object)) + $object = $object[$prop]; + else + throw new TInvalidPropertyException('sqlmap_invalid_property',$path); + } + else if(is_object($object)) + { + $getter = 'get'.$prop; + if(method_exists($object, $getter) && is_callable(array($object, $getter))) + $object = $object->{$getter}(); + else if(in_array($prop, array_keys(get_object_vars($object)))) + $object = $object->{$prop}; + elseif(method_exists($object, '__get') && is_callable(array($object, '__get'))) + $object = $object->{$prop}; + else + throw new TInvalidPropertyException('sqlmap_invalid_property',$path); + } + else + throw new TInvalidPropertyException('sqlmap_invalid_property',$path); + } + return $object; + } + + /** + * @param mixed object or array + * @param string property path. + * @return boolean true if property path is valid + */ + public static function has($object, $path) + { + if(!is_array($object) && !is_object($object)) + return false; + $properties = explode('.', $path); + foreach($properties as $prop) + { + if(is_array($object) || $object instanceof ArrayAccess) + { + if(array_key_exists($prop, $object)) + $object = $object[$prop]; + else + return false; + } + else if(is_object($object)) + { + $getter = 'get'.$prop; + if(method_exists($object, $getter) && is_callable(array($object, $getter))) + $object = $object->{$getter}(); + else if(in_array($prop, array_keys(get_object_vars($object)))) + $object = $object->{$prop}; + elseif(method_exists($object, '__get') && is_callable(array($object, '__get'))) + $object = $object->{$prop}; + else + return false; + } + else + return false; + } + return true; + } + + /** + * Sets the property value. + * @param mixed object or array + * @param string property path. + * @param mixed new property value. + * @throws TInvalidDataValueException if property path is invalid. + */ + public static function set(&$originalObject, $path, $value) + { + $properties = explode('.', $path); + $prop = array_pop($properties); + if(count($properties) > 0) + $object = self::get($originalObject, implode('.',$properties)); + else + $object = &$originalObject; + + if(is_array($object) || $object instanceof ArrayAccess) + { + $object[$prop] = $value; + } + else if(is_object($object)) + { + $setter = 'set'.$prop; + if (method_exists($object, $setter) && is_callable(array($object, $setter))) + $object->{$setter}($value); + else + $object->{$prop} = $value; + } + else + throw new TInvalidPropertyException('sqlmap_invalid_property_type',$path); + } + +} + +?> diff --git a/framework/Data/SqlMap/DataMapper/TSqlMapCache.php b/framework/Data/SqlMap/DataMapper/TSqlMapCache.php index db027013..4e713fea 100644 --- a/framework/Data/SqlMap/DataMapper/TSqlMapCache.php +++ b/framework/Data/SqlMap/DataMapper/TSqlMapCache.php @@ -1,295 +1,295 @@ -<?php
-/**
- * TSqlMapCache class file contains FIFO, LRU, and GLOBAL cache implementations.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap
- */
-
-/**
- * Allow different implementation of caching strategy. See <tt>TSqlMapFifoCache</tt>
- * for a first-in-first-out implementation. See <tt>TSqlMapLruCache</tt> for
- * a least-recently-used cache implementation.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-abstract class TSqlMapCache implements ICache
-{
- protected $_keyList;
- protected $_cache;
- protected $_cacheSize = 100;
- protected $_cacheModel = null;
-
- /**
- * Create a new cache with limited cache size.
- * @param TSqlMapCacheModel $cacheModel.
- */
- public function __construct($cacheModel=null)
- {
- $this->_cache = new TMap;
- $this->_keyList = new TList;
- $this->_cacheModel=$cacheModel;
- }
-
- /**
- * Maximum number of items to cache. Default size is 100.
- * @param int cache size.
- */
- public function setCacheSize($value)
- {
- $this->_cacheSize=TPropertyValue::ensureInteger($value,100);
- }
-
- /**
- * @return int cache size.
- */
- public function getCacheSize()
- {
- return $this->_cacheSize;
- }
-
- /**
- * @return object the object removed if exists, null otherwise.
- */
- public function delete($key)
- {
- $object = $this->get($key);
- $this->_cache->remove($key);
- $this->_keyList->remove($key);
- return $object;
- }
-
- /**
- * Clears the cache.
- */
- public function flush()
- {
- $this->_keyList->clear();
- $this->_cache->clear();
- }
-
- /**
- * @throws TSqlMapException not implemented.
- */
- public function add($id,$value,$expire=0,$dependency=null)
- {
- throw new TSqlMapException('sqlmap_use_set_to_store_cache');
- }
-}
-
-/**
- * First-in-First-out cache implementation, removes
- * object that was first added when the cache is full.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapFifoCache extends TSqlMapCache
-{
- /**
- * @return mixed Gets a cached object with the specified key.
- */
- public function get($key)
- {
- return $this->_cache->itemAt($key);
- }
-
- /**
- * Stores a value identified by a key into cache.
- * The expire and dependency parameters are ignored.
- * @param string cache key
- * @param mixed value to cache.
- */
- public function set($key, $value,$expire=0,$dependency=null)
- {
- $this->_cache->add($key, $value);
- $this->_keyList->add($key);
- if($this->_keyList->getCount() > $this->_cacheSize)
- {
- $oldestKey = $this->_keyList->removeAt(0);
- $this->_cache->remove($oldestKey);
- }
- }
-}
-
-/**
- * Least recently used cache implementation, removes
- * object that was accessed last when the cache is full.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapLruCache extends TSqlMapCache
-{
- /**
- * @return mixed Gets a cached object with the specified key.
- */
- public function get($key)
- {
- if($this->_keyList->contains($key))
- {
- $this->_keyList->remove($key);
- $this->_keyList->add($key);
- return $this->_cache->itemAt($key);
- }
- }
-
- /**
- * Stores a value identified by a key into cache.
- * The expire and dependency parameters are ignored.
- * @param string the key identifying the value to be cached
- * @param mixed the value to be cached
- */
- public function set($key, $value,$expire=0,$dependency=null)
- {
- $this->_cache->add($key, $value);
- $this->_keyList->add($key);
- if($this->_keyList->getCount() > $this->_cacheSize)
- {
- $oldestKey = $this->_keyList->removeAt(0);
- $this->_cache->remove($oldestKey);
- }
- }
-}
-
-/**
- * TSqlMapApplicationCache uses the default Prado application cache for
- * caching SqlMap results.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapApplicationCache implements ICache
-{
- protected $_cacheModel=null;
-
- /**
- * Create a new cache with limited cache size.
- * @param TSqlMapCacheModel $cacheModel.
- */
- public function __construct($cacheModel=null)
- {
- $this->_cacheModel=$cacheModel;
- }
-
- /**
- *
- * @return string a KeyListID for the cache model.
- */
- protected function getKeyListId()
- {
- $id='keyList';
- if ($this->_cacheModel instanceof TSqlMapCacheModel)
- $id.='_'.$this->_cacheModel->getId();
- return $id;
- }
- /**
- * Retreive keylist from cache or create it if it doesn't exists
- * @return TList
- */
- protected function getKeyList()
- {
- if (($keyList=$this->getCache()->get($this->getKeyListId()))===false)
- {
- $keyList=new TList();
- $this->getCache()->set($this->getKeyListId(), $keyList);
- }
- return $keyList;
- }
-
- protected function setKeyList($keyList)
- {
- $this->getCache()->set($this->getKeyListId(), $keyList);
- }
-
- /**
- * @param string item to be deleted.
- */
- public function delete($key)
- {
- $keyList=$this->getKeyList();
- $keyList->remove($key);
- $this->getCache()->delete($key);
- $this->setKeyList($keyList);
- }
-
- /**
- * Deletes all items in the cache, only for data cached by sqlmap cachemodel
- */
- public function flush()
- {
- $keyList=$this->getKeyList();
- $cache=$this->getCache();
- foreach ($keyList as $key)
- {
- $cache->delete($key);
- }
- // Remove the old keylist
- $cache->delete($this->getKeyListId());
- }
-
- /**
- * @return mixed Gets a cached object with the specified key.
- */
- public function get($key)
- {
- $result = $this->getCache()->get($key);
- if ($result === false)
- {
- // if the key has not been found in cache (e.g expired), remove from keylist
- $keyList=$this->getKeyList();
- if ($keyList->contains($key))
- {
- $keyList->remove($key);
- $this->setKeyList($keyList);
- }
- }
- return $result === false ? null : $result;
- }
-
- /**
- * Stores a value identified by a key into cache.
- * @param string the key identifying the value to be cached
- * @param mixed the value to be cached
- */
- public function set($key, $value,$expire=0,$dependency=null)
- {
- $this->getCache()->set($key, $value, $expire,$dependency);
- $keyList=$this->getKeyList();
- if (!$keyList->contains($key))
- {
- $keyList->add($key);
- $this->setKeyList($keyList);
- }
- }
-
- /**
- * @return ICache Application cache instance.
- */
- protected function getCache()
- {
- return Prado::getApplication()->getCache();
- }
-
- /**
- * @throws TSqlMapException not implemented.
- */
- public function add($id,$value,$expire=0,$dependency=null)
- {
- throw new TSqlMapException('sqlmap_use_set_to_store_cache');
- }
-}
-
+<?php +/** + * TSqlMapCache class file contains FIFO, LRU, and GLOBAL cache implementations. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap + */ + +/** + * Allow different implementation of caching strategy. See <tt>TSqlMapFifoCache</tt> + * for a first-in-first-out implementation. See <tt>TSqlMapLruCache</tt> for + * a least-recently-used cache implementation. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +abstract class TSqlMapCache implements ICache +{ + protected $_keyList; + protected $_cache; + protected $_cacheSize = 100; + protected $_cacheModel = null; + + /** + * Create a new cache with limited cache size. + * @param TSqlMapCacheModel $cacheModel. + */ + public function __construct($cacheModel=null) + { + $this->_cache = new TMap; + $this->_keyList = new TList; + $this->_cacheModel=$cacheModel; + } + + /** + * Maximum number of items to cache. Default size is 100. + * @param int cache size. + */ + public function setCacheSize($value) + { + $this->_cacheSize=TPropertyValue::ensureInteger($value,100); + } + + /** + * @return int cache size. + */ + public function getCacheSize() + { + return $this->_cacheSize; + } + + /** + * @return object the object removed if exists, null otherwise. + */ + public function delete($key) + { + $object = $this->get($key); + $this->_cache->remove($key); + $this->_keyList->remove($key); + return $object; + } + + /** + * Clears the cache. + */ + public function flush() + { + $this->_keyList->clear(); + $this->_cache->clear(); + } + + /** + * @throws TSqlMapException not implemented. + */ + public function add($id,$value,$expire=0,$dependency=null) + { + throw new TSqlMapException('sqlmap_use_set_to_store_cache'); + } +} + +/** + * First-in-First-out cache implementation, removes + * object that was first added when the cache is full. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapFifoCache extends TSqlMapCache +{ + /** + * @return mixed Gets a cached object with the specified key. + */ + public function get($key) + { + return $this->_cache->itemAt($key); + } + + /** + * Stores a value identified by a key into cache. + * The expire and dependency parameters are ignored. + * @param string cache key + * @param mixed value to cache. + */ + public function set($key, $value,$expire=0,$dependency=null) + { + $this->_cache->add($key, $value); + $this->_keyList->add($key); + if($this->_keyList->getCount() > $this->_cacheSize) + { + $oldestKey = $this->_keyList->removeAt(0); + $this->_cache->remove($oldestKey); + } + } +} + +/** + * Least recently used cache implementation, removes + * object that was accessed last when the cache is full. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapLruCache extends TSqlMapCache +{ + /** + * @return mixed Gets a cached object with the specified key. + */ + public function get($key) + { + if($this->_keyList->contains($key)) + { + $this->_keyList->remove($key); + $this->_keyList->add($key); + return $this->_cache->itemAt($key); + } + } + + /** + * Stores a value identified by a key into cache. + * The expire and dependency parameters are ignored. + * @param string the key identifying the value to be cached + * @param mixed the value to be cached + */ + public function set($key, $value,$expire=0,$dependency=null) + { + $this->_cache->add($key, $value); + $this->_keyList->add($key); + if($this->_keyList->getCount() > $this->_cacheSize) + { + $oldestKey = $this->_keyList->removeAt(0); + $this->_cache->remove($oldestKey); + } + } +} + +/** + * TSqlMapApplicationCache uses the default Prado application cache for + * caching SqlMap results. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapApplicationCache implements ICache +{ + protected $_cacheModel=null; + + /** + * Create a new cache with limited cache size. + * @param TSqlMapCacheModel $cacheModel. + */ + public function __construct($cacheModel=null) + { + $this->_cacheModel=$cacheModel; + } + + /** + * + * @return string a KeyListID for the cache model. + */ + protected function getKeyListId() + { + $id='keyList'; + if ($this->_cacheModel instanceof TSqlMapCacheModel) + $id.='_'.$this->_cacheModel->getId(); + return $id; + } + /** + * Retreive keylist from cache or create it if it doesn't exists + * @return TList + */ + protected function getKeyList() + { + if (($keyList=$this->getCache()->get($this->getKeyListId()))===false) + { + $keyList=new TList(); + $this->getCache()->set($this->getKeyListId(), $keyList); + } + return $keyList; + } + + protected function setKeyList($keyList) + { + $this->getCache()->set($this->getKeyListId(), $keyList); + } + + /** + * @param string item to be deleted. + */ + public function delete($key) + { + $keyList=$this->getKeyList(); + $keyList->remove($key); + $this->getCache()->delete($key); + $this->setKeyList($keyList); + } + + /** + * Deletes all items in the cache, only for data cached by sqlmap cachemodel + */ + public function flush() + { + $keyList=$this->getKeyList(); + $cache=$this->getCache(); + foreach ($keyList as $key) + { + $cache->delete($key); + } + // Remove the old keylist + $cache->delete($this->getKeyListId()); + } + + /** + * @return mixed Gets a cached object with the specified key. + */ + public function get($key) + { + $result = $this->getCache()->get($key); + if ($result === false) + { + // if the key has not been found in cache (e.g expired), remove from keylist + $keyList=$this->getKeyList(); + if ($keyList->contains($key)) + { + $keyList->remove($key); + $this->setKeyList($keyList); + } + } + return $result === false ? null : $result; + } + + /** + * Stores a value identified by a key into cache. + * @param string the key identifying the value to be cached + * @param mixed the value to be cached + */ + public function set($key, $value,$expire=0,$dependency=null) + { + $this->getCache()->set($key, $value, $expire,$dependency); + $keyList=$this->getKeyList(); + if (!$keyList->contains($key)) + { + $keyList->add($key); + $this->setKeyList($keyList); + } + } + + /** + * @return ICache Application cache instance. + */ + protected function getCache() + { + return Prado::getApplication()->getCache(); + } + + /** + * @throws TSqlMapException not implemented. + */ + public function add($id,$value,$expire=0,$dependency=null) + { + throw new TSqlMapException('sqlmap_use_set_to_store_cache'); + } +} + diff --git a/framework/Data/SqlMap/DataMapper/TSqlMapException.php b/framework/Data/SqlMap/DataMapper/TSqlMapException.php index 0bf0ac32..694774d8 100644 --- a/framework/Data/SqlMap/DataMapper/TSqlMapException.php +++ b/framework/Data/SqlMap/DataMapper/TSqlMapException.php @@ -1,115 +1,115 @@ -<?php
-
-/**
- * TSqlMapException is the base exception class for all SqlMap exceptions.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapException extends TException
-{
- /**
- * Constructor, similar to the parent constructor. For parameters that
- * are of SimpleXmlElement, the tag name and its attribute names and values
- * are expanded into a string.
- */
- public function __construct($errorMessage)
- {
- $this->setErrorCode($errorMessage);
- $errorMessage=$this->translateErrorMessage($errorMessage);
- $args=func_get_args();
- array_shift($args);
- $n=count($args);
- $tokens=array();
- for($i=0;$i<$n;++$i)
- {
- if($args[$i] instanceof SimpleXmlElement)
- $tokens['{'.$i.'}']=$this->implodeNode($args[$i]);
- else
- $tokens['{'.$i.'}']=TPropertyValue::ensureString($args[$i]);
- }
- parent::__construct(strtr($errorMessage,$tokens));
- }
-
- /**
- * @param SimpleXmlElement node
- * @return string tag name and attribute names and values.
- */
- protected function implodeNode($node)
- {
- $attributes=array();
- foreach($node->attributes() as $k=>$v)
- $attributes[]=$k.'="'.(string)$v.'"';
- return '<'.$node->getName().' '.implode(' ',$attributes).'>';
- }
-
- /**
- * @return string path to the error message file
- */
- protected function getErrorMessageFile()
- {
- $lang=Prado::getPreferredLanguage();
- $dir=dirname(__FILE__);
- $msgFile=$dir.'/messages-'.$lang.'.txt';
- if(!is_file($msgFile))
- $msgFile=$dir.'/messages.txt';
- return $msgFile;
- }
-}
-
-/**
- * TSqlMapConfigurationException, raised during configuration file parsing.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapConfigurationException extends TSqlMapException
-{
-
-}
-
-/**
- * TSqlMapUndefinedException, raised when mapped statemented are undefined.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapUndefinedException extends TSqlMapException
-{
-
-}
-
-/**
- * TSqlMapDuplicateException, raised when a duplicate mapped statement is found.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapDuplicateException extends TSqlMapException
-{
-}
-
-/**
- * TInvalidPropertyException, raised when setting or getting an invalid property.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TInvalidPropertyException extends TSqlMapException
-{
-}
-
-class TSqlMapExecutionException extends TSqlMapException
-{
-}
-
+<?php + +/** + * TSqlMapException is the base exception class for all SqlMap exceptions. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapException extends TException +{ + /** + * Constructor, similar to the parent constructor. For parameters that + * are of SimpleXmlElement, the tag name and its attribute names and values + * are expanded into a string. + */ + public function __construct($errorMessage) + { + $this->setErrorCode($errorMessage); + $errorMessage=$this->translateErrorMessage($errorMessage); + $args=func_get_args(); + array_shift($args); + $n=count($args); + $tokens=array(); + for($i=0;$i<$n;++$i) + { + if($args[$i] instanceof SimpleXmlElement) + $tokens['{'.$i.'}']=$this->implodeNode($args[$i]); + else + $tokens['{'.$i.'}']=TPropertyValue::ensureString($args[$i]); + } + parent::__construct(strtr($errorMessage,$tokens)); + } + + /** + * @param SimpleXmlElement node + * @return string tag name and attribute names and values. + */ + protected function implodeNode($node) + { + $attributes=array(); + foreach($node->attributes() as $k=>$v) + $attributes[]=$k.'="'.(string)$v.'"'; + return '<'.$node->getName().' '.implode(' ',$attributes).'>'; + } + + /** + * @return string path to the error message file + */ + protected function getErrorMessageFile() + { + $lang=Prado::getPreferredLanguage(); + $dir=dirname(__FILE__); + $msgFile=$dir.'/messages-'.$lang.'.txt'; + if(!is_file($msgFile)) + $msgFile=$dir.'/messages.txt'; + return $msgFile; + } +} + +/** + * TSqlMapConfigurationException, raised during configuration file parsing. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapConfigurationException extends TSqlMapException +{ + +} + +/** + * TSqlMapUndefinedException, raised when mapped statemented are undefined. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapUndefinedException extends TSqlMapException +{ + +} + +/** + * TSqlMapDuplicateException, raised when a duplicate mapped statement is found. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapDuplicateException extends TSqlMapException +{ +} + +/** + * TInvalidPropertyException, raised when setting or getting an invalid property. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TInvalidPropertyException extends TSqlMapException +{ +} + +class TSqlMapExecutionException extends TSqlMapException +{ +} + diff --git a/framework/Data/SqlMap/DataMapper/TSqlMapPagedList.php b/framework/Data/SqlMap/DataMapper/TSqlMapPagedList.php index 7c6a8e87..57949561 100644 --- a/framework/Data/SqlMap/DataMapper/TSqlMapPagedList.php +++ b/framework/Data/SqlMap/DataMapper/TSqlMapPagedList.php @@ -1,208 +1,208 @@ -<?php
-/**
- * TSqlMapPagedList class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap
- */
-
-Prado::using('System.Collections.TPagedList');
-
-/**
- * TSqlMapPagedList implements a list with paging functionality that retrieves
- * data from a SqlMap statement.
- *
- * The maximum number of records fetched is 3 times the page size. It fetches
- * the current, the previous and the next page at a time. This allows the paged
- * list to determine if the page is a the begin, the middle or the end of the list.
- *
- * The paged list does not need to know about the total number of records.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapPagedList extends TPagedList
-{
- private $_statement;
- private $_parameter;
- private $_prevPageList;
- private $_nextPageList;
- private $_delegate=null;
-
- /**
- * Create a new SqlMap paged list.
- * @param IMappedStatement SqlMap statement.
- * @param mixed query parameters
- * @param int page size
- * @param mixed delegate for each data row retrieved.
- * @param int number of page to fetch on initialization
- */
- public function __construct(IMappedStatement $statement,$parameter, $pageSize, $delegate=null, $page=0)
- {
- parent::__construct();
- parent::setCustomPaging(true);
- $this->initialize($statement,$parameter, $pageSize, $page);
- $this->_delegate=$delegate;
- }
-
- /**
- * Initialize the paged list.
- * @param IMappedStatement SqlMap statement.
- * @param mixed query parameters
- * @param int page size.
- * @param int number of page.
- */
- protected function initialize($statement, $parameter, $pageSize, $page)
- {
- $this->_statement = $statement;
- $this->_parameter = $parameter;
- $this->setPageSize($pageSize);
- $this->attachEventHandler('OnFetchData', array($this, 'fetchDataFromStatement'));
- $this->gotoPage($page);
- }
-
- /**
- * @throws TSqlMapException custom paging must be enabled.
- */
- public function setCustomPaging($value)
- {
- throw new TSqlMapException('sqlmap_must_enable_custom_paging');
- }
-
- /**
- * Fetch data by executing the SqlMap statement.
- * @param TPageList current object.
- * @param TPagedListFetchDataEventParameter fetch parameters
- */
- protected function fetchDataFromStatement($sender, $param)
- {
- $limit = $this->getOffsetAndLimit($param);
- $connection = $this->_statement->getManager()->getDbConnection();
- $data = $this->_statement->executeQueryForList($connection,
- $this->_parameter, null, $limit[0], $limit[1], $this->_delegate);
- $this->populateData($param, $data);
- }
-
- /**
- * Switches to the next page.
- * @return integer|boolean the new page index, false if next page is not availabe.
- */
- public function nextPage()
- {
- return $this->getIsNextPageAvailable() ? parent::nextPage() : false;
- }
-
- /**
- * Switches to the previous page.
- * @return integer|boolean the new page index, false if previous page is not availabe.
- */
- public function previousPage()
- {
- return $this->getIsPreviousPageAvailable() ? parent::previousPage() : false;
- }
-
- /**
- * Populate the list with the fetched data.
- * @param TPagedListFetchDataEventParameter fetch parameters
- * @param array fetched data.
- */
- protected function populateData($param, $data)
- {
- $total = $data instanceof TList ? $data->getCount() : count($data);
- $pageSize = $this->getPageSize();
- if($total < 1)
- {
- $param->setData($data);
- $this->_prevPageList = null;
- $this->_nextPageList = null;
- return;
- }
-
- if($param->getNewPageIndex() < 1)
- {
- $this->_prevPageList = null;
- if($total <= $pageSize)
- {
- $param->setData($data);
- $this->_nextPageList = null;
- }
- else
- {
- $param->setData(array_slice($data, 0, $pageSize));
- $this->_nextPageList = array_slice($data, $pageSize-1,$total);
- }
- }
- else
- {
- if($total <= $pageSize)
- {
- $this->_prevPageList = array_slice($data, 0, $total);
- $param->setData(array());
- $this->_nextPageList = null;
- }
- else if($total <= $pageSize*2)
- {
- $this->_prevPageList = array_slice($data, 0, $pageSize);
- $param->setData(array_slice($data, $pageSize, $total));
- $this->_nextPageList = null;
- }
- else
- {
- $this->_prevPageList = array_slice($data, 0, $pageSize);
- $param->setData(array_slice($data, $pageSize, $pageSize));
- $this->_nextPageList = array_slice($data, $pageSize*2, $total-$pageSize*2);
- }
- }
- }
-
- /**
- * Calculate the data fetch offsets and limits.
- * @param TPagedListFetchDataEventParameter fetch parameters
- * @return array 1st element is the offset, 2nd element is the limit.
- */
- protected function getOffsetAndLimit($param)
- {
- $index = $param->getNewPageIndex();
- $pageSize = $this->getPageSize();
- return $index < 1 ? array($index, $pageSize*2) : array(($index-1)*$pageSize, $pageSize*3);
- }
-
- /**
- * @return boolean true if the next page is available, false otherwise.
- */
- public function getIsNextPageAvailable()
- {
- return $this->_nextPageList!==null;
- }
-
- /**
- * @return boolean true if the previous page is available, false otherwise.
- */
- public function getIsPreviousPageAvailable()
- {
- return $this->_prevPageList!==null;
- }
-
- /**
- * @return boolean true if is the very last page, false otherwise.
- */
- public function getIsLastPage()
- {
- return ($this->_nextPageList===null) || $this->_nextPageList->getCount() < 1;
- }
-
- /**
- * @return boolean true if is not first nor last page, false otherwise.
- */
- public function getIsMiddlePage()
- {
- return !($this->getIsFirstPage() || $this->getIsLastPage());
- }
-}
-
+<?php +/** + * TSqlMapPagedList class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap + */ + +Prado::using('System.Collections.TPagedList'); + +/** + * TSqlMapPagedList implements a list with paging functionality that retrieves + * data from a SqlMap statement. + * + * The maximum number of records fetched is 3 times the page size. It fetches + * the current, the previous and the next page at a time. This allows the paged + * list to determine if the page is a the begin, the middle or the end of the list. + * + * The paged list does not need to know about the total number of records. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapPagedList extends TPagedList +{ + private $_statement; + private $_parameter; + private $_prevPageList; + private $_nextPageList; + private $_delegate=null; + + /** + * Create a new SqlMap paged list. + * @param IMappedStatement SqlMap statement. + * @param mixed query parameters + * @param int page size + * @param mixed delegate for each data row retrieved. + * @param int number of page to fetch on initialization + */ + public function __construct(IMappedStatement $statement,$parameter, $pageSize, $delegate=null, $page=0) + { + parent::__construct(); + parent::setCustomPaging(true); + $this->initialize($statement,$parameter, $pageSize, $page); + $this->_delegate=$delegate; + } + + /** + * Initialize the paged list. + * @param IMappedStatement SqlMap statement. + * @param mixed query parameters + * @param int page size. + * @param int number of page. + */ + protected function initialize($statement, $parameter, $pageSize, $page) + { + $this->_statement = $statement; + $this->_parameter = $parameter; + $this->setPageSize($pageSize); + $this->attachEventHandler('OnFetchData', array($this, 'fetchDataFromStatement')); + $this->gotoPage($page); + } + + /** + * @throws TSqlMapException custom paging must be enabled. + */ + public function setCustomPaging($value) + { + throw new TSqlMapException('sqlmap_must_enable_custom_paging'); + } + + /** + * Fetch data by executing the SqlMap statement. + * @param TPageList current object. + * @param TPagedListFetchDataEventParameter fetch parameters + */ + protected function fetchDataFromStatement($sender, $param) + { + $limit = $this->getOffsetAndLimit($param); + $connection = $this->_statement->getManager()->getDbConnection(); + $data = $this->_statement->executeQueryForList($connection, + $this->_parameter, null, $limit[0], $limit[1], $this->_delegate); + $this->populateData($param, $data); + } + + /** + * Switches to the next page. + * @return integer|boolean the new page index, false if next page is not availabe. + */ + public function nextPage() + { + return $this->getIsNextPageAvailable() ? parent::nextPage() : false; + } + + /** + * Switches to the previous page. + * @return integer|boolean the new page index, false if previous page is not availabe. + */ + public function previousPage() + { + return $this->getIsPreviousPageAvailable() ? parent::previousPage() : false; + } + + /** + * Populate the list with the fetched data. + * @param TPagedListFetchDataEventParameter fetch parameters + * @param array fetched data. + */ + protected function populateData($param, $data) + { + $total = $data instanceof TList ? $data->getCount() : count($data); + $pageSize = $this->getPageSize(); + if($total < 1) + { + $param->setData($data); + $this->_prevPageList = null; + $this->_nextPageList = null; + return; + } + + if($param->getNewPageIndex() < 1) + { + $this->_prevPageList = null; + if($total <= $pageSize) + { + $param->setData($data); + $this->_nextPageList = null; + } + else + { + $param->setData(array_slice($data, 0, $pageSize)); + $this->_nextPageList = array_slice($data, $pageSize-1,$total); + } + } + else + { + if($total <= $pageSize) + { + $this->_prevPageList = array_slice($data, 0, $total); + $param->setData(array()); + $this->_nextPageList = null; + } + else if($total <= $pageSize*2) + { + $this->_prevPageList = array_slice($data, 0, $pageSize); + $param->setData(array_slice($data, $pageSize, $total)); + $this->_nextPageList = null; + } + else + { + $this->_prevPageList = array_slice($data, 0, $pageSize); + $param->setData(array_slice($data, $pageSize, $pageSize)); + $this->_nextPageList = array_slice($data, $pageSize*2, $total-$pageSize*2); + } + } + } + + /** + * Calculate the data fetch offsets and limits. + * @param TPagedListFetchDataEventParameter fetch parameters + * @return array 1st element is the offset, 2nd element is the limit. + */ + protected function getOffsetAndLimit($param) + { + $index = $param->getNewPageIndex(); + $pageSize = $this->getPageSize(); + return $index < 1 ? array($index, $pageSize*2) : array(($index-1)*$pageSize, $pageSize*3); + } + + /** + * @return boolean true if the next page is available, false otherwise. + */ + public function getIsNextPageAvailable() + { + return $this->_nextPageList!==null; + } + + /** + * @return boolean true if the previous page is available, false otherwise. + */ + public function getIsPreviousPageAvailable() + { + return $this->_prevPageList!==null; + } + + /** + * @return boolean true if is the very last page, false otherwise. + */ + public function getIsLastPage() + { + return ($this->_nextPageList===null) || $this->_nextPageList->getCount() < 1; + } + + /** + * @return boolean true if is not first nor last page, false otherwise. + */ + public function getIsMiddlePage() + { + return !($this->getIsFirstPage() || $this->getIsLastPage()); + } +} + diff --git a/framework/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php b/framework/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php index 7a54e347..61c97245 100644 --- a/framework/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php +++ b/framework/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php @@ -1,192 +1,192 @@ -<?php
-/**
- * TSqlMapTypeHandlerRegistry, and abstract TSqlMapTypeHandler classes file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TSqlMapTypeHandlerRegistry, and abstract TSqlMapTypeHandler classes file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap
- */
-
-/**
- * TTypeHandlerFactory provides type handler classes to convert database field type
- * to PHP types and vice versa.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapTypeHandlerRegistry
-{
- private $_typeHandlers=array();
-
- /**
- * @param string database field type
- * @return TSqlMapTypeHandler type handler for give database field type.
- */
- public function getDbTypeHandler($dbType='NULL')
- {
- foreach($this->_typeHandlers as $handler)
- if($handler->getDbType()===$dbType)
- return $handler;
- }
-
- /**
- * @param string type handler class name
- * @return TSqlMapTypeHandler type handler
- */
- public function getTypeHandler($class)
- {
- if(isset($this->_typeHandlers[$class]))
- return $this->_typeHandlers[$class];
- }
-
- /**
- * @param TSqlMapTypeHandler registers a new type handler
- */
- public function registerTypeHandler(TSqlMapTypeHandler $handler)
- {
- $this->_typeHandlers[$handler->getType()] = $handler;
- }
-
- /**
- * Creates a new instance of a particular class (for PHP primative types,
- * their corresponding default value for given type is used).
- * @param string PHP type name
- * @return mixed default type value, if no type is specified null is returned.
- * @throws TSqlMapException if class name is not found.
- */
- public function createInstanceOf($type='')
- {
- if(strlen($type) > 0)
- {
- switch(strtolower($type))
- {
- case 'string': return '';
- case 'array': return array();
- case 'float': case 'double': case 'decimal': return 0.0;
- case 'integer': case 'int': return 0;
- case 'bool': case 'boolean': return false;
- }
-
- if(class_exists('Prado', false))
- return Prado::createComponent($type);
- else if(class_exists($type, false)) //NO auto loading
- return new $type;
- else
- throw new TSqlMapException('sqlmap_unable_to_find_class', $type);
- }
- }
-
- /**
- * Converts the value to given type using PHP's settype() function.
- * @param string PHP primative type.
- * @param mixed value to be casted
- * @return mixed type casted value.
- */
- public function convertToType($type, $value)
- {
- switch(strtolower($type))
- {
- case 'integer': case 'int':
- $type = 'integer'; break;
- case 'float': case 'double': case 'decimal':
- $type = 'float'; break;
- case 'boolean': case 'bool':
- $type = 'boolean'; break;
- case 'string' :
- $type = 'string'; break;
- default:
- return $value;
- }
- settype($value, $type);
- return $value;
- }
-}
-
-/**
- * A simple interface for implementing custom type handlers.
- *
- * Using this interface, you can implement a type handler that
- * will perform customized processing before parameters are set
- * on and after values are retrieved from the database.
- * Using a custom type handler you can extend
- * the framework to handle types that are not supported, or
- * handle supported types in a different way. For example,
- * you might use a custom type handler to implement proprietary
- * BLOB support (e.g. Oracle), or you might use it to handle
- * booleans using "Y" and "N" instead of the more typical 0/1.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-abstract class TSqlMapTypeHandler extends TComponent
-{
- private $_dbType='NULL';
- private $_type;
- /**
- * @param string database field type.
- */
- public function setDbType($value)
- {
- $this->_dbType=$value;
- }
-
- /**
- * @return string database field type.
- */
- public function getDbType()
- {
- return $this->_dbType;
- }
-
- public function getType()
- {
- if($this->_type===null)
- return get_class($this);
- else
- return $this->_type;
- }
-
- public function setType($value)
- {
- $this->_type=$value;
- }
-
- /**
- * Performs processing on a value before it is used to set
- * the parameter of a IDbCommand.
- * @param object The interface for setting the value.
- * @param object The value to be set.
- */
- public abstract function getParameter($object);
-
-
- /**
- * Performs processing on a value before after it has been retrieved
- * from a database
- * @param object The interface for getting the value.
- * @return mixed The processed value.
- */
- public abstract function getResult($string);
-
-
- /**
- * Casts the string representation of a value into a type recognized by
- * this type handler. This method is used to translate nullValue values
- * into types that can be appropriately compared. If your custom type handler
- * cannot support nullValues, or if there is no reasonable string representation
- * for this type (e.g. File type), you can simply return the String representation
- * as it was passed in. It is not recommended to return null, unless null was passed
- * in.
- * @param array result row.
- * @return mixed
- */
- public abstract function createNewInstance($row=null);
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap + */ + +/** + * TTypeHandlerFactory provides type handler classes to convert database field type + * to PHP types and vice versa. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapTypeHandlerRegistry +{ + private $_typeHandlers=array(); + + /** + * @param string database field type + * @return TSqlMapTypeHandler type handler for give database field type. + */ + public function getDbTypeHandler($dbType='NULL') + { + foreach($this->_typeHandlers as $handler) + if($handler->getDbType()===$dbType) + return $handler; + } + + /** + * @param string type handler class name + * @return TSqlMapTypeHandler type handler + */ + public function getTypeHandler($class) + { + if(isset($this->_typeHandlers[$class])) + return $this->_typeHandlers[$class]; + } + + /** + * @param TSqlMapTypeHandler registers a new type handler + */ + public function registerTypeHandler(TSqlMapTypeHandler $handler) + { + $this->_typeHandlers[$handler->getType()] = $handler; + } + + /** + * Creates a new instance of a particular class (for PHP primative types, + * their corresponding default value for given type is used). + * @param string PHP type name + * @return mixed default type value, if no type is specified null is returned. + * @throws TSqlMapException if class name is not found. + */ + public function createInstanceOf($type='') + { + if(strlen($type) > 0) + { + switch(strtolower($type)) + { + case 'string': return ''; + case 'array': return array(); + case 'float': case 'double': case 'decimal': return 0.0; + case 'integer': case 'int': return 0; + case 'bool': case 'boolean': return false; + } + + if(class_exists('Prado', false)) + return Prado::createComponent($type); + else if(class_exists($type, false)) //NO auto loading + return new $type; + else + throw new TSqlMapException('sqlmap_unable_to_find_class', $type); + } + } + + /** + * Converts the value to given type using PHP's settype() function. + * @param string PHP primative type. + * @param mixed value to be casted + * @return mixed type casted value. + */ + public function convertToType($type, $value) + { + switch(strtolower($type)) + { + case 'integer': case 'int': + $type = 'integer'; break; + case 'float': case 'double': case 'decimal': + $type = 'float'; break; + case 'boolean': case 'bool': + $type = 'boolean'; break; + case 'string' : + $type = 'string'; break; + default: + return $value; + } + settype($value, $type); + return $value; + } +} + +/** + * A simple interface for implementing custom type handlers. + * + * Using this interface, you can implement a type handler that + * will perform customized processing before parameters are set + * on and after values are retrieved from the database. + * Using a custom type handler you can extend + * the framework to handle types that are not supported, or + * handle supported types in a different way. For example, + * you might use a custom type handler to implement proprietary + * BLOB support (e.g. Oracle), or you might use it to handle + * booleans using "Y" and "N" instead of the more typical 0/1. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +abstract class TSqlMapTypeHandler extends TComponent +{ + private $_dbType='NULL'; + private $_type; + /** + * @param string database field type. + */ + public function setDbType($value) + { + $this->_dbType=$value; + } + + /** + * @return string database field type. + */ + public function getDbType() + { + return $this->_dbType; + } + + public function getType() + { + if($this->_type===null) + return get_class($this); + else + return $this->_type; + } + + public function setType($value) + { + $this->_type=$value; + } + + /** + * Performs processing on a value before it is used to set + * the parameter of a IDbCommand. + * @param object The interface for setting the value. + * @param object The value to be set. + */ + public abstract function getParameter($object); + + + /** + * Performs processing on a value before after it has been retrieved + * from a database + * @param object The interface for getting the value. + * @return mixed The processed value. + */ + public abstract function getResult($string); + + + /** + * Casts the string representation of a value into a type recognized by + * this type handler. This method is used to translate nullValue values + * into types that can be appropriately compared. If your custom type handler + * cannot support nullValues, or if there is no reasonable string representation + * for this type (e.g. File type), you can simply return the String representation + * as it was passed in. It is not recommended to return null, unless null was passed + * in. + * @param array result row. + * @return mixed + */ + public abstract function createNewInstance($row=null); +} + diff --git a/framework/Data/SqlMap/Statements/IMappedStatement.php b/framework/Data/SqlMap/Statements/IMappedStatement.php index dc628c9e..15f61fad 100644 --- a/framework/Data/SqlMap/Statements/IMappedStatement.php +++ b/framework/Data/SqlMap/Statements/IMappedStatement.php @@ -1,82 +1,82 @@ -<?php
-/**
- * IMappedStatement interface file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-/**
- * Interface for all mapping statements.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-interface IMappedStatement
-{
- /**
- * @return string Name used to identify the MappedStatement amongst the others.
- */
- public function getID();
-
- /**
- * @return TSqlMapStatement The SQL statment used by this TMappedStatement.
- */
- public function getStatement();
-
- /**
- * @return TSqlMap The TSqlMap used by this TMappedStatement
- */
- public function getManager();
-
- /**
- * Executes the SQL and retuns all rows selected in a map that is keyed on
- * the property named in the <tt>$keyProperty</tt> parameter. The value at
- * each key will be the value of the property specified in the
- * <tt>$valueProperty</tt> parameter. If <tt>$valueProperty</tt> is
- * <tt>null</tt>, the entire result object will be entered.
- * @param IDbConnection database connection to execute the query
- * @param mixed The object used to set the parameters in the SQL.
- * @param string The property of the result object to be used as the key.
- * @param string The property of the result object to be used as the value (or null)
- * @return TMap A map of object containing the rows keyed by <tt>$keyProperty</tt>.
- */
- public function executeQueryForMap($connection, $parameter, $keyProperty, $valueProperty=null);
-
-
- /**
- * Execute an update statement. Also used for delete statement. Return the
- * number of row effected.
- * @param IDbConnection database connection to execute the query
- * @param mixed The object used to set the parameters in the SQL.
- * @return integer The number of row effected.
- */
- public function executeUpdate($connection, $parameter);
-
-
- /**
- * Executes the SQL and retuns a subset of the rows selected.
- * @param IDbConnection database connection to execute the query
- * @param mixed The object used to set the parameters in the SQL.
- * @param TList A list to populate the result with.
- * @param integer The number of rows to skip over.
- * @param integer The maximum number of rows to return.
- * @return TList A TList of result objects.
- */
- public function executeQueryForList($connection, $parameter, $result=null, $skip=-1, $max=-1);
-
-
- /**
- * Executes an SQL statement that returns a single row as an object
- * of the type of the <tt>$result</tt> passed in as a parameter.
- * @param IDbConnection database connection to execute the query
- * @param mixed The object used to set the parameters in the SQL.
- * @param object The result object.
- * @return object result.
- */
- public function executeQueryForObject($connection,$parameter, $result=null);
-}
-
+<?php +/** + * IMappedStatement interface file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +/** + * Interface for all mapping statements. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +interface IMappedStatement +{ + /** + * @return string Name used to identify the MappedStatement amongst the others. + */ + public function getID(); + + /** + * @return TSqlMapStatement The SQL statment used by this TMappedStatement. + */ + public function getStatement(); + + /** + * @return TSqlMap The TSqlMap used by this TMappedStatement + */ + public function getManager(); + + /** + * Executes the SQL and retuns all rows selected in a map that is keyed on + * the property named in the <tt>$keyProperty</tt> parameter. The value at + * each key will be the value of the property specified in the + * <tt>$valueProperty</tt> parameter. If <tt>$valueProperty</tt> is + * <tt>null</tt>, the entire result object will be entered. + * @param IDbConnection database connection to execute the query + * @param mixed The object used to set the parameters in the SQL. + * @param string The property of the result object to be used as the key. + * @param string The property of the result object to be used as the value (or null) + * @return TMap A map of object containing the rows keyed by <tt>$keyProperty</tt>. + */ + public function executeQueryForMap($connection, $parameter, $keyProperty, $valueProperty=null); + + + /** + * Execute an update statement. Also used for delete statement. Return the + * number of row effected. + * @param IDbConnection database connection to execute the query + * @param mixed The object used to set the parameters in the SQL. + * @return integer The number of row effected. + */ + public function executeUpdate($connection, $parameter); + + + /** + * Executes the SQL and retuns a subset of the rows selected. + * @param IDbConnection database connection to execute the query + * @param mixed The object used to set the parameters in the SQL. + * @param TList A list to populate the result with. + * @param integer The number of rows to skip over. + * @param integer The maximum number of rows to return. + * @return TList A TList of result objects. + */ + public function executeQueryForList($connection, $parameter, $result=null, $skip=-1, $max=-1); + + + /** + * Executes an SQL statement that returns a single row as an object + * of the type of the <tt>$result</tt> passed in as a parameter. + * @param IDbConnection database connection to execute the query + * @param mixed The object used to set the parameters in the SQL. + * @param object The result object. + * @return object result. + */ + public function executeQueryForObject($connection,$parameter, $result=null); +} + diff --git a/framework/Data/SqlMap/Statements/TCachingStatement.php b/framework/Data/SqlMap/Statements/TCachingStatement.php index 54664e37..cac84458 100644 --- a/framework/Data/SqlMap/Statements/TCachingStatement.php +++ b/framework/Data/SqlMap/Statements/TCachingStatement.php @@ -1,108 +1,108 @@ -<?php
-/**
- * TCachingStatement class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-/**
- * TCacheingStatement class.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TCachingStatement extends TComponent implements IMappedStatement
-{
- private $_mappedStatement;
-
- public function __construct(TMappedStatement $statement)
- {
- $this->_mappedStatement = $statement;
- }
-
- public function getID()
- {
- return $this->_mappedStatement->getID();
- }
-
- public function getStatement()
- {
- return $this->_mappedStatement->getStatement();
- }
-
- public function getManager()
- {
- return $this->_mappedStatement->getManager();
- }
-
- public function executeQueryForMap($connection, $parameter,$keyProperty, $valueProperty=null, $skip=-1, $max=-1,$delegate=null)
- {
- $sql = $this->createCommand($connection, $parameter, $skip, $max);
- $key = $this->getCacheKey(array(clone($sql), $keyProperty, $valueProperty,$skip, $max));
- $map = $this->getStatement()->getCache()->get($key);
- if($map===null)
- {
- $map = $this->_mappedStatement->runQueryForMap(
- $connection, $parameter, $sql, $keyProperty, $valueProperty, $delegate);
- $this->getStatement()->getCache()->set($key, $map);
- }
- return $map;
- }
-
- public function executeUpdate($connection, $parameter)
- {
- return $this->_mappedStatement->executeUpdate($connection, $parameter);
- }
-
- public function executeInsert($connection, $parameter)
- {
- return $this->executeInsert($connection, $parameter);
- }
-
- public function executeQueryForList($connection, $parameter, $result=null, $skip=-1, $max=-1, $delegate=null)
- {
- $sql = $this->createCommand($connection, $parameter, $skip, $max);
- $key = $this->getCacheKey(array(clone($sql), $parameter, $skip, $max));
- $list = $this->getStatement()->getCache()->get($key);
- if($list===null)
- {
- $list = $this->_mappedStatement->runQueryForList(
- $connection, $parameter, $sql, $result, $delegate);
- $this->getStatement()->getCache()->set($key, $list);
- }
- return $list;
- }
-
- public function executeQueryForObject($connection, $parameter, $result=null)
- {
- $sql = $this->createCommand($connection, $parameter);
- $key = $this->getCacheKey(array(clone($sql), $parameter));
- $object = $this->getStatement()->getCache()->get($key);
- if($object===null)
- {
- $object = $this->_mappedStatement->runQueryForObject($connection, $sql, $result);
- $this->getStatement()->getCache()->set($key, $object);
- }
- return $object;
- }
-
- protected function getCacheKey($object)
- {
- $cacheKey = new TSqlMapCacheKey($object);
- return $cacheKey->getHash();
- }
-
- protected function createCommand($connection, $parameter, $skip=null, $max=null)
- {
- return $this->_mappedStatement->getCommand()->create($this->getManager(),
- $connection, $this->getStatement(), $parameter, $skip, $max);
- }
-}
-
+<?php +/** + * TCachingStatement class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +/** + * TCacheingStatement class. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TCachingStatement extends TComponent implements IMappedStatement +{ + private $_mappedStatement; + + public function __construct(TMappedStatement $statement) + { + $this->_mappedStatement = $statement; + } + + public function getID() + { + return $this->_mappedStatement->getID(); + } + + public function getStatement() + { + return $this->_mappedStatement->getStatement(); + } + + public function getManager() + { + return $this->_mappedStatement->getManager(); + } + + public function executeQueryForMap($connection, $parameter,$keyProperty, $valueProperty=null, $skip=-1, $max=-1,$delegate=null) + { + $sql = $this->createCommand($connection, $parameter, $skip, $max); + $key = $this->getCacheKey(array(clone($sql), $keyProperty, $valueProperty,$skip, $max)); + $map = $this->getStatement()->getCache()->get($key); + if($map===null) + { + $map = $this->_mappedStatement->runQueryForMap( + $connection, $parameter, $sql, $keyProperty, $valueProperty, $delegate); + $this->getStatement()->getCache()->set($key, $map); + } + return $map; + } + + public function executeUpdate($connection, $parameter) + { + return $this->_mappedStatement->executeUpdate($connection, $parameter); + } + + public function executeInsert($connection, $parameter) + { + return $this->executeInsert($connection, $parameter); + } + + public function executeQueryForList($connection, $parameter, $result=null, $skip=-1, $max=-1, $delegate=null) + { + $sql = $this->createCommand($connection, $parameter, $skip, $max); + $key = $this->getCacheKey(array(clone($sql), $parameter, $skip, $max)); + $list = $this->getStatement()->getCache()->get($key); + if($list===null) + { + $list = $this->_mappedStatement->runQueryForList( + $connection, $parameter, $sql, $result, $delegate); + $this->getStatement()->getCache()->set($key, $list); + } + return $list; + } + + public function executeQueryForObject($connection, $parameter, $result=null) + { + $sql = $this->createCommand($connection, $parameter); + $key = $this->getCacheKey(array(clone($sql), $parameter)); + $object = $this->getStatement()->getCache()->get($key); + if($object===null) + { + $object = $this->_mappedStatement->runQueryForObject($connection, $sql, $result); + $this->getStatement()->getCache()->set($key, $object); + } + return $object; + } + + protected function getCacheKey($object) + { + $cacheKey = new TSqlMapCacheKey($object); + return $cacheKey->getHash(); + } + + protected function createCommand($connection, $parameter, $skip=null, $max=null) + { + return $this->_mappedStatement->getCommand()->create($this->getManager(), + $connection, $this->getStatement(), $parameter, $skip, $max); + } +} + diff --git a/framework/Data/SqlMap/Statements/TDeleteMappedStatement.php b/framework/Data/SqlMap/Statements/TDeleteMappedStatement.php index a3cbaadb..562720ed 100644 --- a/framework/Data/SqlMap/Statements/TDeleteMappedStatement.php +++ b/framework/Data/SqlMap/Statements/TDeleteMappedStatement.php @@ -1,24 +1,24 @@ -<?php
-/**
- * TDeleteMappedStatement class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TDeleteMappedStatement class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-/**
- * TDeleteMappedStatement class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TDeleteMappedStatement extends TUpdateMappedStatement
-{
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +/** + * TDeleteMappedStatement class. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TDeleteMappedStatement extends TUpdateMappedStatement +{ +} + diff --git a/framework/Data/SqlMap/Statements/TInsertMappedStatement.php b/framework/Data/SqlMap/Statements/TInsertMappedStatement.php index c7cd6ff6..e91ca3aa 100644 --- a/framework/Data/SqlMap/Statements/TInsertMappedStatement.php +++ b/framework/Data/SqlMap/Statements/TInsertMappedStatement.php @@ -1,49 +1,49 @@ -<?php
-/**
- * TInsertMappedStatement class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TInsertMappedStatement class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-/**
- * TInsertMappedStatement class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TInsertMappedStatement extends TMappedStatement
-{
- public function executeQueryForMap($connection, $parameter,
- $keyProperty, $valueProperty=null)
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_cannot_execute_query_for_map', get_class($this), $this->getID());
- }
-
- public function executeUpdate($connection, $parameter)
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_cannot_execute_update', get_class($this), $this->getID());
- }
-
- public function executeQueryForList($connection, $parameter, $result=null,
- $skip=-1, $max=-1)
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_cannot_execute_query_for_list', get_class($this), $this->getID());
- }
-
- public function executeQueryForObject($connection, $parameter, $result=null)
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_cannot_execute_query_for_object', get_class($this), $this->getID());
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +/** + * TInsertMappedStatement class. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TInsertMappedStatement extends TMappedStatement +{ + public function executeQueryForMap($connection, $parameter, + $keyProperty, $valueProperty=null) + { + throw new TSqlMapExecutionException( + 'sqlmap_cannot_execute_query_for_map', get_class($this), $this->getID()); + } + + public function executeUpdate($connection, $parameter) + { + throw new TSqlMapExecutionException( + 'sqlmap_cannot_execute_update', get_class($this), $this->getID()); + } + + public function executeQueryForList($connection, $parameter, $result=null, + $skip=-1, $max=-1) + { + throw new TSqlMapExecutionException( + 'sqlmap_cannot_execute_query_for_list', get_class($this), $this->getID()); + } + + public function executeQueryForObject($connection, $parameter, $result=null) + { + throw new TSqlMapExecutionException( + 'sqlmap_cannot_execute_query_for_object', get_class($this), $this->getID()); + } +} + diff --git a/framework/Data/SqlMap/Statements/TMappedStatement.php b/framework/Data/SqlMap/Statements/TMappedStatement.php index 0dbc8def..ee54df95 100644 --- a/framework/Data/SqlMap/Statements/TMappedStatement.php +++ b/framework/Data/SqlMap/Statements/TMappedStatement.php @@ -1,1242 +1,1242 @@ -<?php
-/**
- * TMappedStatement and related classes.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-/**
- * TMappedStatement class executes SQL mapped statements. Mapped Statements can
- * hold any SQL statement and use Parameter Maps and Result Maps for input and output.
- *
- * This class is usualy instantiated during SQLMap configuration by TSqlDomBuilder.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.0
- */
-class TMappedStatement extends TComponent implements IMappedStatement
-{
- /**
- * @var TSqlMapStatement current SQL statement.
- */
- private $_statement;
-
- /**
- * @var TPreparedCommand SQL command prepareer
- */
- private $_command;
-
- /**
- * @var TSqlMapper sqlmap used by this mapper.
- */
- private $_manager;
-
- /**
- * @var TPostSelectBinding[] post select statement queue.
- */
- private $_selectQueue=array();
-
- /**
- * @var boolean true when data is mapped to a particular row.
- */
- private $_IsRowDataFound = false;
-
- /**
- * @var TSQLMapObjectCollectionTree group by object collection tree
- */
- private $_groupBy;
-
- /**
- * @var Post select is to query for list.
- */
- const QUERY_FOR_LIST = 0;
-
- /**
- * @var Post select is to query for list.
- */
- const QUERY_FOR_ARRAY = 1;
-
- /**
- * @var Post select is to query for object.
- */
- const QUERY_FOR_OBJECT = 2;
-
- /**
- * @return string Name used to identify the TMappedStatement amongst the others.
- * This the name of the SQL statement by default.
- */
- public function getID()
- {
- return $this->_statement->ID;
- }
-
- /**
- * @return TSqlMapStatement The SQL statment used by this MappedStatement
- */
- public function getStatement()
- {
- return $this->_statement;
- }
-
- /**
- * @return TSqlMapper The SqlMap used by this MappedStatement
- */
- public function getManager()
- {
- return $this->_manager;
- }
-
- /**
- * @return TPreparedCommand command to prepare SQL statements.
- */
- public function getCommand()
- {
- return $this->_command;
- }
-
- /**
- * Empty the group by results cache.
- */
- protected function initialGroupByResults()
- {
- $this->_groupBy = new TSqlMapObjectCollectionTree();
- }
-
- /**
- * Creates a new mapped statement.
- * @param TSqlMapper an sqlmap.
- * @param TSqlMapStatement An SQL statement.
- */
- public function __construct(TSqlMapManager $sqlMap, TSqlMapStatement $statement)
- {
- $this->_manager = $sqlMap;
- $this->_statement = $statement;
- $this->_command = new TPreparedCommand();
- $this->initialGroupByResults();
- }
-
- public function getSqlString()
- {
- return $this->getStatement()->getSqlText()->getPreparedStatement()->getPreparedSql();
- }
-
- /**
- * Execute SQL Query.
- * @param IDbConnection database connection
- * @param array SQL statement and parameters.
- * @return mixed record set if applicable.
- * @throws TSqlMapExecutionException if execution error or false record set.
- * @throws TSqlMapQueryExecutionException if any execution error
- */
-/* protected function executeSQLQuery($connection, $sql)
- {
- try
- {
- if(!($recordSet = $connection->execute($sql['sql'],$sql['parameters'])))
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_execution_error_no_record', $this->getID(),
- $connection->ErrorMsg());
- }
- return $recordSet;
- }
- catch (Exception $e)
- {
- throw new TSqlMapQueryExecutionException($this->getStatement(), $e);
- }
- }*/
-
- /**
- * Execute SQL Query with limits.
- * @param IDbConnection database connection
- * @param array SQL statement and parameters.
- * @return mixed record set if applicable.
- * @throws TSqlMapExecutionException if execution error or false record set.
- * @throws TSqlMapQueryExecutionException if any execution error
- */
- protected function executeSQLQueryLimit($connection, $command, $max, $skip)
- {
- if($max>-1 || $skip > -1)
- {
- $maxStr=$max>0?' LIMIT '.$max:'';
- $skipStr=$skip>0?' OFFSET '.$skip:'';
- $command->setText($command->getText().$maxStr.$skipStr);
- }
- $connection->setActive(true);
- return $command->query();
-
- /*//var_dump($command);
- try
- {
- $recordSet = $connection->selectLimit($sql['sql'],$max,$skip,$sql['parameters']);
- if(!$recordSet)
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_execution_error_query_for_list',
- $connection->ErrorMsg());
- }
- return $recordSet;
- }
- catch (Exception $e)
- {
- throw new TSqlMapQueryExecutionException($this->getStatement(), $e);
- }*/
- }
-
- /**
- * Executes the SQL and retuns a List of result objects.
- * @param IDbConnection database connection
- * @param mixed The object used to set the parameters in the SQL.
- * @param object result collection object.
- * @param integer The number of rows to skip over.
- * @param integer The maximum number of rows to return.
- * @return array a list of result objects
- * @param callback row delegate handler
- * @see executeQueryForList()
- */
- public function executeQueryForList($connection, $parameter, $result=null, $skip=-1, $max=-1, $delegate=null)
- {
- $sql = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter,$skip,$max);
- return $this->runQueryForList($connection, $parameter, $sql, $result, $delegate);
- }
-
- /**
- * Executes the SQL and retuns a List of result objects.
- *
- * This method should only be called by internal developers, consider using
- * <tt>executeQueryForList()</tt> first.
- *
- * @param IDbConnection database connection
- * @param mixed The object used to set the parameters in the SQL.
- * @param array SQL string and subsititution parameters.
- * @param object result collection object.
- * @param integer The number of rows to skip over.
- * @param integer The maximum number of rows to return.
- * @param callback row delegate handler
- * @return array a list of result objects
- * @see executeQueryForList()
- */
- public function runQueryForList($connection, $parameter, $sql, $result, $delegate=null)
- {
- $registry=$this->getManager()->getTypeHandlers();
- $list = $result instanceof ArrayAccess ? $result :
- $this->_statement->createInstanceOfListClass($registry);
- $connection->setActive(true);
- $reader = $sql->query();
- //$reader = $this->executeSQLQueryLimit($connection, $sql, $max, $skip);
- if($delegate!==null)
- {
- foreach($reader as $row)
- {
- $obj = $this->applyResultMap($row);
- $param = new TResultSetListItemParameter($obj, $parameter, $list);
- $this->raiseRowDelegate($delegate, $param);
- }
- }
- else
- {
- //var_dump($sql,$parameter);
- foreach($reader as $row)
- {
-// var_dump($row);
- $list[] = $this->applyResultMap($row);
- }
- }
-
- if(!$this->_groupBy->isEmpty())
- {
- $list = $this->_groupBy->collect();
- $this->initialGroupByResults();
- }
-
- $this->executePostSelect($connection);
- $this->onExecuteQuery($sql);
-
- return $list;
- }
-
- /**
- * Executes the SQL and retuns all rows selected in a map that is keyed on
- * the property named in the keyProperty parameter. The value at each key
- * will be the value of the property specified in the valueProperty parameter.
- * If valueProperty is null, the entire result object will be entered.
- * @param IDbConnection database connection
- * @param mixed The object used to set the parameters in the SQL.
- * @param string The property of the result object to be used as the key.
- * @param string The property of the result object to be used as the value (or null).
- * @param callback row delegate handler
- * @return array An array of object containing the rows keyed by keyProperty.
- */
- public function executeQueryForMap($connection, $parameter, $keyProperty, $valueProperty=null, $skip=-1, $max=-1, $delegate=null)
- {
- $sql = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter, $skip, $max);
- return $this->runQueryForMap($connection, $parameter, $sql, $keyProperty, $valueProperty, $delegate);
- }
-
- /**
- * Executes the SQL and retuns all rows selected in a map that is keyed on
- * the property named in the keyProperty parameter. The value at each key
- * will be the value of the property specified in the valueProperty parameter.
- * If valueProperty is null, the entire result object will be entered.
- *
- * This method should only be called by internal developers, consider using
- * <tt>executeQueryForMap()</tt> first.
- *
- * @param IDbConnection database connection
- * @param mixed The object used to set the parameters in the SQL.
- * @param array SQL string and subsititution parameters.
- * @param string The property of the result object to be used as the key.
- * @param string The property of the result object to be used as the value (or null).
- * @param callback row delegate, a callback function
- * @return array An array of object containing the rows keyed by keyProperty.
- * @see executeQueryForMap()
- */
- public function runQueryForMap($connection, $parameter, $command, $keyProperty, $valueProperty=null, $delegate=null)
- {
- $map = array();
- //$recordSet = $this->executeSQLQuery($connection, $sql);
- $connection->setActive(true);
- $reader = $command->query();
- if($delegate!==null)
- {
- //while($row = $recordSet->fetchRow())
- foreach($reader as $row)
- {
- $obj = $this->applyResultMap($row);
- $key = TPropertyAccess::get($obj, $keyProperty);
- $value = ($valueProperty===null) ? $obj :
- TPropertyAccess::get($obj, $valueProperty);
- $param = new TResultSetMapItemParameter($key, $value, $parameter, $map);
- $this->raiseRowDelegate($delegate, $param);
- }
- }
- else
- {
- //while($row = $recordSet->fetchRow())
- foreach($reader as $row)
- {
- $obj = $this->applyResultMap($row);
- $key = TPropertyAccess::get($obj, $keyProperty);
- $map[$key] = ($valueProperty===null) ? $obj :
- TPropertyAccess::get($obj, $valueProperty);
- }
- }
- $this->onExecuteQuery($command);
- return $map;
- }
-
- /**
- * Raises delegate handler.
- * This method is invoked for each new list item. It is the responsibility
- * of the handler to add the item to the list.
- * @param object event parameter
- */
- protected function raiseRowDelegate($handler, $param)
- {
- if(is_string($handler))
- {
- call_user_func($handler,$this,$param);
- }
- else if(is_callable($handler,true))
- {
- // an array: 0 - object, 1 - method name/path
- list($object,$method)=$handler;
- if(is_string($object)) // static method call
- call_user_func($handler,$this,$param);
- else
- {
- if(($pos=strrpos($method,'.'))!==false)
- {
- $object=$this->getSubProperty(substr($method,0,$pos));
- $method=substr($method,$pos+1);
- }
- $object->$method($this,$param);
- }
- }
- else
- throw new TInvalidDataValueException('sqlmap_invalid_delegate', $this->getID(), $handler);
- }
-
- /**
- * Executes an SQL statement that returns a single row as an object of the
- * type of the <tt>$result</tt> passed in as a parameter.
- * @param IDbConnection database connection
- * @param mixed The parameter data (object, arrary, primitive) used to set the parameters in the SQL
- * @param mixed The result object.
- * @return ${return}
- */
- public function executeQueryForObject($connection, $parameter, $result=null)
- {
- $sql = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter);
- return $this->runQueryForObject($connection, $sql, $result);
- }
-
- /**
- * Executes an SQL statement that returns a single row as an object of the
- * type of the <tt>$result</tt> passed in as a parameter.
- *
- * This method should only be called by internal developers, consider using
- * <tt>executeQueryForObject()</tt> first.
- *
- * @param IDbConnection database connection
- * @param array SQL string and subsititution parameters.
- * @param object The result object.
- * @return object the object.
- * @see executeQueryForObject()
- */
- public function runQueryForObject($connection, $command, &$result)
- {
- $object = null;
- $connection->setActive(true);
- foreach($command->query() as $row)
- $object = $this->applyResultMap($row, $result);
-
- if(!$this->_groupBy->isEmpty())
- {
- $list = $this->_groupBy->collect();
- $this->initialGroupByResults();
- $object = $list[0];
- }
-
- $this->executePostSelect($connection);
- $this->onExecuteQuery($command);
-
- return $object;
- }
-
- /**
- * Execute an insert statement. Fill the parameter object with the ouput
- * parameters if any, also could return the insert generated key.
- * @param IDbConnection database connection
- * @param mixed The parameter object used to fill the statement.
- * @return string the insert generated key.
- */
- public function executeInsert($connection, $parameter)
- {
- $generatedKey = $this->getPreGeneratedSelectKey($connection, $parameter);
-
- $command = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter);
-// var_dump($command,$parameter);
- $result = $command->execute();
-
- if($generatedKey===null)
- $generatedKey = $this->getPostGeneratedSelectKey($connection, $parameter);
-
- $this->executePostSelect($connection);
- $this->onExecuteQuery($command);
- return $generatedKey;
- }
-
- /**
- * Gets the insert generated ID before executing an insert statement.
- * @param IDbConnection database connection
- * @param mixed insert statement parameter.
- * @return string new insert ID if pre-select key statement was executed, null otherwise.
- */
- protected function getPreGeneratedSelectKey($connection, $parameter)
- {
- if($this->_statement instanceof TSqlMapInsert)
- {
- $selectKey = $this->_statement->getSelectKey();
- if(($selectKey!==null) && !$selectKey->getIsAfter())
- return $this->executeSelectKey($connection, $parameter, $selectKey);
- }
- }
-
- /**
- * Gets the inserted row ID after executing an insert statement.
- * @param IDbConnection database connection
- * @param mixed insert statement parameter.
- * @return string last insert ID, null otherwise.
- */
- protected function getPostGeneratedSelectKey($connection, $parameter)
- {
- if($this->_statement instanceof TSqlMapInsert)
- {
- $selectKey = $this->_statement->getSelectKey();
- if(($selectKey!==null) && $selectKey->getIsAfter())
- return $this->executeSelectKey($connection, $parameter, $selectKey);
- }
- }
-
- /**
- * Execute the select key statement, used to obtain last insert ID.
- * @param IDbConnection database connection
- * @param mixed insert statement parameter
- * @param TSqlMapSelectKey select key statement
- * @return string last insert ID.
- */
- protected function executeSelectKey($connection, $parameter, $selectKey)
- {
- $mappedStatement = $this->getManager()->getMappedStatement($selectKey->getID());
- $generatedKey = $mappedStatement->executeQueryForObject(
- $connection, $parameter, null);
- if(strlen($prop = $selectKey->getProperty()) > 0)
- TPropertyAccess::set($parameter, $prop, $generatedKey);
- return $generatedKey;
- }
-
- /**
- * Execute an update statement. Also used for delete statement.
- * Return the number of rows effected.
- * @param IDbConnection database connection
- * @param mixed The object used to set the parameters in the SQL.
- * @return integer The number of rows effected.
- */
- public function executeUpdate($connection, $parameter)
- {
- $sql = $this->_command->create($this->getManager(),$connection, $this->_statement, $parameter);
- $affectedRows = $sql->execute();
- //$this->executeSQLQuery($connection, $sql);
- $this->executePostSelect($connection);
- $this->onExecuteQuery($sql);
- return $affectedRows;
- }
-
- /**
- * Process 'select' result properties
- * @param IDbConnection database connection
- */
- protected function executePostSelect($connection)
- {
- while(count($this->_selectQueue))
- {
- $postSelect = array_shift($this->_selectQueue);
- $method = $postSelect->getMethod();
- $statement = $postSelect->getStatement();
- $property = $postSelect->getResultProperty()->getProperty();
- $keys = $postSelect->getKeys();
- $resultObject = $postSelect->getResultObject();
-
- if($method == self::QUERY_FOR_LIST || $method == self::QUERY_FOR_ARRAY)
- {
- $values = $statement->executeQueryForList($connection, $keys, null);
-
- if($method == self::QUERY_FOR_ARRAY)
- $values = $values->toArray();
- TPropertyAccess::set($resultObject, $property, $values);
- }
- else if($method == self::QUERY_FOR_OBJECT)
- {
- $value = $statement->executeQueryForObject($connection, $keys, null);
- TPropertyAccess::set($resultObject, $property, $value);
- }
- }
- }
-
- /**
- * Raise the execute query event.
- * @param array prepared SQL statement and subsititution parameters
- */
- public function onExecuteQuery($sql)
- {
- $this->raiseEvent('OnExecuteQuery', $this, $sql);
- }
-
- /**
- * Apply result mapping.
- * @param array a result set row retrieved from the database
- * @param object the result object, will create if necessary.
- * @return object the result filled with data, null if not filled.
- */
- protected function applyResultMap($row, &$resultObject=null)
- {
- if($row === false) return null;
-
- $resultMapName = $this->_statement->getResultMap();
- $resultClass = $this->_statement->getResultClass();
-
- $obj=null;
- if($this->getManager()->getResultMaps()->contains($resultMapName))
- $obj = $this->fillResultMap($resultMapName, $row, null, $resultObject);
- else if(strlen($resultClass) > 0)
- $obj = $this->fillResultClass($resultClass, $row, $resultObject);
- else
- $obj = $this->fillDefaultResultMap(null, $row, $resultObject);
- if(class_exists('TActiveRecord',false) && $obj instanceof TActiveRecord)
- //Create a new clean active record.
- $obj=TActiveRecord::createRecord(get_class($obj),$obj);
- return $obj;
- }
-
- /**
- * Fill the result using ResultClass, will creates new result object if required.
- * @param string result object class name
- * @param array a result set row retrieved from the database
- * @param object the result object, will create if necessary.
- * @return object result object filled with data
- */
- protected function fillResultClass($resultClass, $row, $resultObject)
- {
- if($resultObject===null)
- {
- $registry = $this->getManager()->getTypeHandlers();
- $resultObject = $this->_statement->createInstanceOfResultClass($registry,$row);
- }
-
- if($resultObject instanceOf ArrayAccess)
- return $this->fillResultArrayList($row, $resultObject);
- else if(is_object($resultObject))
- return $this->fillResultObjectProperty($row, $resultObject);
- else
- return $this->fillDefaultResultMap(null, $row, $resultObject);
- }
-
- /**
- * Apply the result to a TList or an array.
- * @param array a result set row retrieved from the database
- * @param object result object, array or list
- * @return object result filled with data.
- */
- protected function fillResultArrayList($row, $resultObject)
- {
- if($resultObject instanceof TList)
- foreach($row as $v)
- $resultObject[] = $v;
- else
- foreach($row as $k => $v)
- $resultObject[$k] = $v;
- return $resultObject;
- }
-
- /**
- * Apply the result to an object.
- * @param array a result set row retrieved from the database
- * @param object result object, array or list
- * @return object result filled with data.
- */
- protected function fillResultObjectProperty($row, $resultObject)
- {
- $index = 0;
- $registry=$this->getManager()->getTypeHandlers();
- foreach($row as $k=>$v)
- {
- $property = new TResultProperty;
- if(is_string($k) && strlen($k) > 0)
- $property->setColumn($k);
- $property->setColumnIndex(++$index);
- $type = gettype(TPropertyAccess::get($resultObject,$k));
- $property->setType($type);
- $value = $property->getPropertyValue($registry,$row);
- TPropertyAccess::set($resultObject, $k,$value);
- }
- return $resultObject;
- }
-
- /**
- * Fills the result object according to result mappings.
- * @param string result map name.
- * @param array a result set row retrieved from the database
- * @param object result object to fill, will create new instances if required.
- * @return object result object filled with data.
- */
- protected function fillResultMap($resultMapName, $row, $parentGroup=null, &$resultObject=null)
- {
- $resultMap = $this->getManager()->getResultMap($resultMapName);
- $registry = $this->getManager()->getTypeHandlers();
- $resultMap = $resultMap->resolveSubMap($registry,$row);
-
- if($resultObject===null)
- $resultObject = $resultMap->createInstanceOfResult($registry);
-
- if(is_object($resultObject))
- {
- if(strlen($resultMap->getGroupBy()) > 0)
- return $this->addResultMapGroupBy($resultMap, $row, $parentGroup, $resultObject);
- else
- foreach($resultMap->getColumns() as $property)
- $this->setObjectProperty($resultMap, $property, $row, $resultObject);
- }
- else
- {
- $resultObject = $this->fillDefaultResultMap($resultMap, $row, $resultObject);
- }
- return $resultObject;
- }
-
- /**
- * ResultMap with GroupBy property. Save object collection graph in a tree
- * and collect the result later.
- * @param TResultMap result mapping details.
- * @param array a result set row retrieved from the database
- * @param object the result object
- * @return object result object.
- */
- protected function addResultMapGroupBy($resultMap, $row, $parent, &$resultObject)
- {
- $group = $this->getResultMapGroupKey($resultMap, $row);
-
- if(empty($parent))
- {
- $rootObject = array('object'=>$resultObject, 'property' => null);
- $this->_groupBy->add(null, $group, $rootObject);
- }
-
- foreach($resultMap->getColumns() as $property)
- {
- //set properties.
- $this->setObjectProperty($resultMap, $property, $row, $resultObject);
- $nested = $property->getResultMapping();
-
- //nested property
- if($this->getManager()->getResultMaps()->contains($nested))
- {
- $nestedMap = $this->getManager()->getResultMap($nested);
- $groupKey = $this->getResultMapGroupKey($nestedMap, $row);
-
- //add the node reference first
- if(empty($parent))
- $this->_groupBy->add($group, $groupKey, '');
-
- //get the nested result mapping value
- $value = $this->fillResultMap($nested, $row, $groupKey);
-
- //add it to the object tree graph
- $groupObject = array('object'=>$value, 'property' => $property->getProperty());
- if(empty($parent))
- $this->_groupBy->add($group, $groupKey, $groupObject);
- else
- $this->_groupBy->add($parent, $groupKey, $groupObject);
- }
- }
- return $resultObject;
- }
-
- /**
- * Gets the result 'group by' groupping key for each row.
- * @param TResultMap result mapping details.
- * @param array a result set row retrieved from the database
- * @return string groupping key.
- */
- protected function getResultMapGroupKey($resultMap, $row)
- {
- $groupBy = $resultMap->getGroupBy();
- if(isset($row[$groupBy]))
- return $resultMap->getID().$row[$groupBy];
- else
- return $resultMap->getID().crc32(serialize($row));
- }
-
- /**
- * Fill the result map using default settings. If <tt>$resultMap</tt> is null
- * the result object returned will be guessed from <tt>$resultObject</tt>.
- * @param TResultMap result mapping details.
- * @param array a result set row retrieved from the database
- * @param object the result object
- * @return mixed the result object filled with data.
- */
- protected function fillDefaultResultMap($resultMap, $row, $resultObject)
- {
- if($resultObject===null)
- $resultObject='';
-
- if($resultMap!==null)
- $result = $this->fillArrayResultMap($resultMap, $row, $resultObject);
- else
- $result = $row;
-
- //if scalar result types
- if(count($result) == 1 && ($type = gettype($resultObject))!= 'array')
- return $this->getScalarResult($result, $type);
- else
- return $result;
- }
-
- /**
- * Retrieve the result map as an array.
- * @param TResultMap result mapping details.
- * @param array a result set row retrieved from the database
- * @param object the result object
- * @return array array list of result objects.
- */
- protected function fillArrayResultMap($resultMap, $row, $resultObject)
- {
- $result = array();
- $registry=$this->getManager()->getTypeHandlers();
- foreach($resultMap->getColumns() as $column)
- {
- if(($column->getType()===null)
- && ($resultObject!==null) && !is_object($resultObject))
- $column->setType(gettype($resultObject));
- $result[$column->getProperty()] = $column->getPropertyValue($registry,$row);
- }
- return $result;
- }
-
- /**
- * Converts the first array value to scalar value of given type.
- * @param array list of results
- * @param string scalar type.
- * @return mixed scalar value.
- */
- protected function getScalarResult($result, $type)
- {
- $scalar = array_shift($result);
- settype($scalar, $type);
- return $scalar;
- }
-
- /**
- * Set a property of the result object with appropriate value.
- * @param TResultMap result mapping details.
- * @param TResultProperty the result property to fill.
- * @param array a result set row retrieved from the database
- * @param object the result object
- */
- protected function setObjectProperty($resultMap, $property, $row, &$resultObject)
- {
- $select = $property->getSelect();
- $key = $property->getProperty();
- $nested = $property->getNestedResultMap();
- $registry=$this->getManager()->getTypeHandlers();
- if($key === '')
- {
- $resultObject = $property->getPropertyValue($registry,$row);
- }
- else if(strlen($select) == 0 && ($nested===null))
- {
- $value = $property->getPropertyValue($registry,$row);
-
- $this->_IsRowDataFound = $this->_IsRowDataFound || ($value != null);
- if(is_array($resultObject) || is_object($resultObject))
- TPropertyAccess::set($resultObject, $key, $value);
- else
- $resultObject = $value;
- }
- else if($nested!==null)
- {
- if($property->instanceOfListType($resultObject) || $property->instanceOfArrayType($resultObject))
- {
- if(strlen($resultMap->getGroupBy()) <= 0)
- throw new TSqlMapExecutionException(
- 'sqlmap_non_groupby_array_list_type', $resultMap->getID(),
- get_class($resultObject), $key);
- }
- else
- {
- $obj = $nested->createInstanceOfResult($this->getManager()->getTypeHandlers());
- if($this->fillPropertyWithResultMap($nested, $row, $obj) == false)
- $obj = null;
- TPropertyAccess::set($resultObject, $key, $obj);
- }
- }
- else //'select' ResultProperty
- {
- $this->enquequePostSelect($select, $resultMap, $property, $row, $resultObject);
- }
- }
-
- /**
- * Add nested result property to post select queue.
- * @param string post select statement ID
- * @param TResultMap current result mapping details.
- * @param TResultProperty current result property.
- * @param array a result set row retrieved from the database
- * @param object the result object
- */
- protected function enquequePostSelect($select, $resultMap, $property, $row, $resultObject)
- {
- $statement = $this->getManager()->getMappedStatement($select);
- $key = $this->getPostSelectKeys($resultMap, $property, $row);
- $postSelect = new TPostSelectBinding;
- $postSelect->setStatement($statement);
- $postSelect->setResultObject($resultObject);
- $postSelect->setResultProperty($property);
- $postSelect->setKeys($key);
-
- if($property->instanceOfListType($resultObject))
- {
- $values = null;
- if($property->getLazyLoad())
- {
- $values = TLazyLoadList::newInstance($statement, $key,
- $resultObject, $property->getProperty());
- TPropertyAccess::set($resultObject, $property->getProperty(), $values);
- }
- else
- $postSelect->setMethod(self::QUERY_FOR_LIST);
- }
- else if($property->instanceOfArrayType($resultObject))
- $postSelect->setMethod(self::QUERY_FOR_ARRAY);
- else
- $postSelect->setMethod(self::QUERY_FOR_OBJECT);
-
- if(!$property->getLazyLoad())
- $this->_selectQueue[] = $postSelect;
- }
-
- /**
- * Finds in the post select property the SQL statement primary selection keys.
- * @param TResultMap result mapping details
- * @param TResultProperty result property
- * @param array current row data.
- * @return array list of primary key values.
- */
- protected function getPostSelectKeys($resultMap, $property,$row)
- {
- $value = $property->getColumn();
- if(is_int(strpos($value.',',0)) || is_int(strpos($value, '=',0)))
- {
- $keys = array();
- foreach(explode(',', $value) as $entry)
- {
- $pair =explode('=',$entry);
- $keys[trim($pair[0])] = $row[trim($pair[1])];
- }
- return $keys;
- }
- else
- {
- $registry=$this->getManager()->getTypeHandlers();
- return $property->getPropertyValue($registry,$row);
- }
- }
-
- /**
- * Fills the property with result mapping results.
- * @param TResultMap nested result mapping details.
- * @param array a result set row retrieved from the database
- * @param object the result object
- * @return boolean true if the data was found, false otherwise.
- */
- protected function fillPropertyWithResultMap($resultMap, $row, &$resultObject)
- {
- $dataFound = false;
- foreach($resultMap->getColumns() as $property)
- {
- $this->_IsRowDataFound = false;
- $this->setObjectProperty($resultMap, $property, $row, $resultObject);
- $dataFound = $dataFound || $this->_IsRowDataFound;
- }
- $this->_IsRowDataFound = $dataFound;
- return $dataFound;
- }
-
- public function __wakeup()
- {
- parent::__wakeup();
- if (is_null($this->_selectQueue)) $this->_selectQueue = array();
- }
-
- public function __sleep()
- {
- $exprops = array(); $cn = __CLASS__;
- if (!count($this->_selectQueue)) $exprops[] = "\0$cn\0_selectQueue";
- if (is_null($this->_groupBy)) $exprops[] = "\0$cn\0_groupBy";
- if (!$this->_IsRowDataFound) $exprops[] = "\0$cn\0_IsRowDataFound";
- return array_diff(parent::__sleep(),$exprops);
- }
-}
-
-/**
- * TPostSelectBinding class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TPostSelectBinding
-{
- private $_statement=null;
- private $_property=null;
- private $_resultObject=null;
- private $_keys=null;
- private $_method=TMappedStatement::QUERY_FOR_LIST;
-
- public function getStatement(){ return $this->_statement; }
- public function setStatement($value){ $this->_statement = $value; }
-
- public function getResultProperty(){ return $this->_property; }
- public function setResultProperty($value){ $this->_property = $value; }
-
- public function getResultObject(){ return $this->_resultObject; }
- public function setResultObject($value){ $this->_resultObject = $value; }
-
- public function getKeys(){ return $this->_keys; }
- public function setKeys($value){ $this->_keys = $value; }
-
- public function getMethod(){ return $this->_method; }
- public function setMethod($value){ $this->_method = $value; }
-}
-
-/**
- * TSQLMapObjectCollectionTree class.
- *
- * Maps object collection graphs as trees. Nodes in the collection can
- * be {@link add} using parent relationships. The object collections can be
- * build using the {@link collect} method.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TSqlMapObjectCollectionTree extends TComponent
-{
- /**
- * @var array object graph as tree
- */
- private $_tree = array();
- /**
- * @var array tree node values
- */
- private $_entries = array();
- /**
- * @var array resulting object collection
- */
- private $_list = array();
-
- /**
- * @return boolean true if the graph is empty
- */
- public function isEmpty()
- {
- return count($this->_entries) == 0;
- }
-
- /**
- * Add a new node to the object tree graph.
- * @param string parent node id
- * @param string new node id
- * @param mixed node value
- */
- public function add($parent, $node, $object='')
- {
- if(isset($this->_entries[$parent]) && ($this->_entries[$parent]!==null)
- && isset($this->_entries[$node]) && ($this->_entries[$node]!==null))
- {
- $this->_entries[$node] = $object;
- return;
- }
- $this->_entries[$node] = $object;
- if(empty($parent))
- {
- if(isset($this->_entries[$node]))
- return;
- $this->_tree[$node] = array();
- }
- $found = $this->addNode($this->_tree, $parent, $node);
- if(!$found && !empty($parent))
- {
- $this->_tree[$parent] = array();
- if(!isset($this->_entries[$parent]) || $object !== '')
- $this->_entries[$parent] = $object;
- $this->addNode($this->_tree, $parent, $node);
- }
- }
-
- /**
- * Find the parent node and add the new node as its child.
- * @param array list of nodes to check
- * @param string parent node id
- * @param string new node id
- * @return boolean true if parent node is found.
- */
- protected function addNode(&$childs, $parent, $node)
- {
- $found = false;
- reset($childs);
- for($i = 0, $k = count($childs); $i < $k; $i++)
- {
- $key = key($childs);
- next($childs);
- if($key == $parent)
- {
- $found = true;
- $childs[$key][$node] = array();
- }
- else
- {
- $found = $found || $this->addNode($childs[$key], $parent, $node);
- }
- }
- return $found;
- }
-
- /**
- * @return array object collection
- */
- public function collect()
- {
- while(count($this->_tree) > 0)
- $this->collectChildren(null, $this->_tree);
- return $this->getCollection();
- }
-
- /**
- * @param array list of nodes to check
- * @return boolean true if all nodes are leaf nodes, false otherwise
- */
- protected function hasChildren(&$nodes)
- {
- $hasChildren = false;
- foreach($nodes as $node)
- if(count($node) != 0)
- return true;
- return $hasChildren;
- }
-
- /**
- * Visit all the child nodes and collect them by removing.
- * @param string parent node id
- * @param array list of child nodes.
- */
- protected function collectChildren($parent, &$nodes)
- {
- $noChildren = !$this->hasChildren($nodes);
- $childs = array();
- for(reset($nodes); $key = key($nodes);)
- {
- next($nodes);
- if($noChildren)
- {
- $childs[] = $key;
- unset($nodes[$key]);
- }
- else
- $this->collectChildren($key, $nodes[$key]);
- }
- if(count($childs) > 0)
- $this->onChildNodesVisited($parent, $childs);
- }
-
- /**
- * Set the object properties for all the child nodes visited.
- * @param string parent node id
- * @param array list of child nodes visited.
- */
- protected function onChildNodesVisited($parent, $nodes)
- {
- if(empty($parent) || empty($this->_entries[$parent]))
- return;
-
- $parentObject = $this->_entries[$parent]['object'];
- $property = $this->_entries[$nodes[0]]['property'];
-
- $list = TPropertyAccess::get($parentObject, $property);
-
- foreach($nodes as $node)
- {
- if($list instanceof TList)
- $parentObject->{$property}[] = $this->_entries[$node]['object'];
- else if(is_array($list))
- $list[] = $this->_entries[$node]['object'];
- else
- throw new TSqlMapExecutionException(
- 'sqlmap_property_must_be_list');
- }
-
- if(is_array($list))
- TPropertyAccess::set($parentObject, $property, $list);
-
- if($this->_entries[$parent]['property'] === null)
- $this->_list[] = $parentObject;
- }
-
- /**
- * @return array object collection.
- */
- protected function getCollection()
- {
- return $this->_list;
- }
-
- public function __sleep()
- {
- $exprops = array(); $cn = __CLASS__;
- if (!count($this->_tree)) $exprops[] = "\0$cn\0_tree";
- if (!count($this->_entries)) $exprops[] = "\0$cn\0_entries";
- if (!count($this->_list)) $exprops[] = "\0$cn\0_list";
- return array_diff(parent::__sleep(),$exprops);
- }
-}
-
-/**
- * TResultSetListItemParameter class
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TResultSetListItemParameter extends TComponent
-{
- private $_resultObject;
- private $_parameterObject;
- private $_list;
-
- public function __construct($result, $parameter, &$list)
- {
- $this->_resultObject = $result;
- $this->_parameterObject = $parameter;
- $this->_list = &$list;
- }
-
- public function getResult()
- {
- return $this->_resultObject;
- }
-
- public function getParameter()
- {
- return $this->_parameterObject;
- }
-
- public function &getList()
- {
- return $this->_list;
- }
-}
-
-/**
- * TResultSetMapItemParameter class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TResultSetMapItemParameter extends TComponent
-{
- private $_key;
- private $_value;
- private $_parameterObject;
- private $_map;
-
- public function __construct($key, $value, $parameter, &$map)
- {
- $this->_key = $key;
- $this->_value = $value;
- $this->_parameterObject = $parameter;
- $this->_map = &$map;
- }
-
- public function getKey()
- {
- return $this->_key;
- }
-
- public function getValue()
- {
- return $this->_value;
- }
-
- public function getParameter()
- {
- return $this->_parameterObject;
- }
-
- public function &getMap()
- {
- return $this->_map;
- }
-}
-
+<?php +/** + * TMappedStatement and related classes. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +/** + * TMappedStatement class executes SQL mapped statements. Mapped Statements can + * hold any SQL statement and use Parameter Maps and Result Maps for input and output. + * + * This class is usualy instantiated during SQLMap configuration by TSqlDomBuilder. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.0 + */ +class TMappedStatement extends TComponent implements IMappedStatement +{ + /** + * @var TSqlMapStatement current SQL statement. + */ + private $_statement; + + /** + * @var TPreparedCommand SQL command prepareer + */ + private $_command; + + /** + * @var TSqlMapper sqlmap used by this mapper. + */ + private $_manager; + + /** + * @var TPostSelectBinding[] post select statement queue. + */ + private $_selectQueue=array(); + + /** + * @var boolean true when data is mapped to a particular row. + */ + private $_IsRowDataFound = false; + + /** + * @var TSQLMapObjectCollectionTree group by object collection tree + */ + private $_groupBy; + + /** + * @var Post select is to query for list. + */ + const QUERY_FOR_LIST = 0; + + /** + * @var Post select is to query for list. + */ + const QUERY_FOR_ARRAY = 1; + + /** + * @var Post select is to query for object. + */ + const QUERY_FOR_OBJECT = 2; + + /** + * @return string Name used to identify the TMappedStatement amongst the others. + * This the name of the SQL statement by default. + */ + public function getID() + { + return $this->_statement->ID; + } + + /** + * @return TSqlMapStatement The SQL statment used by this MappedStatement + */ + public function getStatement() + { + return $this->_statement; + } + + /** + * @return TSqlMapper The SqlMap used by this MappedStatement + */ + public function getManager() + { + return $this->_manager; + } + + /** + * @return TPreparedCommand command to prepare SQL statements. + */ + public function getCommand() + { + return $this->_command; + } + + /** + * Empty the group by results cache. + */ + protected function initialGroupByResults() + { + $this->_groupBy = new TSqlMapObjectCollectionTree(); + } + + /** + * Creates a new mapped statement. + * @param TSqlMapper an sqlmap. + * @param TSqlMapStatement An SQL statement. + */ + public function __construct(TSqlMapManager $sqlMap, TSqlMapStatement $statement) + { + $this->_manager = $sqlMap; + $this->_statement = $statement; + $this->_command = new TPreparedCommand(); + $this->initialGroupByResults(); + } + + public function getSqlString() + { + return $this->getStatement()->getSqlText()->getPreparedStatement()->getPreparedSql(); + } + + /** + * Execute SQL Query. + * @param IDbConnection database connection + * @param array SQL statement and parameters. + * @return mixed record set if applicable. + * @throws TSqlMapExecutionException if execution error or false record set. + * @throws TSqlMapQueryExecutionException if any execution error + */ +/* protected function executeSQLQuery($connection, $sql) + { + try + { + if(!($recordSet = $connection->execute($sql['sql'],$sql['parameters']))) + { + throw new TSqlMapExecutionException( + 'sqlmap_execution_error_no_record', $this->getID(), + $connection->ErrorMsg()); + } + return $recordSet; + } + catch (Exception $e) + { + throw new TSqlMapQueryExecutionException($this->getStatement(), $e); + } + }*/ + + /** + * Execute SQL Query with limits. + * @param IDbConnection database connection + * @param array SQL statement and parameters. + * @return mixed record set if applicable. + * @throws TSqlMapExecutionException if execution error or false record set. + * @throws TSqlMapQueryExecutionException if any execution error + */ + protected function executeSQLQueryLimit($connection, $command, $max, $skip) + { + if($max>-1 || $skip > -1) + { + $maxStr=$max>0?' LIMIT '.$max:''; + $skipStr=$skip>0?' OFFSET '.$skip:''; + $command->setText($command->getText().$maxStr.$skipStr); + } + $connection->setActive(true); + return $command->query(); + + /*//var_dump($command); + try + { + $recordSet = $connection->selectLimit($sql['sql'],$max,$skip,$sql['parameters']); + if(!$recordSet) + { + throw new TSqlMapExecutionException( + 'sqlmap_execution_error_query_for_list', + $connection->ErrorMsg()); + } + return $recordSet; + } + catch (Exception $e) + { + throw new TSqlMapQueryExecutionException($this->getStatement(), $e); + }*/ + } + + /** + * Executes the SQL and retuns a List of result objects. + * @param IDbConnection database connection + * @param mixed The object used to set the parameters in the SQL. + * @param object result collection object. + * @param integer The number of rows to skip over. + * @param integer The maximum number of rows to return. + * @return array a list of result objects + * @param callback row delegate handler + * @see executeQueryForList() + */ + public function executeQueryForList($connection, $parameter, $result=null, $skip=-1, $max=-1, $delegate=null) + { + $sql = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter,$skip,$max); + return $this->runQueryForList($connection, $parameter, $sql, $result, $delegate); + } + + /** + * Executes the SQL and retuns a List of result objects. + * + * This method should only be called by internal developers, consider using + * <tt>executeQueryForList()</tt> first. + * + * @param IDbConnection database connection + * @param mixed The object used to set the parameters in the SQL. + * @param array SQL string and subsititution parameters. + * @param object result collection object. + * @param integer The number of rows to skip over. + * @param integer The maximum number of rows to return. + * @param callback row delegate handler + * @return array a list of result objects + * @see executeQueryForList() + */ + public function runQueryForList($connection, $parameter, $sql, $result, $delegate=null) + { + $registry=$this->getManager()->getTypeHandlers(); + $list = $result instanceof ArrayAccess ? $result : + $this->_statement->createInstanceOfListClass($registry); + $connection->setActive(true); + $reader = $sql->query(); + //$reader = $this->executeSQLQueryLimit($connection, $sql, $max, $skip); + if($delegate!==null) + { + foreach($reader as $row) + { + $obj = $this->applyResultMap($row); + $param = new TResultSetListItemParameter($obj, $parameter, $list); + $this->raiseRowDelegate($delegate, $param); + } + } + else + { + //var_dump($sql,$parameter); + foreach($reader as $row) + { +// var_dump($row); + $list[] = $this->applyResultMap($row); + } + } + + if(!$this->_groupBy->isEmpty()) + { + $list = $this->_groupBy->collect(); + $this->initialGroupByResults(); + } + + $this->executePostSelect($connection); + $this->onExecuteQuery($sql); + + return $list; + } + + /** + * Executes the SQL and retuns all rows selected in a map that is keyed on + * the property named in the keyProperty parameter. The value at each key + * will be the value of the property specified in the valueProperty parameter. + * If valueProperty is null, the entire result object will be entered. + * @param IDbConnection database connection + * @param mixed The object used to set the parameters in the SQL. + * @param string The property of the result object to be used as the key. + * @param string The property of the result object to be used as the value (or null). + * @param callback row delegate handler + * @return array An array of object containing the rows keyed by keyProperty. + */ + public function executeQueryForMap($connection, $parameter, $keyProperty, $valueProperty=null, $skip=-1, $max=-1, $delegate=null) + { + $sql = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter, $skip, $max); + return $this->runQueryForMap($connection, $parameter, $sql, $keyProperty, $valueProperty, $delegate); + } + + /** + * Executes the SQL and retuns all rows selected in a map that is keyed on + * the property named in the keyProperty parameter. The value at each key + * will be the value of the property specified in the valueProperty parameter. + * If valueProperty is null, the entire result object will be entered. + * + * This method should only be called by internal developers, consider using + * <tt>executeQueryForMap()</tt> first. + * + * @param IDbConnection database connection + * @param mixed The object used to set the parameters in the SQL. + * @param array SQL string and subsititution parameters. + * @param string The property of the result object to be used as the key. + * @param string The property of the result object to be used as the value (or null). + * @param callback row delegate, a callback function + * @return array An array of object containing the rows keyed by keyProperty. + * @see executeQueryForMap() + */ + public function runQueryForMap($connection, $parameter, $command, $keyProperty, $valueProperty=null, $delegate=null) + { + $map = array(); + //$recordSet = $this->executeSQLQuery($connection, $sql); + $connection->setActive(true); + $reader = $command->query(); + if($delegate!==null) + { + //while($row = $recordSet->fetchRow()) + foreach($reader as $row) + { + $obj = $this->applyResultMap($row); + $key = TPropertyAccess::get($obj, $keyProperty); + $value = ($valueProperty===null) ? $obj : + TPropertyAccess::get($obj, $valueProperty); + $param = new TResultSetMapItemParameter($key, $value, $parameter, $map); + $this->raiseRowDelegate($delegate, $param); + } + } + else + { + //while($row = $recordSet->fetchRow()) + foreach($reader as $row) + { + $obj = $this->applyResultMap($row); + $key = TPropertyAccess::get($obj, $keyProperty); + $map[$key] = ($valueProperty===null) ? $obj : + TPropertyAccess::get($obj, $valueProperty); + } + } + $this->onExecuteQuery($command); + return $map; + } + + /** + * Raises delegate handler. + * This method is invoked for each new list item. It is the responsibility + * of the handler to add the item to the list. + * @param object event parameter + */ + protected function raiseRowDelegate($handler, $param) + { + if(is_string($handler)) + { + call_user_func($handler,$this,$param); + } + else if(is_callable($handler,true)) + { + // an array: 0 - object, 1 - method name/path + list($object,$method)=$handler; + if(is_string($object)) // static method call + call_user_func($handler,$this,$param); + else + { + if(($pos=strrpos($method,'.'))!==false) + { + $object=$this->getSubProperty(substr($method,0,$pos)); + $method=substr($method,$pos+1); + } + $object->$method($this,$param); + } + } + else + throw new TInvalidDataValueException('sqlmap_invalid_delegate', $this->getID(), $handler); + } + + /** + * Executes an SQL statement that returns a single row as an object of the + * type of the <tt>$result</tt> passed in as a parameter. + * @param IDbConnection database connection + * @param mixed The parameter data (object, arrary, primitive) used to set the parameters in the SQL + * @param mixed The result object. + * @return ${return} + */ + public function executeQueryForObject($connection, $parameter, $result=null) + { + $sql = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter); + return $this->runQueryForObject($connection, $sql, $result); + } + + /** + * Executes an SQL statement that returns a single row as an object of the + * type of the <tt>$result</tt> passed in as a parameter. + * + * This method should only be called by internal developers, consider using + * <tt>executeQueryForObject()</tt> first. + * + * @param IDbConnection database connection + * @param array SQL string and subsititution parameters. + * @param object The result object. + * @return object the object. + * @see executeQueryForObject() + */ + public function runQueryForObject($connection, $command, &$result) + { + $object = null; + $connection->setActive(true); + foreach($command->query() as $row) + $object = $this->applyResultMap($row, $result); + + if(!$this->_groupBy->isEmpty()) + { + $list = $this->_groupBy->collect(); + $this->initialGroupByResults(); + $object = $list[0]; + } + + $this->executePostSelect($connection); + $this->onExecuteQuery($command); + + return $object; + } + + /** + * Execute an insert statement. Fill the parameter object with the ouput + * parameters if any, also could return the insert generated key. + * @param IDbConnection database connection + * @param mixed The parameter object used to fill the statement. + * @return string the insert generated key. + */ + public function executeInsert($connection, $parameter) + { + $generatedKey = $this->getPreGeneratedSelectKey($connection, $parameter); + + $command = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter); +// var_dump($command,$parameter); + $result = $command->execute(); + + if($generatedKey===null) + $generatedKey = $this->getPostGeneratedSelectKey($connection, $parameter); + + $this->executePostSelect($connection); + $this->onExecuteQuery($command); + return $generatedKey; + } + + /** + * Gets the insert generated ID before executing an insert statement. + * @param IDbConnection database connection + * @param mixed insert statement parameter. + * @return string new insert ID if pre-select key statement was executed, null otherwise. + */ + protected function getPreGeneratedSelectKey($connection, $parameter) + { + if($this->_statement instanceof TSqlMapInsert) + { + $selectKey = $this->_statement->getSelectKey(); + if(($selectKey!==null) && !$selectKey->getIsAfter()) + return $this->executeSelectKey($connection, $parameter, $selectKey); + } + } + + /** + * Gets the inserted row ID after executing an insert statement. + * @param IDbConnection database connection + * @param mixed insert statement parameter. + * @return string last insert ID, null otherwise. + */ + protected function getPostGeneratedSelectKey($connection, $parameter) + { + if($this->_statement instanceof TSqlMapInsert) + { + $selectKey = $this->_statement->getSelectKey(); + if(($selectKey!==null) && $selectKey->getIsAfter()) + return $this->executeSelectKey($connection, $parameter, $selectKey); + } + } + + /** + * Execute the select key statement, used to obtain last insert ID. + * @param IDbConnection database connection + * @param mixed insert statement parameter + * @param TSqlMapSelectKey select key statement + * @return string last insert ID. + */ + protected function executeSelectKey($connection, $parameter, $selectKey) + { + $mappedStatement = $this->getManager()->getMappedStatement($selectKey->getID()); + $generatedKey = $mappedStatement->executeQueryForObject( + $connection, $parameter, null); + if(strlen($prop = $selectKey->getProperty()) > 0) + TPropertyAccess::set($parameter, $prop, $generatedKey); + return $generatedKey; + } + + /** + * Execute an update statement. Also used for delete statement. + * Return the number of rows effected. + * @param IDbConnection database connection + * @param mixed The object used to set the parameters in the SQL. + * @return integer The number of rows effected. + */ + public function executeUpdate($connection, $parameter) + { + $sql = $this->_command->create($this->getManager(),$connection, $this->_statement, $parameter); + $affectedRows = $sql->execute(); + //$this->executeSQLQuery($connection, $sql); + $this->executePostSelect($connection); + $this->onExecuteQuery($sql); + return $affectedRows; + } + + /** + * Process 'select' result properties + * @param IDbConnection database connection + */ + protected function executePostSelect($connection) + { + while(count($this->_selectQueue)) + { + $postSelect = array_shift($this->_selectQueue); + $method = $postSelect->getMethod(); + $statement = $postSelect->getStatement(); + $property = $postSelect->getResultProperty()->getProperty(); + $keys = $postSelect->getKeys(); + $resultObject = $postSelect->getResultObject(); + + if($method == self::QUERY_FOR_LIST || $method == self::QUERY_FOR_ARRAY) + { + $values = $statement->executeQueryForList($connection, $keys, null); + + if($method == self::QUERY_FOR_ARRAY) + $values = $values->toArray(); + TPropertyAccess::set($resultObject, $property, $values); + } + else if($method == self::QUERY_FOR_OBJECT) + { + $value = $statement->executeQueryForObject($connection, $keys, null); + TPropertyAccess::set($resultObject, $property, $value); + } + } + } + + /** + * Raise the execute query event. + * @param array prepared SQL statement and subsititution parameters + */ + public function onExecuteQuery($sql) + { + $this->raiseEvent('OnExecuteQuery', $this, $sql); + } + + /** + * Apply result mapping. + * @param array a result set row retrieved from the database + * @param object the result object, will create if necessary. + * @return object the result filled with data, null if not filled. + */ + protected function applyResultMap($row, &$resultObject=null) + { + if($row === false) return null; + + $resultMapName = $this->_statement->getResultMap(); + $resultClass = $this->_statement->getResultClass(); + + $obj=null; + if($this->getManager()->getResultMaps()->contains($resultMapName)) + $obj = $this->fillResultMap($resultMapName, $row, null, $resultObject); + else if(strlen($resultClass) > 0) + $obj = $this->fillResultClass($resultClass, $row, $resultObject); + else + $obj = $this->fillDefaultResultMap(null, $row, $resultObject); + if(class_exists('TActiveRecord',false) && $obj instanceof TActiveRecord) + //Create a new clean active record. + $obj=TActiveRecord::createRecord(get_class($obj),$obj); + return $obj; + } + + /** + * Fill the result using ResultClass, will creates new result object if required. + * @param string result object class name + * @param array a result set row retrieved from the database + * @param object the result object, will create if necessary. + * @return object result object filled with data + */ + protected function fillResultClass($resultClass, $row, $resultObject) + { + if($resultObject===null) + { + $registry = $this->getManager()->getTypeHandlers(); + $resultObject = $this->_statement->createInstanceOfResultClass($registry,$row); + } + + if($resultObject instanceOf ArrayAccess) + return $this->fillResultArrayList($row, $resultObject); + else if(is_object($resultObject)) + return $this->fillResultObjectProperty($row, $resultObject); + else + return $this->fillDefaultResultMap(null, $row, $resultObject); + } + + /** + * Apply the result to a TList or an array. + * @param array a result set row retrieved from the database + * @param object result object, array or list + * @return object result filled with data. + */ + protected function fillResultArrayList($row, $resultObject) + { + if($resultObject instanceof TList) + foreach($row as $v) + $resultObject[] = $v; + else + foreach($row as $k => $v) + $resultObject[$k] = $v; + return $resultObject; + } + + /** + * Apply the result to an object. + * @param array a result set row retrieved from the database + * @param object result object, array or list + * @return object result filled with data. + */ + protected function fillResultObjectProperty($row, $resultObject) + { + $index = 0; + $registry=$this->getManager()->getTypeHandlers(); + foreach($row as $k=>$v) + { + $property = new TResultProperty; + if(is_string($k) && strlen($k) > 0) + $property->setColumn($k); + $property->setColumnIndex(++$index); + $type = gettype(TPropertyAccess::get($resultObject,$k)); + $property->setType($type); + $value = $property->getPropertyValue($registry,$row); + TPropertyAccess::set($resultObject, $k,$value); + } + return $resultObject; + } + + /** + * Fills the result object according to result mappings. + * @param string result map name. + * @param array a result set row retrieved from the database + * @param object result object to fill, will create new instances if required. + * @return object result object filled with data. + */ + protected function fillResultMap($resultMapName, $row, $parentGroup=null, &$resultObject=null) + { + $resultMap = $this->getManager()->getResultMap($resultMapName); + $registry = $this->getManager()->getTypeHandlers(); + $resultMap = $resultMap->resolveSubMap($registry,$row); + + if($resultObject===null) + $resultObject = $resultMap->createInstanceOfResult($registry); + + if(is_object($resultObject)) + { + if(strlen($resultMap->getGroupBy()) > 0) + return $this->addResultMapGroupBy($resultMap, $row, $parentGroup, $resultObject); + else + foreach($resultMap->getColumns() as $property) + $this->setObjectProperty($resultMap, $property, $row, $resultObject); + } + else + { + $resultObject = $this->fillDefaultResultMap($resultMap, $row, $resultObject); + } + return $resultObject; + } + + /** + * ResultMap with GroupBy property. Save object collection graph in a tree + * and collect the result later. + * @param TResultMap result mapping details. + * @param array a result set row retrieved from the database + * @param object the result object + * @return object result object. + */ + protected function addResultMapGroupBy($resultMap, $row, $parent, &$resultObject) + { + $group = $this->getResultMapGroupKey($resultMap, $row); + + if(empty($parent)) + { + $rootObject = array('object'=>$resultObject, 'property' => null); + $this->_groupBy->add(null, $group, $rootObject); + } + + foreach($resultMap->getColumns() as $property) + { + //set properties. + $this->setObjectProperty($resultMap, $property, $row, $resultObject); + $nested = $property->getResultMapping(); + + //nested property + if($this->getManager()->getResultMaps()->contains($nested)) + { + $nestedMap = $this->getManager()->getResultMap($nested); + $groupKey = $this->getResultMapGroupKey($nestedMap, $row); + + //add the node reference first + if(empty($parent)) + $this->_groupBy->add($group, $groupKey, ''); + + //get the nested result mapping value + $value = $this->fillResultMap($nested, $row, $groupKey); + + //add it to the object tree graph + $groupObject = array('object'=>$value, 'property' => $property->getProperty()); + if(empty($parent)) + $this->_groupBy->add($group, $groupKey, $groupObject); + else + $this->_groupBy->add($parent, $groupKey, $groupObject); + } + } + return $resultObject; + } + + /** + * Gets the result 'group by' groupping key for each row. + * @param TResultMap result mapping details. + * @param array a result set row retrieved from the database + * @return string groupping key. + */ + protected function getResultMapGroupKey($resultMap, $row) + { + $groupBy = $resultMap->getGroupBy(); + if(isset($row[$groupBy])) + return $resultMap->getID().$row[$groupBy]; + else + return $resultMap->getID().crc32(serialize($row)); + } + + /** + * Fill the result map using default settings. If <tt>$resultMap</tt> is null + * the result object returned will be guessed from <tt>$resultObject</tt>. + * @param TResultMap result mapping details. + * @param array a result set row retrieved from the database + * @param object the result object + * @return mixed the result object filled with data. + */ + protected function fillDefaultResultMap($resultMap, $row, $resultObject) + { + if($resultObject===null) + $resultObject=''; + + if($resultMap!==null) + $result = $this->fillArrayResultMap($resultMap, $row, $resultObject); + else + $result = $row; + + //if scalar result types + if(count($result) == 1 && ($type = gettype($resultObject))!= 'array') + return $this->getScalarResult($result, $type); + else + return $result; + } + + /** + * Retrieve the result map as an array. + * @param TResultMap result mapping details. + * @param array a result set row retrieved from the database + * @param object the result object + * @return array array list of result objects. + */ + protected function fillArrayResultMap($resultMap, $row, $resultObject) + { + $result = array(); + $registry=$this->getManager()->getTypeHandlers(); + foreach($resultMap->getColumns() as $column) + { + if(($column->getType()===null) + && ($resultObject!==null) && !is_object($resultObject)) + $column->setType(gettype($resultObject)); + $result[$column->getProperty()] = $column->getPropertyValue($registry,$row); + } + return $result; + } + + /** + * Converts the first array value to scalar value of given type. + * @param array list of results + * @param string scalar type. + * @return mixed scalar value. + */ + protected function getScalarResult($result, $type) + { + $scalar = array_shift($result); + settype($scalar, $type); + return $scalar; + } + + /** + * Set a property of the result object with appropriate value. + * @param TResultMap result mapping details. + * @param TResultProperty the result property to fill. + * @param array a result set row retrieved from the database + * @param object the result object + */ + protected function setObjectProperty($resultMap, $property, $row, &$resultObject) + { + $select = $property->getSelect(); + $key = $property->getProperty(); + $nested = $property->getNestedResultMap(); + $registry=$this->getManager()->getTypeHandlers(); + if($key === '') + { + $resultObject = $property->getPropertyValue($registry,$row); + } + else if(strlen($select) == 0 && ($nested===null)) + { + $value = $property->getPropertyValue($registry,$row); + + $this->_IsRowDataFound = $this->_IsRowDataFound || ($value != null); + if(is_array($resultObject) || is_object($resultObject)) + TPropertyAccess::set($resultObject, $key, $value); + else + $resultObject = $value; + } + else if($nested!==null) + { + if($property->instanceOfListType($resultObject) || $property->instanceOfArrayType($resultObject)) + { + if(strlen($resultMap->getGroupBy()) <= 0) + throw new TSqlMapExecutionException( + 'sqlmap_non_groupby_array_list_type', $resultMap->getID(), + get_class($resultObject), $key); + } + else + { + $obj = $nested->createInstanceOfResult($this->getManager()->getTypeHandlers()); + if($this->fillPropertyWithResultMap($nested, $row, $obj) == false) + $obj = null; + TPropertyAccess::set($resultObject, $key, $obj); + } + } + else //'select' ResultProperty + { + $this->enquequePostSelect($select, $resultMap, $property, $row, $resultObject); + } + } + + /** + * Add nested result property to post select queue. + * @param string post select statement ID + * @param TResultMap current result mapping details. + * @param TResultProperty current result property. + * @param array a result set row retrieved from the database + * @param object the result object + */ + protected function enquequePostSelect($select, $resultMap, $property, $row, $resultObject) + { + $statement = $this->getManager()->getMappedStatement($select); + $key = $this->getPostSelectKeys($resultMap, $property, $row); + $postSelect = new TPostSelectBinding; + $postSelect->setStatement($statement); + $postSelect->setResultObject($resultObject); + $postSelect->setResultProperty($property); + $postSelect->setKeys($key); + + if($property->instanceOfListType($resultObject)) + { + $values = null; + if($property->getLazyLoad()) + { + $values = TLazyLoadList::newInstance($statement, $key, + $resultObject, $property->getProperty()); + TPropertyAccess::set($resultObject, $property->getProperty(), $values); + } + else + $postSelect->setMethod(self::QUERY_FOR_LIST); + } + else if($property->instanceOfArrayType($resultObject)) + $postSelect->setMethod(self::QUERY_FOR_ARRAY); + else + $postSelect->setMethod(self::QUERY_FOR_OBJECT); + + if(!$property->getLazyLoad()) + $this->_selectQueue[] = $postSelect; + } + + /** + * Finds in the post select property the SQL statement primary selection keys. + * @param TResultMap result mapping details + * @param TResultProperty result property + * @param array current row data. + * @return array list of primary key values. + */ + protected function getPostSelectKeys($resultMap, $property,$row) + { + $value = $property->getColumn(); + if(is_int(strpos($value.',',0)) || is_int(strpos($value, '=',0))) + { + $keys = array(); + foreach(explode(',', $value) as $entry) + { + $pair =explode('=',$entry); + $keys[trim($pair[0])] = $row[trim($pair[1])]; + } + return $keys; + } + else + { + $registry=$this->getManager()->getTypeHandlers(); + return $property->getPropertyValue($registry,$row); + } + } + + /** + * Fills the property with result mapping results. + * @param TResultMap nested result mapping details. + * @param array a result set row retrieved from the database + * @param object the result object + * @return boolean true if the data was found, false otherwise. + */ + protected function fillPropertyWithResultMap($resultMap, $row, &$resultObject) + { + $dataFound = false; + foreach($resultMap->getColumns() as $property) + { + $this->_IsRowDataFound = false; + $this->setObjectProperty($resultMap, $property, $row, $resultObject); + $dataFound = $dataFound || $this->_IsRowDataFound; + } + $this->_IsRowDataFound = $dataFound; + return $dataFound; + } + + public function __wakeup() + { + parent::__wakeup(); + if (is_null($this->_selectQueue)) $this->_selectQueue = array(); + } + + public function __sleep() + { + $exprops = array(); $cn = __CLASS__; + if (!count($this->_selectQueue)) $exprops[] = "\0$cn\0_selectQueue"; + if (is_null($this->_groupBy)) $exprops[] = "\0$cn\0_groupBy"; + if (!$this->_IsRowDataFound) $exprops[] = "\0$cn\0_IsRowDataFound"; + return array_diff(parent::__sleep(),$exprops); + } +} + +/** + * TPostSelectBinding class. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TPostSelectBinding +{ + private $_statement=null; + private $_property=null; + private $_resultObject=null; + private $_keys=null; + private $_method=TMappedStatement::QUERY_FOR_LIST; + + public function getStatement(){ return $this->_statement; } + public function setStatement($value){ $this->_statement = $value; } + + public function getResultProperty(){ return $this->_property; } + public function setResultProperty($value){ $this->_property = $value; } + + public function getResultObject(){ return $this->_resultObject; } + public function setResultObject($value){ $this->_resultObject = $value; } + + public function getKeys(){ return $this->_keys; } + public function setKeys($value){ $this->_keys = $value; } + + public function getMethod(){ return $this->_method; } + public function setMethod($value){ $this->_method = $value; } +} + +/** + * TSQLMapObjectCollectionTree class. + * + * Maps object collection graphs as trees. Nodes in the collection can + * be {@link add} using parent relationships. The object collections can be + * build using the {@link collect} method. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TSqlMapObjectCollectionTree extends TComponent +{ + /** + * @var array object graph as tree + */ + private $_tree = array(); + /** + * @var array tree node values + */ + private $_entries = array(); + /** + * @var array resulting object collection + */ + private $_list = array(); + + /** + * @return boolean true if the graph is empty + */ + public function isEmpty() + { + return count($this->_entries) == 0; + } + + /** + * Add a new node to the object tree graph. + * @param string parent node id + * @param string new node id + * @param mixed node value + */ + public function add($parent, $node, $object='') + { + if(isset($this->_entries[$parent]) && ($this->_entries[$parent]!==null) + && isset($this->_entries[$node]) && ($this->_entries[$node]!==null)) + { + $this->_entries[$node] = $object; + return; + } + $this->_entries[$node] = $object; + if(empty($parent)) + { + if(isset($this->_entries[$node])) + return; + $this->_tree[$node] = array(); + } + $found = $this->addNode($this->_tree, $parent, $node); + if(!$found && !empty($parent)) + { + $this->_tree[$parent] = array(); + if(!isset($this->_entries[$parent]) || $object !== '') + $this->_entries[$parent] = $object; + $this->addNode($this->_tree, $parent, $node); + } + } + + /** + * Find the parent node and add the new node as its child. + * @param array list of nodes to check + * @param string parent node id + * @param string new node id + * @return boolean true if parent node is found. + */ + protected function addNode(&$childs, $parent, $node) + { + $found = false; + reset($childs); + for($i = 0, $k = count($childs); $i < $k; $i++) + { + $key = key($childs); + next($childs); + if($key == $parent) + { + $found = true; + $childs[$key][$node] = array(); + } + else + { + $found = $found || $this->addNode($childs[$key], $parent, $node); + } + } + return $found; + } + + /** + * @return array object collection + */ + public function collect() + { + while(count($this->_tree) > 0) + $this->collectChildren(null, $this->_tree); + return $this->getCollection(); + } + + /** + * @param array list of nodes to check + * @return boolean true if all nodes are leaf nodes, false otherwise + */ + protected function hasChildren(&$nodes) + { + $hasChildren = false; + foreach($nodes as $node) + if(count($node) != 0) + return true; + return $hasChildren; + } + + /** + * Visit all the child nodes and collect them by removing. + * @param string parent node id + * @param array list of child nodes. + */ + protected function collectChildren($parent, &$nodes) + { + $noChildren = !$this->hasChildren($nodes); + $childs = array(); + for(reset($nodes); $key = key($nodes);) + { + next($nodes); + if($noChildren) + { + $childs[] = $key; + unset($nodes[$key]); + } + else + $this->collectChildren($key, $nodes[$key]); + } + if(count($childs) > 0) + $this->onChildNodesVisited($parent, $childs); + } + + /** + * Set the object properties for all the child nodes visited. + * @param string parent node id + * @param array list of child nodes visited. + */ + protected function onChildNodesVisited($parent, $nodes) + { + if(empty($parent) || empty($this->_entries[$parent])) + return; + + $parentObject = $this->_entries[$parent]['object']; + $property = $this->_entries[$nodes[0]]['property']; + + $list = TPropertyAccess::get($parentObject, $property); + + foreach($nodes as $node) + { + if($list instanceof TList) + $parentObject->{$property}[] = $this->_entries[$node]['object']; + else if(is_array($list)) + $list[] = $this->_entries[$node]['object']; + else + throw new TSqlMapExecutionException( + 'sqlmap_property_must_be_list'); + } + + if(is_array($list)) + TPropertyAccess::set($parentObject, $property, $list); + + if($this->_entries[$parent]['property'] === null) + $this->_list[] = $parentObject; + } + + /** + * @return array object collection. + */ + protected function getCollection() + { + return $this->_list; + } + + public function __sleep() + { + $exprops = array(); $cn = __CLASS__; + if (!count($this->_tree)) $exprops[] = "\0$cn\0_tree"; + if (!count($this->_entries)) $exprops[] = "\0$cn\0_entries"; + if (!count($this->_list)) $exprops[] = "\0$cn\0_list"; + return array_diff(parent::__sleep(),$exprops); + } +} + +/** + * TResultSetListItemParameter class + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TResultSetListItemParameter extends TComponent +{ + private $_resultObject; + private $_parameterObject; + private $_list; + + public function __construct($result, $parameter, &$list) + { + $this->_resultObject = $result; + $this->_parameterObject = $parameter; + $this->_list = &$list; + } + + public function getResult() + { + return $this->_resultObject; + } + + public function getParameter() + { + return $this->_parameterObject; + } + + public function &getList() + { + return $this->_list; + } +} + +/** + * TResultSetMapItemParameter class. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TResultSetMapItemParameter extends TComponent +{ + private $_key; + private $_value; + private $_parameterObject; + private $_map; + + public function __construct($key, $value, $parameter, &$map) + { + $this->_key = $key; + $this->_value = $value; + $this->_parameterObject = $parameter; + $this->_map = &$map; + } + + public function getKey() + { + return $this->_key; + } + + public function getValue() + { + return $this->_value; + } + + public function getParameter() + { + return $this->_parameterObject; + } + + public function &getMap() + { + return $this->_map; + } +} + diff --git a/framework/Data/SqlMap/Statements/TPreparedCommand.php b/framework/Data/SqlMap/Statements/TPreparedCommand.php index 1d4a7088..7aa249ee 100644 --- a/framework/Data/SqlMap/Statements/TPreparedCommand.php +++ b/framework/Data/SqlMap/Statements/TPreparedCommand.php @@ -1,67 +1,67 @@ -<?php
-/**
- * TPreparedCommand class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TPreparedCommand class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-Prado::using('System.Data.Common.TDbMetaData');
-Prado::using('System.Data.Common.TDbCommandBuilder');
-
-/**
- * TPreparedCommand class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TPreparedCommand
-{
- public function create(TSqlMapManager $manager, $connection, $statement, $parameterObject,$skip=null,$max=null)
- {
- $sqlText = $statement->getSQLText();
-
- $prepared = $sqlText->getPreparedStatement($parameterObject);
- $connection->setActive(true);
- $sql = $prepared->getPreparedSql();
-
- if($sqlText instanceof TSimpleDynamicSql)
- $sql = $sqlText->replaceDynamicParameter($sql, $parameterObject);
-
- if($max!==null || $skip!==null)
- {
- $builder = TDbMetaData::getInstance($connection)->createCommandBuilder();
- $sql = $builder->applyLimitOffset($sql,$max,$skip);
- }
- $command = $connection->createCommand($sql);
- $this->applyParameterMap($manager, $command, $prepared, $statement, $parameterObject);
-
- return $command;
- }
-
- protected function applyParameterMap($manager,$command,$prepared, $statement, $parameterObject)
- {
- $properties = $prepared->getParameterNames();
- $parameters = $prepared->getParameterValues();
- $registry=$manager->getTypeHandlers();
- for($i = 0, $k=$properties->getCount(); $i<$k; $i++)
- {
- $property = $statement->parameterMap()->getProperty($i);
- $value = $statement->parameterMap()->getPropertyValue($registry,$property, $parameterObject);
- $dbType = $property->getDbType();
- if($dbType=='') //relies on PHP lax comparison
- $command->bindValue($i+1,$value, TDbCommandBuilder::getPdoType($value));
- else if(strpos($dbType, 'PDO::')===0)
- $command->bindValue($i+1,$value, constant($property->getDbType())); //assumes PDO types, e.g. PDO::PARAM_INT
- else
- $command->bindValue($i+1,$value);
- }
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +Prado::using('System.Data.Common.TDbMetaData'); +Prado::using('System.Data.Common.TDbCommandBuilder'); + +/** + * TPreparedCommand class. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TPreparedCommand +{ + public function create(TSqlMapManager $manager, $connection, $statement, $parameterObject,$skip=null,$max=null) + { + $sqlText = $statement->getSQLText(); + + $prepared = $sqlText->getPreparedStatement($parameterObject); + $connection->setActive(true); + $sql = $prepared->getPreparedSql(); + + if($sqlText instanceof TSimpleDynamicSql) + $sql = $sqlText->replaceDynamicParameter($sql, $parameterObject); + + if($max!==null || $skip!==null) + { + $builder = TDbMetaData::getInstance($connection)->createCommandBuilder(); + $sql = $builder->applyLimitOffset($sql,$max,$skip); + } + $command = $connection->createCommand($sql); + $this->applyParameterMap($manager, $command, $prepared, $statement, $parameterObject); + + return $command; + } + + protected function applyParameterMap($manager,$command,$prepared, $statement, $parameterObject) + { + $properties = $prepared->getParameterNames(); + $parameters = $prepared->getParameterValues(); + $registry=$manager->getTypeHandlers(); + for($i = 0, $k=$properties->getCount(); $i<$k; $i++) + { + $property = $statement->parameterMap()->getProperty($i); + $value = $statement->parameterMap()->getPropertyValue($registry,$property, $parameterObject); + $dbType = $property->getDbType(); + if($dbType=='') //relies on PHP lax comparison + $command->bindValue($i+1,$value, TDbCommandBuilder::getPdoType($value)); + else if(strpos($dbType, 'PDO::')===0) + $command->bindValue($i+1,$value, constant($property->getDbType())); //assumes PDO types, e.g. PDO::PARAM_INT + else + $command->bindValue($i+1,$value); + } + } +} + diff --git a/framework/Data/SqlMap/Statements/TPreparedStatement.php b/framework/Data/SqlMap/Statements/TPreparedStatement.php index d091861f..3abd7442 100644 --- a/framework/Data/SqlMap/Statements/TPreparedStatement.php +++ b/framework/Data/SqlMap/Statements/TPreparedStatement.php @@ -1,57 +1,57 @@ -<?php
-/**
- * TPreparedStatement class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TPreparedStatement class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-/**
- * TpreparedStatement class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TPreparedStatement extends TComponent
-{
- private $_sqlString='';
- private $_parameterNames;
- private $_parameterValues;
-
- public function __construct()
- {
- $this->_parameterNames=new TList;
- $this->_parameterValues=new TMap;
- }
-
- public function getPreparedSql(){ return $this->_sqlString; }
- public function setPreparedSql($value){ $this->_sqlString = $value; }
-
- public function getParameterNames(){ return $this->_parameterNames; }
- public function setParameterNames($value){ $this->_parameterNames = $value; }
-
- public function getParameterValues(){ return $this->_parameterValues; }
- public function setParameterValues($value){ $this->_parameterValues = $value; }
-
- public function __wakeup()
- {
- parent::__wakeup();
- if (!$this->_parameterNames) $this->_parameterNames = new TList;
- if (!$this->_parameterValues) $this->_parameterValues = new TMap;
- }
-
- public function __sleep()
- {
- $exprops = array(); $cn = __CLASS__;
- if (!$this->_parameterNames->getCount()) $exprops[] = "\0$cn\0_parameterNames";
- if (!$this->_parameterValues->getCount()) $exprops[] = "\0$cn\0_parameterValues";
- return array_diff(parent::__sleep(),$exprops);
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +/** + * TpreparedStatement class. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TPreparedStatement extends TComponent +{ + private $_sqlString=''; + private $_parameterNames; + private $_parameterValues; + + public function __construct() + { + $this->_parameterNames=new TList; + $this->_parameterValues=new TMap; + } + + public function getPreparedSql(){ return $this->_sqlString; } + public function setPreparedSql($value){ $this->_sqlString = $value; } + + public function getParameterNames(){ return $this->_parameterNames; } + public function setParameterNames($value){ $this->_parameterNames = $value; } + + public function getParameterValues(){ return $this->_parameterValues; } + public function setParameterValues($value){ $this->_parameterValues = $value; } + + public function __wakeup() + { + parent::__wakeup(); + if (!$this->_parameterNames) $this->_parameterNames = new TList; + if (!$this->_parameterValues) $this->_parameterValues = new TMap; + } + + public function __sleep() + { + $exprops = array(); $cn = __CLASS__; + if (!$this->_parameterNames->getCount()) $exprops[] = "\0$cn\0_parameterNames"; + if (!$this->_parameterValues->getCount()) $exprops[] = "\0$cn\0_parameterValues"; + return array_diff(parent::__sleep(),$exprops); + } +} + diff --git a/framework/Data/SqlMap/Statements/TPreparedStatementFactory.php b/framework/Data/SqlMap/Statements/TPreparedStatementFactory.php index 0d8286fa..9e70ba00 100644 --- a/framework/Data/SqlMap/Statements/TPreparedStatementFactory.php +++ b/framework/Data/SqlMap/Statements/TPreparedStatementFactory.php @@ -1,49 +1,49 @@ -<?php
-/**
- * TPreparedStatementFactory class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-/**
- * TPreparedStatementFactory class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TPreparedStatementFactory
-{
- private $_statement;
- private $_preparedStatement;
- private $_parameterPrefix = 'param';
- private $_commandText;
-
- public function __construct($statement, $sqlString)
- {
- $this->_statement = $statement;
- $this->_commandText = $sqlString;
- }
-
- public function prepare()
- {
- $this->_preparedStatement = new TPreparedStatement();
- $this->_preparedStatement->setPreparedSql($this->_commandText);
- if($this->_statement->parameterMap()!==null)
- $this->createParametersForTextCommand();
- return $this->_preparedStatement;
- }
-
- protected function createParametersForTextCommand()
- {
- foreach($this->_statement->ParameterMap()->getProperties() as $prop)
- $this->_preparedStatement->getParameterNames()->add($prop->getProperty());
- }
-}
-
+<?php +/** + * TPreparedStatementFactory class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +/** + * TPreparedStatementFactory class. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TPreparedStatementFactory +{ + private $_statement; + private $_preparedStatement; + private $_parameterPrefix = 'param'; + private $_commandText; + + public function __construct($statement, $sqlString) + { + $this->_statement = $statement; + $this->_commandText = $sqlString; + } + + public function prepare() + { + $this->_preparedStatement = new TPreparedStatement(); + $this->_preparedStatement->setPreparedSql($this->_commandText); + if($this->_statement->parameterMap()!==null) + $this->createParametersForTextCommand(); + return $this->_preparedStatement; + } + + protected function createParametersForTextCommand() + { + foreach($this->_statement->ParameterMap()->getProperties() as $prop) + $this->_preparedStatement->getParameterNames()->add($prop->getProperty()); + } +} + diff --git a/framework/Data/SqlMap/Statements/TSelectMappedStatement.php b/framework/Data/SqlMap/Statements/TSelectMappedStatement.php index 4b1e5c65..5a2b25f0 100644 --- a/framework/Data/SqlMap/Statements/TSelectMappedStatement.php +++ b/framework/Data/SqlMap/Statements/TSelectMappedStatement.php @@ -1,36 +1,36 @@ -<?php
-/**
- * TSelectMappedStatement class.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TSelectMappedStatement class. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-/**
- * TSelectMappedStatment class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TSelectMappedStatement extends TMappedStatement
-{
- public function executeInsert($connection, $parameter)
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_cannot_execute_insert', get_class($this), $this->getID());
- }
-
- public function executeUpdate($connection, $parameter)
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_cannot_execute_update', get_class($this), $this->getID());
- }
-
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +/** + * TSelectMappedStatment class. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TSelectMappedStatement extends TMappedStatement +{ + public function executeInsert($connection, $parameter) + { + throw new TSqlMapExecutionException( + 'sqlmap_cannot_execute_insert', get_class($this), $this->getID()); + } + + public function executeUpdate($connection, $parameter) + { + throw new TSqlMapExecutionException( + 'sqlmap_cannot_execute_update', get_class($this), $this->getID()); + } + +} + diff --git a/framework/Data/SqlMap/Statements/TSimpleDynamicSql.php b/framework/Data/SqlMap/Statements/TSimpleDynamicSql.php index 81ae4d76..377563ed 100644 --- a/framework/Data/SqlMap/Statements/TSimpleDynamicSql.php +++ b/framework/Data/SqlMap/Statements/TSimpleDynamicSql.php @@ -1,40 +1,40 @@ -<?php
-/**
- * TSimpleDynamicSql class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TSimpleDynamicSql class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-/**
- * TSimpleDynamicSql class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TSimpleDynamicSql extends TStaticSql
-{
- private $_mappings=array();
-
- public function __construct($mappings)
- {
- $this->_mappings = $mappings;
- }
-
- public function replaceDynamicParameter($sql, $parameter)
- {
- foreach($this->_mappings as $property)
- {
- $value = TPropertyAccess::get($parameter, $property);
- $sql = preg_replace('/'.TSimpleDynamicParser::DYNAMIC_TOKEN.'/', str_replace('$', '\$', $value), $sql, 1);
- }
- return $sql;
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +/** + * TSimpleDynamicSql class. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TSimpleDynamicSql extends TStaticSql +{ + private $_mappings=array(); + + public function __construct($mappings) + { + $this->_mappings = $mappings; + } + + public function replaceDynamicParameter($sql, $parameter) + { + foreach($this->_mappings as $property) + { + $value = TPropertyAccess::get($parameter, $property); + $sql = preg_replace('/'.TSimpleDynamicParser::DYNAMIC_TOKEN.'/', str_replace('$', '\$', $value), $sql, 1); + } + return $sql; + } +} + diff --git a/framework/Data/SqlMap/Statements/TStaticSql.php b/framework/Data/SqlMap/Statements/TStaticSql.php index e6949c35..6374745d 100644 --- a/framework/Data/SqlMap/Statements/TStaticSql.php +++ b/framework/Data/SqlMap/Statements/TStaticSql.php @@ -1,36 +1,36 @@ -<?php
-/**
- * TStaticSql class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TStaticSql class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-/**
- * TStaticSql class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TStaticSql extends TComponent
-{
- private $_preparedStatement;
-
- public function buildPreparedStatement($statement, $sqlString)
- {
- $factory = new TPreparedStatementFactory($statement, $sqlString);
- $this->_preparedStatement = $factory->prepare();
- }
-
- public function getPreparedStatement($parameter=null)
- {
- return $this->_preparedStatement;
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +/** + * TStaticSql class. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TStaticSql extends TComponent +{ + private $_preparedStatement; + + public function buildPreparedStatement($statement, $sqlString) + { + $factory = new TPreparedStatementFactory($statement, $sqlString); + $this->_preparedStatement = $factory->prepare(); + } + + public function getPreparedStatement($parameter=null) + { + return $this->_preparedStatement; + } +} + diff --git a/framework/Data/SqlMap/Statements/TUpdateMappedStatement.php b/framework/Data/SqlMap/Statements/TUpdateMappedStatement.php index 76bc8ae5..af300a0e 100644 --- a/framework/Data/SqlMap/Statements/TUpdateMappedStatement.php +++ b/framework/Data/SqlMap/Statements/TUpdateMappedStatement.php @@ -1,49 +1,49 @@ -<?php
-/**
- * TUpdateMappedStatement class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TUpdateMappedStatement class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- */
-
-/**
- * TUpdateMappedStatement class.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap.Statements
- * @since 3.1
- */
-class TUpdateMappedStatement extends TMappedStatement
-{
- public function executeInsert($connection, $parameter)
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_cannot_execute_insert', get_class($this), $this->getID());
- }
-
- public function executeQueryForMap($connection, $parameter, $keyProperty,
- $valueProperty=null)
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_cannot_execute_query_for_map', get_class($this), $this->getID());
- }
-
- public function executeQueryForList($connection, $parameter, $result=null,
- $skip=-1, $max=-1)
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_cannot_execute_query_for_list', get_class($this), $this->getID());
- }
-
- public function executeQueryForObject($connection, $parameter, $result=null)
- {
- throw new TSqlMapExecutionException(
- 'sqlmap_cannot_execute_query_for_object', get_class($this), $this->getID());
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Statements + */ + +/** + * TUpdateMappedStatement class. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TUpdateMappedStatement extends TMappedStatement +{ + public function executeInsert($connection, $parameter) + { + throw new TSqlMapExecutionException( + 'sqlmap_cannot_execute_insert', get_class($this), $this->getID()); + } + + public function executeQueryForMap($connection, $parameter, $keyProperty, + $valueProperty=null) + { + throw new TSqlMapExecutionException( + 'sqlmap_cannot_execute_query_for_map', get_class($this), $this->getID()); + } + + public function executeQueryForList($connection, $parameter, $result=null, + $skip=-1, $max=-1) + { + throw new TSqlMapExecutionException( + 'sqlmap_cannot_execute_query_for_list', get_class($this), $this->getID()); + } + + public function executeQueryForObject($connection, $parameter, $result=null) + { + throw new TSqlMapExecutionException( + 'sqlmap_cannot_execute_query_for_object', get_class($this), $this->getID()); + } +} + diff --git a/framework/Data/SqlMap/TSqlMapConfig.php b/framework/Data/SqlMap/TSqlMapConfig.php index 1e9dcdd3..ee3685fe 100644 --- a/framework/Data/SqlMap/TSqlMapConfig.php +++ b/framework/Data/SqlMap/TSqlMapConfig.php @@ -1,181 +1,181 @@ -<?php
-/**
- * TSqlMapConfig class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TSqlMapConfig class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap
- */
-
-Prado::using('System.Data.TDataSourceConfig');
-
-/**
- * TSqlMapConfig module configuration class.
- *
- * Database connection and TSqlMapManager configuration.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapConfig extends TDataSourceConfig
-{
- private $_configFile;
- private $_sqlmap;
- private $_enableCache=false;
-
- /**
- * File extension of external configuration file
- */
- const CONFIG_FILE_EXT='.xml';
-
- /**
- * @return string module ID + configuration file path.
- */
- private function getCacheKey()
- {
- return $this->getID().$this->getConfigFile();
- }
-
- /**
- * Deletes the configuration cache.
- */
- public function clearCache()
- {
- $cache = $this->getApplication()->getCache();
- if($cache !== null) {
- $cache->delete($this->getCacheKey());
- }
- }
-
- /**
- * Create and configure the data mapper using sqlmap configuration file.
- * Or if cache is enabled and manager already cached load from cache.
- * If cache is enabled, the data mapper instance is cached.
- *
- * @return TSqlMapManager SqlMap manager instance
- * @since 3.1.7
- */
- public function getSqlMapManager() {
- Prado::using('System.Data.SqlMap.TSqlMapManager');
- if(($manager = $this->loadCachedSqlMapManager())===null)
- {
- $manager = new TSqlMapManager($this->getDbConnection());
- if(strlen($file=$this->getConfigFile()) > 0)
- {
- $manager->configureXml($file);
- $this->cacheSqlMapManager($manager);
- }
- }
- elseif($this->getConnectionID() !== '') {
- $manager->setDbConnection($this->getDbConnection());
- }
- return $manager;
- }
-
- /**
- * Saves the current SqlMap manager to cache.
- * @return boolean true if SqlMap manager was cached, false otherwise.
- */
- protected function cacheSqlMapManager($manager)
- {
- if($this->getEnableCache())
- {
- $cache = $this->getApplication()->getCache();
- if($cache !== null) {
- $dependencies = null;
- if($this->getApplication()->getMode() !== TApplicationMode::Performance)
- $dependencies = $manager->getCacheDependencies();
- return $cache->set($this->getCacheKey(), $manager, 0, $dependencies);
- }
- }
- return false;
- }
-
- /**
- * Loads SqlMap manager from cache.
- * @return TSqlMapManager SqlMap manager intance if load was successful, null otherwise.
- */
- protected function loadCachedSqlMapManager()
- {
- if($this->getEnableCache())
- {
- $cache = $this->getApplication()->getCache();
- if($cache !== null)
- {
- $manager = $cache->get($this->getCacheKey());
- if($manager instanceof TSqlMapManager)
- return $manager;
- }
- }
- return null;
- }
-
- /**
- * @return string SqlMap configuration file.
- */
- public function getConfigFile()
- {
- return $this->_configFile;
- }
-
- /**
- * @param string external configuration file in namespace format. The file
- * extension must be '.xml'.
- * @throws TConfigurationException if the file is invalid.
- */
- public function setConfigFile($value)
- {
- if(is_file($value))
- $this->_configFile=$value;
- else
- {
- $file = Prado::getPathOfNamespace($value,self::CONFIG_FILE_EXT);
- if($file === null || !is_file($file))
- throw new TConfigurationException('sqlmap_configfile_invalid',$value);
- else
- $this->_configFile = $file;
- }
- }
-
- /**
- * Set true to cache sqlmap instances.
- * @param boolean true to cache sqlmap instance.
- */
- public function setEnableCache($value)
- {
- $this->_enableCache = TPropertyValue::ensureBoolean($value);
- }
-
- /**
- * @return boolean true if configuration should be cached, false otherwise.
- */
- public function getEnableCache()
- {
- return $this->_enableCache;
- }
-
- /**
- * @return TSqlMapGateway SqlMap gateway instance.
- */
- protected function createSqlMapGateway()
- {
- return $this->getSqlMapManager()->getSqlmapGateway();
- }
-
- /**
- * Initialize the sqlmap if necessary, returns the TSqlMapGateway instance.
- * @return TSqlMapGateway SqlMap gateway instance.
- */
- public function getClient()
- {
- if($this->_sqlmap===null )
- $this->_sqlmap=$this->createSqlMapGateway();
- return $this->_sqlmap;
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap + */ + +Prado::using('System.Data.TDataSourceConfig'); + +/** + * TSqlMapConfig module configuration class. + * + * Database connection and TSqlMapManager configuration. + * + * @author Wei Zhuo <weizho[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapConfig extends TDataSourceConfig +{ + private $_configFile; + private $_sqlmap; + private $_enableCache=false; + + /** + * File extension of external configuration file + */ + const CONFIG_FILE_EXT='.xml'; + + /** + * @return string module ID + configuration file path. + */ + private function getCacheKey() + { + return $this->getID().$this->getConfigFile(); + } + + /** + * Deletes the configuration cache. + */ + public function clearCache() + { + $cache = $this->getApplication()->getCache(); + if($cache !== null) { + $cache->delete($this->getCacheKey()); + } + } + + /** + * Create and configure the data mapper using sqlmap configuration file. + * Or if cache is enabled and manager already cached load from cache. + * If cache is enabled, the data mapper instance is cached. + * + * @return TSqlMapManager SqlMap manager instance + * @since 3.1.7 + */ + public function getSqlMapManager() { + Prado::using('System.Data.SqlMap.TSqlMapManager'); + if(($manager = $this->loadCachedSqlMapManager())===null) + { + $manager = new TSqlMapManager($this->getDbConnection()); + if(strlen($file=$this->getConfigFile()) > 0) + { + $manager->configureXml($file); + $this->cacheSqlMapManager($manager); + } + } + elseif($this->getConnectionID() !== '') { + $manager->setDbConnection($this->getDbConnection()); + } + return $manager; + } + + /** + * Saves the current SqlMap manager to cache. + * @return boolean true if SqlMap manager was cached, false otherwise. + */ + protected function cacheSqlMapManager($manager) + { + if($this->getEnableCache()) + { + $cache = $this->getApplication()->getCache(); + if($cache !== null) { + $dependencies = null; + if($this->getApplication()->getMode() !== TApplicationMode::Performance) + $dependencies = $manager->getCacheDependencies(); + return $cache->set($this->getCacheKey(), $manager, 0, $dependencies); + } + } + return false; + } + + /** + * Loads SqlMap manager from cache. + * @return TSqlMapManager SqlMap manager intance if load was successful, null otherwise. + */ + protected function loadCachedSqlMapManager() + { + if($this->getEnableCache()) + { + $cache = $this->getApplication()->getCache(); + if($cache !== null) + { + $manager = $cache->get($this->getCacheKey()); + if($manager instanceof TSqlMapManager) + return $manager; + } + } + return null; + } + + /** + * @return string SqlMap configuration file. + */ + public function getConfigFile() + { + return $this->_configFile; + } + + /** + * @param string external configuration file in namespace format. The file + * extension must be '.xml'. + * @throws TConfigurationException if the file is invalid. + */ + public function setConfigFile($value) + { + if(is_file($value)) + $this->_configFile=$value; + else + { + $file = Prado::getPathOfNamespace($value,self::CONFIG_FILE_EXT); + if($file === null || !is_file($file)) + throw new TConfigurationException('sqlmap_configfile_invalid',$value); + else + $this->_configFile = $file; + } + } + + /** + * Set true to cache sqlmap instances. + * @param boolean true to cache sqlmap instance. + */ + public function setEnableCache($value) + { + $this->_enableCache = TPropertyValue::ensureBoolean($value); + } + + /** + * @return boolean true if configuration should be cached, false otherwise. + */ + public function getEnableCache() + { + return $this->_enableCache; + } + + /** + * @return TSqlMapGateway SqlMap gateway instance. + */ + protected function createSqlMapGateway() + { + return $this->getSqlMapManager()->getSqlmapGateway(); + } + + /** + * Initialize the sqlmap if necessary, returns the TSqlMapGateway instance. + * @return TSqlMapGateway SqlMap gateway instance. + */ + public function getClient() + { + if($this->_sqlmap===null ) + $this->_sqlmap=$this->createSqlMapGateway(); + return $this->_sqlmap; + } +} + diff --git a/framework/Data/SqlMap/TSqlMapGateway.php b/framework/Data/SqlMap/TSqlMapGateway.php index f1915e86..3be4e12f 100644 --- a/framework/Data/SqlMap/TSqlMapGateway.php +++ b/framework/Data/SqlMap/TSqlMapGateway.php @@ -1,261 +1,261 @@ -<?php
-/**
- * TSqlMapGateway class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TSqlMapGateway class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap
- */
-
-Prado::using('System.Data.SqlMap.TSqlMapManager');
-
-/**
- * DataMapper client, a fascade to provide access the rest of the DataMapper
- * framework. It provides three core functions:
- *
- * # execute an update query (including insert and delete).
- * # execute a select query for a single object
- * # execute a select query for a list of objects
- *
- * This class should be instantiated from a TSqlMapManager instance.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapGateway extends TComponent
-{
- /**
- * @var TSqlMapManager manager
- */
- private $_manager;
-
- public function __construct($manager)
- {
- $this->_manager=$manager;
- }
-
- /**
- * @return TSqlMapManager sqlmap manager.
- */
- public function getSqlMapManager()
- {
- return $this->_manager;
- }
-
- /**
- * @return TDbConnection database connection.
- */
- public function getDbConnection()
- {
- return $this->getSqlMapManager()->getDbConnection();
- }
-
- /**
- * Executes a Sql SELECT statement that returns that returns data
- * to populate a single object instance.
- *
- * The parameter object is generally used to supply the input
- * data for the WHERE clause parameter(s) of the SELECT statement.
- *
- * @param string The name of the sql statement to execute.
- * @param mixed The object used to set the parameters in the SQL.
- * @param mixed An object of the type to be returned.
- * @return object A single result object populated with the result set data.
- */
- public function queryForObject($statementName, $parameter=null, $result=null)
- {
- $statement = $this->getSqlMapManager()->getMappedStatement($statementName);
- return $statement->executeQueryForObject($this->getDbConnection(), $parameter, $result);
- }
-
- /**
- * Executes a Sql SELECT statement that returns data to populate a number
- * of result objects.
- *
- * The parameter object is generally used to supply the input
- * data for the WHERE clause parameter(s) of the SELECT statement.
- *
- * @param string The name of the sql statement to execute.
- * @param mixed The object used to set the parameters in the SQL.
- * @param TList An Ilist object used to hold the objects,
- * pass in null if want to return a list instead.
- * @param int The number of rows to skip over.
- * @param int The maximum number of rows to return.
- * @return TList A List of result objects.
- */
- public function queryForList($statementName, $parameter=null, $result=null, $skip=-1, $max=-1)
- {
- $statement = $this->getSqlMapManager()->getMappedStatement($statementName);
- return $statement->executeQueryForList($this->getDbConnection(),$parameter, $result, $skip, $max);
- }
-
- /**
- * Runs a query for list with a custom object that gets a chance to deal
- * with each row as it is processed.
- *
- * Example: $sqlmap->queryWithRowDelegate('getAccounts', array($this, 'rowHandler'));
- *
- * @param string The name of the sql statement to execute.
- * @param callback Row delegate handler, a valid callback required.
- * @param mixed The object used to set the parameters in the SQL.
- * @param TList An Ilist object used to hold the objects,
- * pass in null if want to return a list instead.
- * @param int The number of rows to skip over.
- * @param int The maximum number of rows to return.
- * @return TList A List of result objects.
- */
- public function queryWithRowDelegate($statementName, $delegate, $parameter=null, $result=null, $skip=-1, $max=-1)
- {
- $statement = $this->getSqlMapManager()->getMappedStatement($statementName);
- return $statement->executeQueryForList($this->getDbConnection(), $parameter, $result, $skip, $max, $delegate);
- }
-
- /**
- * Executes the SQL and retuns a subset of the results in a dynamic
- * TPagedList that can be used to automatically scroll through results
- * from a database table.
- * @param string The name of the sql statement to execute.
- * @param mixed The object used to set the parameters in the SQL.
- * @param integer The maximum number of objects to store in each page.
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap + */ + +Prado::using('System.Data.SqlMap.TSqlMapManager'); + +/** + * DataMapper client, a fascade to provide access the rest of the DataMapper + * framework. It provides three core functions: + * + * # execute an update query (including insert and delete). + * # execute a select query for a single object + * # execute a select query for a list of objects + * + * This class should be instantiated from a TSqlMapManager instance. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapGateway extends TComponent +{ + /** + * @var TSqlMapManager manager + */ + private $_manager; + + public function __construct($manager) + { + $this->_manager=$manager; + } + + /** + * @return TSqlMapManager sqlmap manager. + */ + public function getSqlMapManager() + { + return $this->_manager; + } + + /** + * @return TDbConnection database connection. + */ + public function getDbConnection() + { + return $this->getSqlMapManager()->getDbConnection(); + } + + /** + * Executes a Sql SELECT statement that returns that returns data + * to populate a single object instance. + * + * The parameter object is generally used to supply the input + * data for the WHERE clause parameter(s) of the SELECT statement. + * + * @param string The name of the sql statement to execute. + * @param mixed The object used to set the parameters in the SQL. + * @param mixed An object of the type to be returned. + * @return object A single result object populated with the result set data. + */ + public function queryForObject($statementName, $parameter=null, $result=null) + { + $statement = $this->getSqlMapManager()->getMappedStatement($statementName); + return $statement->executeQueryForObject($this->getDbConnection(), $parameter, $result); + } + + /** + * Executes a Sql SELECT statement that returns data to populate a number + * of result objects. + * + * The parameter object is generally used to supply the input + * data for the WHERE clause parameter(s) of the SELECT statement. + * + * @param string The name of the sql statement to execute. + * @param mixed The object used to set the parameters in the SQL. + * @param TList An Ilist object used to hold the objects, + * pass in null if want to return a list instead. + * @param int The number of rows to skip over. + * @param int The maximum number of rows to return. + * @return TList A List of result objects. + */ + public function queryForList($statementName, $parameter=null, $result=null, $skip=-1, $max=-1) + { + $statement = $this->getSqlMapManager()->getMappedStatement($statementName); + return $statement->executeQueryForList($this->getDbConnection(),$parameter, $result, $skip, $max); + } + + /** + * Runs a query for list with a custom object that gets a chance to deal + * with each row as it is processed. + * + * Example: $sqlmap->queryWithRowDelegate('getAccounts', array($this, 'rowHandler')); + * + * @param string The name of the sql statement to execute. + * @param callback Row delegate handler, a valid callback required. + * @param mixed The object used to set the parameters in the SQL. + * @param TList An Ilist object used to hold the objects, + * pass in null if want to return a list instead. + * @param int The number of rows to skip over. + * @param int The maximum number of rows to return. + * @return TList A List of result objects. + */ + public function queryWithRowDelegate($statementName, $delegate, $parameter=null, $result=null, $skip=-1, $max=-1) + { + $statement = $this->getSqlMapManager()->getMappedStatement($statementName); + return $statement->executeQueryForList($this->getDbConnection(), $parameter, $result, $skip, $max, $delegate); + } + + /** + * Executes the SQL and retuns a subset of the results in a dynamic + * TPagedList that can be used to automatically scroll through results + * from a database table. + * @param string The name of the sql statement to execute. + * @param mixed The object used to set the parameters in the SQL. + * @param integer The maximum number of objects to store in each page. * @param integer The number of the page to initially load into the list. - * @return TPagedList A PaginatedList of beans containing the rows.
- */
- public function queryForPagedList($statementName, $parameter=null, $pageSize=10, $page=0)
- {
- $statement = $this->getSqlMapManager()->getMappedStatement($statementName);
- return new TSqlMapPagedList($statement, $parameter, $pageSize, null, $page);
- }
-
- /**
- * Executes the SQL and retuns a subset of the results in a dynamic
- * TPagedList that can be used to automatically scroll through results
- * from a database table.
- *
- * Runs paged list query with row delegate
- * Example: $sqlmap->queryForPagedListWithRowDelegate('getAccounts', array($this, 'rowHandler'));
- *
- * @param string The name of the sql statement to execute.
- * @param callback Row delegate handler, a valid callback required.
- * @param mixed The object used to set the parameters in the SQL.
- * @param integer The maximum number of objects to store in each page.
+ * @return TPagedList A PaginatedList of beans containing the rows. + */ + public function queryForPagedList($statementName, $parameter=null, $pageSize=10, $page=0) + { + $statement = $this->getSqlMapManager()->getMappedStatement($statementName); + return new TSqlMapPagedList($statement, $parameter, $pageSize, null, $page); + } + + /** + * Executes the SQL and retuns a subset of the results in a dynamic + * TPagedList that can be used to automatically scroll through results + * from a database table. + * + * Runs paged list query with row delegate + * Example: $sqlmap->queryForPagedListWithRowDelegate('getAccounts', array($this, 'rowHandler')); + * + * @param string The name of the sql statement to execute. + * @param callback Row delegate handler, a valid callback required. + * @param mixed The object used to set the parameters in the SQL. + * @param integer The maximum number of objects to store in each page. * @param integer The number of the page to initially load into the list. - * @return TPagedList A PaginatedList of beans containing the rows.
- */
- public function queryForPagedListWithRowDelegate($statementName,$delegate, $parameter=null, $pageSize=10, $page=0)
- {
- $statement = $this->getSqlMapManager()->getMappedStatement($statementName);
- return new TSqlMapPagedList($statement, $parameter, $pageSize, $delegate,$page);
- }
-
-
- /**
- * Executes the SQL and retuns all rows selected in a map that is keyed on
- * the property named in the keyProperty parameter. The value at each key
- * will be the value of the property specified in the valueProperty
- * parameter. If valueProperty is null, the entire result object will be
- * entered.
- * @param string The name of the sql statement to execute.
- * @param mixed The object used to set the parameters in the SQL.
- * @param string The property of the result object to be used as the key.
- * @param string The property of the result object to be used as the value.
- * @return TMap Array object containing the rows keyed by keyProperty.
- */
- public function queryForMap($statementName, $parameter=null, $keyProperty=null, $valueProperty=null, $skip=-1, $max=-1)
- {
- $statement = $this->getSqlMapManager()->getMappedStatement($statementName);
- return $statement->executeQueryForMap($this->getDbConnection(), $parameter, $keyProperty, $valueProperty, $skip, $max);
- }
-
- /**
- * Runs a query with a custom object that gets a chance to deal
- * with each row as it is processed.
- *
- * Example: $sqlmap->queryForMapWithRowDelegate('getAccounts', array($this, 'rowHandler'));
- *
- * @param string The name of the sql statement to execute.
- * @param callback Row delegate handler, a valid callback required.
- * @param mixed The object used to set the parameters in the SQL.
- * @param string The property of the result object to be used as the key.
- * @param string The property of the result object to be used as the value.
- * @return TMap Array object containing the rows keyed by keyProperty.
- */
- public function queryForMapWithRowDelegate($statementName, $delegate, $parameter=null, $keyProperty=null, $valueProperty=null, $skip=-1, $max=-1)
- {
- $statement = $this->getSqlMapManager()->getMappedStatement($statementName);
- return $statement->executeQueryForMap($this->getDbConnection(), $parameter, $keyProperty, $valueProperty, $skip, $max, $delegate);
- }
-
- /**
- * Executes a Sql INSERT statement.
- *
- * Insert is a bit different from other update methods, as it provides
- * facilities for returning the primary key of the newly inserted row
- * (rather than the effected rows),
- *
- * The parameter object is generally used to supply the input data for the
- * INSERT values.
- *
- * @param string The name of the statement to execute.
- * @param string The parameter object.
- * @return mixed The primary key of the newly inserted row.
- * This might be automatically generated by the RDBMS,
- * or selected from a sequence table or other source.
- */
- public function insert($statementName, $parameter=null)
- {
- $statement = $this->getSqlMapManager()->getMappedStatement($statementName);
- return $statement->executeInsert($this->getDbConnection(), $parameter);
- }
-
- /**
- * Executes a Sql UPDATE statement.
- *
- * Update can also be used for any other update statement type, such as
- * inserts and deletes. Update returns the number of rows effected.
- *
- * The parameter object is generally used to supply the input data for the
- * UPDATE values as well as the WHERE clause parameter(s).
- *
- * @param string The name of the statement to execute.
- * @param mixed The parameter object.
- * @return integer The number of rows effected.
- */
- public function update($statementName, $parameter=null)
- {
- $statement = $this->getSqlMapManager()->getMappedStatement($statementName);
- return $statement->executeUpdate($this->getDbConnection(), $parameter);
- }
-
- /**
- * Executes a Sql DELETE statement. Delete returns the number of rows effected.
- * @param string The name of the statement to execute.
- * @param mixed The parameter object.
- * @return integer The number of rows effected.
- */
- public function delete($statementName, $parameter=null)
- {
- return $this->update($statementName, $parameter);
- }
-
- /**
- * Flushes all cached objects that belong to this SqlMap
- */
- public function flushCaches()
- {
- $this->getSqlMapManager()->flushCacheModels();
- }
-
- /**
- * @param TSqlMapTypeHandler new type handler.
- */
- public function registerTypeHandler($typeHandler)
- {
- $this->getSqlMapManager()->getTypeHandlers()->registerTypeHandler($typeHandler);
- }
-}
-
+ * @return TPagedList A PaginatedList of beans containing the rows. + */ + public function queryForPagedListWithRowDelegate($statementName,$delegate, $parameter=null, $pageSize=10, $page=0) + { + $statement = $this->getSqlMapManager()->getMappedStatement($statementName); + return new TSqlMapPagedList($statement, $parameter, $pageSize, $delegate,$page); + } + + + /** + * Executes the SQL and retuns all rows selected in a map that is keyed on + * the property named in the keyProperty parameter. The value at each key + * will be the value of the property specified in the valueProperty + * parameter. If valueProperty is null, the entire result object will be + * entered. + * @param string The name of the sql statement to execute. + * @param mixed The object used to set the parameters in the SQL. + * @param string The property of the result object to be used as the key. + * @param string The property of the result object to be used as the value. + * @return TMap Array object containing the rows keyed by keyProperty. + */ + public function queryForMap($statementName, $parameter=null, $keyProperty=null, $valueProperty=null, $skip=-1, $max=-1) + { + $statement = $this->getSqlMapManager()->getMappedStatement($statementName); + return $statement->executeQueryForMap($this->getDbConnection(), $parameter, $keyProperty, $valueProperty, $skip, $max); + } + + /** + * Runs a query with a custom object that gets a chance to deal + * with each row as it is processed. + * + * Example: $sqlmap->queryForMapWithRowDelegate('getAccounts', array($this, 'rowHandler')); + * + * @param string The name of the sql statement to execute. + * @param callback Row delegate handler, a valid callback required. + * @param mixed The object used to set the parameters in the SQL. + * @param string The property of the result object to be used as the key. + * @param string The property of the result object to be used as the value. + * @return TMap Array object containing the rows keyed by keyProperty. + */ + public function queryForMapWithRowDelegate($statementName, $delegate, $parameter=null, $keyProperty=null, $valueProperty=null, $skip=-1, $max=-1) + { + $statement = $this->getSqlMapManager()->getMappedStatement($statementName); + return $statement->executeQueryForMap($this->getDbConnection(), $parameter, $keyProperty, $valueProperty, $skip, $max, $delegate); + } + + /** + * Executes a Sql INSERT statement. + * + * Insert is a bit different from other update methods, as it provides + * facilities for returning the primary key of the newly inserted row + * (rather than the effected rows), + * + * The parameter object is generally used to supply the input data for the + * INSERT values. + * + * @param string The name of the statement to execute. + * @param string The parameter object. + * @return mixed The primary key of the newly inserted row. + * This might be automatically generated by the RDBMS, + * or selected from a sequence table or other source. + */ + public function insert($statementName, $parameter=null) + { + $statement = $this->getSqlMapManager()->getMappedStatement($statementName); + return $statement->executeInsert($this->getDbConnection(), $parameter); + } + + /** + * Executes a Sql UPDATE statement. + * + * Update can also be used for any other update statement type, such as + * inserts and deletes. Update returns the number of rows effected. + * + * The parameter object is generally used to supply the input data for the + * UPDATE values as well as the WHERE clause parameter(s). + * + * @param string The name of the statement to execute. + * @param mixed The parameter object. + * @return integer The number of rows effected. + */ + public function update($statementName, $parameter=null) + { + $statement = $this->getSqlMapManager()->getMappedStatement($statementName); + return $statement->executeUpdate($this->getDbConnection(), $parameter); + } + + /** + * Executes a Sql DELETE statement. Delete returns the number of rows effected. + * @param string The name of the statement to execute. + * @param mixed The parameter object. + * @return integer The number of rows effected. + */ + public function delete($statementName, $parameter=null) + { + return $this->update($statementName, $parameter); + } + + /** + * Flushes all cached objects that belong to this SqlMap + */ + public function flushCaches() + { + $this->getSqlMapManager()->flushCacheModels(); + } + + /** + * @param TSqlMapTypeHandler new type handler. + */ + public function registerTypeHandler($typeHandler) + { + $this->getSqlMapManager()->getTypeHandlers()->registerTypeHandler($typeHandler); + } +} + diff --git a/framework/Data/SqlMap/TSqlMapManager.php b/framework/Data/SqlMap/TSqlMapManager.php index e27ad079..d8a16407 100644 --- a/framework/Data/SqlMap/TSqlMapManager.php +++ b/framework/Data/SqlMap/TSqlMapManager.php @@ -1,274 +1,274 @@ -<?php
-/**
- * TSqlMapManager class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TSqlMapManager class file. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.SqlMap
- */
-
-Prado::using('System.Data.SqlMap.TSqlMapGateway');
-Prado::using('System.Data.SqlMap.DataMapper.TSqlMapException');
-Prado::using('System.Data.SqlMap.DataMapper.TSqlMapTypeHandlerRegistry');
-Prado::using('System.Data.SqlMap.DataMapper.TSqlMapCache');
-Prado::using('System.Data.SqlMap.Configuration.TSqlMapStatement');
-Prado::using('System.Data.SqlMap.Configuration.*');
-Prado::using('System.Data.SqlMap.DataMapper.*');
-Prado::using('System.Data.SqlMap.Statements.*');
-Prado::using('System.Caching.TCache');
-
-
-/**
- * TSqlMapManager class holds the sqlmap configuation result maps, statements
- * parameter maps and a type handler factory.
- *
- * Use {@link SqlMapGateway getSqlMapGateway()} property to obtain the gateway
- * instance used for querying statements defined in the SqlMap configuration files.
- *
- * <code>
- * $conn = new TDbConnection($dsn,$dbuser,$dbpass);
- * $manager = new TSqlMapManager($conn);
- * $manager->configureXml('mydb-sqlmap.xml');
- * $sqlmap = $manager->getSqlMapGateway();
- * $result = $sqlmap->queryForObject('Products');
- * </code>
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.SqlMap
- * @since 3.1
- */
-class TSqlMapManager extends TComponent
-{
- private $_mappedStatements;
- private $_resultMaps;
- private $_parameterMaps;
- private $_typeHandlers;
- private $_cacheModels;
-
- private $_connection;
- private $_gateway;
- private $_cacheDependencies;
-
- /**
- * Constructor, create a new SqlMap manager.
- * @param TDbConnection database connection
- * @param string configuration file.
- */
- public function __construct($connection=null)
- {
- $this->_connection=$connection;
-
- $this->_mappedStatements=new TMap;
- $this->_resultMaps=new TMap;
- $this->_parameterMaps=new TMap;
- $this->_cacheModels=new TMap;
- }
-
- /**
- * @param TDbConnection default database connection
- */
- public function setDbConnection($conn)
- {
- $this->_connection=$conn;
- }
-
- /**
- * @return TDbConnection default database connection
- */
- public function getDbConnection()
- {
- return $this->_connection;
- }
-
- /**
- * @return TTypeHandlerFactory The TypeHandlerFactory
- */
- public function getTypeHandlers()
- {
- if($this->_typeHandlers===null)
- $this->_typeHandlers= new TSqlMapTypeHandlerRegistry();
- return $this->_typeHandlers;
- }
-
- /**
- * @return TSqlMapGateway SqlMap gateway.
- */
- public function getSqlmapGateway()
- {
- if($this->_gateway===null)
- $this->_gateway=$this->createSqlMapGateway();
- return $this->_gateway;
- }
-
- /**
- * Loads and parses the SqlMap configuration file.
- * @param string xml configuration file.
- */
- public function configureXml($file)
- {
- $config = new TSqlMapXmlConfiguration($this);
- $config->configure($file);
- }
-
- /**
- * @return TChainedCacheDependency
- * @since 3.1.5
- */
- public function getCacheDependencies()
- {
- if($this->_cacheDependencies === null)
- $this->_cacheDependencies=new TChainedCacheDependency();
-
- return $this->_cacheDependencies;
- }
-
- /**
- * Configures the current TSqlMapManager using the given xml configuration file
- * defined in {@link ConfigFile setConfigFile()}.
- * @return TSqlMapGateway create and configure a new TSqlMapGateway.
- */
- protected function createSqlMapGateway()
- {
- return new TSqlMapGateway($this);
- }
-
- /**
- * @return TMap mapped statements collection.
- */
- public function getMappedStatements()
- {
- return $this->_mappedStatements;
- }
-
- /**
- * Gets a MappedStatement by name.
- * @param string The name of the statement.
- * @return IMappedStatement The MappedStatement
- * @throws TSqlMapUndefinedException
- */
- public function getMappedStatement($name)
- {
- if($this->_mappedStatements->contains($name) == false)
- throw new TSqlMapUndefinedException('sqlmap_contains_no_statement', $name);
- return $this->_mappedStatements[$name];
- }
-
- /**
- * Adds a (named) MappedStatement.
- * @param string The key name
- * @param IMappedStatement The statement to add
- * @throws TSqlMapDuplicateException
- */
- public function addMappedStatement(IMappedStatement $statement)
- {
- $key = $statement->getID();
- if($this->_mappedStatements->contains($key) == true)
- throw new TSqlMapDuplicateException('sqlmap_already_contains_statement', $key);
- $this->_mappedStatements->add($key, $statement);
- }
-
- /**
- * @return TMap result maps collection.
- */
- public function getResultMaps()
- {
- return $this->_resultMaps;
- }
-
- /**
- * Gets a named result map
- * @param string result name.
- * @return TResultMap the result map.
- * @throws TSqlMapUndefinedException
- */
- public function getResultMap($name)
- {
- if($this->_resultMaps->contains($name) == false)
- throw new TSqlMapUndefinedException('sqlmap_contains_no_result_map', $name);
- return $this->_resultMaps[$name];
- }
-
- /**
- * @param TResultMap add a new result map to this SQLMap
- * @throws TSqlMapDuplicateException
- */
- public function addResultMap(TResultMap $result)
- {
- $key = $result->getID();
- if($this->_resultMaps->contains($key) == true)
- throw new TSqlMapDuplicateException('sqlmap_already_contains_result_map', $key);
- $this->_resultMaps->add($key, $result);
- }
-
- /**
- * @return TMap parameter maps collection.
- */
- public function getParameterMaps()
- {
- return $this->_parameterMaps;
- }
-
- /**
- * @param string parameter map ID name.
- * @return TParameterMap the parameter with given ID.
- * @throws TSqlMapUndefinedException
- */
- public function getParameterMap($name)
- {
- if($this->_parameterMaps->contains($name) == false)
- throw new TSqlMapUndefinedException('sqlmap_contains_no_parameter_map', $name);
- return $this->_parameterMaps[$name];
- }
-
- /**
- * @param TParameterMap add a new parameter map to this SQLMap.
- * @throws TSqlMapDuplicateException
- */
- public function addParameterMap(TParameterMap $parameter)
- {
- $key = $parameter->getID();
- if($this->_parameterMaps->contains($key) == true)
- throw new TSqlMapDuplicateException('sqlmap_already_contains_parameter_map', $key);
- $this->_parameterMaps->add($key, $parameter);
- }
-
- /**
- * Adds a named cache.
- * @param TSqlMapCacheModel the cache to add.
- * @throws TSqlMapConfigurationException
- */
- public function addCacheModel(TSqlMapCacheModel $cacheModel)
- {
- if($this->_cacheModels->contains($cacheModel->getID()))
- throw new TSqlMapConfigurationException('sqlmap_cache_model_already_exists', $cacheModel->getID());
- else
- $this->_cacheModels->add($cacheModel->getID(), $cacheModel);
- }
-
- /**
- * Gets a cache by name
- * @param string the name of the cache to get.
- * @return TSqlMapCacheModel the cache object.
- * @throws TSqlMapConfigurationException
- */
- public function getCacheModel($name)
- {
- if(!$this->_cacheModels->contains($name))
- throw new TSqlMapConfigurationException('sqlmap_unable_to_find_cache_model', $name);
- return $this->_cacheModels[$name];
- }
-
- /**
- * Flushes all cached objects that belong to this SqlMap
- */
- public function flushCacheModels()
- {
- foreach($this->_cacheModels as $cache)
- $cache->flush();
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap + */ + +Prado::using('System.Data.SqlMap.TSqlMapGateway'); +Prado::using('System.Data.SqlMap.DataMapper.TSqlMapException'); +Prado::using('System.Data.SqlMap.DataMapper.TSqlMapTypeHandlerRegistry'); +Prado::using('System.Data.SqlMap.DataMapper.TSqlMapCache'); +Prado::using('System.Data.SqlMap.Configuration.TSqlMapStatement'); +Prado::using('System.Data.SqlMap.Configuration.*'); +Prado::using('System.Data.SqlMap.DataMapper.*'); +Prado::using('System.Data.SqlMap.Statements.*'); +Prado::using('System.Caching.TCache'); + + +/** + * TSqlMapManager class holds the sqlmap configuation result maps, statements + * parameter maps and a type handler factory. + * + * Use {@link SqlMapGateway getSqlMapGateway()} property to obtain the gateway + * instance used for querying statements defined in the SqlMap configuration files. + * + * <code> + * $conn = new TDbConnection($dsn,$dbuser,$dbpass); + * $manager = new TSqlMapManager($conn); + * $manager->configureXml('mydb-sqlmap.xml'); + * $sqlmap = $manager->getSqlMapGateway(); + * $result = $sqlmap->queryForObject('Products'); + * </code> + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Id$ + * @package System.Data.SqlMap + * @since 3.1 + */ +class TSqlMapManager extends TComponent +{ + private $_mappedStatements; + private $_resultMaps; + private $_parameterMaps; + private $_typeHandlers; + private $_cacheModels; + + private $_connection; + private $_gateway; + private $_cacheDependencies; + + /** + * Constructor, create a new SqlMap manager. + * @param TDbConnection database connection + * @param string configuration file. + */ + public function __construct($connection=null) + { + $this->_connection=$connection; + + $this->_mappedStatements=new TMap; + $this->_resultMaps=new TMap; + $this->_parameterMaps=new TMap; + $this->_cacheModels=new TMap; + } + + /** + * @param TDbConnection default database connection + */ + public function setDbConnection($conn) + { + $this->_connection=$conn; + } + + /** + * @return TDbConnection default database connection + */ + public function getDbConnection() + { + return $this->_connection; + } + + /** + * @return TTypeHandlerFactory The TypeHandlerFactory + */ + public function getTypeHandlers() + { + if($this->_typeHandlers===null) + $this->_typeHandlers= new TSqlMapTypeHandlerRegistry(); + return $this->_typeHandlers; + } + + /** + * @return TSqlMapGateway SqlMap gateway. + */ + public function getSqlmapGateway() + { + if($this->_gateway===null) + $this->_gateway=$this->createSqlMapGateway(); + return $this->_gateway; + } + + /** + * Loads and parses the SqlMap configuration file. + * @param string xml configuration file. + */ + public function configureXml($file) + { + $config = new TSqlMapXmlConfiguration($this); + $config->configure($file); + } + + /** + * @return TChainedCacheDependency + * @since 3.1.5 + */ + public function getCacheDependencies() + { + if($this->_cacheDependencies === null) + $this->_cacheDependencies=new TChainedCacheDependency(); + + return $this->_cacheDependencies; + } + + /** + * Configures the current TSqlMapManager using the given xml configuration file + * defined in {@link ConfigFile setConfigFile()}. + * @return TSqlMapGateway create and configure a new TSqlMapGateway. + */ + protected function createSqlMapGateway() + { + return new TSqlMapGateway($this); + } + + /** + * @return TMap mapped statements collection. + */ + public function getMappedStatements() + { + return $this->_mappedStatements; + } + + /** + * Gets a MappedStatement by name. + * @param string The name of the statement. + * @return IMappedStatement The MappedStatement + * @throws TSqlMapUndefinedException + */ + public function getMappedStatement($name) + { + if($this->_mappedStatements->contains($name) == false) + throw new TSqlMapUndefinedException('sqlmap_contains_no_statement', $name); + return $this->_mappedStatements[$name]; + } + + /** + * Adds a (named) MappedStatement. + * @param string The key name + * @param IMappedStatement The statement to add + * @throws TSqlMapDuplicateException + */ + public function addMappedStatement(IMappedStatement $statement) + { + $key = $statement->getID(); + if($this->_mappedStatements->contains($key) == true) + throw new TSqlMapDuplicateException('sqlmap_already_contains_statement', $key); + $this->_mappedStatements->add($key, $statement); + } + + /** + * @return TMap result maps collection. + */ + public function getResultMaps() + { + return $this->_resultMaps; + } + + /** + * Gets a named result map + * @param string result name. + * @return TResultMap the result map. + * @throws TSqlMapUndefinedException + */ + public function getResultMap($name) + { + if($this->_resultMaps->contains($name) == false) + throw new TSqlMapUndefinedException('sqlmap_contains_no_result_map', $name); + return $this->_resultMaps[$name]; + } + + /** + * @param TResultMap add a new result map to this SQLMap + * @throws TSqlMapDuplicateException + */ + public function addResultMap(TResultMap $result) + { + $key = $result->getID(); + if($this->_resultMaps->contains($key) == true) + throw new TSqlMapDuplicateException('sqlmap_already_contains_result_map', $key); + $this->_resultMaps->add($key, $result); + } + + /** + * @return TMap parameter maps collection. + */ + public function getParameterMaps() + { + return $this->_parameterMaps; + } + + /** + * @param string parameter map ID name. + * @return TParameterMap the parameter with given ID. + * @throws TSqlMapUndefinedException + */ + public function getParameterMap($name) + { + if($this->_parameterMaps->contains($name) == false) + throw new TSqlMapUndefinedException('sqlmap_contains_no_parameter_map', $name); + return $this->_parameterMaps[$name]; + } + + /** + * @param TParameterMap add a new parameter map to this SQLMap. + * @throws TSqlMapDuplicateException + */ + public function addParameterMap(TParameterMap $parameter) + { + $key = $parameter->getID(); + if($this->_parameterMaps->contains($key) == true) + throw new TSqlMapDuplicateException('sqlmap_already_contains_parameter_map', $key); + $this->_parameterMaps->add($key, $parameter); + } + + /** + * Adds a named cache. + * @param TSqlMapCacheModel the cache to add. + * @throws TSqlMapConfigurationException + */ + public function addCacheModel(TSqlMapCacheModel $cacheModel) + { + if($this->_cacheModels->contains($cacheModel->getID())) + throw new TSqlMapConfigurationException('sqlmap_cache_model_already_exists', $cacheModel->getID()); + else + $this->_cacheModels->add($cacheModel->getID(), $cacheModel); + } + + /** + * Gets a cache by name + * @param string the name of the cache to get. + * @return TSqlMapCacheModel the cache object. + * @throws TSqlMapConfigurationException + */ + public function getCacheModel($name) + { + if(!$this->_cacheModels->contains($name)) + throw new TSqlMapConfigurationException('sqlmap_unable_to_find_cache_model', $name); + return $this->_cacheModels[$name]; + } + + /** + * Flushes all cached objects that belong to this SqlMap + */ + public function flushCacheModels() + { + foreach($this->_cacheModels as $cache) + $cache->flush(); + } +} + |