From: konrad Date: Wed, 4 Feb 2009 18:33:09 +0000 (+0000) Subject: work on unifying old DB abstraction layer with new woc X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=bbf516293b5bbfcdd701933703dd47ae6e133b00;p=web%2Fkonrad%2Fsmoke.git work on unifying old DB abstraction layer with new woc git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@264 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- diff --git a/wob/order.wolf b/wob/order.wolf index a3449f0..b6a9194 100644 --- a/wob/order.wolf +++ b/wob/order.wolf @@ -48,7 +48,7 @@ - +
@@ -58,7 +58,7 @@
- +
diff --git a/woc/phpout.cpp b/woc/phpout.cpp index f48915f..c0677c6 100644 --- a/woc/phpout.cpp +++ b/woc/phpout.cpp @@ -81,11 +81,12 @@ void WocPHPServerOut::newTable(const WocTable&tbl) return; } tf.write(PHPSTART); - QString code="class WT"+tbl.name()+" extends WobTable\n{\n"; + QString code="class WT"+tbl.name()+" extends "+tbl.baseClass()+"\n{\n"; //initializer code+="protected function __construct(array $data,$isfromdb){parent::__construct($data,$isfromdb,\""+tbl.name()+"\");}\n\n"; //static get instance + QStringList cols=tbl.columns(); QStringList pcols=tbl.primaryColumns(); code+="public static function getFromDB("; for(int i=0;iselect(\""+tbl.name()+"\",\"*\",$where);\n\tif($res===false || count($res)<1)return array();\n\t"; code+="$r=array();\n\tforeach($res as $row)\n\t\t$r[]=new WT"+tbl.name()+"($row,true);\n\treturn $r;\n}\n\n"; - //TODO:automatic resolution of internal foreign keys + //go through columns, generate specific code + for(int i=0;iescapeColumn(\""+foreign[0]+"\",\""+foreign[1]+"\",$this->"+cols[i]+"));\n}\n\n"; + } + //implement enum check for set method of enum columns + if(tbl.columnType(cols[i]).startsWith("enum")){ + code+="private function verifyValue"+cols[i]+"($v){if(false"; + QList >ens=tbl.columnEnums(cols[i]); + QListenvs; + for(int j=0;jescapeColumn(\""; + code+="public function "+fs[i]+"(){\n\tglobal "+dbi+";\n\treturn WT"+foreign[0]+"::selectFromDB(\""+foreign[1]+"=\"."+dbi+"->escapeColumn(\""; code+=foreign[0]+"\",\""+foreign[1]+"\",$this->"+local+"));\n}\n\n"; } @@ -139,7 +161,6 @@ void WocPHPServerOut::newTable(const WocTable&tbl) //extend schema file //column definitions - QStringList cols=tbl.columns(); code="\t$this->scheme[\""+tbl.name()+"\"]=array("; for(int i=0;i > WocTable::columnEnums(QString c)const +{ + for(int i=0;i >(); +} QList > WocTable::getEnums()const { diff --git a/woc/processor.h b/woc/processor.h index c522b22..4d5aff8 100644 --- a/woc/processor.h +++ b/woc/processor.h @@ -40,6 +40,7 @@ class WocTable QString name()const{return m_name;} bool inBackup()const{return m_backup;} + QString baseClass()const{return m_base;} bool hasColumn(QString)const; QStringList columns()const; @@ -53,6 +54,7 @@ class WocTable QString columnForeign(QString)const; bool columnIsIndexed(QString)const; bool columnIsUnique(QString)const; + QList > columnEnums(QString)const; QList > getEnums()const; @@ -63,7 +65,7 @@ class WocTable QList > presets()const{return m_presets;} private: bool m_valid,m_backup; - QString m_name; + QString m_name,m_base; struct s_col { QString name,type,foreign,defaultval; bool isnull,isprime,isindex,isunique; diff --git a/www/inc/db/db.php b/www/inc/db/db.php index 9db7399..1b0c300 100644 --- a/www/inc/db/db.php +++ b/www/inc/db/db.php @@ -43,7 +43,7 @@ abstract class DbEngine } /**returns whether the table exists; must be implemented by driver*/ - public abstract function haveTable($tablename); + public abstract function hasTable($tablename); /**begins a transaction; must be implemented by driver; use sqlBeginTransaction to create the SQL statement!*/ public abstract function beginTransaction(); @@ -60,7 +60,7 @@ abstract class DbEngine /**unlocks the database - only used by the backup functions; if necessary should also commit a transaction; default just commits*/ protected function unlockDB(){$this->commitTransaction();} - /**gets some data from the database; $table is the name of the table, $cols is the list of columns to return or "*" for all, $where is the where clause of the SQL-statement, $orderby may contain additional ORDER BY or GROUP BY clauses; returns array of rows, which are in *_fetch_array format; returns false on error; use sqlSelect to create the SQL statement!*/ + /**gets some data from the database; $table is the name of the table, $cols is the list of columns to return or "*" for all, $where is the where clause of the SQL-statement, $orderby may contain additional ORDER BY or GROUP BY clauses; returns array of rows, which are in *_fetch_array format; returns false on error; use sqlSelect to create the SQL statement!; make sure that NULL values are returned as PHP value null (most DB drivers already do this)*/ public abstract function select($table,$cols,$where,$orderby=""); /**insert values into a table; returns false on failure, the new primary key if a sequence was set, true otherwise; use sqlInsert to create the SQL statement!*/ @@ -272,35 +272,36 @@ abstract class DbEngine return "ROLLBACK TRANSACTION"; } - /**escapes integers; the default implementation just makes sure it is an int*/ + /**escapes integers; the default implementation just makes sure it is an int (false and null are translated to NULL)*/ public function escapeInt($i) { - if($i === false)return "NULL"; + if($i === false || $i === null)return "NULL"; return round($i + 0); } - /**escapes strings; the default uses addslashes and encloses the value in ''; it is recommended to overwrite this with the proper escaping procedure for the target DB*/ + /**escapes strings; the default uses addslashes and encloses the value in ''; it is recommended to overwrite this with the proper escaping procedure for the target DB (false and null are translated to NULL)*/ public function escapeString($s) { - if($s === false) return "NULL"; + if($s === false || $s === null) return "NULL"; return "'".addslashes($s)."'"; } /**escapes blobs; the default uses addslashes and encloses the value in ''; it is recommended to overwrite this with the proper escaping procedure for the target DB*/ public function escapeBlob($s) { - if($s === false) return "NULL"; + if($s === false || $s===null) return "NULL"; return "'".addslashes($s)."'"; } - /**escapes a boolean value; the default translates 0, '0', 'f', 'false', 'no' to FALSE and numerics !=0, 't', 'true', 'yes' to TRUE; any other value (incl. the PHP constant false) is translated to NULL (exception: the constant true is treated as 'true')*/ + /**escapes a boolean value; the default translates 0, '0', 'f', 'false', 'n', 'no', false to FALSE and numerics !=0, 't', 'true', 'y', 'yes', true to TRUE; any other value (incl. the PHP constant null) is translated to NULL*/ public function escapeBool($s) { + if($s===null)return "NULL"; if(is_numeric($s)){ if(($s+0)!=0)return "TRUE"; else return "FALSE"; } - if($s===false)return "NULL"; + if($s===false)return "FALSE"; if($s===true)return "TRUE"; switch(strtolower($s)){ case "t":case "true":case "yes":case "y": @@ -345,7 +346,7 @@ abstract class DbEngine /**tries to find out whether the connected DB version is usable*/ public function canUseDb() { - if(!$this->haveTable("config")) + if(!$this->hasTable("config")) return false; return $this->getConfig("MagicSmokeVersion")==$this->needVersion(); } @@ -397,10 +398,10 @@ abstract class DbEngine /**returns the error string of the last operation*/ public abstract function lastError(); - /**returns whether the result value is NULL; the default interprets both null and false as NULL; overwrite if the DB can return false for a boolean*/ + /**returns whether the result value is NULL; the default interprets only the special value null as NULL*/ public function isNull($val) { - if($val===false || $val===null)return true; + if($val===null)return true; else return false; } @@ -454,13 +455,13 @@ abstract class DbEngine private function unescapeBackup($fmt,$val) { switch($fmt){ - case "NULL":return false; + case "NULL":return null; case "int":return $val+0; case "str":return base64_decode($val); case "bool":return $val+0; default: print("Warning: encountered unknown data encoding \"".htmlspecialchars($fmt)."\". Using NULL instead.
\n"); - return false; + return null; } } @@ -519,7 +520,7 @@ abstract class DbEngine case "table": $data=array(); $table=$cmd[1]; - if(!$this->haveTable($table)){ + if(!$this->hasTable($table)){ print("Switching to non-existing table ".htmlspecialchars($table)." - ignoring data that follows.
\n"); $table=""; }else diff --git a/www/inc/db/db_mysql.php b/www/inc/db/db_mysql.php index fac5f50..cda3b4b 100644 --- a/www/inc/db/db_mysql.php +++ b/www/inc/db/db_mysql.php @@ -61,10 +61,10 @@ class MysqlEngine extends DbEngine die("Cannot make this database transaction safe, aborting"); } - public function haveTable($tnm) + public function hasTable($tnm) { global $dbScheme; - if(!$dbScheme->haveTable($tnm))return false; + if(!$dbScheme->hasTable($tnm))return false; $res=mysqli_query($this->dbhdl,"select * from ".$this->tableName($tnm)." where 1=2"); if($res===false)return false; mysqli_free_result($res); @@ -235,14 +235,16 @@ class MysqlEngine extends DbEngine /**escapes strings; it uses mysqli_escape_string and encloses the value in ''*/ public function escapeString($s) { - if($s === false) return "NULL"; + if($s === false||$s===null) return "NULL"; return "'".mysqli_real_escape_string($this->dbhdl,$s)."'"; } /**escapes blobs; it uses mysqli_escape_string and encloses the value in '' - blobs are binary strings in MySQL*/ public function escapeBlob($s) { - if($s === false) return "NULL"; + if($s === false||$s===null) return "NULL"; return "'".mysqli_real_escape_string($this->dbhdl,$s)."'"; } -}; \ No newline at end of file +}; + +?> \ No newline at end of file diff --git a/www/inc/wbase/schema.php b/www/inc/wbase/schema.php index 7e74ee3..fb368ba 100644 --- a/www/inc/wbase/schema.php +++ b/www/inc/wbase/schema.php @@ -20,7 +20,7 @@ class WobSchemaBase { } /**returns whether a table exists in the schema*/ - public function haveTable($t) + public function hasTable($t) { return in_array($t,array_keys($this->scheme)); } @@ -51,6 +51,12 @@ class WobSchemaBase { return $r; } + /**return whether the table has this column*/ + public function tableHasColumn($tab,$col) + { + return isset($this->scheme[$tab][$col]); + } + /**return default lines of the table for the initialization; returns empty array if there are none*/ public function tableDefaults($tab) { diff --git a/www/inc/wbase/table.php b/www/inc/wbase/table.php index afa6ef5..79070d2 100644 --- a/www/inc/wbase/table.php +++ b/www/inc/wbase/table.php @@ -11,6 +11,14 @@ // // +class ValueOutOfRange extends Exception +{ + public function __construct($tab,$col,$val) + { + $this->message="Value of table '$tab' column '$col' is out of range. Value '$val' not allowed."; + } +}; + class WobTable { private $data; @@ -26,38 +34,79 @@ class WobTable public function __set($name,$value) { + global $db,$dbScheme; //verify name against scheme - //escape value + if(!$dbScheme->tableHasColumn($this->table,$name))return; + //verify enum vals + $vm="verifyValue".$name; + if(method_exists($this,$vm)) + if(!$t->$vm($value)) + throw ValueOutOfRange($this->table,$name,$value); //DB update (if from DB) + $succ=true; + if($this->isfromdb){ + $succ=$db->update($this->table,array($name => $value),$this->where()); + } //if successful: store + if($succ)$this->data[$name]=$value; + } + + public function where() + { + global $dbScheme,$db; + $r=""; + $pk=$dbScheme->primaryKeyColumns($this->table); + foreach($pk as $c){ + if($r!="")$r.=" AND "; + $r.=$c."=".$db->escapeColumn($this->table,$c,$this->data[$c]); + } + return $r; } public function __get($name) { //verify name - //return value or false + //return value or null + if(isset($this->data[$name]))return $this->data[$name]; + else return null; } public function __isset($name) { + global $db; //verify name and return true on existence AND notnull + if(isset($this->data[$name]))return !$db->isNull($this->data[$name]); + else return false; } public function __unset($name) { + global $dbScheme; //reset to null + if($dbScheme->tableHasColumn($name))$this->data[$name]=null; } - /**insert the object under a new primary key value into the DB (implicitly calls newKey)*/ + /**insert the object under a new primary key value into the DB (implicitly calls newKey); returns true on success*/ public function insert() { + //remove PK from object (so it is set to default) + global $dbScheme; + $this->isfromdb=false; + $pk=$dbScheme->primaryKeyColumns($this->table); + foreach($pk as $c)unset($this->data[$c]); + //optionally create new key + $this->newKey(); + //now insert + $r=$db->insert($this->table,$this->data); + if($r===false)return false; + //TODO: make this a bit more safe: + if($r!==true)$this->data[$pk[0]]=$r; + return true; } /**generate a new primary key value for insert and marks the object as not yet in the DB; the default sets the primary key to NULL; call the original first if you overwrite it*/ public function newKey() { - $this->isfromdb=false; - //get primary key columns and set them to false } };