From 04aa11aaab2dbfe93278c6dd365aceb076f083dd Mon Sep 17 00:00:00 2001 From: Felipe Nascimento de Moura Date: Wed, 30 Mar 2011 22:09:55 -0300 Subject: [PATCH] fixed bugs around default values and fks which were also pks Also, added the program dqb to build DDL codes Working on postgres DDL generator --- docs/drafts/database-layers-thoughts.txt | 3 + docs/drafts/workflow.txt | 0 docs/ide/gif-loading.gif | Bin docs/ide/index.php | 345 +++++++++++---------- docs/ide/loading_animation.gif | Bin docs/tools.txt | 6 +- mind | 2 +- mind3rd/API/DBMS/DBMS.php | 17 + mind3rd/API/DBMS/mysql.php | 15 + mind3rd/API/DBMS/pgsql.php | 92 ++++++ mind3rd/API/classes/DAO/Project.php | 14 +- mind3rd/API/classes/DAO/ProjectFactory.php | 14 + mind3rd/API/classes/DQB/Query.php | 165 ++++++++++ mind3rd/API/classes/DQB/QueryFactory.php | 59 ++++ mind3rd/API/classes/MindProperty.php | 7 + mind3rd/API/cortex/analyst/Analyst.php | 2 +- mind3rd/API/cortex/analyst/Normalizer.php | 2 +- mind3rd/API/models/mind/app/.ignore | 0 mind3rd/API/models/mind/docs/.ignore | 0 mind3rd/API/models/mind/temp/.ignore | 0 mind3rd/API/programs/Commit.php | 0 mind3rd/API/programs/dqb.php | 119 +++++++ mind3rd/API/utils.php | 3 +- mind3rd/API/utils/constants.php | 2 +- mind3rd/API/utils/header.php | 3 +- mind3rd/SQLite/ddl.sql | 1 + mind3rd/env/defaults.ini | 5 +- mind3rd/projects/.ignore | 0 28 files changed, 705 insertions(+), 171 deletions(-) create mode 100755 docs/drafts/database-layers-thoughts.txt delete mode 100755 docs/drafts/workflow.txt mode change 100644 => 100755 docs/ide/gif-loading.gif mode change 100644 => 100755 docs/ide/loading_animation.gif create mode 100644 mind3rd/API/DBMS/DBMS.php create mode 100644 mind3rd/API/DBMS/mysql.php create mode 100644 mind3rd/API/DBMS/pgsql.php mode change 100644 => 100755 mind3rd/API/classes/DAO/Project.php mode change 100644 => 100755 mind3rd/API/classes/DAO/ProjectFactory.php create mode 100644 mind3rd/API/classes/DQB/Query.php create mode 100644 mind3rd/API/classes/DQB/QueryFactory.php mode change 100644 => 100755 mind3rd/API/models/mind/app/.ignore mode change 100644 => 100755 mind3rd/API/models/mind/docs/.ignore mode change 100644 => 100755 mind3rd/API/models/mind/temp/.ignore mode change 100644 => 100755 mind3rd/API/programs/Commit.php create mode 100644 mind3rd/API/programs/dqb.php mode change 100644 => 100755 mind3rd/projects/.ignore diff --git a/docs/drafts/database-layers-thoughts.txt b/docs/drafts/database-layers-thoughts.txt new file mode 100755 index 0000000..768ba67 --- /dev/null +++ b/docs/drafts/database-layers-thoughts.txt @@ -0,0 +1,3 @@ +DAO - the abstrction layer which access the internal database to record the current structure +DBAL - DataBase Abstraction Layer: Will deal with the real database(the external) to create or change it +DQB - Database Query Builder: creates the queries to each BDMS, to be used dealing with the external database diff --git a/docs/drafts/workflow.txt b/docs/drafts/workflow.txt deleted file mode 100755 index e69de29..0000000 diff --git a/docs/ide/gif-loading.gif b/docs/ide/gif-loading.gif old mode 100644 new mode 100755 diff --git a/docs/ide/index.php b/docs/ide/index.php index 8117b8f..0e5659a 100755 --- a/docs/ide/index.php +++ b/docs/ide/index.php @@ -1,165 +1,192 @@ - - - - - - - - - - -
- - + + + + + + + + + + + +
+ + + function showQueries() + { + setLoading(); + $.ajax({ + type:'POST', + url:'../../', + data:{ + program:'dqb', + query: 'create', + table: '*' + }, + success: function(retQ){ + document.getElementById('result').innerHTML= retQ; + } + }); + } + + function logoff() + { + setLoading(); + $.ajax({ + type:'POST', + url:'../../', + data:{ + program:'exit' + }, + success: function(ret){ + document.getElementById('result').innerHTML= ret + } + }); + } + + diff --git a/docs/ide/loading_animation.gif b/docs/ide/loading_animation.gif old mode 100644 new mode 100755 diff --git a/docs/tools.txt b/docs/tools.txt index 3cd5ea7..92e013c 100755 --- a/docs/tools.txt +++ b/docs/tools.txt @@ -1,7 +1,7 @@ -Diagrama de sequĂȘncia +Sequence diagram http://www.websequencediagrams.com/ -Diagrama ER - http://thewebmind.org/ +ER Diagram + http://thewebmind.org/ (second version) MindMap http://www.mindmeister.com/ Class Diagram diff --git a/mind b/mind index 30ed3cc..56b373e 100755 --- a/mind +++ b/mind @@ -28,5 +28,5 @@ exit; } // if not installing, it should be redirected to mind3rd/API/shell.php - include('location:./mind3rd/API/shell.php'); + header('location:./mind3rd/API/shell.php'); } \ No newline at end of file diff --git a/mind3rd/API/DBMS/DBMS.php b/mind3rd/API/DBMS/DBMS.php new file mode 100644 index 0000000..00b97a8 --- /dev/null +++ b/mind3rd/API/DBMS/DBMS.php @@ -0,0 +1,17 @@ + + * @license licenses/mind3rd.license + */ + +/** + * Description of pgsql + * + * @author Felipe Nascimento de Moura + * @package DBMS + */ +class pgsql implements DBMS{ + + public function createDefault() + { + return "DEFAULT "; + } + + public function property() + { + return " "; + } + + public function createOptionsCheck() + { + return "CHECK ()"; + } + + public function notNullDefinition() + { + return "NOT NULL"; + } + + public function autoIncrementType() + { + return "serial"; + } + + public function createUnique() + { + return "UNIQUE"; + } + + public function createFK() + { + return " +ALTER TABLE + ADD CONSTRAINT + FOREIGN KEY () REFERENCES +() +"; + } + + public function createPrimaryKeys() + { + return " + CONSTRAINT PRIMARY KEY () +"; + } + + public function createPK() + { + return " +ALTER TABLE + ADD PRIMARY KEY (); +"; + } + + public function createTable() + { + return " +CREATE TABLE +( + + +); +"; + } + + public function getModel($command) + { + if(method_exists($this, $command)) + return $this->$command(); + return false; + } +} \ No newline at end of file diff --git a/mind3rd/API/classes/DAO/Project.php b/mind3rd/API/classes/DAO/Project.php old mode 100644 new mode 100755 index 2049ec9..f5dfb8b --- a/mind3rd/API/classes/DAO/Project.php +++ b/mind3rd/API/classes/DAO/Project.php @@ -33,7 +33,7 @@ class Project{ * @return Array An array with all the entities for the project in the curret * or passed(if passed) version. */ - public function getCurrentEntities($vs=false) + public function getCurrentEntities($vs=false, $name=false, $pk=false) { $qr= "SELECT entity.name as name, pk_entity, @@ -43,8 +43,13 @@ class Project{ where fk_project = ".\Mind::$currentProject['pk_project']." and fk_version= pk_version and status = ".\COMMIT_STATUS_OK; + if($vs) $qr.= " and fk_version = ".$vs.""; + if($name) + $qr.= " and entity.name = '".$name."'"; + if($pk) + $qr.= " and pk_entity = ".$pk.""; $entities= $this->db->query($qr); return $entities; @@ -63,13 +68,16 @@ class Project{ { $refs= ""; if($prop->refTo) + { $refs= $prop->refTo[0]->name.".".$prop->refTo[1]->name; + } $qr= "INSERT into property ( name, type, size, options, + is_pk, default_value, unique_value, required, @@ -84,6 +92,7 @@ class Project{ '".$prop->type."', '".$prop->size."', '".JSON_encode($prop->options)."', + '".(($prop->key)? 1: 0)."', '".$prop->default."', '".$prop->unique."', '".$prop->required."', @@ -110,6 +119,7 @@ class Project{ type, size, options, + is_pk, default_value, unique_value, required, @@ -232,7 +242,7 @@ class Project{ )"; $entities= $this->db->execute($qr); $enKey= $this->db->lastInsertedId; - + foreach($entity->properties as &$prop) { $this->insertProperty($prop, $enKey); diff --git a/mind3rd/API/classes/DAO/ProjectFactory.php b/mind3rd/API/classes/DAO/ProjectFactory.php old mode 100644 new mode 100755 index 4244b92..c825b1b --- a/mind3rd/API/classes/DAO/ProjectFactory.php +++ b/mind3rd/API/classes/DAO/ProjectFactory.php @@ -147,6 +147,20 @@ class ProjectFactory extends Project{ return $data; } + /** + * This method will get the passed entity attributes. + * + * @param mixed $entity you can pass either the pk or the name of the entity + * @return the query return itself + */ + public function getEntity($entity) + { + if(\is_string($entity)) + return $this->getCurrentEntities(false, $entity); + else + return $this->getCurrentEntities(false, false, $entity); + } + /** * Commits the current data to the SQLite database. * It will commit the analyzed structure to the databse into a diff --git a/mind3rd/API/classes/DQB/Query.php b/mind3rd/API/classes/DQB/Query.php new file mode 100644 index 0000000..65d5c0e --- /dev/null +++ b/mind3rd/API/classes/DQB/Query.php @@ -0,0 +1,165 @@ + + * @license licenses/mind3rd.license + */ + +namespace DQB; +/** + * Description of Query + * + * @author Felipe Nascimento de Moura + * @package DQB + */ +class Query { + + const TABLE_NAME = '//'; + const PROPS = '//'; + const PROPS_NAME = '//'; + const PROP_NAME = '//'; + const PROP_TYPE = '//'; + const PROP_SIZE = '//'; + const PROP_DETAILS= '//'; + const PROP_DEFAULT= '//'; + const PROP_OPTIONS= '//'; + const PRIMARY_KEYS= '//'; + const FK_NAME= '//'; + public $query= ""; + private $pks= Array(); // temporary variable + private $fks= Array(); // temporary variable + + public function setUp() + { + $this->pks= false; + $this->pks= Array(); + $this->fks= false; + $this->fks= Array(); + } + + private function parseDetails(Array $prop, $table) + { + $details= Array(); + + // parsing te default value + if(!empty($prop['default_value'])) + { + $default= QueryFactory::getQueryString('createDefault'); + + $details[]= preg_replace(self::PROP_DEFAULT, + $prop['default_value'], + $default); + } + + // checking the not null attribute + if($prop['required']) + $details[]= QueryFactory::getQueryString('notNullDefinition'); + + // + $prop['options']= JSON_decode($prop['options']); + if(sizeof($prop['options'])>0) + { + $optionsTplt= QueryFactory::getQueryString('createOptionsCheck'); + $options= Array(); + foreach($prop['options'] as $opt) + { + $opt= \is_string($opt[0])? "'".$opt[0]."'": $opt[0]; + $options[]= $opt; + } + $details[]= preg_replace(self::PROP_OPTIONS, + $prop['name']."=". + implode(" OR ".$prop['name'] + ."=", + $options), + $optionsTplt); + } + //print_r($prop); + if($prop['unique_value']) + { + $details[]= QueryFactory::getQueryString('createUnique'); + } + if($prop['ref_to_property']) + { + $this->fks[]= $prop; + } + return implode(' ', $details); + } + + private function createProperties(&$query, $table) + { + $template= QueryFactory::getQueryString('property'); + $tmpQuery= ""; + foreach($table['properties'] as $prop) + { + if($prop['is_pk']) + $this->pks[]= $prop['name']; + + $propQuery= ""; + $propQuery= preg_replace(self::PROP_NAME, $prop['name'], $template); + + if($prop['default_value'] == \AUTOINCREMENT_DEFVAL) + { + $prop['type']= QueryFactory::getQueryString('autoIncrementType'); + $prop['default_value']= false; + } + + if($prop['size']) + $propQuery= preg_replace(self::PROP_SIZE, "(".$prop['size'].")", $propQuery); + else + $propQuery= preg_replace(self::PROP_SIZE, "", $propQuery); + $propQuery= preg_replace(self::PROP_NAME, $prop['name'], $propQuery); + $propQuery= preg_replace(self::PROP_DETAILS, + $this->parseDetails($prop, $table), + $propQuery); + + $propQuery= preg_replace(self::PROP_TYPE, $prop['type'], $propQuery); + + $tmpQuery.= $propQuery."\n "; + } + + $query= preg_replace(self::PROPS, trim($tmpQuery), $query); + } + + public function createPrimaryKeys(&$query, $table) + { + $tmplt= QueryFactory::getQueryString('createPrimaryKeys'); + //print_r($this->pks); + $tmpQuery= preg_replace(self::PROPS_NAME, + implode(', ', $this->pks), + $tmplt); + $tmpQuery= preg_replace(self::FK_NAME, + $table['name']."_".implode('_', $this->pks), + $tmpQuery); + $query= preg_replace(self::PRIMARY_KEYS, trim($tmpQuery), $query); + } + + public function __construct($command, Array $table, $template) + { + $query= ''; + $this->setUp(); + + switch($command) + { + case 'createTable': + $query= preg_replace(self::TABLE_NAME, $table['name'], $template); + + //if(preg_match(self::PROPS, $template)) + self::createProperties($query, $table); + self::createPrimaryKeys($query, $table); + break; + } + + $this->query= $query; + return $query; + } + + public function __toString() + { + return htmlentities($this->query); + } + +} \ No newline at end of file diff --git a/mind3rd/API/classes/DQB/QueryFactory.php b/mind3rd/API/classes/DQB/QueryFactory.php new file mode 100644 index 0000000..e181806 --- /dev/null +++ b/mind3rd/API/classes/DQB/QueryFactory.php @@ -0,0 +1,59 @@ + + * @license licenses/mind3rd.license + */ + +namespace DQB; +/** + * Description of QueryBuilder + * + * @author Felipe Nascimento de Moura + * @package DQB + */ +class QueryFactory { + + public static $queries= Array(); + public static $dbms= Array(); + + public static function addQuery($command, Array $table, $template) + { + if(!isset(self::$queries[$command])) + self::$queries[$command]= Array(); + self::$queries[$command][$table['name']]= new Query($command, $table, $template); + return self::$queries[$command][$table['name']]->query; + } + + public static function getQueryString($command) + { + return self::$dbms->getModel($command); + } + + public static function build($command, Array $table) + { + $template= self::$dbms->getModel($command); + return self::addQuery($command, $table, $template); + } + + public static function setUp($dbDriver) + { + self::$queries= false; + self::$queries= Array(); + self::$dbms= @new $dbDriver(); + if(!self::$dbms) + { + // TODO: put it into the L10N + echo "Database Driver not found."; + } + } + + public function __construct($dbDriver) + { + self::setUp($dbDriver); + } +} \ No newline at end of file diff --git a/mind3rd/API/classes/MindProperty.php b/mind3rd/API/classes/MindProperty.php index a03854c..f4fd42f 100755 --- a/mind3rd/API/classes/MindProperty.php +++ b/mind3rd/API/classes/MindProperty.php @@ -221,6 +221,8 @@ */ private function parse() { + GLOBAL $_MIND; + $str= $this->definition; $one= 1; @@ -265,6 +267,11 @@ // identifying its size if(preg_match(PROP_SIZE, $details, $size)) $this->setSize($size[0]); + else{ + if($this->type == 'varchar' || $this->type == 'char') + $this->setSize($_MIND-> + defaults['default_character_length']); + } // identifying the options if(preg_match(PROP_OPTIONS, $details, $options)) diff --git a/mind3rd/API/cortex/analyst/Analyst.php b/mind3rd/API/cortex/analyst/Analyst.php index 0960d04..24af4c5 100755 --- a/mind3rd/API/cortex/analyst/Analyst.php +++ b/mind3rd/API/cortex/analyst/Analyst.php @@ -128,7 +128,7 @@ class Analyst extends Analysis { "AUTO_INCREMENT"; if(sizeof($prop->options) > 0) { - $opts= "{".implode("|", array_keys($prop->default))."}"; + $opts= "{".implode("|", array_keys($prop->options))."}"; $details[]= $opts; } diff --git a/mind3rd/API/cortex/analyst/Normalizer.php b/mind3rd/API/cortex/analyst/Normalizer.php index 9e51b57..3091ab5 100755 --- a/mind3rd/API/cortex/analyst/Normalizer.php +++ b/mind3rd/API/cortex/analyst/Normalizer.php @@ -294,7 +294,7 @@ $fk->setRequired(true); if($relation->linkType == 'must') $fk->setRequired (true); - if($relation->uniqueRef) + if($relation->uniqueRef || $entity->linkTable) { if(!$entity->linkTable|| ($entity->linkTable && $entity->hasHardKey()) diff --git a/mind3rd/API/models/mind/app/.ignore b/mind3rd/API/models/mind/app/.ignore old mode 100644 new mode 100755 diff --git a/mind3rd/API/models/mind/docs/.ignore b/mind3rd/API/models/mind/docs/.ignore old mode 100644 new mode 100755 diff --git a/mind3rd/API/models/mind/temp/.ignore b/mind3rd/API/models/mind/temp/.ignore old mode 100644 new mode 100755 diff --git a/mind3rd/API/programs/Commit.php b/mind3rd/API/programs/Commit.php old mode 100644 new mode 100755 diff --git a/mind3rd/API/programs/dqb.php b/mind3rd/API/programs/dqb.php new file mode 100644 index 0000000..4e8ab2f --- /dev/null +++ b/mind3rd/API/programs/dqb.php @@ -0,0 +1,119 @@ +setName('dqb') + ->setDescription('Performs some tests on theWebMind') + ->setRestrict(true) + ->setDefinition(array( + new InputArgument('query', + InputArgument::REQUIRED, + 'Options: create, drop, alter, insert, delete, select and update'), + new InputArgument('table', + InputArgument::REQUIRED, + "Which table will have its query built. Use * to see them all."), + )) + ->setHelp(<<query= $input->getArgument('query'); + $this->table= $input->getArgument('table'); + $this->runAction(); + } + + public function HTTPExecute() + { + GLOBAL $_REQ; + if(!parent::HTTPExecute()) + return false; + if(isset($_REQ['data']['query']) && isset($_REQ['data']['table'])) + { + $this->query= $_REQ['data']['query']; + $this->table= $_REQ['data']['table']; + } + $this->runAction(); + } + + private function action() + { + GLOBAL $_MIND; + if(!parent::verifyCredentials()) + return false; + + //$query= new DQB\QueryFactory(Mind::$currentProject['database_drive']); + DQB\QueryFactory::setUp(Mind::$currentProject['database_drive']); + $query= "DQB\QueryFactory"; + $p= new DAO\ProjectFactory(Mind::$currentProject); + $param= ($this->table=='*')? false: $this->table; + $entities= $p->getEntity($param); + //print_r($entities); + switch($this->query) + { + case 'create': + case 'c': + $this->query= 'createTable'; + break; + case 'select': + case 's': + case 'query': + $this->query= 'select'; + break; + case 'delete': + case 'del': + case 'd': + $this->query= 'delete'; + break; + case 'insert': + case 'ins': + case 'i': + $this->query= 'insert'; + break; + case 'update': + case 'upd': + case 'u': + $this->query= 'update'; + break; + } + + foreach($entities as $entity) + { + $entity['properties']= $p->getProperties($entity); + + $query::build($this->query, $entity); + } + + foreach($query::$queries as $qrs) + { + foreach($qrs as $qr) + { + echo $qr; + } + } + return $this; + } + + public function runAction() + { + $ret= $this->action(); + parent::runAction(); + return $ret; + } +} \ No newline at end of file diff --git a/mind3rd/API/utils.php b/mind3rd/API/utils.php index 1f84e5d..551560b 100755 --- a/mind3rd/API/utils.php +++ b/mind3rd/API/utils.php @@ -45,7 +45,8 @@ new Create(), new Show(), new Analyze(), - new SetUse() + new SetUse(), + new dqb() )); if($_REQ['env']=='shell') diff --git a/mind3rd/API/utils/constants.php b/mind3rd/API/utils/constants.php index 8a6e8b6..cee770b 100755 --- a/mind3rd/API/utils/constants.php +++ b/mind3rd/API/utils/constants.php @@ -11,7 +11,7 @@ define('PROP_OPTIONS', "/\{(.+?)\}/"); define('PROP_OPTIONS_CLEAR', "/^\{|\}$/"); define('PROP_DEFEXEC', "/(^(\"=)|(\"exec\:))|(\"$)/i"); - define('PROP_SIZE', "/\d+(\.?\d+)/"); + define('PROP_SIZE', "/\d+(\.?\d+)?/"); define('COMA_SEPARATOR', "/\s/"); define('SINGLE_COMMENT', "/\/\/.+\n/"); define('MULTILINE_COMMENT', "/\/\*.+?\*\//"); diff --git a/mind3rd/API/utils/header.php b/mind3rd/API/utils/header.php index c77436c..d18200f 100755 --- a/mind3rd/API/utils/header.php +++ b/mind3rd/API/utils/header.php @@ -21,7 +21,8 @@ _MINDSRC_.'/mind3rd/API/cortex/syntaxer/', _MINDSRC_.'/mind3rd/API/cortex/analyst/', _MINDSRC_.'/mind3rd/API/cortex/Darwin/', - _MINDSRC_.'/mind3rd/API/languages/' + _MINDSRC_.'/mind3rd/API/languages/', + _MINDSRC_.'/mind3rd/API/DBMS/' )); function __autoload($what) diff --git a/mind3rd/SQLite/ddl.sql b/mind3rd/SQLite/ddl.sql index e6d63ae..b5fb4b0 100755 --- a/mind3rd/SQLite/ddl.sql +++ b/mind3rd/SQLite/ddl.sql @@ -130,6 +130,7 @@ CREATE TABLE property type varchar(16), size float, options varchar(1024), /* insert the json value */ + is_pk boolean, default_value text, unique_value boolean, required boolean, diff --git a/mind3rd/env/defaults.ini b/mind3rd/env/defaults.ini index f6c714d..6584f17 100755 --- a/mind3rd/env/defaults.ini +++ b/mind3rd/env/defaults.ini @@ -35,4 +35,7 @@ add_pk_prefix_to_all_keys=on fk_prefix="fk_" ; this will be the name of the additional column on tables which require a ; new column to enumerate multiple PrimaryKeys -counter_col="counter" \ No newline at end of file +counter_col="counter" +; Varchar and Char properties should have mandatorily a size, if none is passed, +; the following value will be used as size +default_character_length=255 \ No newline at end of file diff --git a/mind3rd/projects/.ignore b/mind3rd/projects/.ignore old mode 100644 new mode 100755