implement PgCatalogue;
include "sys.m";
sys: Sys;
include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;
include "daytime.m";
daytime : Daytime;
include "pgbase.m";
pgbase :PgBase;
Connection : import pgbase;
include "pg_catalogue.m";
disconnect(c : ref Connection)
{
c.disconnect();
}
new_connection(ip, port, user, password, database, options, parameters: string) : ref Connection
{
pgbase = load PgBase "pgbase.dis";
c := ref Connection;
c.user = user;
c.password = password;
c.database = database;
if(c.connect(ip, port, options, parameters))
return c;
raise "connection failed";
}
new_catalogue(conn : ref Connection) : ref Catalogue
{
c := ref Catalogue;
c.conn = conn;
return c;
}
Catalogue.sync(c : self ref Catalogue) : int
{
if(daytime == nil)
daytime = load Daytime Daytime->PATH;
c.err_chan <- = "sync";
c.fill_procs();
c.fill_types();
c.fill_users();
c.last_sync = daytime->now();
return c.last_sync;
}
Catalogue.drop_proc(c : self ref Catalogue, id : int) : int
{
c.err_chan <- = "drop_proc";
return (c != nil && id != -1);
}
Catalogue.user_sysid(c : self ref Catalogue, username : string) : (string,int)
{
if(c.conn.parse("", "SELECT usesysid FROM pg_user WHERE usename=$1;", nil)) {
recordset := c.conn.execute("", "", nil, array[1] of {array of byte username}, array[1] of {0}, 0);
if(recordset == nil)
return ("Not Found", 0);
return (nil, int string recordset.rows[0][0]);
}
return ("Database choked in user_sysid", 0);
}
Catalogue.print_procs_full(c : self ref Catalogue, user_sysid: int)
{
if(sys == nil)
sys = load Sys Sys->PATH;
if(c.procs == nil && c.fill_procs() == 0) {
sys->print("No Procs found\n");
return;
}
for(r := 0; r < len c.procs; r++) {
if(c.procs[r].owner != user_sysid) continue;
sys->print("P: oid %bd\n", c.procs[r].oid);
sys->print("name %s\n", c.procs[r].name);
sys->print("namespace %bd\n", c.procs[r].namespace);
sys->print("owner %d\n", c.procs[r].owner);
sys->print("lang %bd\n", c.procs[r].lang);
sys->print("isagg %d\n", c.procs[r].isagg);
sys->print("secdef %d\n", c.procs[r].secdef);
sys->print("isstrict %d\n", c.procs[r].isstrict);
sys->print("retset %d\n", c.procs[r].retset);
sys->print("volatile %d\n", c.procs[r].volatile);
sys->print("nargs %d\n", c.procs[r].nargs);
sys->print("rettype %bd\n", c.procs[r].rettype);
sys->print("argtypes :\n");
for(i := 0; i < len c.procs[r].argtypes; i++)
sys->print(" type : %bd %s\n", c.procs[r].argtypes[i], c.type_name(c.procs[r].argtypes[i]));
sys->print("argnames :\n");
for(i = 0; i < len c.procs[r].argnames; i++)
sys->print(" names : %s\n", c.procs[r].argnames[i]);
}
}
Catalogue.proc_sql(c : self ref Catalogue, r : int) : string
{
c.err_chan <- = "proc_sql";
p := c.procs[r];
sql := "CREATE OR REPLACE FUNCTION " + p.name + "(";
for(k := 0; k < p.nargs; k++) {
if(p.argnames != nil)
sql += p.argnames[k] + " ";
sql += c.type_name(p.argtypes[k]);
if(k < p.nargs -1)
sql += ", ";
}
sql += ") RETURNS " + c.type_name(p.rettype) + " AS $_$" + p.src + "$_$ LANGUAGE " + c.language_name(p.lang) + ";\n";
return sql;
}
Catalogue.print_procs(c : self ref Catalogue, user_sysid: int)
{
if(sys == nil)
sys = load Sys Sys->PATH;
if(c.procs == nil && c.fill_procs() == 0) {
sys->print("No Procs found\n");
return;
}
nl := "";
for(r := 0; r < len c.procs; r++) {
if(c.procs[r].owner != user_sysid) continue;
sys->print("%s%s", nl, c.proc_sql(r));
nl = "\n";
}
}
Catalogue.fill_procs(c : self ref Catalogue) : int
{
c.err_chan <- = "fill_procs";
if(sys == nil)
sys = load Sys Sys->PATH;
stderr := sys->fildes(2);
if(c.conn == nil) {
sys->fprint(stderr, "conn is nil, fool\n");
return 0;
}
if(!c.conn.parse("", "SELECT oid, proname, pronamespace, proowner, prolang, proisagg, prosecdef, proisstrict, proretset, provolatile, pronargs, prorettype, proargtypes, proargnames, prosrc FROM pg_proc;", nil)) {
sys->fprint(stderr, "proc parse failed\n");
return 0;
}
recordset := c.conn.execute("", "", nil, nil, nil, 0);
if(recordset == nil)
return 0;
s : int;
c.procs = array[len recordset.rows] of Proc;
for(r := 0; r < len recordset.rows; r++) {
s = 0;
c.procs[r].rows = recordset.rows[r];
c.procs[r].oid = big string recordset.rows[r][s++];
c.procs[r].name = string recordset.rows[r][s++];
c.procs[r].namespace = big string recordset.rows[r][s++];
c.procs[r].owner = int string recordset.rows[r][s++];
c.procs[r].lang = big string recordset.rows[r][s++];
c.procs[r].isagg = int string recordset.rows[r][s++];
c.procs[r].secdef = int string recordset.rows[r][s++];
c.procs[r].isstrict = int string recordset.rows[r][s++];
c.procs[r].retset = int string recordset.rows[r][s++];
c.procs[r].volatile = int string recordset.rows[r][s++];
c.procs[r].nargs = int string recordset.rows[r][s++];
c.procs[r].rettype = big string recordset.rows[r][s++];
i : int;
(errs, types) := sys->tokenize(string recordset.rows[r][s++], " ");
if(len types > 0) {
c.procs[r].argtypes = array[c.procs[r].nargs] of big;
for(i = 0; i < c.procs[r].nargs; i++) {
c.procs[r].argtypes[i] = big hd types;
types = tl types;
}
}
c.procs[r].argnames = nil;
names := string recordset.rows[r][s++];
if(len names > 0) {
(errs, types) = sys->tokenize(names[1:len names -1], ",");
if(len types > 0) {
c.procs[r].argnames = array[c.procs[r].nargs] of string;
for(i = 0; i < c.procs[r].nargs; i++) {
c.procs[r].argnames[i] = hd types;
types = tl types;
}
}
}
c.procs[r].src = string recordset.rows[r][s++];
}
return len c.procs;
}
Catalogue.print_types(c : self ref Catalogue)
{
if(sys == nil)
sys = load Sys Sys->PATH;
if(c.types == nil && c.fill_types() == 0) {
sys->print("No Types found\n");
return;
}
sys->print("%d Type(s)\n", len c.types);
for(r := 0; r < len c.types; r++) {
sys->print("T: oid %bd\n", c.types[r].oid);
sys->print("name %s\n", c.types[r].name);
sys->print("namespace %bd\n", c.types[r].namespace);
sys->print("owner %bd\n", c.types[r].owner);
sys->print("length %d\n", c.types[r].length);
sys->print("byval %d\n", c.types[r].byval);
sys->print("typ %s\n", c.types[r].typ);
sys->print("isdefined %d\n", c.types[r].isdefined);
sys->print("delim %s\n", c.types[r].delim);
sys->print("relid %bd\n", c.types[r].relid);
sys->print("elem %bd\n", c.types[r].elem);
sys->print("input %d\n", c.types[r].input);
sys->print("output %d\n", c.types[r].output);
sys->print("receive %d\n", c.types[r].receive);
sys->print("send %d\n", c.types[r].send);
sys->print("analyze %d\n", c.types[r].analyze);
sys->print("align %s\n", c.types[r].align);
sys->print("storage %s\n", c.types[r].storage);
sys->print("notnull %d\n", c.types[r].notnull);
sys->print("basetype %bd\n", c.types[r].basetype);
sys->print("typmod %d\n", c.types[r].typmod);
sys->print("ndims %d\n", c.types[r].ndims);
sys->print("defaultbin %s\n", string c.types[r].defaultbin);
sys->print("default %s\n", c.types[r].default);
}
}
Catalogue.fill_types(c : self ref Catalogue) : int
{
c.err_chan <- = "fill_types";
if(!c.conn.parse("", "SELECT oid, typname, typnamespace, typowner, typlen, typbyval, typtype, typisdefined, typdelim, typrelid, typelem, typinput, typoutput, typreceive, typsend, typanalyze, typalign, typstorage, typnotnull, typbasetype, typtypmod, typndims, typdefaultbin, typdefault FROM pg_type;", nil))
raise "Database choked in types";
recordset := c.conn.execute("", "", nil, nil, nil, 0);
if(recordset == nil)
raise "No Types found";
s : int;
c.types = array[len recordset.rows] of Type;
for(r := 0; r < len recordset.rows; r++) {
s = 0;
c.types[r].oid = big string recordset.rows[r][s++];
c.types[r].name = string recordset.rows[r][s++];
c.types[r].namespace = big string recordset.rows[r][s++];
c.types[r].owner = big string recordset.rows[r][s++];
c.types[r].length = int string recordset.rows[r][s++];
c.types[r].byval = int string recordset.rows[r][s++];
c.types[r].typ = string recordset.rows[r][s++];
c.types[r].isdefined = int string recordset.rows[r][s++];
c.types[r].delim = string recordset.rows[r][s++];
c.types[r].relid = big string recordset.rows[r][s++];
c.types[r].elem = big string recordset.rows[r][s++];
c.types[r].input = int string recordset.rows[r][s++];
c.types[r].output = int string recordset.rows[r][s++];
c.types[r].receive = int string recordset.rows[r][s++];
c.types[r].send = int string recordset.rows[r][s++];
c.types[r].analyze = int string recordset.rows[r][s++];
c.types[r].align = string recordset.rows[r][s++];
c.types[r].storage = string recordset.rows[r][s++];
c.types[r].notnull = int string recordset.rows[r][s++];
c.types[r].basetype = big string recordset.rows[r][s++];
c.types[r].typmod = int string recordset.rows[r][s++];
c.types[r].ndims = int string recordset.rows[r][s++];
c.types[r].defaultbin = recordset.rows[r][s++];
c.types[r].default = string recordset.rows[r][s++];
}
return len c.types;
}
Catalogue.type_name(c : self ref Catalogue, oid : big) : string
{
if(c.types == nil)
c.fill_types();
for(i := 0; i < len c.types; i++) {
if(c.types[i].oid == oid)
return c.types[i].name;
}
return nil;
}
Catalogue.fill_languages(c : self ref Catalogue) : int
{
c.err_chan <- = "fill_languages";
if(!c.conn.parse("", "SELECT oid, lanname, lanispl, lanpltrusted, lanplcallfoid, lanvalidator, lanacl FROM pg_language;", nil))
raise "Database choked in languages";
recordset := c.conn.execute("", "", nil, nil, nil, 0);
if(recordset == nil)
raise "No Languages found";
s : int;
c.languages = array[len recordset.rows] of Language;
for(r := 0; r < len recordset.rows; r++) {
s = 0;
c.languages[r].oid = big string recordset.rows[r][s++];
c.languages[r].name = string recordset.rows[r][s++];
c.languages[r].ispl = int string recordset.rows[r][s++];
c.languages[r].pltrusted = int string recordset.rows[r][s++];
c.languages[r].plcallfoid = big string recordset.rows[r][s++];
c.languages[r].validator = big string recordset.rows[r][s++];
c.languages[r].acl = string recordset.rows[r][s++];
}
return len c.languages;
}
Catalogue.language_name(c : self ref Catalogue, oid : big) : string
{
if(c.languages == nil)
c.fill_languages();
for(i := 0; i < len c.languages; i++) {
if(c.languages[i].oid == oid)
return c.languages[i].name;
}
return nil;
}
Catalogue.fill_users(c : self ref Catalogue) : int
{
if(!c.conn.parse("", "SELECT usename, usesysid, usecreatedb, usesuper, usecatupd, valuntil, useconfig FROM pg_user;", nil))
raise "Database choked in users";
recordset := c.conn.execute("", "", nil, nil, nil, 0);
if(recordset == nil)
raise "No Users found";
s : int;
c.users = array[len recordset.rows] of User;
for(r := 0; r < len recordset.rows; r++) {
s = 0;
c.users[r].name = string recordset.rows[r][s++];
c.users[r].sysid = int string recordset.rows[r][s++];
c.users[r].createdb = int string recordset.rows[r][s++];
c.users[r].super = int string recordset.rows[r][s++];
c.users[r].catupd = int string recordset.rows[r][s++];
c.users[r].valuntil = string recordset.rows[r][s++];
c.users[r].config = string recordset.rows[r][s++];
}
c.err_chan <- = "filled_users";
return len c.users;
}
Catalogue.user_name(c : self ref Catalogue, sysid : int) : string
{
if(c.users == nil)
c.fill_users();
for(i := 0; i < len c.users; i++) {
if(c.users[i].sysid == sysid)
return c.users[i].name;
}
return nil;
}
|