<?php
/*******************************************************************************
* Copyright 2008 Rafael Marques Martins
*
* This file is part of SQLReactor.
*
* SQLReactor is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* SQLReactor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with SQLReactor; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*******************************************************************************/
class SQLReactorColumnList{
final public function __clone(){
foreach( get_object_vars( $this ) as $cn => $c ){
$this->$cn = clone $c;
}
}
}
class SQLReactorTable{
public $connection;
public $class;
public $name;
public $columns;
public $primaryKey = array();
public $unique = array();
public $indexes = array();
final public function __clone(){
$this->columns = clone $this->columns;
}
final public function __construct( &$class, $name ){
$this->class = $class;
$this->connection = &$class->_connection;
$this->name = $name ? $name : $this->getNormalizedName();
$this->columns = new SQLReactorColumnList();
}
final public function getNormalizedName(){
$tmpName = get_class( $this->class );
if( $this->class->_ignoreSuffix ){
$tmpName = preg_replace( "/(.+){$this->class->_ignoreSuffix}$/", "\\1", $tmpName );
}
$name = preg_replace( "/^_/", "", strtolower( preg_replace( "/([A-Z]+)/", "_\\1", $tmpName ) ) );
return $name;
}
public function getCreateSQL(){
$sql = "CREATE TABLE {$this->connection->engine->escapeName}{$this->name}{$this->connection->engine->escapeName} ( \r\n";
$columns = array();
foreach( get_object_vars( $this->columns ) as $attribute => $column ){
if( $column instanceof ForeignKey || $column instanceof Backref ) continue;
$columns[] = "\t" . $column->getCreateSQL();
}
if( $this->primaryKey ){
$keyNames = array();
foreach( $this->primaryKey as $keyName ){
$keyNames[] = "{$this->connection->engine->escapeName}{$this->columns->$keyName->name}{$this->connection->engine->escapeName}";
}
$columns[] = "\tPRIMARY KEY ( " . implode( ", ", $keyNames ) . " )";
}
foreach( $this->unique as $unique ){
$keyNames = array();
foreach( $unique as $keyName ){
$keyNames[] = "{$this->connection->engine->escapeName}{$this->columns->$keyName->name}{$this->connection->engine->escapeName}";
}
$columns[] = "\tUNIQUE ( " . implode( ", ", $keyNames ) . " )";
}
foreach( get_object_vars( $this->columns ) as $attribute => $column ){
if( $column instanceof ForeignKey ){
$tmp = $column->getCreateSQL();
if( !is_null( $tmp ) ){
$columns[] = "\t" . $column->getCreateSQL();
}
}
}
$sql .= implode( ",\r\n", $columns );
$sql .= "\r\n)";
return $sql;
}
public function createIndexes(){
foreach( $this->indexes as $index ){
$indexName = "idx_{$this->name}";
$columns = array();
foreach( $index as $columnName ){
$indexName .= "_{$this->columns->$columnName->name}";
$columns[] = "{$this->connection->engine->escapeName}{$this->columns->$columnName->name}{$this->connection->engine->escapeName}";
}
if( $columns ){
$sql = "CREATE INDEX {$this->connection->engine->escapeName}{$indexName}{$this->connection->engine->escapeName} ON {$this->connection->engine->escapeName}{$this->name}{$this->connection->engine->escapeName} ( " . implode( ', ', $columns ) . " )";
var_dump( $sql );
$this->connection->query( $sql );
}
}
}
public function createTable(){
$this->connection->query( $this->getCreateSQL() );
if( $this->class->_primaryKey == array( 'id' ) ){
$sql = $this->columns->id->getCreateSequenceSQL();
if( $sql ){
$this->connection->query( $sql );
}
}
$this->createIndexes();
}
public function getInsertSQL(){
$sql = "INSERT INTO {$this->connection->engine->escapeName}{$this->name}{$this->connection->engine->escapeName} ( ";
$columnNames = array();
$columnValues = array();
foreach( $this->columns as $attribute => $column ){
if( $column instanceof ForeignKey || $column instanceof Backref ) continue;
if( $column instanceof SerialCol && $column->insertIgnore ) continue;
$columnNames[] = "{$this->connection->engine->escapeName}{$column->name}{$this->connection->engine->escapeName}";
$columnValues[] = $column->getValueToDB();
}
$sql .= implode( ", ", $columnNames ) . " ) VALUES ( ";
$sql .= implode( ", ", $columnValues );
$sql .= " )";
return $sql;
}
public function getUpdateSQL(){
$sql = "UPDATE {$this->connection->engine->escapeName}{$this->name}{$this->connection->engine->escapeName} SET ";
$columnSet = array();
foreach( get_object_vars( $this->columns ) as $attribute => $column ){
if( $column instanceof ForeignKey || $column instanceof Backref ) continue;
if( $column->changed ){
$set = "{$this->connection->engine->escapeName}{$column->name}{$this->connection->engine->escapeName} = " . $column->getValueToDB();
$columnSet[] = $set;
}
}
$sql .= implode( ", ", $columnSet );
$clauses = array();
foreach( $this->class->_primaryKey as $pkName ){
$clauses[] = "{$this->connection->engine->escapeName}{$this->class->_columnNames->$pkName}{$this->connection->engine->escapeName} = " . $this->columns->$pkName->getValueToDB();
}
if( $clauses ){
$sql .= " WHERE " . implode( " AND ", $clauses );
}
if( $columnSet ){
return $sql;
}
return null;
}
protected function insert(){
$this->connection->engine->insert( $this );
}
protected function update(){
$this->connection->engine->update( $this );
}
public function save(){
if( $this->class->_properties[ 'exists' ] ){
$return = $this->update();
}else{
$return = $this->insert();
}
$this->class->_properties[ 'exists' ] = true;
foreach( get_object_vars( $this->columns ) as $column ){
$column->changed = false;
}
return $return;
}
public function getDeleteSQL(){
$sql = "DELETE FROM {$this->connection->engine->escapeName}{$this->name}{$this->connection->engine->escapeName}";
$clauses = array();
foreach( $this->class->_primaryKey as $pkName ){
$clauses[] = "{$this->connection->engine->escapeName}{$this->class->_columnNames->$pkName}{$this->connection->engine->escapeName} = " . $this->columns->$pkName->getValueToDB();
}
if( $clauses ){
$sql .= " WHERE " . implode( " AND ", $clauses );
}
return $sql;
}
public function delete(){
if( !$this->class->_properties[ 'exists' ] ) return;
$this->connection->engine->delete( $this );
}
}
?>