From a8b3ebe8f62c3888b216d827c1c5dcba8a47d4e1 Mon Sep 17 00:00:00 2001 From: wei <> Date: Sun, 26 Nov 2006 22:15:58 +0000 Subject: Adding active record implementation. --- framework/Data/ActiveRecord/Vendor/TDbMetaData.php | 363 +++++++++++++++++++++ 1 file changed, 363 insertions(+) create mode 100644 framework/Data/ActiveRecord/Vendor/TDbMetaData.php (limited to 'framework/Data/ActiveRecord/Vendor/TDbMetaData.php') diff --git a/framework/Data/ActiveRecord/Vendor/TDbMetaData.php b/framework/Data/ActiveRecord/Vendor/TDbMetaData.php new file mode 100644 index 00000000..490515f6 --- /dev/null +++ b/framework/Data/ActiveRecord/Vendor/TDbMetaData.php @@ -0,0 +1,363 @@ + + * @version $Id$ + * @package System.Data.ActiveRecord.Vendor + */ + +/** + * Table meta data for Active Record. + * + * TDbMetaData is the base class for database vendor specific that builds + * the appropriate database commands for active record finder and commit methods. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.ActiveRecord.Vendor + * @since 3.1 + */ +abstract class TDbMetaData extends TComponent +{ + private $_primaryKeys=array(); + private $_foreignKeys=array(); + private $_columns=array(); + private $_table; + private $_isView=false; + + /** + * Initialize the meta data. + * @param string table name + * @param array name value pair of column meta data in the table + * @param array primary key field names + * @param array foriegn key field meta data. + */ + public function __construct($table, $cols, $pk, $fk=array(),$view=false) + { + $this->_table=$table; + $this->_columns=$cols; + $this->_primaryKeys=$pk; + $this->_foreignKeys=$fk; + $this->_isView=$view; + } + + public function getIsView() + { + return $this->_isView; + } + + /** + * @return string table name + */ + public function getTableName() + { + return $this->_table; + } + + /** + * @return array primary key field names. + */ + public function getPrimaryKeys() + { + return $this->_primaryKeys; + } + + /** + * @return array foreign key meta data. + */ + public function getForeignKeys() + { + return $this->_foreignKeys; + } + + /** + * @return array name value pair column meta data + */ + public function getColumns() + { + return $this->_columns; + } + + /** + * @param unknown_type $name + */ + public function getColumn($name) + { + return $this->_columns[$name]; + } + + /** + * Post process the rows after returning from a 1 row query. + * @param mixed row data, may be null. + * @return mixed processed rows. + */ + public function postQueryRow($row) + { + return $row; + } + + /** + * Post process the rows after returning from a 1 row query. + * @param TDbDataReader multiple row data + * @return array post processed data. + */ + public function postQuery($rows) + { + return $rows; + } + + /** + * @return string command separated list of all fields in the table, field names are quoted. + */ + protected function getSelectionColumns() + { + $columns = array(); + foreach($this->getColumns() as $column) + $columns[] = $column->getName(); + return implode(', ', $columns); + } + + /** + * Construct search criteria using primary key names + * @return string SQL string for used after WHERE statement. + */ + protected function getPrimaryKeyCriteria() + { + if(count($this->getPrimaryKeys())===0) + throw new TActiveRecordException('ar_no_primary_key_found',$this->getTableName()); + $criteria=array(); + foreach($this->getPrimaryKeys() as $key) + $criteria[] = $this->getColumn($key)->getName(). ' = :'.$key; + return implode(' AND ', $criteria); + } + + /** + * Bind a list of variables in the command. The named parameters is taken + * from the values of the $keys parameter. The bind value is taken from the + * $values parameter using the index taken from the each value of $keys array. + * @param TDbCommand SQL database command + * @param array named parameters + * @param array binding values (index should match that of $keys) + */ + protected function bindArrayKeyValues($command, $keys, $values) + { + if(!is_array($values)) $values = array($values); + foreach($keys as $i => $key) + { + $value = isset($values[$i]) ? $values[$i] : $values[$key]; + $command->bindValue(':'.$key, $value); + } + $command->prepare(); + } + + /** + * Returns a list of name value pairs from the object. + * @param array named parameters + * @param TActiveRecord record object + * @return array name value pairs. + */ + protected function getObjectKeyValues($keys, $object) + { + $properties = array(); + foreach($keys as $key) + $properties[$key] = $object->{$key}; + return $properties; + } + + /** + * Gets the columns that can be inserted into the database. + * @param TActiveRecord record object to be inserted. + * @return array name value pairs of fields to be added. + */ + protected function getInsertableColumns($record) + { + $columns = array(); + foreach($this->getColumns() as $name=>$column) + { + $value = $record->{$name}; + if($column->getNotNull() && $value===null && !$column->getIsPrimaryKey()) + { + throw new TActiveRecordException( + 'ar_value_must_not_be_null', get_class($record), + $this->getTableName(), $name); + } + if($value!==null) + $columns[$name] = $value; + } + return $columns; + } + + /** + * Gets the columns that will be updated, it exculdes primary key columns + * and record properties that are null. + * @param TActiveRecord record object with new data for update. + * @return array name value pairs of fields to be updated. + */ + protected function getUpdatableColumns($record) + { + $columns = array(); + foreach($this->getColumns() as $name => $column) + { + $value = $record->{$name}; + if(!$column->getIsPrimaryKey() && $value !== null) + $columns[$name] = $value; + } + return $columns; + } + + /** + * Gets a comma delimited string of name parameters for update. +x * @param array name value pairs of columns for update. + * @return string update named parameter string. + */ + protected function getUpdateBindings($columns) + { + $fields = array(); + foreach($columns as $name=>$value) + $fields[] = $this->getColumn($name)->getName(). '= :'.$name; + return implode(', ', $fields); + } + + /** + * Create a new database command based on the given $sql and bind the + * named parameters given by $names with values corresponding in $values. + * @param TDbConnection database connection. + * @param string SQL string. + * @param array named parameters + * @param array matching named parameter values + * @return TDbCommand binded command, ready for execution. + */ + protected function createBindedCommand($conn, $sql, $names,$values) + { + $conn->setActive(true); + $command = $conn->createCommand($sql); + $this->bindArrayKeyValues($command,$names,$values); + return $command; + } + + /** + * Creates a new database command and bind the values from the criteria object. + * + * @param TDbConnection database connection. + * @param string SQL string. + * @param TActiveRecordCriteria search criteria + * @return TDbCommand binded command. + */ + protected function createCriteriaBindedCommand($conn,$sql,$criteria) + { + $conn->setActive(true); + $command = $conn->createCommand($sql); + if($criteria!==null) + { + if($criteria->getIsNamedParameters()) + { + foreach($criteria->getParameters() as $name=>$value) + $command->bindValue($name,$value); + } + else + { + $index=1; + foreach($criteria->getParameters() as $value) + $command->bindValue($index++,$value); + } + } + $command->prepare(); + return $command; + } + + /** + * Bind parameter values. + */ + protected function bindParameterValues($conn,$command,$parameters) + { + $index=1; + foreach($parameters as $key=>$value) + { + if(is_string($key)) + $command->bindValue($key,$value); + else + $command->bindValue($index++,$value); + } + $command->prepare(); + } + + /** + * Gets the comma delimited string of fields name for insert command. + */ + protected function getInsertColumNames($columns) + { + $fields = array(); + foreach($columns as $name=>$column) + $fields[] = $this->getColumn($name)->getName(); + return implode(', ', $fields); + } + + /** + * Gets the comma delimited string of name bindings for insert command. + */ + protected function getInsertColumnValues($columns) + { + $fields = array(); + foreach(array_keys($columns) as $column) + $fields[] = ':'.$column; + return implode(', ', $fields); + } + + /** + * @param TDbConnection database connection + * @param array primary key values. + * @return string delete criteria for multiple scalar primary keys. + */ + protected function getDeleteInPkCriteria($conn, $keys) + { + $pk = $this->getPrimaryKeys(); + $column = $this->getColumn($pk[0])->getName(); + $values = array(); + foreach($keys as $key) + { + if(is_array($key)) + { + throw new TActiveRecordException('ar_primary_key_is_scalar', + $this->getTableName(),$column,'array('.implode(', ',$key).')'); + } + $values[] = $conn->quoteString($key); + } + $pks = implode(', ', $values); + return "$column IN ($pks)"; + } + + /** + * @param TDbConnection database connection + * @param array primary key values. + * @return string delete criteria for multiple composite primary keys. + */ + protected function getDeleteMultiplePkCriteria($conn,$pks) + { + //check for 1 set composite keys + if(count($pks)>0 && !is_array($pks[0])) + $pks = array($pks); + $conditions=array(); + foreach($pks as $keys) + $conditions[] = $this->getDeleteCompositeKeyCondition($conn,$keys); + return implode(' OR ', $conditions); + } + + /** + * @return string delete criteria for 1 composite key. + */ + protected function getDeleteCompositeKeyCondition($conn,$keys) + { + $condition=array(); + $index = 0; + foreach($this->getPrimarykeys() as $pk) + { + $name = $this->getColumn($pk)->getName(); + $value = isset($keys[$pk]) ? $keys[$pk] : $keys[$index]; + $condition[] = "$name = ".$conn->quoteString($value); + $index++; + } + return '('.implode(' AND ', $condition).')'; + } +} +?> \ No newline at end of file -- cgit v1.2.3