Plan 9 from Bell Labs’s /usr/web/sources/contrib/maht/limbo/pg/pg_catalogue.b

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


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;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.