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
Esse commit está contido em:
Felipe Nascimento de Moura
2011-03-30 22:09:55 -03:00
commit 04aa11aaab
28 arquivos alterados com 705 adições e 171 exclusões
+3
Ver Arquivo
@@ -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
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo

Antes

Largura:  |  Altura:  |  Tamanho: 1.2 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 1.2 KiB

+186 -159
Ver Arquivo
@@ -1,165 +1,192 @@
<script src='scripts/jquery.js'></script>
<body>
<input type='button' value='autenticate' onclick="autenticate()"/>
<input type='button' value='run test' onclick="runTest()"/>
<input type='button' value='run info' onclick="runInfo()"/>
<input type='button' value='show projects' onclick="showProjects()"/>
<input type='button' value='show users' onclick="showUsers()"/>
<input type='button' value='analyze project x' onclick="analyzeX()"/>
<input type='button' value='analyze project y' onclick="analyzeY()"/>
<input type='button' value='logoff' onclick="logoff()"/>
<pre><div id='result' style='white-space:pre;'></div></pre>
</body>
<script>
function setLoading()
{
document.getElementById('result').innerHTML= "&nbsp;&nbsp;<img src='loading_animation.gif' /><br/>Loading...";
}
<html>
<head>
<script src='scripts/jquery.js'></script>
<style tye='text/css'>
property
{
font-weight:bold;
}
</style>
</head>
<body>
<input type='button' value='autenticate' onclick="autenticate()"/>
<input type='button' value='run test' onclick="runTest()"/>
<input type='button' value='run info' onclick="runInfo()"/>
<input type='button' value='show projects' onclick="showProjects()"/>
<input type='button' value='show users' onclick="showUsers()"/>
<input type='button' value='analyze project demo_en' onclick="analyzeX()"/>
<input type='button' value='show queries' onclick="showQueries()"/>
<input type='button' value='logoff' onclick="logoff()"/>
<pre><div id='result' style='white-space:pre;'></div></pre>
</body>
<script>
function setLoading()
{
document.getElementById('result').innerHTML= "&nbsp;&nbsp;<img src='loading_animation.gif' /><br/>Loading...";
}
function autenticate(){
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'auth',
login:"admin",
pwd:'admin'
},
success: function(ret){
document.getElementById('result').innerHTML= ret
}
});
}
function runTest()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'test',
unit: true
},
success: function(ret){
document.getElementById('result').innerHTML= ret
}
});
}
function runInfo()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program: 'info'
},
success: function(ret){
document.getElementById('result').innerHTML= ret
}
});
}
function autenticate(){
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'auth',
login:"admin",
pwd:'admin'
},
success: function(ret){
document.getElementById('result').innerHTML= ret
}
});
}
function runTest()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'test',
unit: true
},
success: function(ret){
document.getElementById('result').innerHTML= ret
}
});
}
function runInfo()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program: 'info'
},
success: function(ret){
document.getElementById('result').innerHTML= ret
}
});
}
function showProjects()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'show',
what:'projects',
detailed:'1'
},
success: function(ret){
document.getElementById('result').innerHTML= ret
}
});
}
function showProjects()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'show',
what:'projects',
detailed:'1'
},
success: function(ret){
document.getElementById('result').innerHTML= ret
}
});
}
function showUsers()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'show',
what:'users',
detailed:'1'
},
success: function(ret){
document.getElementById('result').innerHTML= ret
}
});
}
function showUsers()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'show',
what:'users',
detailed:'1'
},
success: function(ret){
document.getElementById('result').innerHTML= ret
}
});
}
function analyzeX()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'use',
what:'project',
name:'x'
},
success: function(ret){
$.ajax({
type:'POST',
url:'../../',
data:{
program:'analyze',
commit:true
},
success: function(ret){
document.getElementById('result').innerHTML= ret;
}
});
}
});
}
function analyzeX()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'use',
what:'project',
name:'demo_en'
},
success: function(ret){
$.ajax({
type:'POST',
url:'../../',
data:{
program:'analyze',
commit:true
},
success: function(ret){
document.getElementById('result').innerHTML= ret;
}
});
}
});
}
function analyzeY()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'use',
what:'project',
name:'y'
},
success: function(ret){
$.ajax({
type:'POST',
url:'../../',
data:{
program:'analyze'
},
success: function(retY){
document.getElementById('result').innerHTML= retY;
}
});
}
});
}
function analyzeY()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'use',
what:'project',
name:'y'
},
success: function(ret){
$.ajax({
type:'POST',
url:'../../',
data:{
program:'analyze'
},
success: function(retY){
document.getElementById('result').innerHTML= retY;
}
});
}
});
}
function logoff()
{
setLoading();
$.ajax({
type:'POST',
url:'../../',
data:{
program:'exit'
},
success: function(ret){
document.getElementById('result').innerHTML= ret
}
});
}
</script>
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
}
});
}
</script>
</html>
Arquivo normal → Arquivo executável
Ver Arquivo

Antes

Largura:  |  Altura:  |  Tamanho: 12 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 12 KiB

+3 -3
Ver Arquivo
@@ -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
+1 -1
Ver Arquivo
@@ -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');
}
+17
Ver Arquivo
@@ -0,0 +1,17 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
* Description of DBMS
*
* @author felipe
*/
interface DBMS {
public function createTable();
public function createPK();
public function createPrimaryKeys();
}
+15
Ver Arquivo
@@ -0,0 +1,15 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
* Description of mysql
*
* @author felipe
*/
class mysql {
//put your code here
}
+92
Ver Arquivo
@@ -0,0 +1,92 @@
<?php
/**
* This file is part of TheWebMind 3rd generation.
*
* Notice that, these packages are being used only for documentation,
* not to organize the classes.
*
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
* @license licenses/mind3rd.license
*/
/**
* Description of pgsql
*
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
* @package DBMS
*/
class pgsql implements DBMS{
public function createDefault()
{
return "DEFAULT <defaultvalue>";
}
public function property()
{
return "<property><propertyname></property> <propertytype><propertysize> <propertydetails>";
}
public function createOptionsCheck()
{
return "CHECK (<options>)";
}
public function notNullDefinition()
{
return "NOT NULL";
}
public function autoIncrementType()
{
return "serial";
}
public function createUnique()
{
return "UNIQUE";
}
public function createFK()
{
return "
<command>ALTER </command><object>TABLE</object> <tablename>
<command>ADD</command> <object>CONSTRAINT</object> <constraintname>
<object>FOREIGN KEY (<column>)</object> <command>REFERENCES </command>
<referencetablename>(<referencecolumnname>)
";
}
public function createPrimaryKeys()
{
return "
<object>CONSTRAINT</object> <fkname> <object>PRIMARY KEY</object> (<propertienames>)
";
}
public function createPK()
{
return "
<command>ALTER</command> <object>TABLE</object> <tablename>
<command>ADD</command> <object>PRIMARY KEY</object> (<propertienames>);
";
}
public function createTable()
{
return "
<command>CREATE </command><object>TABLE</object> <tablename>
(
<properties>
<primarykeys>
);
";
}
public function getModel($command)
{
if(method_exists($this, $command))
return $this->$command();
return false;
}
}
Arquivo normal → Arquivo executável
+12 -2
Ver Arquivo
@@ -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);
Arquivo normal → Arquivo executável
+14
Ver Arquivo
@@ -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
+165
Ver Arquivo
@@ -0,0 +1,165 @@
<?php
/**
* This file is part of TheWebMind 3rd generation.
*
* Notice that, these packages are being used only for documentation,
* not to organize the classes.
*
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
* @license licenses/mind3rd.license
*/
namespace DQB;
/**
* Description of Query
*
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
* @package DQB
*/
class Query {
const TABLE_NAME = '/<tablename(\/)?>/';
const PROPS = '/<properties(\/)?>/';
const PROPS_NAME = '/<propertienames(\/)?>/';
const PROP_NAME = '/<propertyname(\/)?>/';
const PROP_TYPE = '/<propertytype(\/)?>/';
const PROP_SIZE = '/<propertysize(\/)?>/';
const PROP_DETAILS= '/<propertydetails(\/)?>/';
const PROP_DEFAULT= '/<defaultvalue(\/)?>/';
const PROP_OPTIONS= '/<options(\/)?>/';
const PRIMARY_KEYS= '/<primarykeys(\/)?>/';
const FK_NAME= '/<fkname(\/)?>/';
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);
}
}
+59
Ver Arquivo
@@ -0,0 +1,59 @@
<?php
/**
* This file is part of TheWebMind 3rd generation.
*
* Notice that, these packages are being used only for documentation,
* not to organize the classes.
*
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
* @license licenses/mind3rd.license
*/
namespace DQB;
/**
* Description of QueryBuilder
*
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
* @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);
}
}
+7
Ver Arquivo
@@ -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))
+1 -1
Ver Arquivo
@@ -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;
}
+1 -1
Ver Arquivo
@@ -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())
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
Arquivo normal → Arquivo executável
Ver Arquivo
+119
Ver Arquivo
@@ -0,0 +1,119 @@
<?php
use Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Symfony\Component\Console;
/**
* Description of Info
*
* @author felipe
*/
class DQB extends MindCommand implements program
{
public function configure()
{
$this
->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(<<<EOT
This program will create the needed query to the selected database.
Notice that it will NOT execute then, only return them as a string.
EOT
);
}
public function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
{
if(!parent::execute($input, $output))
return false;
$this->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;
}
}
+2 -1
Ver Arquivo
@@ -45,7 +45,8 @@
new Create(),
new Show(),
new Analyze(),
new SetUse()
new SetUse(),
new dqb()
));
if($_REQ['env']=='shell')
+1 -1
Ver Arquivo
@@ -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', "/\/\*.+?\*\//");
+2 -1
Ver Arquivo
@@ -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)
+1
Ver Arquivo
@@ -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,
+4 -1
Ver Arquivo
@@ -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"
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
Arquivo normal → Arquivo executável
Ver Arquivo