From: Nicolas Boisselier Date: Tue, 5 Apr 2016 00:03:54 +0000 (+0100) Subject: Bed X-Git-Url: https://git.nbdom.net/?a=commitdiff_plain;h=1795e6d7bd447275af998e2e346e57853d96fd0f;p=nb.git Bed --- diff --git a/lib/php/db.php b/lib/php/db.php index 2b1c58e4..cf32676c 100644 --- a/lib/php/db.php +++ b/lib/php/db.php @@ -9,8 +9,8 @@ require_once(dirname(__FILE__).'/nb.php'); require_once(dirname(__FILE__).'/out.php'); require_once(dirname(__FILE__).'/db/table.php'); -$DB_TYPES = array(); -# NB 29.03.16 require_once(dirname(__FILE__).'/db/types.php'); +require_once(dirname(__FILE__).'/db/field.php'); +$DB_TYPES = array(); # See db/types/*.php class Db extends nb { @@ -206,7 +206,7 @@ class Db extends nb { return $r; } - function query($sql) { + public function query($sql) { # See: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers try { @@ -220,7 +220,7 @@ class Db extends nb { } - function row($sql,$sep=' ') { + public function row($sql,$sep=' ') { $query = $this->query($sql); $result = $query->fetch(PDO::FETCH_NUM); if (!is_array($result)) return $result; @@ -476,7 +476,6 @@ EOF; array('db.help','This help'), array('[db.]dbs','List databases'), array('[db.]tables','List tables'), - array('[db.]html_menu','Html menu for tables with links'), array('[table.]rows','Dump one table, use format='), array('[table.]fields','List fields'), @@ -499,11 +498,6 @@ EOF; } elseif ($action == 'db.dbs' or $action == 'dbs') { $return = $this->out2($this->dbs,"name"); - } elseif ($action == 'db.html_menu' or $action == 'html_menu') { - $this->print_header($this->p('format','html')); - echo $this->html_menu(); - $return = true; - } elseif (preg_match('/^db\.(\w+)/',$action,$m)) { if ($rows = $this->$m[1]()) $return = $this->out2($rows,(is_scalar($rows) ? $m[1] : array())); @@ -705,6 +699,33 @@ EOF; #'dbs' => join(' ',array_values($this->dbs)), )+$status; } + + public function fields($st) { + # See: http://php.net/manual/en/pdostatement.getcolumnmeta.php + $fields = array(); + for ($i = 0; $i < $st->columnCount(); $i++) { + $col = $st->getColumnMeta($i); + + $f = new Field(); + $col['type'] = $f->pdo2type($col['pdo_type']); + unset($col['pdo_type']); + + if (!empty($col['flags'])) { + $col['null'] = in_array('not_null',$col['flags']) ? false : true; + $col['key'] = in_array('primary_key',$col['flags']) ? true : false; + } + unset($col['flags']); + + unset($col['len']); # never right ! + unset($col['precision']); # ??? + + $f->__construct($col); + $fields[] = $f; + } + + return $fields; + } + } # < Class ?> diff --git a/lib/php/db/field.php b/lib/php/db/field.php index c83b61af..15d8cf9f 100644 --- a/lib/php/db/field.php +++ b/lib/php/db/field.php @@ -9,15 +9,14 @@ $DB_FIELD_TYPES = array( ); */ class field { - private $table = null; - + private $table; public $name; public $type = 'text'; - public $null = false; + public $null = true; public $key = false; - public $default = null; + public $default; public $autoincrement = false; - public $extra = null; + public $extra; public function __sleep() { return array( 'name', @@ -137,7 +136,7 @@ class field { # - NB 25.03.16 * Return the value quoted public function sql($v) { - $type = $this->pdo_type($this->type); + $type = $this->type2pdo($this->type); if ($type === PDO::PARAM_NULL) { return 'NULL'; } elseif ($type === PDO::PARAM_INT) { @@ -150,7 +149,15 @@ class field { } */ - public function pdo_type() { + public static function pdo2type($pdo) { + if ($pdo === PDO::PARAM_BOOL) return 'bool'; + if ($pdo === PDO::PARAM_LOB) return 'blob'; + if ($pdo === PDO::PARAM_INT) return 'int'; + if ($pdo === PDO::PARAM_STR) return 'varchar'; + self::bye("Unknow pdo type: `$pdo`"); + } + + public function type2pdo() { if (func_get_args()>0 and func_get_arg(0) === null) return PDO::PARAM_NULL; if ($this->numeric()) return PDO::PARAM_INT; if (strpos($this->type,'bool') !== false ) return PDO::PARAM_BOOL; @@ -162,8 +169,8 @@ class field { # See: http://php.net/manual/en/pdostatement.bindparam.php if ($name === null) $name = ':'.$this->name; #debug($this->name . " | $name | $value | $this->type | " . $this->size()."
"); - return $sth->bindParam($name, $value, $this->pdo_type($value), $this->size()); -// NB 27.07.15 return $sth->bindParam($name, $value, $this->pdo_type($value)); + return $sth->bindParam($name, $value, $this->type2pdo($value), $this->size()); +// NB 27.07.15 return $sth->bindParam($name, $value, $this->type2pdo($value)); } public function out($value,$html_escape=false) { diff --git a/lib/php/db/table.php b/lib/php/db/table.php index 1fc26d67..6563da3a 100644 --- a/lib/php/db/table.php +++ b/lib/php/db/table.php @@ -82,7 +82,7 @@ Class Table extends nb { foreach ($opt as $k => $v) { $this->$k = $v; } // Name, could be a select - if (stripos($this->name,'SELECT ')===0) { + if (0 and stripos($this->name,'SELECT ')===0) { #$temp = '_'.substr(md5($this->name),0,6); $temp = DB_TABLE_QUERY_NAME; #bye("CREATE TEMPORARY VIEW $temp AS $this->name"); @@ -257,7 +257,6 @@ Class Table extends nb { if (!is_array($values)) $values = array($values); $add = false; - #$where = str_replace(' LIKE ','=',$this->where_criterias($values)); $where = $this->where($this->fields(),$values); if (empty($where)) { $where = ' WHERE 1=0'; @@ -547,21 +546,28 @@ Class Table extends nb { // // Select // - $where = $this->where_criterias($this->p(),$this->p('op')); - $select_count = ( $where ? $this->db()->type('select_count') : null ); - if (empty($select_count)) $select_count = array('',''); + if (stripos($this->name,' ') !== false) { + $sql = $this->name; + $limit = $where = ''; - $sql = "SELECT ".trim("$select_count[0] *"). $this->select_extras(); - $sql .= " FROM ".$this->sql_name(); - $sql .= $where; + } else { - if ($this->p('orderby')) $sql .= ' ORDER BY '.$this->p('orderby'); + $where = $this->where_criterias($this->p(),$this->p('op')); + $select_count = ( $where ? $this->db()->type('select_count') : null ); + if (empty($select_count)) $select_count = array('',''); - if ($this->p('limit')) { - $limit = $this->p('limit'); - $sql .= ' LIMIT '.$limit; - } else { - $limit = ''; + $sql = "SELECT ".trim("$select_count[0] *"). $this->select_extras(); + $sql .= " FROM ".$this->sql_name(); + $sql .= $where; + + if ($this->p('orderby')) $sql .= ' ORDER BY '.$this->p('orderby'); + + if ($this->p('limit')) { + $limit = $this->p('limit'); + $sql .= ' LIMIT '.$limit; + } else { + $limit = ''; + } } // @@ -572,6 +578,14 @@ Class Table extends nb { $st = $this->db()->conn->prepare($sql); $st->execute(); + # Fields + $fields = array(); + foreach ($this->db()->fields($st) as $f) { $fields[$f->name] = $f; } + $this->fields = $fields; + #debug($fields); + #bye($this->name); + if (!$this->p('action')) echo $this->html_menu(); + if (!isset($opt['is_html'])) $opt['is_html'] = preg_match('/^(table|div)$/',$format) ? ( $this->p('header')!=="0" @@ -606,10 +620,10 @@ Class Table extends nb { if ($opt['is_html']) echo $this->html_rows_top(); if ($out_conf) { - out::head($out_conf,$this->fields(),array($row)); + out::head($out_conf,$fields,array($row)); } else { - echo $this->{"rows_begin_$format"}($this->fields()); + echo $this->{"rows_begin_$format"}($fields); } } @@ -621,7 +635,7 @@ Class Table extends nb { $count_fields = 0; - foreach ($this->fields() as $f => $field) { + foreach ($fields as $f => $field) { $row[$f] = $field->out($row[$f]); $count_fields++; } @@ -629,7 +643,7 @@ Class Table extends nb { if ($out_conf) { out::row($out_conf,$row); } else { - echo $this->{"rows_rec_$format"}($row); + echo $this->{"rows_rec_$format"}($row,$fields); } } @@ -675,7 +689,7 @@ Class Table extends nb { } if ($count === 0 and $this->p('header') === 'force') { - echo $this->{"rows_begin_$format"}($this->fields()); + echo $this->{"rows_begin_$format"}($fields); } if ($count) { @@ -710,12 +724,12 @@ Class Table extends nb { return "\n-- ".$this->name."\n"; } - public function rows_rec_sql(&$row) { + public function rows_rec_sql(&$row,$fields) { $keys = $values = array(); foreach ($row as $k=>$v) { if (isset($this->extras[$k])) continue; - $f = $this->fields($k); + $f = $fields[$k]; $values[] = $f->quote($v); $keys[] = $f->sql_name(); @@ -1036,7 +1050,7 @@ Class Table extends nb { } #debug($execute); - $info = array('sql'=>$sql,'values'=>$hvalues,'return'=>$query->rowCount()); + $info = array('sql'=>$sql,'values'=>$hvalues,'rowCount'=>$query->rowCount()); $this->debug($info,1); return $query->rowCount(); @@ -1054,7 +1068,7 @@ Class Table extends nb { $sql = 'DELETE FROM ' . $this->sql_name() . $where; #bye($sql); - return $this->db()->exec($sql); + return $this->db()->exec($sql)->fetchColumn(); } # NB 01.04.16 public function out($v,$head=false) { return $this->db()->out($v,$head); } diff --git a/lib/php/db/types.php b/lib/php/db/types.php deleted file mode 100644 index 6edb27ea..00000000 --- a/lib/php/db/types.php +++ /dev/null @@ -1,167 +0,0 @@ - array( - 'sqlite' => true, - ), - - 'sqliteCreateFunction' => array( - 'sqlite' => array( - 'ip2int' => function ($value) { return ip2long($value); }, - 'concat' => function ($v1,$v2) { return $v1.$v2; }, - 'regexp' => function ($pattern, $data, $delimiter = '~', $modifiers = 'isuS') { - if (isset($pattern, $data) === true) { - return (preg_match(sprintf('%1$s%2$s%1$s%3$s', $delimiter, $pattern, $modifiers), $data) > 0); - } - return null; - } - , - 'to_char' => array(function ($value,$format) { - $replace = array( - 'YYYY' => '%Y', - 'MM' => '%m', - 'WW' => '%W', - 'DD' => '%d', - ); - $format = str_replace(array_keys($replace),array_values($replace),$format); - return strftime($format,strtotime($value)); - } - ,2), - ), - ), - - 'localFile' => array( - # hostname:port:database:username:password - 'sqlite' => array(getenv('HOME').'/'.'.sqlite', '^(?:user(?:name)?=(?P\S+)|password=(?P\S+))'), - 'mysql' => array(getenv('HOME').'/'.'.my.cnf', '^(?:user(?:name)?=(?P\S+)|password=(?P\S+))'), - 'pgsql' => array(getenv('HOME').'/'.'.pgpass', '^[^:]+:[^:]+::(?P[^:]+):(?[^:]+)'), - #'sqlite' => array($_SERVER['HOME'].'/'.'.db.pass', '^:(?P[^:]*):(?[^:]*)'), - #'sqlite' => array(), - ), - - 'tables' => array( - 'sqlite' => "SELECT name,type FROM sqlite_master WHERE type IN('table','view') AND name NOT LIKE 'sqlite_%' ORDER BY name", - 'mysql' => "SELECT TABLE_NAME as name" - .",LOWER(IF(TABLE_TYPE='BASE TABLE','TABLE',TABLE_TYPE)) as type" - .",ENGINE as engine" - .",CREATE_TIME as created" - ." FROM information_schema.tables WHERE TABLE_SCHEMA=DATABASE()" - , - 'pgsql' => "SELECT table_name as name" - .",LOWER(CASE table_type WHEN 'BASE TABLE' THEN 'TABLE' ELSE table_type END) as type" - .",table_type" - ." FROM information_schema.tables WHERE table_type in('BASE TABLE','VIEW') AND table_schema NOT IN ('pg_catalog', 'information_schema')" - , - ), - - 'table.fields' => array( - 'sqlite' => array( - 'sql' => "PRAGMA table_info('')", - 'fct' => create_function('&$r',join('',array( - #'debug("zaza");', - '$r["key"] = $r["pk"] == "0" ? 0 : 1;', - '$r["default"] = $r["dflt_value"];', - '$r["null"] = $r["notnull"] == "0" ? 1 : 0;', - '$r["autoincrement"] = preg_match("/[\(,]".$r["name"]." [^\),]+ AUTOINCREMENT/",$r["this"]->sql()) ? 1 : 0;', - ))), - ), - 'mysql' => array( - 'sql' => "SHOW COLUMNS FROM ``", - 'fct' => create_function('&$r',join('',array( - '$r["autoincrement"] = $r["extra"] == "auto_increment" ? 1 : 0;', - '$r["name"] = $r["field"];', - ))), - ), - 'pgsql' => array( - 'fct' => create_function('&$r',join('',array( - 'if (!isset($r["pg_default"])) return;', - 'if (preg_match("/^nextval\(/",$r["pg_default"])) { $r["autoincrement"] = 1; }', - 'elseif (preg_match("/^\'\'/",$r["pg_default"])) { $r["default"] = ""; }', - 'else { $r["default"] = $r["pg_default"]; }', - ))), - 'sql' => "SELECT -a.attname AS name, -pg_catalog.format_type(a.atttypid, a.atttypmod) AS type, -CASE a.attnotnull WHEN 'f' then 1 ELSE 0 END AS null, -(SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) AS pg_default, -(SELECT 1 FROM pg_index i WHERE a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) AND i.indrelid = ''::regclass AND i.indisprimary) as key -FROM pg_catalog.pg_attribute a -WHERE a.attrelid = ( - SELECT c.oid FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relname='' AND pg_catalog.pg_table_is_visible(c.oid) - ) - AND a.attnum > 0 AND NOT a.attisdropped -ORDER BY a.attnum", - ), - ), - - 'table.sql' => array( - 'sqlite' => "SELECT sql FROM sqlite_master WHERE name=''", - 'mysql' => "SHOW CREATE TABLE ``", - # c.relkind::char - 'pgsql' => " -SELECT CASE c.relkind::char WHEN 'r' THEN ( -SELECT - 'CREATE TABLE '||sql.table||'(".NB_EOL." ' - ||array_to_string(array_agg(sql),',".NB_EOL." ') - ||'".NB_EOL.")' as sql -FROM ( - ( - SELECT -- FIELDS - c.oid AS id - ,c.relname as table - ,9 as prio - ,'' - || f.attname - || ' ' || pg_catalog.format_type(f.atttypid,f.atttypmod) - ||CASE WHEN f.attnotnull THEN ' NOT NULL' ELSE '' END - ||CASE WHEN f.atthasdef = 't' AND d.adsrc !=''THEN ' DEFAULT '||d.adsrc ELSE '' END - AS sql - FROM pg_attribute f - JOIN pg_class c ON c.oid = f.attrelid - LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum - WHERE c.relkind::char IN ( 'r' ) --, 'v' ) - AND f.attnum > 0 - ORDER BY f.attnum - ) UNION ( - SELECT -- CONSTRAINTS - c.oid as id - ,c.relname as table - ,0 as prio - ,CASE - WHEN p.contype = 'p' THEN 'PRIMARY KEY' - WHEN p.contype = 'u' THEN 'UNIQ' - ELSE '' END - ||'('||array_to_string(array_agg(f.attname),', ')||')' AS sql - FROM pg_attribute f - JOIN pg_class c ON c.oid = f.attrelid - LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey) - WHERE c.relkind = 'r'::char - AND f.attnum > 0 - AND p.contype IN ('u','p') - GROUP BY c.oid,p.contype,f.attrelid,c.relname - ORDER BY c.oid,f.attrelid - ) -ORDER BY prio DESC) sql -WHERE sql.table='' -GROUP BY sql.id,sql.table -) -WHEN 'v' THEN trim(regexp_replace(pg_catalog.pg_get_viewdef(c.oid::pg_catalog.oid, true),'\s\s+',' ','g')) -ELSE 'NOT' END as sql -FROM pg_catalog.pg_class c WHERE c.relname = '' AND pg_catalog.pg_table_is_visible(c.oid) - ", # < table.sql:psql "SELECT - ), -); -#die($DB_TYPES['tables']['mysql']); -return; -if (empty($argv) or count($argv)<2) return; -$new = array(); -$filter = $argv[1]; -foreach ($DB_TYPES as $key => $types) { - foreach ($types as $type => $val) { - if($filter and $filter!=$type) continue; - $new[$type][$key] = $val; - } -} -var_export($new); -?> diff --git a/lib/php/functions.php b/lib/php/functions.php index 00ac3474..227e98f6 100644 --- a/lib/php/functions.php +++ b/lib/php/functions.php @@ -130,7 +130,8 @@ function err($msg='__err__',$preff='err',$backtrace_deep=0) { function debug($msg,$level=0) { if ($level and $level>nb::p('debug')) return; - $msg = is_scalar($msg) ? $msg : print_r($msg,true); + #$msg = is_scalar($msg) ? $msg : print_r($msg,true); + $msg = is_scalar($msg) ? $msg : var_export($msg,true); if (nb::client_header('Accept','ml')) { $msg = '
'