dblayer : add more debug

dblayer : add more unit tests (foreign keys)
dblayer : add the same answer when updating a line with the same informations
dblayer : better support of foreign keys


git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@1842 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
2014-09-22 10:52:53 +00:00
parent 19966c094c
commit b034fa3625
2 changed files with 161 additions and 37 deletions

View File

@@ -9,9 +9,9 @@
The dbLayer provide an abstraction layer on PDO to be easier on all the CRUD
(Create, Read, Update, Delete) operations, accross all the databases engines.
To use it, extends in your code this class, and define the attributes :
- protected $table : name of the table you want to use
- protected $fields : description of all the fields in the database like :
protected $fields = array (
- public $table : name of the table you want to use
- public $fields : description of all the fields in the database like :
public $fields = array (
"id"=>array ("integer", "not null", "autoincrement"),
"zone"=>array ("varchar", "255", "not null"),
"viewname"=>array ("varchar", "255"),
@@ -20,12 +20,17 @@ To use it, extends in your code this class, and define the attributes :
"opendate"=>array ("datetime", "not null"),
"closedate"=>array ("datetime"),
);
- protected $primary = "id" ; the primary key of the table (in text). Actually
- public $primary = "id" ; the primary key of the table (in text). Actually
the dbLayer abstraction don't supports primary key on multiples columns
- protected $unique = array ("column", array ("column1", "column2");)
- public $unique = array ("column", array ("column1", "column2");)
- public $foreign : Add the support of foreign keys. Must be defined like :
public $foreign = array (
"localfield"=>array ("foreign Table", "foreign key",
"ON UPDATE CASCADE ON DELETE CASCADE"),
);
Optionnaly, you can add the
- protected $debug = TRUE : enable the debug on screen (NOT FOR PROD !!)
- public $debug = TRUE : enable the debug on screen (NOT FOR PROD !!)
*/
require_once ("domframework/verify.php");
@@ -89,20 +94,23 @@ class dblayer extends PDO
public function __construct ($dsn, $username=null, $password=null,
$driver_options=null)
{
try
{
$this->db = new PDO ($dsn, $username, $password, $driver_options);
$this->db->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (Exception $e)
{
throw new Exception ("PDO error : ".$e->getMessage(), 500);
}
$driver = @explode (":", $dsn);
if (! isset ($driver[0]))
throw new Exception (_("No valid DSN provided"), 500);
// Force specifics initialisations
switch ($this->db->getAttribute(PDO::ATTR_DRIVER_NAME))
switch ($driver[0])
{
case "sqlite":
try
{
$this->db = new PDO ($dsn, $username, $password, $driver_options);
$this->db->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (Exception $e)
{
throw new Exception ("PDO error : ".$e->getMessage(), 500);
}
// Look at the right to write in database and in the directory
$file = substr ($dsn, 7);
if (! is_writeable (dirname ($file)))
@@ -121,11 +129,32 @@ class dblayer extends PDO
$this->sep = "`";
break;
case "mysql":
try
{
$driver_options[PDO::MYSQL_ATTR_FOUND_ROWS] = 1;
$this->db = new PDO ($dsn, $username, $password, $driver_options);
$this->db->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (Exception $e)
{
throw new Exception ("PDO error : ".$e->getMessage(), 500);
}
// Set the coding to UTF8
$this->db->exec("SET CHARACTER SET utf8");
$this->sep = "`";
break;
case "pgsql":
try
{
$this->db = new PDO ($dsn, $username, $password, $driver_options);
$this->db->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (Exception $e)
{
throw new Exception ("PDO error : ".$e->getMessage(), 500);
}
// Set the coding to UTF8
$this->db->exec("SET NAMES 'utf8'");
$this->sep = "\"";
@@ -202,9 +231,11 @@ class dblayer extends PDO
*/
public function verify ($datas, $updatekey=false)
{
if ($this->debug) echo "== Entering verify\n";
$errors = array ();
foreach ($this->fields as $key=>$params)
{
if ($this->debug) echo " verify ($key)\n";
if ($updatekey === false)
{
// Don't check if there is an update : the database is already filled
@@ -311,6 +342,7 @@ class dblayer extends PDO
if (count ($errors) !== 0)
return $errors;
if ($this->debug) echo " verify inconsistency\n";
// Check for inconsistency
$verify = $this->verifyAll ($datas);
if (count ($verify))
@@ -325,6 +357,7 @@ class dblayer extends PDO
if ($updatekey !== false)
{
if ($this->debug) echo " verify in updatekey\n";
// Check if the unique constrain is valid before doing the insertion
// 1. Read the actual state
$before = $this->read (array (array ($this->primary, $updatekey)));
@@ -339,14 +372,22 @@ class dblayer extends PDO
}
else
{
if ($this->debug) echo " verify NO updatekey\n";
$after = $datasOK;
}
// Check if the unique constrain is valid before doing the insertion
foreach ($this->unique as $columns)
foreach ($this->unique as $k=>$columns)
{
if ($this->primary === null)
{
return array (dgettext("domframework",
"No field primary defined for tests in primary"));
}
if (is_array ($columns))
{
// Multiple columns in unique
if ($this->debug) echo " verify unique multiple $k\n";
$select = array ();
if ($updatekey !== false)
$select[] = array ($this->primary, $updatekey, "!=");
@@ -372,6 +413,7 @@ class dblayer extends PDO
else
{
// One column in unique
if ($this->debug) echo " verify unique one column $k\n";
if (!array_key_exists ($columns, $after)) continue;
$select = array ();
if ($updatekey !== false)
@@ -395,36 +437,49 @@ class dblayer extends PDO
// Check if the foreign keys constrains are valid before doing the insertion
foreach ($this->foreign as $foreign=>$data)
{
if ($this->debug) echo " verify foreign $foreign\n";
if (! isset ($datas[$foreign]))
{
$errors[] = array ("error", sprintf (dgettext("domframework",
"The foreign column '%s' is not provided"),
$foreign));
return $errors;
}
if (! isset ($datas[$foreign][0]))
{
$errors[] = array ("error", sprintf (dgettext("domframework",
"The field type for column '%s' is not provided"),
$foreign));
return $errors;
continue;
}
$table = $data[0];
$column = $data[1];
$req = "SELECT $column ".
$req = "SELECT $this->sep$column$this->sep ".
"FROM $this->sep$this->tableprefix$table$this->sep ".
"WHERE $this->sep$column$this->sep=:".md5 ($column);
if ($this->debug) echo "DEBUG : $req\n";
$st = $this->db->prepare ($req);
$val = $datas[$foreign];
$key = $column;
if ($this->debug) echo "DEBUG BIND : ".$this->fields[$foreign][0]."\n";
if ($this->debug) echo "DEBUG BIND : $column(".md5 ($column)."->".
var_export ($val, TRUE)."\n";
if ($val === null)
$st->bindValue (":".md5 ($key), $val, PDO::PARAM_NULL);
elseif ($this->fields[$key][0] === "integer")
elseif ($this->fields[$foreign][0] === "integer")
$st->bindValue (":".md5 ($key), $val, PDO::PARAM_INT);
elseif ($this->fields[$key][0] === "varchar")
elseif ($this->fields[$foreign][0] === "varchar")
$st->bindValue (":".md5 ($key), $val, PDO::PARAM_STR);
elseif ($this->fields[$key][0] === "datetime")
elseif ($this->fields[$foreign][0] === "datetime")
$st->bindValue (":".md5 ($key), $val, PDO::PARAM_STR);
elseif ($this->fields[$key][0] === "date")
elseif ($this->fields[$foreign][0] === "date")
$st->bindValue (":".md5 ($key), $val, PDO::PARAM_STR);
else
throw new Exception ("TO BE DEVELOPPED : ".$this->fields[$key][0], 500);
{
throw new Exception ("TO BE DEVELOPPED : ".$this->fields[$foreign][0],
500);
}
$st->execute ();
$res = array ();
while ($d = $st->fetch (PDO::FETCH_ASSOC))
@@ -452,12 +507,16 @@ class dblayer extends PDO
@param array $datas Datas to be recorded (column=>value)*/
public function insert ($datas)
{
if ($this->debug) echo "== Entering insert\n";
if ($this->db === null)
throw new Exception (dgettext("domframework", "Database not connected"),
500);
if ($this->unique === null)
throw new Exception (dgettext("domframework",
"Unique fields of table are not defined"), 500);
if (! is_array ($this->unique))
throw new Exception (dgettext("domframework",
"The unique configuration is not an array"), 500);
if (!is_array ($datas))
throw new Exception (dgettext("domframework",
"The datas provided to create are not array"),
@@ -472,7 +531,10 @@ class dblayer extends PDO
$datasOK = array ();
$errors = $this->verify ($datas);
if (count ($errors) !== 0)
throw new Exception (reset ($errors), 405);
{
$errors = reset ($errors);
throw new Exception ($errors[1], 405);
}
foreach ($this->fields as $field=>$desc)
{
if (isset ($datas[$field]))
@@ -527,6 +589,7 @@ class dblayer extends PDO
public function read ($select=null, $display=null, $order=null,
$whereOr=false)
{
if ($this->debug) echo "== Entering read\n";
if ($this->db === null)
throw new Exception (dgettext("domframework", "Database not connected"),
500);
@@ -638,9 +701,11 @@ class dblayer extends PDO
Return the number of rows modified
@param string|integer $updatekey The key applied on primary key to be
updated
@param array $datas The values to be updated */
@param array $datas The values to be updated
@return the number of lines modified */
public function update ($updatekey, $datas)
{
if ($this->debug) echo "== Entering update\n";
if ($this->db === null)
throw new Exception (dgettext("domframework", "Database not connected"),
500);
@@ -652,7 +717,6 @@ class dblayer extends PDO
$errors = $this->verify ($datas, $updatekey);
if (count ($errors) !== 0)
{
$errors = reset ($errors);
throw new Exception ($errors[1], 405);
}
foreach ($this->fields as $field=>$desc)
@@ -724,6 +788,7 @@ class dblayer extends PDO
@param strin|integer $deletekey The key of primary key to be deleted */
public function delete ($deletekey)
{
if ($this->debug) echo "== Entering delete\n";
if ($this->db === null)
throw new Exception (dgettext("domframework", "Database not connected"));
$req = "DELETE FROM $this->sep$this->tableprefix$this->table$this->sep ";
@@ -740,6 +805,7 @@ class dblayer extends PDO
/** Translation of fields */
public function titles ()
{
if ($this->debug) echo "== Entering titles\n";
if (count ($this->fields) === 0)
throw new Exception (dgettext("domframework", "No Field defined"), 500);
$arr = array ();
@@ -759,6 +825,7 @@ class dblayer extends PDO
/** Drop the table */
public function dropTable ()
{
if ($this->debug) echo "== Entering dropTables\n";
if ($this->db === null)
throw new Exception (dgettext("domframework", "Database not connected"));
$sql = "DROP TABLE $this->sep$this->tableprefix$this->table$this->sep";
@@ -785,6 +852,7 @@ class dblayer extends PDO
*/
public function createTable ()
{
if ($this->debug) echo "== Entering createTable\n";
if ($this->db === null)
throw new Exception (dgettext("domframework", "Database not connected"),
500);
@@ -1089,6 +1157,7 @@ class dblayer extends PDO
Return the an array with the datas */
public function directRead ($sql)
{
if ($this->debug) echo "== Entering directRead\n";
$st = $this->db->prepare ($sql);
$st->execute ();
$res = array ();