Changeset 256
- Timestamp:
- 02/11/07 12:33:23 (1 year ago)
- Files:
-
- trunk/experiments/people/mikey/persistence/MyNewsArticle.php (modified) (5 diffs)
- trunk/experiments/people/mikey/persistence/README (added)
- trunk/experiments/people/mikey/persistence/connection.php (added)
- trunk/experiments/people/mikey/persistence/createTable.php (modified) (1 diff)
- trunk/experiments/people/mikey/persistence/fetchEntry.php (added)
- trunk/experiments/people/mikey/persistence/insertEntry.php (added)
- trunk/experiments/people/mikey/persistence/listEntries.php (added)
- trunk/experiments/people/mikey/persistence/updateEntry.php (added)
- trunk/src/main/php/net/stubbles/rdbms/persistence/EXPERIMENTAL (modified) (1 diff)
- trunk/src/main/php/net/stubbles/rdbms/persistence/finder (added)
- trunk/src/main/php/net/stubbles/rdbms/persistence/finder/stubDatabaseFinder.php (added)
- trunk/src/main/php/net/stubbles/rdbms/persistence/finder/stubDatabaseFinderException.php (added)
- trunk/src/main/php/net/stubbles/rdbms/persistence/serializer (added)
- trunk/src/main/php/net/stubbles/rdbms/persistence/serializer/stubDatabaseSerializer.php (moved) (moved from trunk/src/main/php/net/stubbles/rdbms/persistence/stubDatabaseSerializer.php) (5 diffs)
- trunk/src/main/php/net/stubbles/rdbms/persistence/serializer/stubDatabaseSerializerException.php (moved) (moved from trunk/src/main/php/net/stubbles/rdbms/persistence/stubDatabaseSerializerException.php)
- trunk/src/main/php/net/stubbles/rdbms/persistence/stubDatabaseSerializedValue.php (deleted)
- trunk/src/main/php/net/stubbles/rdbms/persistence/stubPersistenceException.php (added)
- trunk/src/main/php/net/stubbles/rdbms/persistence/stubSetterMethodFactory.php (added)
- trunk/src/main/php/net/stubbles/rdbms/querybuilder (moved) (moved from trunk/src/main/php/net/stubbles/rdbms/persistence/querybuilder)
- trunk/src/main/php/net/stubbles/rdbms/querybuilder/stubDatabaseMySQLQueryBuilder.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/rdbms/querybuilder/stubDatabaseQueryBuilder.php (modified) (1 diff)
- trunk/src/main/php/net/stubbles/rdbms/querybuilder/stubDatabaseQueryBuilderException.php (added)
- trunk/src/main/php/net/stubbles/rdbms/querybuilder/stubDatabaseQueryBuilderFactory.php (added)
- trunk/src/main/php/net/stubbles/rdbms/stubDatabaseConnection.php (modified) (1 diff)
- trunk/src/main/php/net/stubbles/rdbms/stubDatabaseResult.php (modified) (1 diff)
- trunk/src/main/php/net/stubbles/rdbms/stubDatabaseStatement.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/experiments/people/mikey/persistence/MyNewsArticle.php
r195 r256 12 12 * @var int 13 13 */ 14 protected $id ;14 protected $id = null; 15 15 /** 16 16 * switch whether news is stored persistent or not … … 54 54 * @var int 55 55 */ 56 protected $lastChanged = 0;56 protected $lastChanged = null; 57 57 /** 58 58 * status of article … … 60 60 * @var int 61 61 */ 62 protected $status = 0;62 protected $status = null; 63 63 64 64 /** … … 217 217 public function setStatus($status) 218 218 { 219 $this-> lastChanged= $status;219 $this->status = $status; 220 220 } 221 221 … … 256 256 return $this->isPersistent; 257 257 } 258 259 /** 260 * returns a list of all instances with status $status 261 * 262 * @param stubDatabaseFinder $finder the finder to use 263 * @param int $status status that the instances must have 264 * @return array<MyNewsArticle> 265 */ 266 public static function findByStatus(stubDatabaseFinder $finder, $status) 267 { 268 $equalCriterion = new stubEqualCriterion('status', $status, 'news'); 269 return $finder->findByCriterion($equalCriterion, __CLASS__); 270 } 258 271 } 259 272 ?> trunk/experiments/people/mikey/persistence/createTable.php
r196 r256 4 4 stubClassLoader::load('net.stubbles.rdbms.rdbms', 5 5 'net.stubbles.rdbms.persistence.stubPersistable', 6 'net.stubbles.rdbms.persistence.annotations.DBTable', 7 'net.stubbles.rdbms.persistence.annotations.DBColumn', 8 'net.stubbles.rdbms.persistence.querybuilder.stubDatabaseMySQLQueryBuilder', 9 'net.stubbles.reflection.stubReflectionClass' 6 'net.stubbles.rdbms.persistence.querybuilder.stubDatabaseQueryBuilderFactory' 10 7 ); 11 8 require_once 'MyNewsArticle.php'; 9 require_once 'connection.php'; 12 10 13 $refClass = new stubReflectionClass('MyNewsArticle'); 14 if ($refClass->hasAnnotation('DBTable') == false) { 15 throw new stubException('Class ' . $refClass->getName() . ' is missing the DBTable annotation.'); 16 } 17 18 $query = 'CREATE TABLE `' . $refClass->getAnnotation('DBTable')->getName() . "` (\n"; 19 $methods = $refClass->getMethods(); 20 $primaryKeys = array(); 21 $keys = array(); 22 foreach ($methods as $method) { 23 if ($method->hasAnnotation('DBColumn') == false || $method->getDeclaringClass()->equals($refClass) == false) { 24 continue; 25 } 26 27 $dbColumn = $method->getAnnotation('DBColumn'); 28 $query .= ' ' . $dbColumn->getName() . ' ' . $dbColumn->getType(); 29 if (strtoupper($dbColumn->getType()) != 'TEXT') { 30 $query .= '(' . str_replace('_', ',', $dbColumn->getSize()) . ')'; 31 } 32 33 if ($dbColumn->isUnsigned() == true) { 34 $query .= ' UNSIGNED'; 35 } 36 37 if ($dbColumn->isNullable() == true && $dbColumn->getDefaultValue() == null) { 38 $query .= ' DEFAULT NULL'; 39 } else { 40 if ($dbColumn->isNullable() == false) { 41 $query .= ' NOT NULL'; 42 } 43 44 if ($dbColumn->getDefaultValue() !== null) { 45 $query .= " DEFAULT '" . $dbColumn->getDefaultValue() . "'"; 46 } 47 } 48 49 if ($dbColumn->isPrimaryKey() == true) { 50 $query .= ' AUTO_INCREMENT'; 51 $primaryKeys[] = $dbColumn->getName(); 52 } elseif ($dbColumn->isKey() == true) { 53 $keys[] = $dbColumn->getName(); 54 } 55 56 $query .= ",\n"; 57 } 58 if (count($primaryKeys) > 0) { 59 if (count($primaryKeys) > 1) { 60 $query = str_replace(' AUTO_INCREMENT', '', $query); 61 } 62 63 $query .= ' PRIMARY KEY (`' . join('`, `', $primaryKeys) . '`)'; 64 } 65 if (count($keys) > 0) { 66 foreach ($keys as $key) { 67 $query .= ",\n KEY (`" . $key . '`)'; 68 } 69 } 70 $query .= "\n) TYPE=" . $refClass->getAnnotation('DBTable')->getType(); 71 echo $query; 11 $connection = stubDatabaseConnectionPool::getConnection(); 12 $queryBuilder = stubDatabaseQueryBuilderFactory::create($connection); 13 var_dump($connection->exec($queryBuilder->createTable('MyNewsArticle'))); 72 14 ?> trunk/src/main/php/net/stubbles/rdbms/persistence/EXPERIMENTAL
r182 r256 1 Warning: The stuff in this package is highly experimental. It just contains 2 thoughts about how this could look like. Neither has it been tested nor 3 executed. 1 Warning: The stuff in this package is experimental. Use at your own risk. 2 For examples how it can be used see experiments/people/mikey/persistence. trunk/src/main/php/net/stubbles/rdbms/persistence/serializer/stubDatabaseSerializer.php
r182 r256 5 5 * @author Frank Kleine <mikey@stubbles.net> 6 6 * @package stubbles 7 * @subpackage rdbms_persistence 7 * @subpackage rdbms_persistence_serializer 8 8 */ 9 9 stubClassLoader::load('net.stubbles.rdbms.stubDatabaseConnection', 10 'net.stubbles.rdbms.querybuilder.stubDatabaseQueryBuilder', 10 'net.stubbles.rdbms.criteria.stubCriterion', 11 'net.stubbles.rdbms.criteria.stubAndCriterion', 12 'net.stubbles.rdbms.criteria.stubEqualCriterion', 11 13 'net.stubbles.rdbms.persistence.stubPersistable', 12 'net.stubbles.rdbms.persistence.stubDatabaseSerializedValue', 13 'net.stubbles.rdbms.persistence.annotations.DBTable', 14 'net.stubbles.rdbms.persistence.annotations.DBColumn' 14 'net.stubbles.rdbms.persistence.stubSetterMethodFactory', 15 'net.stubbles.rdbms.persistence.annotations.stubDBTableAnnotation', 16 'net.stubbles.rdbms.persistence.annotations.stubDBColumnAnnotation', 17 'net.stubbles.rdbms.persistence.serializer.stubDatabaseSerializerException', 18 'net.stubbles.rdbms.querybuilder.stubDatabaseQueryBuilderFactory' 15 19 ); 16 20 /** … … 18 22 * 19 23 * @package stubbles 20 * @subpackage rdbms_persistence 24 * @subpackage rdbms_persistence_serializer 21 25 */ 22 26 class stubDatabaseSerializer extends stubBaseObject 23 27 { 28 /** 29 * list of serializer instances 30 * 31 * @var array<string,stubDatabaseSerializer> 32 */ 33 protected static $instances = array(); 24 34 /** 25 35 * the connection to use for making the object persistent … … 28 38 */ 29 39 protected $connection; 30 /**31 * the querybuilder to use32 *33 * @var stubDatabaseQueryBuilder34 */35 protected $queryBuilder;36 /**37 * information about the single primary key38 *39 * @var array40 */41 protected $singlePrimaryKey = null;42 40 43 41 /** … … 45 43 * 46 44 * @param stubDatabaseConnection $connection 47 * @param stubDatabaseQueryBuilder $queryBuilder48 45 */ 49 p ublic function __construct(stubDatabaseConnection $connection, stubDatabaseQueryBuilder $queryBuilder)46 protected function __construct(stubDatabaseConnection $connection) 50 47 { 51 48 $this->connection = $connection; 52 $this->queryBuilder = $queryBuilder;53 49 } 54 50 55 51 /** 56 * takes a stubPersistable and serializes it into a stubDatabaseSerializedValue 52 * method to return instances of the finder depending of the connection 53 * 54 * Because the finder itself is stateless and only bound to the connection 55 * this factory methods prevents that a finder for a specific connection is 56 * created more than once. 57 57 * 58 * @param stubPersistable $stubObject 59 * @return stubDatabaseSerializedValue 60 * @throws stubDatabaseSerializerException 58 * @param stubDatabaseConnection $connection connection to use for finding the data 59 * @return stubDatabaseFinder 61 60 */ 62 public function serialize(stubPersistable $stubPersistable)61 public function getInstance(stubDatabaseConnection $connection) 63 62 { 64 $refClass = $stubPersistable->getClass(); 65 $baseTable = null; 66 if ($refClass->hasAnnotation('DBTable') == true) { 67 $baseTable = $refClass->getAnnotation('DBTable')->getName(); 63 if (isset(self::$instances[$connection->hashCode()]) == false) { 64 self::$instances[$connection->hashCode()] = new self($connection); 68 65 } 69 66 70 $serializedValue = new stubDatabaseSerializedValue(); 71 $this->processProperties($refClass->getProperties(), $baseTable, $stubPersistable, $serializedValue); 72 $this->processMethods($refClass->getMethods(), $baseTable, $stubPersistable, $serializedValue); 73 74 75 try { 76 $this->processQueries($this->getQueries($serializedValue, $stubPersistable->isPersistent())); 77 } catch (stubDatabaseException $dbe) { 78 throw new stubDatabaseSerializerException('Can not persist ' . $stubPersistable->getClassName() . ': a database error occured.', $dbe); 79 } 67 return self::$instances[$connection->hashCode()]; 80 68 } 81 69 82 70 /** 83 * process the properties of the persistable object71 * cloning is forbidden 84 72 * 85 * @param array<stubReflectionProperty> $refProperties 86 * @param string $baseTable 87 * @param stubPersistable $stubPersistable 88 * @param stubDatabaseSerializedValue $serializedValue 73 * @throws stubDatabaseFinderException 89 74 */ 90 protected f unction processProperties(array $refProperties, $baseTable, stubPersistable $stubPersistable, stubDatabaseSerializedValue $serializedValue)75 protected final function __clone() 91 76 { 92 foreach ($refProperties as $refProperty) { 93 if ($refProperty->isPublic() == false || $refProperty->hasAnnotation('DBColumn') == false) { 77 throw new stubDatabaseFinderException('Cloning ' . $this->getClassName() . ' is not allowed.'); 78 } 79 80 /** 81 * takes a stubPersistable and serializes it into the database 82 * 83 * @param stubPersistable $persistable 84 * @throws stubDatabaseSerializerException 85 * @throws stubPersistenceException 86 */ 87 public function serialize(stubPersistable $persistable) 88 { 89 $refObject = $persistable->getClass(); 90 if ($refObject->hasAnnotation('DBTable') == false) { 91 throw new stubDatabaseQueryBuilderException('No database table defined for ' . $refObject->getFullQualifiedClassName() . ', class is missing the DBTable annotation.'); 92 } 93 94 $baseTableName = $refObject->getAnnotation('DBTable')->getName(); 95 $methods = $refObject->getMethods(); 96 $serializedValue = array(); 97 $singlePrimaryKey = null; 98 foreach ($methods as $method) { 99 if ($method->isPublic() == false || $method->hasAnnotation('DBColumn') == false) { 94 100 continue; 95 101 } 96 102 97 $table = $baseTable; 98 if (null === $table) { 99 if ($refProperty->hasAnnotation('DBTable') == false) { 100 throw new stubDatabaseSerializerException('No database table defined for property ' . $stubPersistable->getClassName() . '::' . $refProperty->getName()); 103 $tableName = (($method->hasAnnotation('DBTable') == true) ? ($method->getAnnotation('DBTable')->getName()) : ($baseTableName)); 104 if (isset($serializedValue[$tableName]) == false) { 105 $serializedValue[$tableName] = array('criterion' => new stubAndCriterion(), 'columns' => array()); 106 } 107 108 try { 109 $value = $method->invoke($persistable); 110 } catch (ReflectionException $re) { 111 throw new stubDatabaseSerializerException('Can not get return value of ' . $refObject->getFullQualifiedClassName() . '::' . $method->getName() . '(), invokation failed.', $re); 112 } 113 114 $dbColumn = $method->getAnnotation('DBColumn'); 115 if (null === $value && $dbColumn->isPrimaryKey() == true) { 116 if ($persistable->isPersistent() == true) { 117 throw new stubDatabaseSerializerException('Data inconsistent: persistable object is already persistent, but the primary key ' . $refObject->getFullQualifiedClassName() . '::' . $method->getName() . '() is null.'); 101 118 } 102 119 103 $table = $refProperty->getAnnotation('DBTable')->getName(); 120 if (null !== $singlePrimaryKey) { 121 throw new stubDatabaseSerializerException('Persistence error: only one primary key can be null, but at least two primary keys are null: ' . $singlePrimaryKey['propertyName'] . ' and ' . $method->getName()); 122 } 123 124 $singlePrimaryKey = array('propertyName' => $method->getName(), 125 'columnName' => $dbColumn->getName(), 126 'tableName' => $tableName 127 ); 128 continue; 129 } elseif (null !== $value && $dbColumn->isPrimaryKey() == true) { 130 $serializedValue[$tableName]['criterion']->addCriterion(new stubEqualCriterion($dbColumn->getName(), $value, $tableName)); 131 } elseif (null === $value && $persistable->isPersistent() == false) { 132 $value = $dbColumn->getDefaultValue(); 133 $setterMethod = stubSetterMethodFactory::create($dbColumn, $refObject, $method->getName()); 134 135 $setterMethod->invoke($persistable, $value); 104 136 } 105 137 106 $value = $refProperty->getValue($stubPersistable); 107 if (null == $value && $refProperty->getAnnotation('DBColumn')->isPrimaryKey() == true) { 108 if ($stubPersistable->isPersistent() == true) { 109 throw new stubDatabaseSerializerException('Data inconsistent: persistable object is already persistent, but the primary key ' . $stubPersistable->getClassName() . '::' . $refProperty->getName() . ' is null.'); 110 } 111 112 $this->setSinglePrimaryKey($refProperty->getName(), $refProperty->getAnnotation('DBColumn')->getName(), $table); 113 } 114 115 $serializedValue->setColumnValue($table, $refProperty->getAnnotation('DBColumn')->getName(), $value, $refProperty->getAnnotation('DBColumn')->isPrimaryKey()); 138 $serializedValue[$tableName]['columns'][$dbColumn->getName()] = $value; 116 139 } 140 141 try { 142 $this->processQueries($this->getQueries($serializedValue, $persistable->isPersistent()), $persistable, $singlePrimaryKey); 143 } catch (stubDatabaseException $dbe) { 144 throw new stubDatabaseSerializerException('Can not persist ' . $refObject->getFullQualifiedClassName() . ': a database error occured.', $dbe); 145 } 146 147 $persistable->setPersistent(true); 117 148 } 118 149 119 150 /** 120 * process the methods of the persistable object121 *122 * @param array <stubReflectionMethod> $refMethods123 * @param string $baseTable124 * @param stubPersistable $stubPersistable125 * @param stubDatabaseSerializedValue $serializedValue126 */127 protected function processMethods(array $refMethods, $baseTable, stubPersistable $stubPersistable, stubDatabaseSerializedValue $serializedValue)128 {129 foreach ($refMethods as $refMethod) {130 if ($refMethod->isPublic() == false || $refMethod->hasAnnotation('DBColumn') == false) {131 continue;132 }133 134 $table = $baseTable;135 if (null === $table) {136 if ($refMethod->hasAnnotation('DBTable') == false) {137 throw new stubDatabaseSerializerException('No database table defined for return value of ' . $stubPersistable->getClassName() . '::' . $refMethod->getName() . '()');138 }139 140 $table = $refMethod->getAnnotation('DBTable')->getName();141 }142 143 try {144 $value = $refMethod->invoke($stubPersistable);145 } catch (ReflectionException $re) {146 throw new stubDatabaseSerializerException('Can not get return value of ' . $stubPersistable->getClassName() . '::' . $refMethod->getName() . '(), invokation failed.', $re);147 }148 149 if (null == $value && $refMethod->getAnnotation('DBColumn')->isPrimaryKey() == true) {150 if ($stubPersistable->isPersistent() == true) {151 throw new stubDatabaseSerializerException('Data inconsistent: persistable object is already persistent, but the primary key ' . $stubPersistable->getClassName() . '::' . $refMethod->getName() . '() is null.');152 }153 154 $this->setSinglePrimaryKey($refMethod->getName(), $refMethod->getAnnotation('DBColumn')->getName(), $table);155 }156 157 $serializedValue->setColumnValue($table, $refMethod->getAnnotation('DBColumn')->getName(), $value, $refMethod->getAnnotation('DBColumn')->isPrimaryKey());158 }159 }160 161 /**162 * sets the single primary key which may be null163 *164 * @param string $propertyName name of the property or method165 * @param string $columnName name of the column where primary key is stored166 * @param string $tableName name of the table where primary key is stored167 */168 protected function setSinglePrimaryKey($propertyName, $columnName, $tableName)169 {170 if (null != $this->singlePrimaryKey) {171 throw new stubDatabaseSerializerException('Persistence error: only one primary key can be null, but at least two primary keys are null: ' . $$this->singlePrimaryKey['propertyName'] . ' and ' . $propertyName);172 }173 174 $this->singlePrimaryKey = array('propertyName' => $propertyName,175 'columnName' => $columnName,176 'tableName' => $tableName177 );178 }179 180 /**181 151 * build the queries out of the serialized value 182 152 * 183 * @param stubDatabaseSerializedValue $value184 * @param bool $isPersistent185 * @return array <string,string> tableName => query153 * @param array $values 154 * @param bool $isPersistent 155 * @return array(tableName => query) 186 156 */ 187 protected function getQueries( stubDatabaseSerializedValue $value, $isPersistent)157 protected function getQueries(array $values, $isPersistent) 188 158 { 159 $queryBuilder = stubDatabaseQueryBuilderFactory::create($this->connection); 189 160 if (true == $isPersistent) { 190 return $ this->queryBuilder->createUpdate($value);161 return $queryBuilder->createUpdate($values); 191 162 } 192 163 193 return $ this->queryBuilder->createInsert($value);164 return $queryBuilder->createInsert($values); 194 165 } 195 166 … … 197 168 * process the queries 198 169 * 199 * @param array<string,string> $queries tableName => query 170 * @param array(tableName => query) $queries list of queries to process 171 * @param stubPersistable $persistable the persistable object 172 * @param array $singlePrimaryKey information about the single primary key 200 173 * @throws stubDatabaseException 201 174 */ 202 protected function processQueries(array $queries, stubPersistable $ stubPersistable)175 protected function processQueries(array $queries, stubPersistable $persistable, array $singlePrimaryKey = null) 203 176 { 204 177 foreach ($queries as $tableName => $query) { 205 178 $this->connection->exec($query); 206 if (null != $this->singlePrimaryKey && $this->singlePrimaryKey['table'] == $tableName) {207 $ stubPersistable->setId($this->connection->getLastInsertID());179 if (null !== $singlePrimaryKey && $singlePrimaryKey['tableName'] == $tableName) { 180 $persistable->setId($this->connection->getLastInsertID()); 208 181 } 209 182 } 210 183 } 184 185 /** 186 * returns a unique hash code for the class 187 * 188 * Two serializers are equal if they use the same connection. 189 * 190 * @return string 191 */ 192 public function hashCode() 193 { 194 return 'serializer:' . $this->connection->hashCode(); 195 } 211 196 } 212 197 ?> trunk/src/main/php/net/stubbles/rdbms/querybuilder/stubDatabaseMySQLQueryBuilder.php
r195 r256 5 5 * @author Frank Kleine <mikey@stubbles.net> 6 6 * @package stubbles 7 * @subpackage rdbms_ persistence_querybuilder7 * @subpackage rdbms_querybuilder 8 8 */ 9 stubClassLoader::load('net.stubbles.rdbms. persistence.querybuilder.stubDatabaseQueryBuilder');9 stubClassLoader::load('net.stubbles.rdbms.querybuilder.stubDatabaseQueryBuilder'); 10 10 /** 11 11 * Class for creating MySQL specific queries. 12 12 * 13 13 * @package stubbles 14 * @subpackage rdbms_ persistence_querybuilder14 * @subpackage rdbms_querybuilder 15 15 */ 16 16 class stubDatabaseMySQLQueryBuilder extends stubBaseObject implements stubDatabaseQueryBuilder 17 17 { 18 18 /** 19 * creates a select query 20 * 21 * @param stubCriterion $criterion condition for query 22 * @param array $tables list of tables to use in query 23 * @return string 24 */ 25 public function createSelect(stubCriterion $criterion, array $tables) 26 { 27 return 'SELECT * FROM `' . join('`, `', $tables) . '` WHERE ' . $criterion->toSQL(); 28 } 29 30 /** 19 31 * creates insert queries from a serialized value 20 32 * 21 * @param stubDatabaseSerializedValue $value22 * @return array <string,string> tableName => query33 * @param array(tableName => array(columns => array(columnName => columnValue))) $values 34 * @return array(tableName => query) 23 35 */ 24 public function createInsert( stubDatabaseSerializedValue $value)36 public function createInsert(array $values) 25 37 { 26 38 $queries = array(); 27 $tableNames = $value->getTableNames();39 $tableNames = array_keys($values); 28 40 foreach ($tableNames as $tableName) { 29 $columns = $value->getColumnsForTable($tableName); 30 $queries[$tableName] = 'INSERT INTO `' . $tableName . '` (`' . join('`, `', array_keys($columns)) . "`) VALUES ('" . join("', '", array_values($columns)) . "')"; 41 $queries[$tableName] = 'INSERT INTO `' . $tableName . '` (`' . join('`, `', array_keys($values[$tableName]['columns'])) . '`) VALUES ('; 42 $counter = 0; 43 foreach ($values[$tableName]['columns'] as $columnValue) { 44 if (0 < $counter) { 45 $queries[$tableName] .= ', '; 46 } 47 48 if (null === $columnValue) { 49 $queries[$tableName] .= 'NULL'; 50 } else { 51 $queries[$tableName] .= "'" . $columnValue . "'"; 52 } 53 54 $counter++; 55 } 56 57 $queries[$tableName] .= ')'; 31 58 } 32 59 … … 37 64 * creates update queries from a serialized value 38 65 * 39 * @param stubDatabaseSerializedValue $value40 * @return array <string,string> tableName => query66 * @param array(tableName => array(criterion => stubCrition, columns => array(columnName => columnValue))) $values 67 * @return array(tableName => query) 41 68 */ 42 public function createUpdate( stubDatabaseSerializedValue $value)69 public function createUpdate(array $values) 43 70 { 44 71 $queries = array(); 45 $tableNames = $value->getTableNames();72 $tableNames = array_keys($values); 46 73 foreach ($tableNames as $tableName) { 47 $columns = $value->getColumnsForTable($tableName);48 74 $query = 'UPDATE `' . $tableName . '` SET '; 49 75 $where = array(); 50 76 $counter = 0; 51 foreach ($ columnsas $columnName => $columnValue) {77 foreach ($values[$tableName]['columns'] as $columnName => $columnValue) { 52 78 if (0 < $counter) { 53 79 $query .= ', '; 54 80 } 55 81 56 $query .= '`' . $columnName . "` = '" . $columnValue . "'"; 82 $query .= '`' . $columnName . '` = '; 83 if (null === $columnValue) { 84 $query .= 'NULL'; 85 } else { 86 $query .= "'" . $columnValue . "'"; 87 } 57 88 $counter++; 58 59 if ($value->isPrimaryKey($tableName, $columnName) == true) {60 $where[] = '`' . $columnName . "` = '" . $columnValue . "'";61 }62 89 } 63 90 64 $queries[$tableName] = $query . ' WHERE ' . join(' AND ', $where);91 $queries[$tableName] = $query . ' WHERE ' . $values[$tableName]['criterion']->toSQL(); 65 92 } 66 93 67 94 return $queries; 68 95 } 96 97 /** 98 * creates the query to create a table for the given class 99 * 100 * @param string $fqClassName the full qualified classname of the class to create the table for 101 * @throws stubDatabaseQueryBuilderException 102 * @todo put all reflection related stuff to persistence package, 103 * introduce a class that represents a table description 104 */ 105 public function createTable($fqClassName) 106 { 107 $nqClassName = stubClassLoader::getNonQualifiedClassName($fqClassName); 108 if (class_exists($nqClassName, false) == false) { 109 stubClassLoader::load($fqClassName); 110 } 111 112 $refClass = new stubReflectionClass($nqClassName); 113 if ($refClass->hasAnnotation('DBTable') == false) { 114 throw new stubDatabaseQueryBuilderException('Class ' . $refClass->getName() . ' is missing the DBTable annotation.'); 115 } 116 117 $dbTable = $refClass->getAnnotation('DBTable'); 118 $tableName = $dbTable->getName(); 119 $query = 'CREATE TABLE `' . $tableName . "` (\n"; 120 $methods = $refClass->getMethods(); 121 $primaryKeys = array(); 122 $keys = array(); 123 foreach ($methods as $method) { 124 if ($method->hasAnnotation('DBColumn') == false || $method->getDeclaringClass()->equals($refClass) == false) { 125 continue; 126 } elseif ($method->hasAnnotation('DBTable') == true && $method->getAnnotation('DBTable')->getName() != $tableName) { 127 continue; 128 } 129 130 $dbColumn = $method->getAnnotation('DBColumn'); 131 $query .= ' ' . $dbColumn->getName() . ' ' . $dbColumn->getType(); 132 if (strtoupper($dbColumn->getType()) != 'TEXT') { 133 $query .= '(' . str_replace('_', ',', $dbColumn->getSize()) . ')'; 134 } 135 136 if ($dbColumn->isUnsigned() == true) { 137 $query .= ' UNSIGNED'; 138 } 139 140 if ($dbColumn->isNullable() == true && $dbColumn->getDefaultValue() == null) { 141 $query .= ' DEFAULT NULL'; 142 } else { 143 if ($dbColumn->isNullable() == false) { 144 $query .= ' NOT NULL'; 145 } 146 147 if ($dbColumn->getDefaultValue() !== null) { 148 $query .= " DEFAULT '" . $dbColumn->getDefaultValue() . "'"; 149 } 150 } 151 152 if ($dbColumn->isPrimaryKey() == true) { 153 $query .= ' AUTO_INCREMENT'; 154 $primaryKeys[] = $dbColumn->getName(); 155 } elseif ($dbColumn->isKey() == true) { 156 $keys[] = $dbColumn->getName(); 157 } 158 159 $query .= ",\n"; 160 } 161 if (count($primaryKeys) > 0) { 162 if (count($primaryKeys) > 1) { 163 $query = str_replace(' AUTO_INCREMENT', '', $query); 164 } 165 166 $query .= ' PRIMARY KEY (`' . join('`, `', $primaryKeys) . '`)'; 167 } 168 if (count($keys) > 0) { 169 foreach ($keys as $key) { 170 $query .= ",\n KEY (`" . $key . '`)'; 171 } 172 } 173 174 $query .= "\n) TYPE=" . $dbTable->getType(); 175 if ($dbTable->hasCharacterSet() == true) { 176 $query .= ' CHARACTER SET=' . $dbTable->getCharacterSet(); 177 } 178 179 if ($dbTable->hasCollation() == true) { 180 $query .= ' COLLATE=' . $dbTable->getCollation(); 181 } 182 183 if ($dbTable->hasComment() == true) { 184 $query .= ' COMMENT=' . $dbTable->getComment(); 185 } 186 187 return $query; 188 } 69 189 } 70 190 ?> trunk/src/main/php/net/stubbles/rdbms/querybuilder/stubDatabaseQueryBuilder.php
r182 r256 5 5 * @author Frank Kleine <mikey@stubbles.net> 6 6 * @package stubbles 7 * @subpackage rdbms_ persistence_querybuilder7 * @subpackage rdbms_querybuilder 8 8 */ 9 stubClassLoader::load('net.stubbles.rdbms.persistence.stubDatabaseSerializedValue'); 9 stubClassLoader::load('net.stubbles.rdbms.criteria.stubCriterion', 10 'net.stubbles.rdbms.querybuilder.stubDatabaseQueryBuilderException', 11 'net.stubbles.rdbms.persistence.annotations.stubDBTableAnnotation', 12 'net.stubbles.rdbms.persistence.annotations.stubDBColumnAnnotation', 13 'net.stubbles.reflection.reflection' 14 ); 10 15 /** 11 16 * Interface for database specific query builders. 12 17 * 13 18 * @package stubbles 14 * @subpackage rdbms_ persistence_querybuilder19 * @subpackage rdbms_querybuilder 15 20 */ 16 21 interface stubDatabaseQueryBuilder 17 22 { 18 23 /** 24 * creates a select query 25 * 26 * @param stubCriterion $criterion condition for query 27 * @param array $tables list of tables to use in query 28 * @return string 29 */ 30 public function createSelect(stubCriterion $criterion, array $tables); 31 32 /** 19 33 * creates insert queries from a serialized value 20 34 * 21 * @param stubDatabaseSerializedValue $value22 * @return array <string,string> tableName => query35 * @param array(tableName => array(columns => array(columnName => columnValue))) $values 36 * @return array(tableName => query) 23 37 */ 24 public function createInsert( stubDatabaseSerializedValue $value);38 public function createInsert(array $values); 25 39 26 40 /** 27 41 * creates update queries from a serialized value 28 42 * 29 * @param stubDatabaseSerializedValue $value30 * @return array <string,string> tableName => query43 * @param array(tableName => array(criterion => stubCrition, columns => array(columnName => columnValue))) $values 44 * @return array(tableName => query) 31 45 */ 32 public function createUpdate(stubDatabaseSerializedValue $value); 46 public function createUpdate(array $values); 47 48 /** 49 * creates the query to create a table for the given class 50 * 51 * @param string $fqClassName the full qualified classname of the class to create the table for 52 * @throws stubDatabaseQueryBuilderException 53 */ 54 public function createTable($fqClassName); 33 55 } 34 56 ?> trunk/src/main/php/net/stubbles/rdbms/stubDatabaseConnection.php
r243 r256 16 16 * @subpackage rdbms 17 17 */ 18 interface stubDatabaseConnection 18 interface stubDatabaseConnection extends stubObject 19 19 { 20 20 /** trunk/src/main/php/net/stubbles/rdbms/stubDatabaseResult.php
r250 r256 14 14 * @subpackage rdbms 15 15 */ 16 interface stubDatabaseResult 16 interface stubDatabaseResult extends stubObject 17 17 { 18 18 /** trunk/src/main/php/net/stubbles/rdbms/stubDatabaseStatement.php
r250 r256 14 14 * @subpackage rdbms 15 15 */ 16 interface stubDatabaseStatement 16 interface stubDatabaseStatement extends stubObject 17 17 { 18 18 /**
