From 0ae728f460083e1a37ddaeb34153ca31a1dd94e8 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Mon, 25 Jul 2016 10:34:06 +0200 Subject: [PATCH] ORM: Refactor 'fetch' --- manager/ORM/Rows.php | 91 ++++++++++++++++++----------------- manager/ORM/SQLBuilder.php | 88 ++++++++++++--------------------- manager/repo/action_merge.php | 4 +- test/automate.php | 54 ++++++++++++++++++--- 4 files changed, 128 insertions(+), 109 deletions(-) diff --git a/manager/ORM/Rows.php b/manager/ORM/Rows.php index 042f948..f2d48ec 100644 --- a/manager/ORM/Rows.php +++ b/manager/ORM/Rows.php @@ -27,6 +27,7 @@ const SEL_MAX = '__MAX__'; const SEL_MIN = '__MIN__'; const SEL_COUNT = '__COUNT__'; + const SEL_CONCAT = '__GROUP_CONCAT__'; const SEL_DISTINCT = true; @@ -261,7 +262,7 @@ return $this; /* (3) On vérifie @func */ - $funcList = [self::SEL_AVG, self::SEL_SUM, self::SEL_MAX, self::SEL_MIN, self::SEL_COUNT]; + $funcList = [self::SEL_AVG, self::SEL_SUM, self::SEL_MAX, self::SEL_MIN, self::SEL_COUNT, self::SEL_CONCAT]; // Si condition non nulle et pas référencée, on quitte if( !is_null($func) && !in_array($func, $funcList) ) @@ -761,6 +762,11 @@ /* (2) On initialise le conteneur des variables "bindés" */ $bound = []; + /* (3) On récupère la requête générée par chaque @rows de jointure */ + $joinedFetched = []; + foreach($this->joined as $field=>$data) + $joinedFetched[$field] = $data['object']->fetch(false); + /* [1] On rédige la clause SELECT @@ -771,11 +777,20 @@ /* (2) On ajoute les champs locaux */ $selectTables[$this->schema['table']] = $this->select; - /* (3) On ajoute les champs des jointures */ - foreach($this->joined as $rows) - $selectTables[$rows['object']->schema['table']] = $rows['object']->select; - /* (4) On génère la clause SELECT */ + /* (4) On ajoute les champs des jointures (récursif)*/ + foreach($joinedFetched as $field=>$data){ + foreach($data['request']['SELECT'] as $table=>$fields) + foreach($fields as $field=>$sel){ + // Si aucune entrée pour cette table, on l'ajoute + if( !isset($selectTables[$table]) ) + $selectTables[$table] = []; + + $selectTables[$table][$field] = $sel; + } + } + + /* (3) On génère la clause SELECT */ $requestS['SELECT'] = SQLBuilder::SELECT($selectTables); @@ -790,25 +805,9 @@ /* (2) On ajoute les tables de jointures */ // Note: On ajoute les tables de jointures dans la clause FROM avec comme alias le nom de la table - foreach($this->joined as $field=>$data){ - // {1} On récupère la requête/les params de chaque jointure // - $joinedFetched = $data['object']->fetch(false); - - // {2} On met '*' pour la clause SELECT // - $joinedFetched['request']['SELECT'] = [ $data['object']->schema['table'].'.*' ]; - - // {3} On construit la nouvelle requête // - $joinedRequest = SQLBuilder::BUILD($joinedFetched['request']); - - // {4} On supprime les retours à la ligne // - $joinedRequest = str_replace("\n", " ", $joinedRequest); - - // {5} On l'ajoute à la clause FROM avec comme alias le nom de la table de @data['object'] // - $requestS['FROM'][] = "($joinedRequest) as ".$data['object']->schema['table']; - - // {6} On ajoute les variables à la requête courante // - $bound = array_merge($bound, $joinedFetched['bound']); - } + foreach($joinedFetched as $field=>$data) + // On ajoute la clause FROM de jointure à la clause FROM locale // + $requestS['FROM'] = array_merge($data['request']['FROM'], $requestS['FROM']); @@ -834,40 +833,40 @@ $c++; } + /* (3) On ajoute les conditions des jointures */ + foreach($joinedFetched as $field=>$data){ + /* On ajoute la clause WHERE de jointure à la clause WHERE locale */ + $requestS['WHERE'] = array_merge($data['request']['WHERE'], $requestS['WHERE']); + + /* On ajoute les variables à la requête courante */ + $bound = array_merge($bound, $data['bound']); + } + /* [6] Clause GROUP BY =========================================================*/ /* (0) On initialise la liste des @rows non aggrégés */ - $notAggregatedRows = []; - - /* (1) On cherche dans les champs locaux local */ - foreach($this->select as $field=>$sel) - if( is_null($sel[0]) ) - $notAggregatedRows[] = $this; - - /* (2) On cherche dans les champs des jointures */ - foreach($this->joined as $data) - foreach($data['object']->select as $field=>$sel) - if( is_null($sel[0]) ) - $notAggregatedRows[] = $data['object']; - - /* (3) Pour chaque table, on récupère les clés primaires */ $groupBy = []; - foreach($notAggregatedRows as $i=>$rows){ - $groupBy[$rows->schema['table']] = []; + /* (1) On cherche dans les champs locaux local */ + foreach($selectTables as $table=>$fields) + foreach($fields as $field=>$sel) + if( is_null($sel[0]) ){ + if( !isset($groupBy[$table]) ) + $groupBy[$table] = []; - foreach($rows->schema['columns'] as $field=>$data) - if( $data['primary'] ) - $groupBy[$rows->schema['table']][] = $field; - } + $groupBy[$table][] = $field; + } - /* (4) On rédige la clause GROUP BY */ + + /* (2) On rédige la clause GROUP BY */ if( count($groupBy) > 0) $requestS['GROUPBY'] = SQLBuilder::GROUPBY($groupBy); + + /* [6] Clause LIMIT =========================================================*/ $requestS['LIMIT'] = ($this->unique) ? SQLBuilder::LIMIT(1) : SQLBuilder::LIMIT([]); @@ -881,6 +880,8 @@ /* (2) On compose la requête */ $requestString = SQLBuilder::BUILD($requestS).';'; + var_dump($requestS); + var_dump($requestString); /* (3) On prépare la requête */ $request = Database::getPDO()->prepare($requestString); diff --git a/manager/ORM/SQLBuilder.php b/manager/ORM/SQLBuilder.php index 65c61e2..2442b28 100644 --- a/manager/ORM/SQLBuilder.php +++ b/manager/ORM/SQLBuilder.php @@ -11,43 +11,13 @@ /* CONSTRUIT LA REQUETE FORMATTEE "SELECT" AVEC UNE LISTE DE CHAMPS * - * @sqlFields Liste de champs : [table => field => func, alias] + * @sqlFields Liste de champs : [table => field => [func, alias] ] * * @return sql Renvoie un tableau formatté * */ public static function SELECT($sqlFields){ - /* [0] Initialisation - =========================================================*/ - $sql = []; - - /* [1] On construit la requête - =========================================================*/ - $c = 0; - foreach($sqlFields as $table=>$tableContent) - foreach($tableContent as $field=>$select){ - - /* (1) On construit le nom du champ */ - $fieldStr = "$table.$field"; - - /* (2) On ajout le DISTINCT s'il y a lieu */ - if( $select[1] ) - $fieldStr = "DISTINCT $fieldStr"; - - /* (3) On ajoute la fonction d'aggrégation s'il y a lieu */ - if( !is_null($select[0]) ) - $fieldStr = substr($select[0], 2, -2)."($fieldStr)"; - - - /* (4) On ajoute l'alias */ - if( $field != '*' ) $sql[$c] = "$fieldStr as $field"; - else $sql[$c] = "$fieldStr"; - - - $c++; - } - - return $sql; + return $sqlFields; } @@ -64,20 +34,7 @@ * */ public static function GROUPBY($tables){ - /* [0] Initialisation - =========================================================*/ - $sql = []; - - /* [1] On construit la requête - =========================================================*/ - $c = 0; - foreach($tables as $table=>$fields) - foreach($fields as $field){ - $sql[] = "$table.$field"; - $c++; - } - - return $sql; + return $tables; } @@ -255,13 +212,13 @@ public static function LIMIT($count=null){ /* [0] Initialisation =========================================================*/ - $sql = []; + $sql = ''; /* [1] On construit la requête =========================================================*/ if( intval($count) == $count ) - $sql = intval($count); + $sql = intval($count); return $sql; } @@ -299,11 +256,27 @@ /* (1) Clause SELECT ---------------------------------------------------------*/ case 'SELECT': - $sql .= 'SELECT '; + $sql .= "SELECT "; + $c = 0; + foreach($statements as $table=>$fields) + foreach($fields as $field=>$select){ + + /* (1) On construit le nom du champ */ + $fieldStr = ($c==0) ? "$table.$field" : ", $table.$field"; + + /* (2) On ajout le DISTINCT s'il y a lieu */ + if( isset($select[1]) && $select[1] ) + $fieldStr = "DISTINCT $fieldStr"; + + /* (3) On ajoute la fonction d'aggrégation s'il y a lieu */ + if( isset($select[0]) && !is_null($select[0]) ) + $fieldStr = substr($select[0], 2, -2)."($fieldStr)"; + + + /* (4) On ajoute l'alias */ + $sql .= "$fieldStr"; + - $c = 0; - foreach($statements as $field){ - $sql .= ($c==0) ? $field : ", $field"; $c++; } @@ -317,7 +290,7 @@ $c = 0; foreach($statements as $field){ - $sql .= ($c==0) ? $field : ", $field"; + $sql .= ($c==0) ? "$field" : ", $field"; $c++; } @@ -379,10 +352,11 @@ $sql .= 'GROUP BY '; $c = 0; - foreach($statements as $field){ - $sql .= ($c==0) ? $field : ", $field"; - $c++; - } + foreach($statements as $table=>$fields) + foreach($fields as $field){ + $sql .= ($c==0) ? "$table.$field" : ", $table.$field"; + $c++; + } $sql .= "\n"; break; diff --git a/manager/repo/action_merge.php b/manager/repo/action_merge.php index 66b38d9..145ce1b 100644 --- a/manager/repo/action_merge.php +++ b/manager/repo/action_merge.php @@ -4,8 +4,10 @@ use \manager\Database; use \manager\Repo; use \manager\ManagerError; - use \manager\repo\cluster as clusterRepo; + use \manager\ORM\Table; + use \manager\ORM\Rows; + class action_merge extends parentRepo{ protected static function table_name(){ static $table_name = 'action_merge'; return $table_name; } diff --git a/test/automate.php b/test/automate.php index 2e7c163..96a30f5 100755 --- a/test/automate.php +++ b/test/automate.php @@ -445,15 +445,57 @@ // var_dump($myUser); - $module_merge = Table::get('module_merge') - ->whereIdWarehouse(7); + $getPermissions = Database::getPDO()->prepare("SELECT u.id_user, u.code, GROUP_CONCAT(DISTINCT a.id_action ORDER BY a.id_action ASC) as actions + FROM + user as u, + user_cluster as uc, + user_cluster_merge as ucm, + machine as m, + machine_cluster as mc, + machine_cluster_merge as mcm, + action as a, + action_merge as am + + WHERE u.id_user = ucm.id_user + AND uc.id_user_cluster = ucm.id_user_cluster + AND am.id_source = uc.id_user_cluster + AND m.id_warehouse = u.id_warehouse + AND m.id_warehouse = :id_warehouse + AND m.id_machine = :id_machine + AND m.id_machine = mcm.id_machine + AND mc.id_machine_cluster = mcm.id_machine_cluster + AND am.id_target = mc.id_machine_cluster + AND a.id_action = am.id_action + + GROUP BY u.id_user, u.code"); + + $getPermissions->execute([ + ':id_warehouse' => 7, + ':id_machine' => 5 + ]); - $chip = Table::get('chip') - ->join('id_module', $module_merge) - ->select('*'); + var_dump( Database::delNumeric( $getPermissions->fetchAll() ) ); - var_dump($chip->fetch()); + $u = Table::get('user') + ->select('id_user') + ->select('code'); + + $ucm = Table::get('user_cluster_merge') + ->join('id_user', $u); + + $m = Table::get('machine') + ->whereId(5); + + $mcm = Table::get('machine_cluster_merge') + ->join('id_machine', $m); + + $a = Table::get('action_merge') + ->join('id_source', $ucm) + ->join('id_target', $mcm) + ->select('id_action', Rows::SEL_CONCAT, Rows::SEL_DISTINCT); + + var_dump($a->fetch()); // $a = new ModuleRequest('authentificationDefault/warehouse', [