function spip_sqlite_showtable($nom_table, $serveur = '', $requeter = true) { $query = 'SELECT sql, type FROM' . ' (SELECT * FROM sqlite_master UNION ALL' . ' SELECT * FROM sqlite_temp_master)' . " WHERE tbl_name LIKE '{$nom_table}'" . " AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'" . ' ORDER BY substr(type,2,1), name'; $a = spip_sqlite_query($query, $serveur, $requeter); if (!$a) { return ""; } if (!$requeter) { return $a; } if (!($a = spip_sqlite_fetch($a, null, $serveur))) { return ""; } $vue = $a['type'] == 'view'; // table | vue // c'est une table // il faut parser le create if (!$vue) { if (!preg_match("/^[^(),]*\\((([^()]*(\\([^()]*\\))?[^()]*)*)\\)[^()]*\$/", array_shift($a), $r)) { return ""; } else { $desc = $r[1]; // extraction d'une KEY éventuelle en prenant garde de ne pas // relever un champ dont le nom contient KEY (ex. ID_WHISKEY) if (preg_match("/^(.*?),([^,]*KEY[ (].*)\$/s", $desc, $r)) { $namedkeys = $r[2]; $desc = $r[1]; } else { $namedkeys = ""; } $fields = array(); $keys = array(); // enlever les contenus des valeurs DEFAULT 'xxx' qui pourraient perturber // par exemple s'il contiennent une virgule. // /!\ cela peut aussi echapper le nom des champs si la table a eu des operations avec SQLite Manager ! list($desc, $echaps) = query_echappe_textes($desc); // separer toutes les descriptions de champs, separes par des virgules # /!\ explode peut exploser aussi DECIMAL(10,2) ! foreach (explode(",", $desc) as $v) { preg_match("/^\\s*([^\\s]+)\\s+(.*)/", $v, $r); // Les cles de champs peuvent etre entourees // de guillements doubles " , simples ', graves ` ou de crochets [ ], ou rien. // http://www.sqlite.org/lang_keywords.html $k = strtolower(query_reinjecte_textes($r[1], $echaps)); // champ, "champ", [champ]... if ($char = strpbrk($k[0], '\'"[`')) { $k = trim($k, $char); if ($char == '[') { $k = rtrim($k, ']'); } } $def = query_reinjecte_textes($r[2], $echaps); // valeur du champ # rustine pour DECIMAL(10,2) if (false !== strpos($k, ')')) { $fields[$k_precedent] .= ',' . $k . ' ' . $def; continue; } $fields[$k] = $def; $k_precedent = $k; // la primary key peut etre dans une des descriptions de champs // et non en fin de table, cas encore decouvert avec Sqlite Manager if (stripos($r[2], 'PRIMARY KEY') !== false) { $keys['PRIMARY KEY'] = $k; } } // key inclues dans la requete foreach (preg_split('/\\)\\s*,?/', $namedkeys) as $v) { if (preg_match("/^\\s*([^(]*)\\((.*)\$/", $v, $r)) { $k = str_replace("`", '', trim($r[1])); $t = trim(strtolower(str_replace("`", '', $r[2])), '"'); if ($k && !isset($keys[$k])) { $keys[$k] = $t; } else { $keys[] = $t; } } } // sinon ajouter les key index $query = 'SELECT name,sql FROM' . ' (SELECT * FROM sqlite_master UNION ALL' . ' SELECT * FROM sqlite_temp_master)' . " WHERE tbl_name LIKE '{$nom_table}'" . " AND type='index' AND name NOT LIKE 'sqlite_%'" . 'ORDER BY substr(type,2,1), name'; $a = spip_sqlite_query($query, $serveur, $requeter); while ($r = spip_sqlite_fetch($a, null, $serveur)) { $key = str_replace($nom_table . '_', '', $r['name']); // enlever le nom de la table ajoute a l'index $colonnes = preg_replace(',.*\\((.*)\\).*,', '$1', $r['sql']); $keys['KEY ' . $key] = $colonnes; } } // c'est une vue, on liste les champs disponibles simplement } else { if ($res = sql_fetsel('*', $nom_table, '', '', '', '1', '', $serveur)) { // limit 1 $fields = array(); foreach ($res as $c => $v) { $fields[$c] = ''; } $keys = array(); } else { return ""; } } return array('field' => $fields, 'key' => $keys); }
/** * Creer la requete pour la creation d'une table * retourne la requete pour utilisation par sql_create() et sql_alter() * * http://code.spip.net/@_sqlite_requete_create * * @param $nom * @param $champs * @param $cles * @param bool $autoinc * @param bool $temporary * @param bool $_ifnotexists * @param string $serveur * @param bool $requeter * @return bool|string */ function _sqlite_requete_create($nom, $champs, $cles, $autoinc = false, $temporary = false, $_ifnotexists = true, $serveur = '', $requeter = true) { $query = $keys = $s = $p = ''; // certains plugins declarent les tables (permet leur inclusion dans le dump) // sans les renseigner (laisse le compilo recuperer la description) if (!is_array($champs) || !is_array($cles)) { return; } // sqlite ne gere pas KEY tout court dans une requete CREATE TABLE // il faut passer par des create index // Il gere par contre primary key ! // Soit la PK est definie dans les cles, soit dans un champs $c = ""; // le champ de cle primaire if (!isset($cles[$pk = "PRIMARY KEY"]) or !($c = $cles[$pk])) { foreach ($champs as $k => $v) { if (false !== stripos($v, $pk)) { $c = $k; // on n'en a plus besoin dans field, vu que defini dans key $champs[$k] = preg_replace("/{$pk}/is", '', $champs[$k]); break; } } } if ($c) { $keys = "\n\t\t{$pk} ({$c})"; } // Pas de DEFAULT 0 sur les cles primaires en auto-increment if (isset($champs[$c]) and stripos($champs[$c], "default 0") !== false) { $champs[$c] = trim(str_ireplace("default 0", "", $champs[$c])); } $champs = _sqlite_remplacements_definitions_table($champs, $autoinc ? $c : false); foreach ($champs as $k => $v) { $query .= "{$s}\n\t\t{$k} {$v}"; $s = ","; } $ifnotexists = ""; if ($_ifnotexists) { $version = spip_sqlite_fetch(spip_sqlite_query("select sqlite_version() AS sqlite_version", $serveur), '', $serveur); if (!function_exists('spip_version_compare')) { include_spip('plugins/installer'); } if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) { $ifnotexists = ' IF NOT EXISTS'; } else { /* simuler le IF EXISTS - version 2 et sqlite < 3.3a */ $a = spip_sqlite_showtable($table, $serveur); if (isset($a['key']['KEY ' . $nom])) { return true; } } } $temporary = $temporary ? ' TEMPORARY' : ''; $q = "CREATE{$temporary} TABLE{$ifnotexists} {$nom} ({$query}" . ($keys ? ",{$keys}" : '') . ")\n"; return $q; }
function spip_sqlite_showtable($nom_table, $serveur='',$requeter=true){ $query = 'SELECT sql, type FROM' . ' (SELECT * FROM sqlite_master UNION ALL' . ' SELECT * FROM sqlite_temp_master)' . " WHERE tbl_name LIKE '$nom_table'" . " AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'" . ' ORDER BY substr(type,2,1), name'; $a = spip_sqlite_query($query, $serveur, $requeter); if (!$a) return ""; if (!$requeter) return $a; if (!($a = spip_sqlite_fetch($a, null, $serveur))) return ""; $vue = ($a['type'] == 'view'); // table | vue // c'est une table // il faut parser le create if (!$vue) { if (!preg_match("/^[^(),]*\((([^()]*(\([^()]*\))?[^()]*)*)\)[^()]*$/", array_shift($a), $r)) return ""; else { $dec = $r[1]; if (preg_match("/^(.*?),([^,]*KEY.*)$/s", $dec, $r)) { $namedkeys = $r[2]; $dec = $r[1]; } else $namedkeys = ""; $fields = array(); foreach (explode(",",$dec) as $v) { preg_match("/^\s*([^\s]+)\s+(.*)/",$v,$r); // trim car 'Sqlite Manager' (plugin Firefox) utilise des guillemets // lorsqu'on modifie une table avec cet outil. // possible que d'autres fassent de meme. $fields[ trim(strtolower($r[1]),'"') ] = $r[2]; } // key inclues dans la requete $keys = array(); foreach(preg_split('/\)\s*,?/',$namedkeys) as $v) { if (preg_match("/^\s*([^(]*)\((.*)$/",$v,$r)) { $k = str_replace("`", '', trim($r[1])); $t = trim(strtolower(str_replace("`", '', $r[2])), '"'); if ($k && !isset($keys[$k])) $keys[$k] = $t; else $keys[] = $t; } } // sinon ajouter les key index $query = 'SELECT name,sql FROM' . ' (SELECT * FROM sqlite_master UNION ALL' . ' SELECT * FROM sqlite_temp_master)' . " WHERE tbl_name LIKE '$nom_table'" . " AND type='index' AND name NOT LIKE 'sqlite_%'" . 'ORDER BY substr(type,2,1), name'; $a = spip_sqlite_query($query, $serveur, $requeter); while ($r = spip_sqlite_fetch($a, null, $serveur)) { $key = str_replace($nom_table.'_','',$r['name']); // enlever le nom de la table ajoute a l'index $colonnes = preg_replace(',.*\((.*)\).*,','$1',$r['sql']); $keys['KEY '.$key] = $colonnes; } } // c'est une vue, on liste les champs disponibles simplement } else { if ($res = sql_fetsel('*',$nom_table,'','','','1','',$serveur)){ // limit 1 $fields = array(); foreach($res as $c=>$v) $fields[$c]=''; $keys = array(); } else { return ""; } } return array('field' => $fields, 'key' => $keys); }