Revert "File.js"
[app.Builder.js] / dbgenerate.js
index f209855..0ea16fd 100644 (file)
  * 
  * write readers..
  * 
- * usage: seed generate.js  
+ * usage: seed generate.js
+ *
+ *
+ *
+ *
+ *Hack needed to latest GLib-2.0.gir 
+ *
+ * <record name="KeyFile" c:type="GKeyFile" disguised="1">
+       <constructor name="new" c:identifier="g_key_file_new">
+        <return-value transfer-ownership="full">
+          <type name="KeyFile" c:type="GKeyFile*"/>
+        </return-value>
+      </constructor>
+ *
+ *
+ * remove introspectable =0 from g_key_file_get_groups
+ *   and add transfer-owneership = none to return value
+ * remove introspectable =0 from g_key_file_get_keys
+ *   and add transfer-owneership = none to return value* 
  * 
  */
 Gda  = imports.gi.Gda;
@@ -25,7 +43,7 @@ console = imports.console;
 File = imports.File.File;
 Options = imports.Options.Options;
 
-Gda.init();
+//Gda.init();
 
 var prov = Gda.Config.list_providers ();
 //print(prov.dump_as_string());
@@ -34,10 +52,12 @@ var o = new Options({
     help_description : 'Element builder for App Builder based on database schema',
     
     options:  [
+        { arg_long : 'DBTYPE' , arg_short : 't', description : 'Database Type (eg. MySQL or PostgreSQL ' },
         { arg_long : 'DBNAME' , arg_short : 'd', description : 'Database Name' },
         { arg_long : 'USERNAME' , arg_short : 'u', description : 'Username'},
-        { arg_long : 'PASSWORD' , arg_short : 'p', description : '' , arg_default :'' },
-        { arg_long : 'INI' , arg_short : 'I', description : 'Either base directory which has Pman/***/DataObjects/***.ini or location of ini file.' },
+        { arg_long : 'PASSWORD' , arg_short : 'p', description : 'Password' , arg_default :'' },
+        { arg_long : 'INI' , arg_short : 'I', description :
+                    'Either base directory which has Pman/***/DataObjects/***.links.ini or location of ini file.' },
     ]
            
 })
@@ -47,9 +67,10 @@ var o = new Options({
 var cfg = o.parse(Seed.argv);
 print(JSON.stringify(cfg, null,4));
 
-var   cnc = Gda.Connection.open_from_string ("MySQL", "DB_NAME=" + cfg.DBNAME, 
-                                              "USERNAME=" + cfg.USERNAME + ';PASSWORD=' + cfg.PASSWORD,
-                                              Gda.ConnectionOptions.NONE, null);
+var   cnc = Gda.Connection.open_from_string (cfg.DBTYPE,
+         "DB_NAME=" + cfg.DBNAME, 
+        "USERNAME=" + cfg.USERNAME + ';PASSWORD=' + cfg.PASSWORD,
+        Gda.ConnectionOptions.NONE, null);
 
 
 
@@ -96,14 +117,22 @@ Gda.DataSelect.prototype.fetchAll = function()
 
 var map = {
     'date' : 'date',
-    'datetime' : 'string',
+    'datetime' : 'date',
+    'timestamp with time zone' : 'date',
+    'timestamp without time zone' : 'date',
+    'time' : 'string', //bogus
     'int' : 'int',
+    'integer' : 'int',
     'bigint' : 'int',
-    
+    'double' : 'float',
     'tinyint' : 'int',
+    'smallint' : 'int',
     'decimal' : 'float',
     'float' : 'float',
+    'numeric' : 'float',
     'char' : 'string',
+    'character' : 'string',
+    'character varying' : 'string',
     'varchar' : 'string',
     'text' : 'string',
     'longtext' : 'string',
@@ -111,7 +140,10 @@ var map = {
     'mediumtext' : 'string',
     'enum' : 'string',
     'timestamp' : 'number',
-    'blob' : 'text'
+    'blob' : 'text',
+    'bytea' : 'text',
+    'boolean' : 'int',
+    'text[]' : 'string',
     
 }
 
@@ -127,15 +159,22 @@ function readIni(fn)
    
     var groups = key_file.get_groups();
     groups.forEach(function(g) {
+        //print("KEY:"+g);
         ini[g] = {}
-           
+        
         var keys = key_file.get_keys(g);
+        if (!keys) { return; }
+        
         keys.forEach(function(k) {
-            ini[g][k] = key_file.get_value(g,k);
-        })
-    })
-    
+                print("GET val: " + k);
+                ini[g][k] = key_file.get_value(g,k);
+                print(ini[g][k] );
+        });
+        //print("DONE KEY:"+g);
+    });
+    //print("DONE KEYS");
 }
 if (File.isFile(cfg.INI)) {
     if (cfg.INI.match(/links\.ini$/)) {
         readIni(cfg.INI);
@@ -144,6 +183,7 @@ if (File.isFile(cfg.INI)) {
     }
 }
 
+
 if (File.isDirectory(cfg.INI)) {
         
 
@@ -194,21 +234,80 @@ if (File.isDirectory(cfg.INI)) {
 }
 //print(JSON.stringify(ini, null,4));
  //console.dump(ini);
-
+print("DONE INI");
 
  //Seed.quit();
 
 //GLib.key_file_load_from_file (key_file, String file, KeyFileFlags flags) : Boolean
 
 
+switch(cfg.DBTYPE) {
+    case "MySQL":
+        query_tables = "SHOW TABLES";
+        query_describe_table = "DESCRIBE `%s`";
+        break;
+    
+    case 'PostgreSQL':
+        query_tables = "select c.relname FROM pg_catalog.pg_class c " + 
+            "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace " + 
+            "WHERE c.relkind IN ('r','') AND n.nspname NOT IN ('pg_catalog', 'pg_toast')" +
+            "AND pg_catalog.pg_table_is_visible(c.oid) ";
+         query_describe_table =  
+                "SELECT " +
+                "f.attnum AS number, " +
+                "f.attname AS Field, " +
+                "f.attnum, " +
+                "CASE WHEN f.attnotnull = 't' THEN 'NO' ELSE 'YES' END AS isNull, " + 
+                "pg_catalog.format_type(f.atttypid,f.atttypmod) AS Type, " +
+                "CASE WHEN p.contype = 'p' THEN 't' ELSE 'f' END AS primarykey, " +
+                "CASE WHEN p.contype = 'u' THEN 't' ELSE 'f' END AS uniquekey, " +
+                "CASE WHEN p.contype = 'f' THEN g.relname END AS foreignkey, " +
+                "CASE WHEN p.contype = 'f' THEN p.confkey END AS foreignkey_fieldnum, " +
+                "CASE WHEN p.contype = 'f' THEN g.relname END AS foreignkey, " +
+                "CASE WHEN p.contype = 'f' THEN p.conkey END AS foreignkey_connnum, " +
+                "CASE WHEN f.atthasdef = 't' THEN d.adsrc END AS default " +
+                "FROM pg_attribute f JOIN pg_class c ON c.oid = f.attrelid " +
+                "        JOIN pg_type t ON t.oid = f.atttypid " +
+                "        LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum " +
+                "        LEFT JOIN pg_namespace n ON n.oid = c.relnamespace " +
+                "        LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY ( p.conkey ) " +
+                "        LEFT JOIN pg_class AS g ON p.confrelid = g.oid " +
+                "WHERE c.relkind = 'r'::char AND n.nspname = '%n' " +
+                "AND c.relname = '%s' AND f.attnum > 0 ORDER BY number";
+                
+                
+                
+        break;
+    default:
+        throw {
+             name: "ArgumentError", 
+             message: "Invalid data base type " + cfg.DBTYPE + " should be MySQL or PostgreSQL"
+         };
+            
+/*
+           "Field": "province",
+        "Type": "varchar(255)",
+        "Null": "NO", << or is null
+        "Key": null,
+        "Default": null,
+        "Extra": 
+*/  
+}
+
 
  
 
-var tables = Gda.execute_select_command(cnc, "SHOW TABLES").fetchAll();
+var tables = cnc.execute_select_command( query_tables).fetchAll();
+print(JSON.stringify(tables));
+
 var readers = [];
 tables.forEach(function(table) {
     //print(table);
-    var schema = Gda.execute_select_command(cnc, "DESCRIBE `" + table+'`').fetchAll();
+    var schema = cnc.execute_select_command(
+            query_describe_table.replace(/%s/, table).replace(/%n/,'public')
+            ).fetchAll();
+    
+    
     var reader = []; 
     var colmodel = []; 
     var combofields= [ { name : 'id', type: 'int' } ]; // technically the primary key..
@@ -217,9 +316,12 @@ tables.forEach(function(table) {
        
     var firstTxtCol = '';
     
-    //print(JSON.stringify(schema, null,4));
+    //print(JSON.stringify(schema, null,4));    Seed.quit();
     
     schema.forEach(function(e)  {
+        e.Type = e.Type || e.type;
+        e.Field = e.Field || e.field;
+         
         var type = e.Type.match(/([^(]+)\(([^\)]+)\)/);
         var row  = { }; 
         if (type) {
@@ -270,6 +372,8 @@ tables.forEach(function(table) {
             "*prop": "colModel[]"
         });
         var xtype = 'TextField';
+        
+        
         if (row.type == 'number') {
             xtype = 'NumberField';
         }
@@ -293,6 +397,11 @@ tables.forEach(function(table) {
             '|xns' : 'Roo.form',
             xtype : xtype
         }
+         if (xtype == 'DateField') {
+            form[row.name].format = 'Y-m-d';
+            form[row.name].width = 100;
+        }
+        
         if (xtype == 'TextArea') {
             form[row.name].height = 100;
         }
@@ -306,8 +415,8 @@ tables.forEach(function(table) {
     var combo = {
         '|xns' : 'Roo.form',
         xtype: 'ComboBox',
-        allowBlank : 'false',
-        editable : 'false',
+        allowBlank : false,
+        editable : false,
         emptyText : 'Select ' + table,
         forceSelection : true,
         listWidth : 400,
@@ -458,6 +567,7 @@ readers.forEach(function(reader) {
 
     var dir = GLib.get_home_dir() + '/.Builder/Roo.data.JsonReader'; 
     if (!File.isDirectory(dir)) {
+        print("mkdir " + dir);
         File.mkdir(dir);
     }
     
@@ -472,8 +582,7 @@ readers.forEach(function(reader) {
         root : "data",
         '*prop' : "reader",
         id : 'id', // maybe no..
-        remoteSort : true,
-        '|sortInfo' : "{ field : '" + reader.firstTxtCol  +  "', direction: 'ASC' }", 
+       
         '|fields' :  JSON.stringify(reader.reader, null,4).replace(/"/g,"'")
     };
     
@@ -486,6 +595,7 @@ readers.forEach(function(reader) {
     // GRIDS
     dir = GLib.get_home_dir() + '/.Builder/Roo.GridPanel'; 
     if (!File.isDirectory(dir)) {
+        print("mkdir " + dir);
         File.mkdir(dir);
     }
     
@@ -504,6 +614,7 @@ readers.forEach(function(reader) {
             "fitContainer": true,
             "tableName": reader.table,
             "background": true,
+            "region" : 'center',
             "listeners": {
                 "|activate": "function() {\n    _this.panel = this;\n    if (_this.grid) {\n        _this.grid.footer.onClick('first');\n    }\n}"
             },
@@ -521,7 +632,14 @@ readers.forEach(function(reader) {
                             "    if (_this.panel.active) {\n" +
                             "       this.footer.onClick('first');\n" +
                             "    }\n" +
-                            "}"
+                            "}",
+                        "|rowdblclick": "function (_self, rowIndex, e)\n" + 
+                            "{\n" + 
+                            "    if (!_this.dialog) return;\n" + 
+                            "    _this.dialog.show( this.getDataSource().getAt(rowIndex).data, function() {\n" + 
+                            "        _this.grid.footer.onClick('first');\n" + 
+                            "    }); \n" + 
+                            "}\n"
                     },
                     "|xns": "Roo.grid",
 
@@ -529,7 +647,8 @@ readers.forEach(function(reader) {
                         {
                             "*prop": "dataSource",
                             "xtype": "Store",
-                            
+                             remoteSort : true,
+                            '|sortInfo' : "{ field : '" + reader.firstTxtCol  +  "', direction: 'ASC' }", 
                             "|xns": "Roo.data",
                             "items": [
                                 
@@ -624,6 +743,7 @@ readers.forEach(function(reader) {
     
     dir = GLib.get_home_dir() + '/.Builder/Roo.form.Form'; 
     if (!File.isDirectory(dir)) {
+        print("mkdir " + dir);
         File.mkdir(dir);
     }
     var formElements = [];
@@ -633,9 +753,13 @@ readers.forEach(function(reader) {
             continue;
         }
         formHeight += reader.form[k].xtype == 'TextArea' ? 100 : 30;
+        
         formElements.push(reader.form[k]);
     }
-    formElements.push(reader.form['id']);
+    if (reader.form['id']) {
+        formElements.push(reader.form['id']);
+    }
+    
 
     print("WRITE: " +  dir + '/' + cfg.DBNAME + '_' + reader.table + '.json');
     var frmCfg = 
@@ -694,6 +818,7 @@ readers.forEach(function(reader) {
     
     dir = GLib.get_home_dir() + '/.Builder/Roo.form.ComboBox'; 
     if (!File.isDirectory(dir)) {
+        print("mkdir " + dir);
         File.mkdir(dir);
     }
    
@@ -716,6 +841,7 @@ readers.forEach(function(reader) {
    
     dir = GLib.get_home_dir() + '/.Builder/Roo.LayoutDialog'; 
     if (!File.isDirectory(dir)) {
+        print("mkdir " + dir);
         File.mkdir(dir);
     }
     var formElements = [];
@@ -741,6 +867,7 @@ readers.forEach(function(reader) {
             "resizable": false,
             "title": "Edit / Create " + reader.table,
             "width": 400,
+            "modal" : true,
             "xtype": "LayoutDialog",
             "|xns": "Roo",
             "items": [