From a1b6e81d53008c5398e48cd0d76e4560b00979d3 Mon Sep 17 00:00:00 2001 From: jorgecc Date: Fri, 22 Jul 2022 18:14:49 -0400 Subject: [PATCH] * 3.8 --- README.md | 2 + examples/clitest/test_complete.php | 4 ++ examples/clitest/testdb2.php | 38 +++++++---- lib/PdoOne.php | 93 +++++++++++++++----------- lib/PdoOneCli.php | 4 +- lib/PdoOneEncryption.php | 4 +- lib/PdoOneQuery.php | 14 ++-- lib/_BasePdoOneRepo.php | 27 ++++++-- lib/template/template_abstractrepo.php | 6 +- 9 files changed, 116 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 6600ff5..deee209 100644 --- a/README.md +++ b/README.md @@ -2035,6 +2035,8 @@ In a nutshell: > > Every decimal version means that it patches/fixes/refactoring a previous functionality i.e. 1.5.0 -> 1.5.1 (fix) +* 3.8 2022-07-22 + * [ORM] fixed a problem when where is used and more than two column (different tables) use the same name of column. * 3.7 2022-07-16 * [ORM] fixed a problem with first * [ORM] fixed a problem with insert and conversion of columns diff --git a/examples/clitest/test_complete.php b/examples/clitest/test_complete.php index b4a28a6..7870a23 100644 --- a/examples/clitest/test_complete.php +++ b/examples/clitest/test_complete.php @@ -16,7 +16,11 @@ $pdo->logLevel=3; $pdo->open(); $pdo->setCacheService(new CacheServicesmysql()); +new \dBug\dBug(InvoiceRepo::recursive(['/_InvCustomer'])->first(227)); +new \dBug\dBug(InvoiceRepo::recursive(['/_InvCustomer'])->where("invoices.flag='1'")->toList()); +new \dBug\dBug(InvoiceRepo::recursive(['/_InvCustomer'])->where(["FlagAlias"=>'1'])->toList()); +die(1); $id=224; diff --git a/examples/clitest/testdb2.php b/examples/clitest/testdb2.php index 31c6b99..31e3d21 100644 --- a/examples/clitest/testdb2.php +++ b/examples/clitest/testdb2.php @@ -14,10 +14,10 @@ "namespace": null, "savegen": "yes", "tables": null, - "tablescolumns": null, - "tablecommand": null, - "convertionselected": "", - "convertionnewvalue": "convert an human readable date to SQL", + "tablescolumns": "", + "tablecommand": "", + "convertionselected": null, + "convertionnewvalue": null, "newclassname": null, "overridegenerate": null, "tablexclass": { @@ -85,7 +85,8 @@ "Name": null, "_City": "MANYTOONE", "_customerxcategories": "MANYTOMANY", - "_invoices": "PARENT" + "_invoices": "PARENT", + "Flag": null }, "customerxcategories": { "Category": null, @@ -99,7 +100,8 @@ "Product": null, "Quantity": null, "_Invoice": "PARENT", - "_Product": "MANYTOONE" + "_Product": "MANYTOONE", + "Flag": null }, "invoices": { "Customer": null, @@ -108,7 +110,8 @@ "Total": null, "_Customer": "MANYTOONE", "_invoicedetails": "ONETOMANY", - "_invoicextypes": "MANYTOMANY" + "_invoicextypes": "MANYTOMANY", + "Flag": null }, "products": { "City": null, @@ -116,7 +119,8 @@ "_City": "MANYTOONE", "_invoicedetails": "PARENT", "Name": null, - "unitPrice": null + "unitPrice": null, + "Flag": null }, "cities": { "IdCity": null, @@ -133,7 +137,8 @@ "invoicetypes": { "IdInvoiceType": null, "NameType": null, - "_invoicextypes": "ONETOMANY" + "_invoicextypes": "ONETOMANY", + "Flag": null }, "invoicextypes": { "IdInvoice": null, @@ -166,7 +171,8 @@ "Product": "Product", "Quantity": "Quantity", "_Invoice": "_Invoice", - "_Product": "_Product" + "_Product": "_Product", + "Flag": "Flag" }, "invoices": { "Customer": "Customer", @@ -175,7 +181,8 @@ "Total": "Total", "_Customer": "_InvCustomer", "_invoicedetails": "_Details", - "_invoicextypes": "_Types" + "_invoicextypes": "_Types", + "Flag": "FlagAlias" }, "products": { "City": "Ciudad", @@ -183,7 +190,8 @@ "Name": "Name", "unitPrice": "unitPrice", "_City": "_CiudadRef", - "_invoicedetails": "_invoicedetails" + "_invoicedetails": "_invoicedetails", + "Flag": "Flag" }, "customers": { "City": "City", @@ -192,7 +200,8 @@ "Name": "Name", "_City": "_City", "_customerxcategories": "_customerxcategories", - "_invoices": "_invoices" + "_invoices": "_invoices", + "Flag": "FlagAlias" }, "users": { "fullname": "fullname", @@ -203,7 +212,8 @@ "invoicetypes": { "IdInvoiceType": "NumInvoiceType", "NameType": "NameType", - "_invoicextypes": "_invoicextypes" + "_invoicextypes": "_invoicextypes", + "Flag": "Flag" }, "invoicextypes": { "IdInvoice": "Col1X", diff --git a/lib/PdoOne.php b/lib/PdoOne.php index fb807ef..c33a842 100644 --- a/lib/PdoOne.php +++ b/lib/PdoOne.php @@ -26,11 +26,11 @@ * @package eftec * @author Jorge Castro Castillo * @copyright (c) Jorge Castro C. Dual Licence: MIT and Commercial License https://github.com/EFTEC/PdoOne - * @version 3.7 + * @version 3.8 */ class PdoOne { - public const VERSION = '3.7'; + public const VERSION = '3.8'; /** @var int We need this value because null and false could be a valid value. */ public const NULL = PHP_INT_MAX; /** @var string Prefix of the tables */ @@ -128,7 +128,7 @@ class PdoOne public $customError = true; /** @var string[] PHP classes excluded by the custom error log todo: quitar */ public $traceBlackList = []; //['PdoOne.php', 'PdoOneQuery.php', 'PdoOne_Mysql.php', 'PdoOne.Sqlsrv.php', 'PdoOne.Oci.php' - //, 'PdoOneTestMockup.php', '_BasePdoOneRepo.php']; + //, 'PdoOneTestMockup.php', '_BasePdoOneRepo.php']; /** @var PDO */ public $conn1; /** @var bool True if the transaction is open */ @@ -295,9 +295,11 @@ public static function newColFK($key, $refcol, $reftable, $extra = null, $name = * @param string $sql * @return array|string|string[] */ - public static function cleanColumns(string $sql) { - return str_replace([chr(0),chr(8),chr(9),chr(13),"'",'"',chr(26),chr(92)],'',$sql); + public static function cleanColumns(string $sql) + { + return str_replace([chr(0), chr(8), chr(9), chr(13), "'", '"', chr(26), chr(92)], '', $sql); } + public static function addParenthesis($txt, $start = '(', $end = ')') { if (self::hasParenthesis($txt, $start, $end) === false) { @@ -1377,14 +1379,14 @@ public function custom_exception_handler($exception, ?string $customMessage = nu } else { $function = @$error['function']; } - $r .= '<<<'.$file . ':' . @$error['line'] . ">>>\t" . $function . '(' + $r .= '<<<' . $file . ':' . @$error['line'] . ">>>\t" . $function . '(' . @implode(' , ', $args) . ')' . "\n"; } } } if (!$isCli) { - $r = str_replace(["\n", '[', ']','<<<','>>>', '{{', '}}', "\t"] - , ["
", "[", "]",'','', '', '', '    '] + $r = str_replace(["\n", '[', ']', '<<<', '>>>', '{{', '}}', "\t"] + , ["
", "[", "]", '', '', '', '', '    '] , $r); } if (!$returnAsString) { @@ -1458,11 +1460,17 @@ public function setMessages(MessageContainer $messageContainer): void $this->messageContainer = $messageContainer; } - public function debugFile($txt, $level = 'INFO'): void + /** + * @param mixed $txt the message to send. If it is an object or an array, then it is serialized. + * @param string $level The level of the message + * @return void + */ + public function debugFile($txt, string $level = 'INFO'): void { if (!$this->logFile) { return; // debug file is disabled. } + $maxl=200*1024*1024; // 200mb if (is_object($txt) || is_array($txt)) { $txtW = print_r($txt, true); } else { @@ -1471,8 +1479,24 @@ public function debugFile($txt, $level = 'INFO'): void if ($this->logLevel === 2) { $txtW .= ' param:' . json_encode($this->lastParam); } - /** @noinspection ForgottenDebugOutputInspection */ - error_log('[PdoOne]' . $level . "\t" . $txtW); + if($level==='INFO') { + $errorfile=ini_get('error_log'); + if($errorfile) { + $infoFile=str_replace('.','_warning.',$errorfile); + if(@filesize($infoFile)>$maxl) { + $fp = @fopen($infoFile, 'wb'); + @fclose($fp); + } + /** @noinspection ForgottenDebugOutputInspection */ + error_log('['.date("M d H:i:s")."] [PdoOne]\t[$level]\t$txtW\n\n", 3,$infoFile); + } else { + /** @noinspection ForgottenDebugOutputInspection */ + error_log("[PdoOne]\t[$level]\t" . $txtW); + } + } else { + /** @noinspection ForgottenDebugOutputInspection */ + error_log("[PdoOne]\t[$level]\t" . $txtW); + } } // @@ -2398,14 +2422,15 @@ public static function varExport($input, $indent = "\t"): ?string } /** - * @param string $tableName + * @param string $tableName * @param array|null $columnRelations - * @param $pkFirst - * @param array $aliasesAllTables + * @param $pkFirst + * @param array $aliasesAllTables * @return array|string * @throws Exception */ - public function generateGetRelations(string $tableName,?array $columnRelations,$pkFirst,array $aliasesAllTables):array { + public function generateGetRelations(string $tableName, ?array $columnRelations, $pkFirst, array $aliasesAllTables): array + { try { $deps = $this->tableDependency(true); } catch (Exception $e) { @@ -2477,14 +2502,14 @@ public function generateGetRelations(string $tableName,?array $columnRelations,$ $defsFK = $this->service->getDefTableFK($relation[$k]['reftable'], false); } catch (Exception $e) { $this->endTry(); - return ['Error: Unable read table dependencies ' . $e->getMessage(),null]; + return ['Error: Unable read table dependencies ' . $e->getMessage(), null]; } try { $keys2 = $this->service->getDefTableKeys($defsFK[$refcol2]['reftable'], true, 'PRIMARY KEY'); } catch (Exception $e) { $this->endTry(); - return ['Error: Unable read table dependencies' . $e->getMessage(),null]; + return ['Error: Unable read table dependencies' . $e->getMessage(), null]; } $relation[$k]['refcol2'] = self::$prefixBase . $refcol2; if (count($keys2) > 0) { @@ -2503,16 +2528,13 @@ public function generateGetRelations(string $tableName,?array $columnRelations,$ $linked = ''; foreach ($relation as $k => $v) { $ksimple = ltrim($k, '_'); // remove the _ from the beginner - $alias = ($aliases[$k] ?? $k); $aliasCol = '_' . ($aliases[$ksimple] ?? $ksimple); $col = ltrim($aliasCol, '_'); $refcol = ltrim($v['refcol'], '_'); $refcol2 = isset($v['refcol2']) ? ltrim($v['refcol2'], '_') : null; $col2 = $v['col2'] ?? null; - $aliasRef = '_' . @$aliasesAllTables[$v['reftable']][$refcol] ?? $refcol; - $relation[$k]['alias'] = $alias; if (isset($v['col'])) { $relation[$k]['colalias'] = $aliases[$v['col']]; @@ -2556,8 +2578,9 @@ public function generateGetRelations(string $tableName,?array $columnRelations,$ ); } } - return [$relation,$linked]; + return [$relation, $linked]; } + /** * It generates a class
* Example:
@@ -2684,21 +2707,15 @@ public function generateAbstractRepo( ), $r); $pk = $this->service->getPK($tableName, '??'); $pkFirst = (is_array($pk) && count($pk) > 0) ? $pk[0] : null; - - - - [$relation,$linked]=$this->generateGetRelations($tableName,$columnRelations,$pkFirst,$aliasesAllTables); - if(!is_array($relation)) { + [$relation, $linked] = $this->generateGetRelations($tableName, $columnRelations, $pkFirst, $aliasesAllTables); + if (!is_array($relation)) { $this->endTry(); return 'Error: Unable read fk of table ' . $relation; } - /* } catch (Exception $e) { - $this->endTry(); - return 'Error: Unable read fk of table ' . $e->getMessage(); - }*/ - - - + /* } catch (Exception $e) { + $this->endTry(); + return 'Error: Unable read fk of table ' . $e->getMessage(); + }*/ //die(1); $convertOutput = ''; $convertInput = ''; @@ -2838,7 +2855,6 @@ public function generateAbstractRepo( $convertOutput .= "\t\t" . str_replace('%s', "\$row['$alias']", $tmp) . "\n"; } } - //$convertOutput.=$linked; $convertOutput = rtrim($convertOutput, "\n"); $convertInput = rtrim($convertInput, "\n"); @@ -2859,7 +2875,6 @@ public function generateAbstractRepo( $noUpdate = array_merge($identities, $defNoUpdate); } else { $noUpdate = $identities; - } /*$copy = $noInsert; $noInsert = []; @@ -2887,7 +2902,7 @@ public function generateAbstractRepo( $relation2 = []; foreach ($relation as $arr) { if ($arr['key'] !== 'FOREIGN KEY' && $arr['key'] !== 'PARENT' && $arr['key'] !== 'NONE') { - @$relation2[$arr['key']][] = '/'.$arr['alias']; + @$relation2[$arr['key']][] = '/' . $arr['alias']; } //if($arr['key']==='MANYTOONE') { // $relation2[]=$col; @@ -3164,9 +3179,9 @@ public function rollback(bool $throw = true): bool } $this->transactionOpen = false; try { - $r = @$this->conn1->rollback(); - } catch(Exception $ex) { - $r=false; + $r = @$this->conn1->rollback(); + } catch (Exception $ex) { + $r = false; } $this->endTry(); return $r; diff --git a/lib/PdoOneCli.php b/lib/PdoOneCli.php index 5391c9e..41b4ff9 100644 --- a/lib/PdoOneCli.php +++ b/lib/PdoOneCli.php @@ -25,11 +25,11 @@ * @package eftec * @author Jorge Castro Castillo * @copyright (c) Jorge Castro C. Dual Licence: MIT and Commercial License https://github.com/EFTEC/PdoOne - * @version 1.1 + * @version 1.2 */ class PdoOneCli { - public const VERSION = '1.1'; + public const VERSION = '1.2'; //
/** * @var array diff --git a/lib/PdoOneEncryption.php b/lib/PdoOneEncryption.php index 220eeb2..4b88179 100644 --- a/lib/PdoOneEncryption.php +++ b/lib/PdoOneEncryption.php @@ -15,7 +15,7 @@ /** * This class is used for encryption. It could encrypt (two ways). * Class PdoOneEncryption - * @version 2.22.1 2022-01-30 + * @version 3.8 * @package eftec * @author Jorge Castro Castillo * @copyright (c) Jorge Castro C. Dual Licence: MIT and Commercial License https://github.com/EFTEC/PdoOne @@ -145,7 +145,7 @@ public function encrypt($data) * It generates a hash based in the hash type ($this->hashType), the data used and the SALT. * * @param mixed $data It could be any type of serializable data. - * @return false|string If the serialization is not set, then it returns the same value. + * @return string If the serialization is not set, then it returns the same value. */ public function hash($data) { diff --git a/lib/PdoOneQuery.php b/lib/PdoOneQuery.php index b5d0220..46e29df 100644 --- a/lib/PdoOneQuery.php +++ b/lib/PdoOneQuery.php @@ -13,7 +13,7 @@ /** * Class PdoOneQuery * - * @version 2.4 2022-02-04 + * @version 3.8 * @package eftec * @author Jorge Castro Castillo * @copyright (c) Jorge Castro C. Dual Licence: MIT and Commercial License https://github.com/EFTEC/PdoOne @@ -444,7 +444,7 @@ public function having($sql, $param = PdoOne::NULL): PdoOneQuery *
      *  where( ['field'=>20] ) // associative array with automatic type
      *  where( ['/_field/subfield',20] ) // (for ORM) recursive query
-     *                                   //, where _field is a relational column.
+     *                                   //, where _field is a relational column (alias).
      *  where('field=20') // literal value
      *  where('field=?',[20]) // positional argument.
      *                        // You can also use >, < , >=, <=, in, etc.
@@ -536,7 +536,7 @@ public function constructParam2(
                     if ($this->ormClass !== null) {
                         /** @var _BasePdoOneRepo $cls */
                         $cls = $this->ormClass;
-                        $where = $cls::convertAliasToDB($where);
+                        $where = $cls::convertAliasToDB($where,true);
                     }
                     // named  column=:arg
                     foreach ($where as $k => $v) {
@@ -1039,13 +1039,8 @@ public function first(int $pk = PdoOne::NULL)
     {
         if ($this->ormClass !== null) {
             $cls = $this->ormClass;
-            if ($pk !== PdoOne::NULL) {
-                /** @noinspection PhpPossiblePolymorphicInvocationInspection */
-                $this->where($cls::PK[0], $pk);
-            }
-            $condition = null;
             /** @see \eftec\_BasePdoOneRepo::_first */
-            return $cls::first($pk);
+            return $cls::first($pk,$this);
             //return $cls::executePlan0($this, $condition, true);
         }
         return $this->_first();
@@ -1800,6 +1795,7 @@ protected function _insert($tableName = null,
                 //todo: aqui se debe recuperar el valor insertado
                 /** @noinspection ForgottenDebugOutputInspection */
                 var_dump($param);
+                throw new RuntimeException('Insert with identity: Not defined for OCI');
             }
             return null;
         }
diff --git a/lib/_BasePdoOneRepo.php b/lib/_BasePdoOneRepo.php
index 636b09d..04354f9 100644
--- a/lib/_BasePdoOneRepo.php
+++ b/lib/_BasePdoOneRepo.php
@@ -12,7 +12,7 @@
  * Class _BasePdoOneRepo.
* This class is used together with the repository classes. * - * @version 6.4 2022-06-05 + * @version 6.5 2022-07-22 * @package eftec * @author Jorge Castro Castillo * @copyright (c) Jorge Castro C. Dual Licence: MIT and Commercial License https://github.com/EFTEC/PdoOne @@ -706,15 +706,18 @@ public static function executePlan(PdoOneQuery $currentQuery, string $absolutePr $where = []; $query = self::startPlan($absolutePrefix, $dependency, $where); [$columnSQL, $fromSQL] = explode('|FROM|', $query); + if ($conditions !== null) { $whereSql = ' '; foreach ($conditions as $k => $v) { $whereSql .= sprintf(" %s ='%s' AND", static::TABLE . '.' . static::addQuote($k), $v); } + $whereSql = substr($whereSql, 0, -4); // we remove the last ' ANDº'; } else { $whereSql = null; } + $currentQuery->select($columnSQL)->from($fromSQL)->where($whereSql); $useCache = $currentQuery->useCache; $currentQuery->useCache = false; @@ -1239,13 +1242,13 @@ protected static function convertSQLValueInit(array &$rows, bool $list = false): * @return array|bool It returns false if not file is found. * @throws Exception */ - public static function first($pk = PdoOne::NULL) + public static function first($pk = PdoOne::NULL,?PdoOneQuery $query=null) { if (static::$useModel) { /** @noinspection PhpUndefinedMethodInspection */ - return static::fromArray(self::_first($pk)); + return static::fromArray(self::_first($pk,$query)); } - return self::_first($pk); + return self::_first($pk,$query); } /** @@ -1281,11 +1284,15 @@ protected static function _first($pk = PdoOne::NULL,PdoOneQuery $query=null) } /** - * It converts an associative array with columns (alias) to database columns + * It converts an associative array with columns (alias) to database columns
+ * If iswhere and aliasrows does not contain '/' or '.', then is converted to aliascolumn => table.dbcolumn + * * @param array $aliasRows + * @param bool $isWhere (false by default). if true, then it convers the column considering the input is used + * in a "where". * @return array */ - public static function convertAliasToDB($aliasRows): array + public static function convertAliasToDB($aliasRows,$isWhere=false): array { $db = []; $aliasCol = static::ALIAS2COL; @@ -1294,9 +1301,10 @@ public static function convertAliasToDB($aliasRows): array // /_relation/column $key = static::transformAliasTosql($keyAlias); $db[$key] = $value; - } else { + } else if (strpos($keyAlias, '.') === false) { // alias=>real column if (strpos($keyAlias, '_') === 0) { + // _column $findKey = false; foreach (static::DEFFK as $key => $val) { if ($val['alias'] === $keyAlias && $val['key'] !== 'FOREIGN KEY') { @@ -1306,7 +1314,11 @@ public static function convertAliasToDB($aliasRows): array } // $findKey = isset(static::DEFFK[$keyAlias]) ? $keyAlias : false; } else { + // column $findKey = $aliasCol[$keyAlias] ?? false; + if ($isWhere && $findKey!==false) { + $findKey = static::addQuote(static::TABLE) . '.' .$findKey; + } } if ($findKey !== false) { $db[$findKey] = $value; @@ -1872,6 +1884,7 @@ protected static function _insert(&$entityAlias, bool $transaction = true, bool if ($entityAlias === null) { throw new RuntimeException('Unable to insert an empty entity'); } + $pdoOneQuery = $newQuery === true ? new PdoOneQuery(static::getPdoOne(), static::class) : self::getQuery(); try { $entityAlias=(static::ME)::convertInputVal($entityAlias); diff --git a/lib/template/template_abstractrepo.php b/lib/template/template_abstractrepo.php index 89df0d9..a8135b0 100644 --- a/lib/template/template_abstractrepo.php +++ b/lib/template/template_abstractrepo.php @@ -291,12 +291,12 @@ public static function limit($first,$second=null) : PdoOneQuery * @return array|bool It returns false if not file is found. * @throws Exception */ - public static function first($pk = PdoOne::NULL) { + public static function first($pk = PdoOne::NULL,?PdoOneQuery $query=null) { if(self::$useModel) { /** @noinspection PhpIncompatibleReturnTypeInspection */ return {classmodelfirst} } - return self::_first($pk); + return self::_first($pk,$query); } /** @@ -327,7 +327,7 @@ public static function exist($entity) { * @throws Exception */ public static function insert(&$entity,$transactional=true) { - return self::_insert($entity,$transactional); + return self::_insert($entity,$transactional,true); } /**