From a83ab9e57e60cfec0997939f5b30dc894fa4ca7f Mon Sep 17 00:00:00 2001
From: "H. William Welliver III" <bill@welliver.org>
Date: Thu, 31 Jul 2008 23:02:36 -0400
Subject: [PATCH] 1. query() doesn't cause a segfault when no rows are returned
 2. query() returns an array of mappings like other database modules 3. added
 list_tables() and list_fields() with behavior similar to other database
 modules

Rev: lib/modules/Sql.pmod/sqlite.pike:1.2
Rev: src/post_modules/SQLite/sqlite.cmod:1.23
---
 lib/modules/Sql.pmod/sqlite.pike    | 88 +++++++++++++++++++++++++++++
 src/post_modules/SQLite/sqlite.cmod | 32 +++++++++--
 2 files changed, 115 insertions(+), 5 deletions(-)

diff --git a/lib/modules/Sql.pmod/sqlite.pike b/lib/modules/Sql.pmod/sqlite.pike
index a9c81bc49e..9597d5e3e8 100644
--- a/lib/modules/Sql.pmod/sqlite.pike
+++ b/lib/modules/Sql.pmod/sqlite.pike
@@ -9,6 +9,94 @@ void create(string a, void|string b, void|mixed c, void|mixed d) {
   ::create(a);
 }
 
+array list_fields(string n, string|void wild)
+{
+  string qry = "";
+
+  qry = "PRAGMA table_info(" + n + ")";
+
+  array r = query(qry);
+
+  // now, we weed out the ones that don't match wild, if provided
+  if(wild)
+  {
+    r = filter(r, lambda(mapping row) 
+              { return (search(row->name, wild) !=-1); }
+          );
+  }
+
+  array fields = ({});
+
+  foreach(r;; mapping f)
+  {
+    mapping fld = ([]);
+
+    fld->name = f->name;
+    fld->table = n;
+  
+    string t, l;   
+ 
+    if(!sscanf(f->type, "%s(%s)", t, l))
+      t = f->type;
+
+    fld->length = (int)l;
+
+    switch(t)
+    {
+      case "char":
+       t = "string";
+       break;
+
+      case "int":
+       t = "integer";
+       break;
+    }
+
+    fld->type = t;
+
+    fld->flags = (<>);
+
+    if((int)f->notnull)
+      fld->flags->not_null = 1;
+
+    if((int)f->pk)
+    {
+      // primary key implies not null.
+      fld->flags->not_null = 1;
+      fld->flags->primary_key = 1;
+    }
+
+    fld->default = f->dflt_value;
+
+    fields += ({fld});
+  }
+
+  return fields;
+}
+
+array list_tables(string|void n)
+{
+  string qry = "";
+
+  if(n)
+    qry = "SELECT name FROM SQLITE_MASTER WHERE name like '" + n + "%' and TYPE='table'";  
+  else
+    qry = "SELECT name FROM SQLITE_MASTER where TYPE='table'";  
+
+  array r = query(qry);
+  array out = ({});
+
+  foreach(r;;mapping row)
+  {
+    if(row->name)
+      out += ({row->name});
+    else
+      out += ({row["sqlite_master.name"] });
+  }
+  return out;
+}
+
 #else
 constant this_program_does_not_exist=1;
 #endif
+
diff --git a/src/post_modules/SQLite/sqlite.cmod b/src/post_modules/SQLite/sqlite.cmod
index 68dda3f501..fcdb455eb8 100644
--- a/src/post_modules/SQLite/sqlite.cmod
+++ b/src/post_modules/SQLite/sqlite.cmod
@@ -1,6 +1,6 @@
 /* sqlite.cmod -*- c -*-
  *
- * $Id: sqlite.cmod,v 1.22 2008/06/29 11:10:55 nilsson Exp $
+ * $Id: sqlite.cmod,v 1.23 2008/08/01 03:02:36 bill Exp $
  */
 
 #include "global.h"
@@ -162,12 +162,32 @@ PIKECLASS ResObj
   }
 
   PIKEFUN array(mapping(string:mixed)) fetch_fields() {
-    int i;
+    int i,t;
     for(i=0; i<THIS->columns; i++) {
       push_constant_text("name");
       push_text(sqlite3_column_name(THIS->stmt, i));
       f_utf8_to_string(1);
-      f_aggregate_mapping(2);
+      push_constant_text("type");
+	  t = sqlite3_column_type(THIS->stmt, i);
+	  switch(t)
+	  {
+		case SQLITE_INTEGER:
+		  push_text("integer");
+		  break;
+		case SQLITE_FLOAT:
+		  push_text("float");
+		  break;
+		case SQLITE_BLOB:
+		  push_text("blob");
+		  break;
+		case SQLITE_NULL:
+		  push_text("null");
+		  break;
+		case SQLITE_TEXT:
+		  push_text("text");
+		  break;
+	  }
+      f_aggregate_mapping(4);
     }
     f_aggregate(THIS->columns);
   }
@@ -304,13 +324,15 @@ PIKECLASS ResObj
 	  if (columns == 0)
 	    columns = sqlite3_column_count(stmt);
 	  for(i=0; i<columns; i++) {
+		push_text(sqlite3_column_name(stmt, i));
+		f_utf8_to_string(1);
 	    push_string( make_shared_binary_string
 			 ( sqlite3_column_blob(stmt, i),
 			   sqlite3_column_bytes(stmt, i) ) );
 	    if( sqlite3_column_type(stmt, i)==SQLITE_TEXT )
 	      f_utf8_to_string(1);
 	  }
-	  f_aggregate(columns);
+	  f_aggregate_mapping(columns*2);
 	  DO_AGGREGATE_ARRAY(100);
 	  break;
 
@@ -323,7 +345,7 @@ PIKECLASS ResObj
       }
     } END_AGGREGATE_ARRAY;
 
-    if (Pike_sp[0].u.array->size == 0) {
+    if (Pike_sp[-1].u.array->size == 0) {
       pop_stack();
       push_int(0);
     }
-- 
GitLab