From 8a37534b574460dd4be6b3c18ad31faae054950d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Thu, 6 Mar 1997 22:21:03 +0100
Subject: [PATCH] Used to be part of sql.pre.pike.

Rev: lib/modules/Sql.pmod/sql.pike:1.1
Rev: lib/modules/Sql.pmod/sql_result.pike:1.1
---
 .gitattributes                       |   2 +
 lib/modules/Sql.pmod/sql.pike        | 239 +++++++++++++++++++++++++++
 lib/modules/Sql.pmod/sql_result.pike |  93 +++++++++++
 3 files changed, 334 insertions(+)
 create mode 100644 lib/modules/Sql.pmod/sql.pike
 create mode 100644 lib/modules/Sql.pmod/sql_result.pike

diff --git a/.gitattributes b/.gitattributes
index 01cc6f292d..86550f50ee 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -19,6 +19,8 @@ testfont binary
 /lib/modules/LR.pmod/scanner.pike foreign_ident
 /lib/modules/Sql.pmod/mysql.pike foreign_ident
 /lib/modules/Sql.pmod/mysql_result.pike foreign_ident
+/lib/modules/Sql.pmod/sql.pike foreign_ident
+/lib/modules/Sql.pmod/sql_result.pike foreign_ident
 /src/backend.c foreign_ident
 /src/builtin_functions.c foreign_ident
 /src/configure.in foreign_ident
diff --git a/lib/modules/Sql.pmod/sql.pike b/lib/modules/Sql.pmod/sql.pike
new file mode 100644
index 0000000000..33b08c6c07
--- /dev/null
+++ b/lib/modules/Sql.pmod/sql.pike
@@ -0,0 +1,239 @@
+/*
+ * $Id: sql.pike,v 1.1 1997/03/06 21:21:02 grubba Exp $
+ *
+ * Implements the generic parts of the SQL-interface
+ *
+ * Henrik Grubbstr�m 1996-01-09
+ */
+
+#define throw_error(X)	throw(({ (X), backtrace() }))
+
+import Array;
+import Simulate;
+
+object master_sql;
+
+void create(void|string|object host, void|string db,
+	    void|string user, void|string password)
+{
+  if (objectp(host)) {
+    master_sql = host;
+    if ((user && user != "") || (password && password != "")) {
+      throw_error("Sql(): Only the database argument is supported when "
+		  "first argument is an object\n");
+    }
+    if (db && db != "") {
+      master_sql->select_db(db);
+    }
+    return;
+  } else {
+    foreach(get_dir(Sql->dirname), string program_name) {
+      if (sizeof(program_name / "_result") == 1 &&
+	  (program_name != "Sql.pike")) {
+	/* Don't call ourselves... */
+	array(mixed) err;
+	
+	err = catch {
+	  program p = Sql[program_name];
+
+	  if (password && password != "") {
+	    master_sql = p(host||"", db||"", user||"", password);
+	  } else if (user && user != "") {
+	    master_sql = p(host||"", db||"", user);
+	  } else if (db && db != "") {
+	    master_sql = p(host||"", db);
+	  } else if (host && host != "") {
+	    master_sql = p(host);
+	  } else {
+	    master_sql = p();
+	  }
+	  return;
+	};
+      }
+    }
+  }
+
+  throw_error("Sql(): Couldn't connect to database\n");
+}
+
+static private array(mapping(string:mixed)) res_obj_to_array(object res_obj)
+{
+  if (res_obj) {
+    /* Not very efficient, but sufficient */
+    array(mapping(string:mixed)) res = ({});
+    array(string) fieldnames;
+    array(mixed) row;
+      
+    fieldnames = map(res_obj->fetch_fields(),
+		     lambda (mapping(string:mixed) m) {
+      return(m->name);	/* Hope this is unique */
+    } );
+
+    while (row = res_obj->fetch_row()) {
+      res += ({ mkmapping(fieldnames, row) });
+    }
+    return(res);
+  } else {
+    return(0);
+  }
+}
+  
+int|string error()
+{
+  return(master_sql->error());
+}
+
+void select_db(string db)
+{
+  master_sql->select_db(db);
+}
+
+array(mapping(string:mixed)) query(string s)
+{
+  object res_obj;
+
+  if (functionp(master_sql->query)) {
+    return(master_sql->query(s));
+  }
+  return(res_obj_to_array(master_sql->big_query(s)));
+}
+
+object big_query(string q)
+{
+  if (functionp(master_sql->big_query)) {
+    return(Sql.Sql_result(master_sql->big_query(q)));
+  }
+  return(Sql.Sql_result(master_sql->query(q)));
+}
+
+void create_db(string db)
+{
+  master_sql->create_db(db);
+}
+
+void drop_db(string db)
+{
+  master_sql->drop_db(db);
+}
+
+void shutdown()
+{
+  if (functionp(master_sql->shutdown)) {
+    master_sql->shutdown();
+  } else {
+    throw_error("sql->shutdown(): Not supported by this database\n");
+  }
+}
+
+void reload()
+{
+  if (functionp(master_sql->reload)) {
+    master_sql->reload();
+  } else {
+    /* Probably safe to make this a NOOP */
+  }
+}
+
+string server_info()
+{
+  if (functionp(master_sql->server_info)) {
+    return(master_sql->server_info());
+  }
+  return("Unknown SQL-server");
+}
+
+string host_info()
+{
+  if (functionp(master_sql->host_info)) {
+    return(master_sql->host_info());
+  } 
+  return("Unknown connection to host");
+}
+
+array(string) list_dbs(string|void wild)
+{
+  array(string)|array(mapping(string:mixed))|object res;
+  
+  if (functionp(master_sql->list_dbs)) {
+    if (objectp(res = master_sql->list_dbs())) {
+      res = res_obj_to_array(res);
+    }
+  } else {
+    res = query("show databases");
+  }
+  if (sizeof(res) && mappingp(res[0])) {
+    res = map(res, lambda (mapping m) {
+      return(values(m)[0]);	/* Hope that there's only one field */
+    } );
+  }
+  if (wild) {
+    res = map_regexp(res, replace(wild, ({ "%", "_" }), ({ ".*", "." }) ));
+  }
+  return(res);
+}
+
+array(string) list_tables(string|void wild)
+{
+  array(string)|array(mapping(string:mixed))|object res;
+  
+  if (functionp(master_sql->list_tables)) {
+    if (objectp(res = master_sql->list_tables())) {
+      res = res_obj_to_array(res);
+    }
+  } else {
+    res = query("show tables");
+  }
+  if (sizeof(res) && mappingp(res[0])) {
+    res = map(res, lambda (mapping m) {
+      return(values(m)[0]);	/* Hope that there's only one field */
+    } );
+  }
+  if (wild) {
+    res = map_regexp(res, replace(wild, ({ "%", "_" }), ({ ".*", "." }) ));
+  }
+  return(res);
+}
+
+array(mapping(string:mixed)) list_fields(string table, string|void wild)
+{
+  array(mapping(string:mixed))|object res;
+
+  if (functionp(master_sql->list_fields)) {
+    if (objectp(res = master_sql->list_fields(table))) {
+      res = res_obj_to_array(res);
+    }
+    if (wild) {
+      /* Not very efficient, but... */
+      res = filter(res, lambda (mapping m, string re) {
+	return(sizeof(map_regexp( ({ m->name }), re)));
+      }, replace(wild, ({ "%", "_" }), ({ ".*", "." }) ) );
+    }
+    return(res);
+  }
+  if (wild) {
+    res = query("show fields from \'" + table +
+		"\' like \'" + wild + "\'");
+  } else {
+    res = query("show fields from \'" + table + "\'");
+  }
+  res = map(res, lambda (mapping m, string table) {
+    foreach(indices(m), string str) {
+      /* Add the lower case variants */
+      string low_str = lower_case(str);
+      if (low_str != str && !m[low_str]) {
+	m[low_str] = m[str];
+	m_delete(m, str);	/* Remove duplicate */
+      }
+    }
+    if ((!m->name) && m->field) {
+      m["name"] = m->field;
+      m_delete(m, "field");	/* Remove duplicate */
+    }
+    if (!m->table) {
+      m["table"] = table;
+    }
+    return(m);
+  }, table);
+  return(res);
+}
+
diff --git a/lib/modules/Sql.pmod/sql_result.pike b/lib/modules/Sql.pmod/sql_result.pike
new file mode 100644
index 0000000000..74851bbba1
--- /dev/null
+++ b/lib/modules/Sql.pmod/sql_result.pike
@@ -0,0 +1,93 @@
+/*
+ * $Id: sql_result.pike,v 1.1 1997/03/06 21:21:03 grubba Exp $
+ *
+ * Implements the generic result module of the SQL-interface
+ *
+ * Henrik Grubbstr�m 1996-01-09
+ */
+
+#define throw_error(X)	throw(({ (X), backtrace() }))
+
+object|array master_res;
+int index;
+
+import Array;
+
+void create(object|array res)
+{
+  if (!(master_res = res) || (!arrayp(res) && !objectp(res))) {
+    throw_error("Bad arguments to Sql_result()\n");
+  }
+  index = 0;
+}
+
+int num_rows()
+{
+  if (arrayp(master_res)) {
+    return(sizeof(master_res));
+  }
+  return(master_res->num_rows());
+}
+
+int num_fields()
+{
+  if (arrayp(master_res)) {
+    return(sizeof(master_res[0]));
+  }
+  return(master_res->num_fields());
+}
+
+int eof()
+{
+  if (arrayp(master_res)) {
+    return(index >= sizeof(master_res));
+  }
+  return(master_res->eof());
+}
+
+array(mapping(string:mixed)) fetch_fields()
+{
+  if (arrayp(master_res)) {
+    /* Only supports the name field */
+    array(mapping(string:mixed)) res = allocate(sizeof(master_res));
+    int index = 0;
+    
+    foreach(sort(indices(master_res)), string name) {
+      res[index++] = ([ "name": name ]);
+    }
+    return(res);
+  }
+  return(master_res->fetch_fields());
+}
+
+void seek(int skip)
+{
+  if (skip < 0) {
+    throw_error("seek(): Argument 1 not positive\n");
+  }
+  if (arrayp(master_res)) {
+    index += skip;
+  } else if (functionp(master_res->seek)) {
+    master_res->seek(index);
+  } else {
+    while (skip--) {
+      master_res->fetch_row();
+    }
+  }
+}
+
+int|array(string|int) fetch_row()
+{
+  if (arrayp(master_res)) {
+    array res;
+      
+    if (index >= sizeof(master_res)) {
+      return(0);
+    }
+    sort(indices(master_res[index]), res = values(master_res[index]));
+    return(res);
+  }
+  return (master_res->fetch_row());
+}
+
+
-- 
GitLab