src/Palete/RooDatabase.vala
authorAlan Knowles <alan@roojs.com>
Mon, 20 Apr 2015 10:03:35 +0000 (18:03 +0800)
committerAlan Knowles <alan@roojs.com>
Mon, 20 Apr 2015 10:03:35 +0000 (18:03 +0800)
src/Palete/RooDatabase.vala [new file with mode: 0644]

diff --git a/src/Palete/RooDatabase.vala b/src/Palete/RooDatabase.vala
new file mode 100644 (file)
index 0000000..9be82b0
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Renderer for Roo Database code
+ * 
+ * - Concept - this code does the SQL queries
+ *   pulls data from information_schema (on mysql only at present..)
+ *   Sends it down the line to the Javascript code. to generate structures 
+ * 
+ */
+ // should this be in palete...
+namespace Palete {
+
+  
+   class RooDatabase : Object 
+    {
+        //public Project.Project project;
+
+               public string DBTYPE;
+               public string DBNAME;
+                
+        public Gda.Connection cnc;
+        
+               public RooDatabase.from_project (Project.Project project)
+        {
+            this.project = project;
+                       this.DBTYPE = this.project.get_string_member("DBTYPE");
+                       this.DBNAME = this.project.get_string_member("DBNAME");
+                       try {
+                               
+                                       this.cnc = Gda.Connection.open_from_string (
+                                       this.DBTYPE,
+                                       "DB_NAME=" + this.DBNAME, 
+                                       "USERNAME=" + this.project.get_string_member("DBUSERNAME") + 
+                                       ";PASSWORD=" + this.project.get_string_member("DBPASSWORD"),
+                                       Gda.ConnectionOptions.NONE
+                               );
+                       } catch(Error) {
+                               this.cnc  = null;
+                               this.DBTYPE = "";
+                       }
+            
+        }
+       
+        public RooDatabase.from_cfg (string dbtype, string dbname, string dbuser, string dbpass)
+         {
+             this.DBTYPE = dbtype;
+                       this.DBNAME = dbname;
+               
+             this.cnc = Gda.Connection.open_from_string (
+                               this.DBTYPE,
+                               "DB_NAME=" + dbname, 
+                               "USERNAME=" + dbuser + 
+                               ";PASSWORD=" + dbpass,
+                               Gda.ConnectionOptions.NONE
+                       );
+
+
+           
+       }
+          
+        
+        public Json.Array readTables()
+        {
+                       
+                       if (this.DBTYPE == "PostgreSQL") {
+                               
+                               return this.fetchAll(this.cnc.execute_select_command( 
+                                       """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) 
+                                       """));
+                               
+                       }
+                       if (this.DBTYPE == "MySQL") { 
+                               return this.fetchAll(this.cnc.execute_select_command( "SHOW TABLES" ));
+                       }
+                       return new Json.Array();
+                       
+               }
+               public Gee.ArrayList readTablesGee()
+               {
+                       var ret = new Gee.ListArray<string>();
+                       var ar = this.readTables();
+                       for(var i = 0; ar.get_length(); i++) {
+                               ret.add(ar.get_string_element(i);
+                       }
+                       return ret;
+                       
+               }
+               
+               public Json.Object readTable(string tablename) 
+               {
+                       
+                       Json.Array res_ar;
+                       var res = new Json.Object();
+                       
+                       switch (this.DBTYPE ) {
+                               case "PostgreSQL":
+                               
+                                       res_ar =   this.fetchAll(this.cnc.execute_select_command( 
+                                       """
+                                       
+                                        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 = 'public' 
+                                               AND c.relname = '""" + tablename + """' AND f.attnum > 0 ORDER BY number;
+                                                       
+                                       """));
+                                       break;
+                                       
+                               case  "MySQL":
+                                       res_ar = this.fetchAll(this.cnc.execute_select_command( "DESCRIBE " + tablename ));
+                                       break;
+                               
+                               default: 
+                                       return res;
+                                       break;
+                       }
+                       
+                       for (var i =0; i < res_ar.get_length(); i++) {
+                               var el = res_ar.get_object_element(i);
+                               res.set_object_member( el.get_string_member("Field"), el);
+                       }
+                       return res;
+                       
+                       
+               }
+               
+        
+                       
+               
+               
+               public Json.Object readForeignKeys(string table)
+        { 
+                       
+                       
+                       var ret =   this.readTable(table);
+                       // technically we should use FK stuff in mysql, but for the momemnt use my hacky FK()
+                       if (this.DBTYPE != "MySQL") { 
+                               return  ret;
+                       }
+                       
+                       var query = """
+                               SELECT 
+                               TABLE_COMMENT 
+                               FROM
+                               information_schema.TABLES
+                               WHERE
+                               TABLE_NAME = '""" + table + """'
+                               AND
+                               TABLE_SCHEMA = '""" + this.DBNAME + """'
+                       """;
+                       
+                       var jarr = this.fetchAll(this.cnc.execute_select_command( 
+                                       query
+                                       ));
+                       if (jarr.get_length() < 1) {
+                               return  ret;
+                       }
+                       
+                       var contents = jarr.get_string_element(0);
+                       
+                        GLib.Regex exp = /FK\(([^\)]+)\)/;
+                        string str = "";
+                        try {
+                               GLib.MatchInfo mi;
+                               if ( exp.match (contents, 0, out mi) ) {
+                                       
+                                       str = mi.fetch(1);
+                                       print("match = %s", str);
+                               }
+                       } catch (GLib.Error e) {
+                               return  ret;
+                       }
+                       var ar = str.split("\n");
+                       for (var i = 0; i < ar.length; i++) {
+                               var kv = ar[i].split("=");
+                               if (!ret.has_member(kv[0].strip())) { 
+                                       continue;
+                               }
+                               var o = ret.get_object_member(kv[0].strip());
+                               
+                               //o.set_string_member("key", kv[0].strip());
+                               var lr = kv[1].split(":");
+                               o.set_string_member("relates_to_table", lr[0].strip());
+                               o.set_string_member("relates_to_col", lr[1].strip());
+                               o.set_object_member("relates_to_schema", this.readTable(lr[0].strip()));
+                               //ret.set_object_member(kv[0].strip(),o);
+                               
+                               
+                       }
+                       return ret;
+                                
+               }
+        public Json.Array fetchAll(Gda.DataModel qnr)
+               {
+                       var cols = new Gee.ArrayList<string>();
+                       
+                       for (var i =0;i < qnr.get_n_columns(); i++) {
+                               cols.add(qnr.get_column_name(i));
+                       }
+                       //print(Json.stringify(cols, null,4));
+                       var iter = qnr.create_iter();
+                       var res = new Json.Array();
+                        //print("ROWS %d\n", qnr.get_n_rows());
+                       
+                       for (var r = 0; r < qnr.get_n_rows(); r++) {
+                               
+                               // single clo..
+                               //print("GOT ROW");
+                               //print("COLS  %d\n", cols.size);
+                               if (cols.size == 1) {
+                                       var str = qnr.get_value_at(0,r).get_string();
+                                       //print("GOT %s\n",str);
+                                       res.add_string_element(qnr.get_value_at(0,r).get_string());
+                                       continue;
+                               }
+                               
+                               var add = new Json.Object();
+                               
+                               for (var i = 0; i < cols.size; i++) { 
+                                       var n = cols.get(i);
+                                       var val = qnr.get_value_at(i,r);
+                                       var type = val.type().name();
+                                       //print("%s\n",type);
+                                       switch(type) {
+                                               case "GdaBinary":
+                                               case "GdaBlob":
+                                                       add.set_string_member(n, "?? big string ??");
+                                                       break;
+                                                       
+                                               case  "GdaNull":
+                                                       add.set_null_member(n);
+                                                       break;
+                                               
+                                               default:
+                                                       add.set_string_member(n, val.get_string());
+                                                       break;
+                                       }
+                                       
+                               }
+                               
+                               res.add_object_element(add);
+                               
+                       }
+                       return res;
+
+               }
+               
+               
+               
+       }
+       
+       
+}
+// valac --pkg libgda-5.0 --pkg gee-1.0 --pkg json-glib-1.0  --pkg libxml-2.0   RooDatabase.vala  -o /tmp/rdtest
+/*
+ void main() {
+     var x = new JsRender.RooDatabase.from_cfg("MySQL", "hydra", "root", "");
+    // var res = x.readTables();
+    //var res= x.readTable("Person");
+    var res= x.readForeignKeys("Person");
+    
+       var  generator = new Json.Generator ();
+    var  root = new Json.Node(Json.NodeType.OBJECT);
+    root.init_object(res);
+    generator.set_root (root);
+    
+           generator.pretty = true;
+           generator.indent = 4;
+    
+
+    print("%s\n", generator.to_data (null));
+ }
+*/