diff --git a/lib/modules/Sql.pmod/sqlite.pike b/lib/modules/Sql.pmod/sqlite.pike
index a9c81bc49eeda1962113997d8c9668805afaee80..9597d5e3e8357e9227d4cad0aff4ab3ef8bf6d5e 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 68dda3f501b26c7bd82e3bd5b46d22b86887c04e..fcdb455eb89af49d000693a3ae1df5db248f98eb 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);
     }