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 {
return $r;
}
- function query($sql) {
+ public function query($sql) {
# See: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers
try {
}
- 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;
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'),
} 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()));
#'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
?>
);
*/
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',
# - 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) {
}
*/
- 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;
# See: http://php.net/manual/en/pdostatement.bindparam.php
if ($name === null) $name = ':'.$this->name;
#debug($this->name . " | $name | $value | $this->type | " . $this->size()."<br/>");
- 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) {
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");
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';
//
// 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 = '';
+ }
}
//
$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"
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);
}
}
$count_fields = 0;
- foreach ($this->fields() as $f => $field) {
+ foreach ($fields as $f => $field) {
$row[$f] = $field->out($row[$f]);
$count_fields++;
}
if ($out_conf) {
out::row($out_conf,$row);
} else {
- echo $this->{"rows_rec_$format"}($row);
+ echo $this->{"rows_rec_$format"}($row,$fields);
}
}
}
if ($count === 0 and $this->p('header') === 'force') {
- echo $this->{"rows_begin_$format"}($this->fields());
+ echo $this->{"rows_begin_$format"}($fields);
}
if ($count) {
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();
}
#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();
$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); }
+++ /dev/null
-<?php
-require_once(dirname(__FILE__).'/../nb.php');
-$DB_TYPES = array(
-
- 'use_path' => 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<user>\S+)|password=(?P<password>\S+))'),
- 'mysql' => array(getenv('HOME').'/'.'.my.cnf', '^(?:user(?:name)?=(?P<user>\S+)|password=(?P<password>\S+))'),
- 'pgsql' => array(getenv('HOME').'/'.'.pgpass', '^[^:]+:[^:]+:<NAME>:(?P<user>[^:]+):(?<password>[^:]+)'),
- #'sqlite' => array($_SERVER['HOME'].'/'.'.db.pass', '^<NAME>:(?P<user>[^:]*):(?<password>[^:]*)'),
- #'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('<NAME>')",
- '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 `<NAME>`",
- '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 = '<NAME>'::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='<NAME>' 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='<NAME>'",
- 'mysql' => "SHOW CREATE TABLE `<NAME>`",
- # 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='<NAME>'
-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 = '<NAME>' 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);
-?>
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 = '<pre class="debug">'