]> git.nbdom.net Git - nb.git/commitdiff
Bed
authorNicolas Boisselier <nicolas.boisselier@gmail.com>
Mon, 28 Mar 2016 04:25:15 +0000 (05:25 +0100)
committerNicolas Boisselier <nicolas.boisselier@gmail.com>
Mon, 28 Mar 2016 04:25:15 +0000 (05:25 +0100)
etc/dbs.yaml
lib/php/db.php
lib/php/db/field.php
lib/php/db/index.php
lib/php/db/table.php
lib/php/db/types.php [new file with mode: 0644]
lib/php/nb.php
lib/php/out.php

index f68c2a8a145b00ecf4239ce8e484d975bab2d469..b5d4dc925a10a879f2a43dba6dd89d748230ae00 100644 (file)
@@ -6,6 +6,17 @@ _mysql:
 crypt:
   pdo: 'sqlite:/dev/shm/crypt.db'
 
+wp:
+  host: admin.izideal.vpn
+  _import:
+    - _nico
+    - _mysql
+nb:
+  host: admin.izideal.vpn
+  _import:
+    - _nico
+    - _mysql
+
 puppetdb:
   #pdo: 'pgsql:host=big;dbname=puppetdb;user=puppetdb;password='
   title: Puppetdb
@@ -36,29 +47,16 @@ izi:
   #pdo: 'mysql:host=admin.izideal.com;port=3306;dbname=izi'
   title: Mysql Izi on Admin
   default_table: process
-
+  host: admin.izideal.vpn
   user: izideal
-  type: mysql
-  host: admin.izideal.com
-  name: izi
-  options:
-    - "PDO::MYSQL_ATTR_INIT_COMMAND: SET NAMES utf8'"
+  _import:
+    - _nico
+    - _mysql
 
 izidev:
-  #pdo: 'mysql:host=big.cascais.loc;port=3306;dbname=izi'
   title: Mysql Izi on Big
-  default_table: process
-
-  user: nico
-  type: mysql
-  host: admin.izideal.com
-  name: izi
-  options:
-    - "PDO::MYSQL_ATTR_INIT_COMMAND: SET NAMES utf8'"
-
-ui-mem:
-  pdo: 'sqlite:/dev/shm/semantico.db'
-  _import: ui
+  _import:
+    - izi
 
 ui:
   pdo: 'sqlite:/opt/semantico/product/releases/sem_ui/db/semantico.db'
@@ -73,6 +71,10 @@ ui:
   replace:
     "SELECT name FROM dc WHERE id='@id'": ".node td.iddc"
 
+ui-mem:
+  pdo: 'sqlite:/dev/shm/semantico.db'
+  _import: ui
+
 rt:
   pdo: 'pgsql:host=db.rt.semantico.net;port=5432;dbname=rtdb;user=rtuser;password='
   title: 'RT'
@@ -125,18 +127,10 @@ rent:
 # NB 10.01.16       #revision: (SELECT GROUP_CONCAT('<a href="template/?id='||id||'&amp;idplace='||idplace||'&amp;idtenant='||idtenant||'&amp;start='||start||'">'||substr(id,0,instr(id,'.'))||'</a>',' ') FROM template)
 # NB 10.01.16     template:
 # NB 10.01.16       View: "'<a href=\"/template/'||id||'\">'||id||'</a>'"
-nb:
-  host: admin.izideal.vpn
-  _import:
-    - _nico
-    - _mysql
 postfix:
   #pdo: 'mysql:host=media.izideal.vpn;port=3306;dbname=postfix'
-  user: postfix
   title: Postfix on Izideal
-
-  type: mysql
   host: media.izideal.vpn
-  name: postfix
-  options:
-    - "PDO::MYSQL_ATTR_INIT_COMMAND: SET NAMES utf8'"
+  user: postfix
+  _import:
+    - _mysql
index 914f41ed0d84540476cd96a42cc334cf2f9b2428..327e7a27665ba1387f32c46599f81d57142da17b 100644 (file)
@@ -9,93 +9,7 @@
 require_once(dirname(__FILE__).'/nb.php');
 require_once(dirname(__FILE__).'/out.php');
 require_once(dirname(__FILE__).'/db/table.php');
-
-$DB_TYPES = array(
-  'config' => array(
-    # hostname:port:database:username:password
-    'pgsql' => array(getenv('HOME').'/'.'.pgpass', '^[^:]+:[^:]+:<NAME>:(?P<user>[^:]+):(?<password>[^:]+)'),
-    'mysql' => array(getenv('HOME').'/'.'.my.cnf', '^(?:user(?:name)?=(?P<user>\S+)|password=(?P<password>\S+))'),
-    'sqlite' => array(getenv('HOME').'/'.'.db.sqlite', '^(?:user(?:name)?=(?P<user>\S+)|password=(?P<password>\S+))'),
-    #'sqlite' => array($_SERVER['HOME'].'/'.'.db.pass', '^<NAME>:(?P<user>[^:]*):(?<password>[^:]*)'),
-    #'sqlite' => array(),
-  ),
-  'tables' => array(
-    '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')"
-    ,
-    '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()"
-    ,
-    'sqlite' => "SELECT name,type FROM sqlite_master WHERE type IN('table','view') AND name NOT LIKE 'sqlite_%' ORDER BY name",
-  ),
-  'table.fields' => array(
-      'pgsql' => "SELECT
-a.attname AS name,
-pg_catalog.format_type(a.atttypid, a.atttypmod) AS type,
-CASE a.attnotnull WHEN 't' then 1 ELSE 0 END AS notnull,
-(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 pk
-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",
-      'mysql' => "SHOW COLUMNS FROM `<NAME>`",
-      'sqlite' => "PRAGMA table_info('<NAME>')",
-    ),
-  'table.sql' => array(
-    'pgsql' => "
-SELECT
-  'CREATE TABLE '||sql.table||'('
-    ||array_to_string(array_agg(sql),', ')
-  ||')' 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 = 'r'::char
-        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
-",
-    'mysql' => "SHOW CREATE TABLE `<NAME>`",
-    'sqlite' => "SELECT sql FROM sqlite_master WHERE name='<NAME>'",
-  ),
-);
-#die($DB_TYPES['tables']['mysql']);
+require_once(dirname(__FILE__).'/db/types.php');
 
 class Db extends nb {
 
@@ -177,7 +91,10 @@ class Db extends nb {
     }
     #$this->bye($this->pdo);
 
-    if ($this->type != 'sqlite') {
+    if ($this->type == 'sqlite') {
+      $this->host = preg_replace('/^\w+:/','',$this->pdo);
+
+    } else {
       foreach (array(
         'host' => 'host',
         'port' => 'port',
@@ -337,9 +254,9 @@ class Db extends nb {
 
   function table($name) {
     $opt = array('db' => $this);
-    if (isset($this->tables) and array_key_exists($name,$this->tables)) {
-      foreach ($this->tables[$name] as $k=>$v) { $opt[$k] = $v; }
-    }
+# NB 28.03.16     if (sset($this->tables) and array_key_exists($name,$this->tables)) {
+# NB 28.03.16       foreach ($this->tables[$name] as $k=>$v) { $opt[$k] = $v; }
+# NB 28.03.16     }
     return new Table($name,$opt);
     #return new Table($name,array_merge($opt));
   }
@@ -584,24 +501,10 @@ EOF;
           $return = true;
 
         } elseif ($action == 'db.tables' or $action == 'tables') {
-
-          foreach ($this->tables(true) as $name => $t) { $row=array('name'=>$t['name']);
-            foreach (array(
-              'type',
-              'count',
-              'engine',
-              'created',
-            ) as $f) {
-              if (isset($t[$f])) $row[$f] = $t[$f];
-              if ($f=='count' and $this->p('count')==='1') $row['count'] = $this->table($name)->count();
-            }
-            $rows[] = $row;
+          foreach ($this->tables() as $name) {
+            $rows[] = $this->table($name)->infos();
           }
-
           $return = $this->out2($rows);
-    # NB 21.03.16       $return = $this->out2($rows,array_keys($row));
-    # NB 21.03.16       $return = $this->out2(array_values($this->tables(true)));
-    # NB 21.03.16       $return = $this->out2($this->tables(),array('name'));
 
         } elseif ($action == 'db.dbs' or $action == 'dbs') {
           $return = $this->out2($this->dbs,"name");
@@ -743,20 +646,34 @@ EOF;
 
   }
 
-  public function sql() {
+  public function dump() {
+    $this->sql(true);
+  }
+
+  public function pdo_info() {
+    return preg_replace_callback('/(\w+)=[^;]*;?/',function($m){
+      return preg_match('/^(host|dbname|name)/',$m[1]) ? $m[0] : ''; 
+    },$this->pdo);
+  }
+
+  public function sql($insert=null) {
+    if ($insert === null) $insert = self::p('insert');
     $this->pset('orderby',null);
+    $this->pset('format','sql');
     $r = array();
+    #if (NB_EOL == "\n")
+    echo ''
+      #."-- Database : ".$this->name."\n"
+      ."-- Date     : ".strftime('%F %T')."\n"
+      ."-- Pdo      : ".$this->pdo_info()."\n"
+      #."-- Host     : ".$this->host."\n"
+    ;
     foreach ($this->tables() as $t) {
       $t = $this->table($t);
-      #$this->pset('format','sql');
-      #$r[] = preg_replace('/\s+/',' ',$t->sql()).";";
-      #if (0)
-      #$r[] = preg_replace('/ +/',' ',$t->sql()).";";
-      $r[] = preg_replace('/\s+/',' ',
-        # Filter comment to generate one sql per line
-        join(' ',preg_grep('/^ *--/',explode("\n",$t->sql()),true))
-      ).";";
-      #$t->rows();
+      if ($insert) echo "\n-- Table: ".$t->name."\n";
+      echo rtrim($t->sql(),';').';'.NB_EOL;
+      if ($insert) $t->rows();
+      #break;
     }
     return $r;
   }
index c4cd3bf91e59e11109b1dc2ebd95fe4104c180c7..c83b61af06bc899e1c0643d211b329d0558484bd 100644 (file)
@@ -9,15 +9,25 @@ $DB_FIELD_TYPES = array(
 );
 */
 class field {
+  private $table = null;
 
   public $name;
   public $type = 'text';
-  public $default = null;
+  public $null = false;
   public $key = false;
-  public $table = null;
+  public $default = null;
+  public $autoincrement = false;
   public $extra = null;
 
-  private $autoincrement = false;
+  public function __sleep() { return array(
+    'name',
+    'type',
+    'null',
+    'key',
+    'default',
+    'autoincrement',
+    'extra',
+  ); }
 
   public function __construct($attr=array()) {
     if (is_scalar($attr)) $attr = array('name'=>$attr);
index 3a38e9d6c640669183c9bc2690eab0a09921479d..485e8e89a93f9bc0f91e28fbc682851a7998210b 100755 (executable)
@@ -18,8 +18,8 @@ if (preg_match('/^(\w+)\.(.*?)$/',Db::p('table'),$m)) {
   Db::pset('db',$m[1]);
   Db::pset('table',$m[2]);
 }
-#$conf = Db::conf_dbs(array( Db::$root_dir.'/etc/dbs.yaml','/etc/dbs.yaml' )); Db::init($conf);
-Db::init(array( Db::$root_dir.'/etc/dbs.yaml','/etc/dbs.yaml' ));
+#$conf = Db::conf_dbs(array( Db::ROOT_DIR.'/etc/dbs.yaml','/etc/dbs.yaml' )); Db::init($conf);
+Db::init(array( Db::ROOT_DIR.'/etc/dbs.yaml','/etc/dbs.yaml' ));
 
 if( defined('DB_JUST_INIT')) return true;
 return $Db->action($Table);
index 33d359c3a08cccef501f8065cde580fc9f1f4dec..04233f70d9c15c82cbbb1fe0b61fe4df01fdd86f 100644 (file)
@@ -26,19 +26,22 @@ if (!defined('DB_TABLE_QUERY_NAME')) define('DB_TABLE_QUERY_NAME','_query_');
 Class Table extends nb {
 
   public $name;
-  public $db;
-  public $sql;
   public $type; # table, view, sql
-  public $fields = null;
-  public $fields_keys = null;
+  public $sql;
+# NB 28.03.16   public $fields_keys;
   public $replace = array(); # replace by javascript
   public $extras = array();
+  public $count;
+  public $engine;
+  public $created;
 
   # hidden, sort, ... fields
   public $params = array( 'table', 'limit', 'debug', 'action');
-
   public $order_by = null;
 
+  public $fields;
+  public $db;
+
   function __construct($name,$opt=array()) {
 
     if (!is_scalar($name)) {
@@ -109,8 +112,20 @@ Class Table extends nb {
 
     $sql = str_replace('<NAME>',$this->name,$this->db->type('table.sql',true));
     $this->sql = $this->db->row($sql);
-    $this->sql = preg_replace("/^\w+\s+(CREATE)/i",'$1',$this->sql); # for mysql
-    #$this->sql = trim($this->sql);
+
+    # Noise before CREATE from mysql
+    $this->sql = preg_replace("/^\w+\s+(CREATE)/i",'$1',$this->sql);
+
+    # Remove comments
+    $this->sql = join(' ',preg_grep('/^ *--/',explode("\n",$this->sql),true));
+
+    # Delete new line and trim for line output
+    $this->sql = trim(preg_replace('/\s\s+/',' ',$this->sql));
+
+    if (self::p('ansi')) {
+      $this->sql = preg_replace("/\s*COLLATE NOCASE/i",'',$this->sql);
+    }
+
     #bye($this->sql);
     return $this->sql;
   }
@@ -125,81 +140,49 @@ Class Table extends nb {
    */
   public function fields($name=null) {
 
-    if ($this->fields === null) {
+    if (!isset($this->fields)) {
+
       $this->fields = array();
-      $sql = str_replace('<NAME>',$this->name,$this->db->type('table.fields',true));
-      $rows = $this->db->conn->query($sql);
+      $conf = str_replace('<NAME>',$this->name,$this->db->type('table.fields',true));
+      if (is_scalar($conf)) $conf = array('sql'=>$conf);
+      $rows = $this->db->conn->query($conf['sql']);
       $rows->setFetchMode(PDO::FETCH_ASSOC);
 
       foreach ($rows as $row) {
 
         $row = array_change_key_case($row,CASE_LOWER);
 
-        // Mysql field name
-        if (isset($row['field'])) {
-          $row['name'] = $row['field'];
-          unset($row['field']);
+        // From config
+        $row['this'] = $this; # for use
+        if (isset($conf['map'])) {
+          foreach ($conf['map'] as $from => $to) {
+            if (!isset($row[$from])) continue;
+            $row[$to] = $row[$from];
+            unset ($row[$from]);
+          }
         }
+        if (isset($conf['fct'])) $conf['fct']($row) ;
 
-#bye($row);
         $field = array(
           'name'          => $row['name'],
-          'extra'         => null, # !!! nothing todo with class variable $extras
           'type'          => strtolower($row['type']),
-          'default'       => null,
-          'key'           => null,
-          'autoincrement' => null,
+          'default'       => (isset($row['default']) ? $row['default'] : null),
+          'key'           => (preg_match('/^(f.*|no|0)?\s*$/i',$row['key']) ? 0 : 1),
+          'null'          => (preg_match('/^(f.*|no|0)?\s*$/i',$row['null']) ? 0 : 1),
+          #'key'           => (isset($row['key']) ? $row['key'] : 0),
+          'extra'         => null, # !!! nothing todo with class variable $extras, this info from the sql server
+          'autoincrement' => (isset($row['autoincrement']) ? $row['autoincrement'] : 0),
         );
 
-        if (isset($row['notnull'])) {
-          $field['null'] = $row['notnull'] == '0' ? 1 : 0;
-
-        } else {
-          $field['null'] = preg_match('/^1|yes|t/i',$row['null']) ? true : false;
-
-        }
-
-        # Autoincrement
-
-        # mysql autoincrement
-        if (isset($row['extra']) and $row['extra'] == 'auto_increment') {
-          $field['autoincrement'] = true;
-
         # sqlite autoincrement only in sql
-        } elseif ($this->db->type == 'sqlite'
+        if ($this->db->type == 'sqlite'
           and preg_match('/[\(,]'.$row['name'].' [^\),]+ AUTOINCREMENT/',$this->sql())
         ) {
-          $field['autoincrement'] = true;
-
-        }
-
-        # Postgres autoincrement / default
-        if (isset($row['pg_default'])) {
-
-          if (preg_match('/^nextval\(/',$row['pg_default'])) {
-            $field['autoincrement'] = true;
-
-          } elseif (preg_match("/^''/",$row['pg_default'])) {
-            $field['default'] = '';
-
-          } else {
-            $field['default'] = $row['pg_default'];
-
-          }
-        }
-
-        # sqlite default
-        foreach (array('dflt_value') as $f) {
-          if (!isset($row[$f])) continue;
-          $field['default'] = $row[$f];
-        }
+          $field['autoincrement'] = 1;
 
-        foreach (array('pk','key','Key') as $f) {
-          if (!isset($row[$f])) continue;
-          $field['key'] = preg_match('/^1|yes|t|PRI/i',$row[$f]) ? 1 : 0;
         }
 
-        $this->fields[$field['name']] = new field($field);
+        $this->fields[$field['name']] = new Field($field);
 
       }
 
@@ -266,7 +249,7 @@ Class Table extends nb {
 
     $sql = "SELECT *" . $this->select_extras();
     $sql .= " FROM ".$this->sql_name().$where;
-    $this->sql = $sql;
+# NB 28.03.16     $this->sql = $sql;
 
     $this->debug($sql,1);
     $st = $this->db->conn->prepare($sql);
@@ -561,7 +544,7 @@ Class Table extends nb {
     //
     // Get results
     //
-    $this->sql = $sql;
+# NB 28.03.16     $this->sql = $sql;
     $this->debug($sql,1);
     $st = $this->db->conn->prepare($sql);
     $st->execute();
@@ -699,6 +682,7 @@ Class Table extends nb {
   -----------------------------------------------------------------*/
   public function rows_begin_sql() {
     return '';
+    return "\n-- ".$this->name."\n";
   }
 
   public function rows_rec_sql(&$row) {
@@ -709,7 +693,7 @@ Class Table extends nb {
       $values[] = $f->quote($v);
     }
 
-    return "INSERT INTO ".$this->sql_name()." (".join(',',array_keys($row)).") VALUE(".join(',',array_values($values)).");\n";
+    return "INSERT INTO ".$this->sql_name()." (".join(',',array_keys($row)).") VALUES (".join(',',array_values($values)).");".NB_EOL;
   }
 
   public function rows_end_sql() {
@@ -1046,10 +1030,29 @@ Class Table extends nb {
   public function out($v,$head=false) { return $this->db->out($v,$head); }
   public function out2($v,$head=array()) { return $this->db->out2($v,$head); }
 
+  public function infos() {
+    return 
+      array(
+        "name" => $this->name,
+        "type" => $this->type,
+        "fields" => count($this->fields()),
+        #"count" => $this->count(),
+        #"sql_name" => $this->sql_name(),
+      )
+      +( self::p('count') ? array("count" => $this->count()) : array() )
+      +( isset($this->engine) ? array("engine" => $this->engine) : array() )
+      +( isset($this->created) ? array("created" => $this->created) : array() )
+      +( self::p('sql') ? array("sql" => $this->sql()) : array() )
+      #+( self::p('sql') ? array("sql" => $this->sql()) : array() )
+    ;
+  }
+
   public function action($action=null) {
     if ($action === null) $action = $this->p('action');
 
     if ($action == 'table.fields' or $action == 'fields') {
+      #return $this->out2(var_export(($this->fields()),true));
+      #return $this->out2(serialize(($this->fields())));
       return $this->out2(array_values($this->object2array($this->fields())));
 
     } elseif ($action == 'table.sql' or $action == 'sql') { return $this->out2($this->sql(),'sql');
@@ -1060,13 +1063,7 @@ Class Table extends nb {
       $this->rows(); return true;
 
     } elseif ($action == 'table') {
-      return $this->out2(array(
-        #"count" => $this->count(),
-        #"sql_name" => $this->sql_name(),
-        "name" => $this->name,
-        "sql" => $this->sql(),
-        #"fields" => $this->object2array($this->fields()),
-      ));
+      return $this->out2($this->infos());
 
     } elseif ($action == 'table.delete' or $action == 'delete') {
       if (!$this->delete($this->p(),$e)) bye($e);
@@ -1141,18 +1138,20 @@ Class Table extends nb {
   public function count() {
     
     if (isset($this->count)) return $this->count;
-      $sql_count = $this->name;
-      if (preg_match('/^[\w_-]+$/',$sql_count)) {
-        $sql_count = "SELECT count(*) FROM ".$this->sql_name($sql_count);
 
-      } else {
-        $sql_count = preg_replace('/ (ORDER|LIMIT) .*?$/s','',$sql_count);
-        $sql_count = preg_replace('/^SELECT .*FROM/s','SELECT count(*) FROM ',$sql_count);
+    $sql_count = $this->name;
+    if (preg_match('/^[\w_-]+$/',$sql_count)) {
+      $sql_count = "SELECT count(*) FROM ".$this->sql_name($sql_count);
 
-      }
+    } else {
+      $sql_count = preg_replace('/ (ORDER|LIMIT) .*?$/s','',$sql_count);
+      $sql_count = preg_replace('/^SELECT .*FROM/s','SELECT count(*) FROM ',$sql_count);
+
+    }
+
+    $this->count = (int)$this->db->row($sql_count);
+    return $this->count;
 
-      $this->count = (int)$this->db->row($sql_count);
-      return $this->count;
   }
 
   public static function err_sql($sql) {
@@ -1203,7 +1202,7 @@ Class Table extends nb {
 
     // Tables
     $r .= '<span class="label">';
-    $r .= '<label for="table">Tables</label>'.html_select_array($this->db->tables(),array(
+    $r .= '<label for="table">Tables</label>'.html_select_array(array_keys($this->db->tables()),array(
       'html'       => 'class="tables" name="table" id="table"',
       'selected'   => $this->p('table'),
       'prettyText' => true,
@@ -1257,50 +1256,44 @@ Class Table extends nb {
     return $r;
   }
 
-  public function unserialize() {
-    $o = unserialize($this->serialize());
-    if (empty($o->db)) {
-      global $Db; $o->db = $Db;
-    }
-    #var_export($o->db);
-    return($o->sql_name());
-    debug($o->sql_name());
-    return var_export($o,true);
+  public function __wakeup() {
+    global $Db;
+    if (empty($this->db) and !empty($Db)) $this->db = $Db;
   }
 
   public function __sleep() {
-    if (1) return array(
+#bye(get_class_vars(__CLASS__));
+    return array(
       'name',
       'sql',
       'type',
       'fields',
-      'fields_keys',
-      'replace',
+# NB 28.03.16       'fields_keys',
+# NB 28.03.16       'replace',
       'extras',
-      'params',
+      #'params',
       'order_by',
+      'count',
+      'engine',
+      'created',
     );
-
-    $vars = array();
-    #foreach (get_class_vars(get_class($this)) as $k=>$v) { if ($k=!'db') $vars[]=$k; };
-    foreach (get_class_vars(get_class($this)) as $k=>$v) { if ($k=!'db') $vars[]=$k; };
-    #foreach (get_class_vars(__CLASS__) as $k=>$v) { if ($k=!'db') $vars[]=$k; };
-    debug($vars);
-    #$vars = get_object_vars($this);
-    return $vars;
   }
 
   public function serialize() {
-    #$o = new self(null,$this);
-    $clone = clone($this);
-    #foreach (get_object_vars($clone) as $k=>$v) { if (is_object($v)) unset($clone->$k); };
-    #var_export($clone->db);
-    #unset($clone->db);
-    #$clone->db = array();
-    #foreach (get_object_vars($this->db) as $k=>$v) { if (!is_object($v)) $clone->db[$k] = $v; };
-    #debug($clone->db);
-    #foreach (get_object_vars($this) as $k=>$v) { unset($this->$k); };
-    return serialize($clone);
+    $this->fields();
+    #$this->count();
+    return serialize($this);
+  }
+
+  public function unserialize() {
+    $o = unserialize($this->serialize());
+    #return $this->out2($this->fields('id'));
+    #return serialize($this->fields());
+    #$this = $o;
+    #return($o->sql_name());
+    #var_export($o->db);
+    #debug($o->sql_name());
+    return var_export($o,true);
   }
 
 } # < Class
diff --git a/lib/php/db/types.php b/lib/php/db/types.php
new file mode 100644 (file)
index 0000000..e31873e
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+$DB_TYPES = array(
+
+  'config' => array(
+    # hostname:port:database:username:password
+    'sqlite' => array(getenv('HOME').'/'.'.db.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']);
+?>
index fa36bb24c5eda8c966b64358b327c311b371357d..d102ec1232ae72d8cc773e2d1f6cd89e7f761cb3 100644 (file)
@@ -8,14 +8,14 @@ require_once(dirname(__FILE__).'/functions.php');
 #print_r(self::p());
 class nb {
 
-  public static $root_dir = NB_ROOT;
+  const ROOT_DIR = NB_ROOT;
 
   # Sql: elect type,ext from mime_type where ext in ('json','csv','txt','yaml','xml','html','doc','xls');
-  public static $content_types_aliases = array(
+  protected static $content_types_aliases = array(
     'text' => 'txt',
   );
 
-  public static $content_types = array(
+  protected static $content_types = array(
     'json' => 'text/json',
     'doc'  => 'application/msword',
     'xls'  => 'application/vnd.ms-excel',
@@ -26,19 +26,16 @@ class nb {
     'yaml' => 'text/yaml',
   );
 
-  public static function zaza() {
-    return (is_object($this) ? 'TRUE' : 'FALSE');
-  }
+  #public static function zaza() { return (is_object($this) ? 'TRUE' : 'FALSE'); }
+
+  public function __sleep() { return array_keys((array)$this); }
+  #public function __wakeup() { }
 
-  function __destruct() {
+  public function __destruct() {
     #foreach (get_object_vars($this) as $k=>$v) { echo ("$k: $v\n"); }
     #if (is_object($this))
-    foreach (get_object_vars($this) as $k=>$v) { unset($this->$k); };
-    #foreach (get_class_vars($this) as $k=>$v) { unset($this->$k); };
-# NB 27.03.16     try {
-# NB 27.03.16       foreach (get_object_vars($this) as $k=>$v) { unset($this->$k); };
-# NB 27.03.16     } catch(Exception $e) {
-# NB 27.03.16     }
+    #foreach (get_object_vars($this) as $k=>$v) { unset($this->$k); };
+    foreach (array_keys((array)$this) as $k) { unset($this->$k); };
   }
 
   /*
index d6ee7e1d67f474259e770904082d7d1eb46d7cdb..33254800841c9a7d0690bc4ee1f7705678302f6e 100644 (file)
@@ -15,6 +15,7 @@ Class Out extends Nb {
     self::$types = array(
       'sql' => array(
       ),
+
       'div' => array(
         'is_html' => true,
         'enclose' => array("<div class=\"rows\">".NB_EOL,"</div>".NB_EOL),
@@ -24,14 +25,16 @@ Class Out extends Nb {
         'function' => 'out_tag',
         'head' => 'out_tag_head',
       ),
+
       'center' => array(
         'is_html' => true,
         'enclose' => array("<center class=\"rows\">".NB_EOL,"</center>".NB_EOL),
         'tag_enclose' => 'div class="row"',
-        'tag' => 'tag',
+        'tag' => 'div',
         'function' => 'out_tag',
         'head' => 'out_tag_head',
       ),
+
       'table' => array(
         'is_html' => true,
         'enclose' => array("<table class=\"rows\">".NB_EOL,"</table>".NB_EOL),
@@ -41,10 +44,17 @@ Class Out extends Nb {
         'function' => 'out_tag',
         'head' => 'out_tag_head',
       ),
+
       'xml' => array(
         'enclose' => array('<?xml version="1.0" encoding="utf-8"?'.'>'.NB_EOL."<rows>".NB_EOL,"</rows>".NB_EOL),
         'function' => 'out_xml',
       ),
+
+      'text' => array(
+        'eol' => "\n",
+        #'function' => 'print',
+      ),
+
       'csv' => array(
         'enclose' => array("","\n"),
         'eol' => "\n",
@@ -72,6 +82,7 @@ Class Out extends Nb {
   }
 
   public static function scalar($v) {
+    if ($v === null) return '';
     if (is_scalar($v)) return $v;
     #if (is_array($v) and !self::is_hash($v)) return join(', ',$v);
     #return var_export($v,true);
@@ -80,13 +91,13 @@ Class Out extends Nb {
       '/^\s*(array \(|\),?)$/m', # sub array
       '/ *\'(.*?)\' =>\s*$\r?\n/m', # sub hash
       '/\s*\d+ => \'(.*?)\'(,)?\r?\n/m', # aray
-      '/$(\r?\n)+$/m', # blank lines
       '/,\s*$/m', # last ,
+      '/$(\r?\n)+$/m', # blank lines
     ),array(
       '$1=$2',
       '',
       '$1=',
-      '$1$2 ',
+      '$1 ', #'$1$2 ',
       '',
       '',
     ),var_export($v,true)));
@@ -94,7 +105,19 @@ Class Out extends Nb {
     return is_scalar($v) ? $v : json_encode($v);
   }
 
-  public static function head($o,$head,$data=array()) {
+  public static function head(&$o,$head,$data=array()) {
+
+    # For sprintf
+    unset($o['head_max_len']);
+    if (!empty($data)) {
+      if (self::is_hash($data[0])) {
+        $o['head_max_len'] = max(self::ar_map('strlen($a)',array_keys($data[0])));
+      } elseif (is_array($data[0])) {
+        $o['head_max_len'] = max(self::ar_map('strlen($a)',$data[0]));
+      }
+      #bye($o);
+    }
+
     #if (self::p('header')==="0") return;
     if (isset($o['enclose'])) echo $o['enclose'][0];
     if (!isset($o['head'])) return;
@@ -116,6 +139,7 @@ Class Out extends Nb {
 
   public static function row($o,&$row) {
 
+    # Defined function
     if (isset($o['function'])) {
       if (preg_match('/^out_/',$o['function'])) {
         $o['function']($row,$o);
@@ -124,8 +148,20 @@ Class Out extends Nb {
       }
       return true;
     }
-    out_tag($row,$o);
-    return false;
+
+    # Assume html/xml tag like
+    if (isset($o['tag'])) {
+      return out_tag($row,$o);
+    }
+
+    # yaml
+    if (!self::is_hash($row)) return out_yaml($row,$o);
+
+    # text
+    foreach ($row as $k => $v) { echo sprintf("%-".(!empty($o['head_max_len']) ? $o['head_max_len']+1 : 10)."s: %s\n",$k,out::escape($v)); }
+    #foreach ($row as $k => $v) { echo "$k: ".out::escape($v)."\n"; }
+
+    return true;
   }
 
   public static function concat($o) {
@@ -145,6 +181,7 @@ Class Out extends Nb {
                return $contents;
     return ob_get_flush();
   }
+
   public static function rows($type,&$data,$head=array()) {
 
     # Ex: for action=tables when header=0
@@ -212,6 +249,7 @@ Class Out extends Nb {
 
     $is_scalar = is_scalar($v);
     $v = out::scalar($v);
+    if ($v==='') $is_scalar = true;
 
     if ($replace_flags === null) {