diff --git a/.gitattributes b/.gitattributes index ea1a5f398d50b956b260da21b0c5a0afa8ac97e3..cb6fe2c5da78ede9b7dc1dd94349c78a27b9debb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -52,6 +52,7 @@ testfont binary /lib/modules/Sql.pmod/odbc.pike foreign_ident /lib/modules/Sql.pmod/odbc_result.pike foreign_ident /lib/modules/Sql.pmod/oracle.pike foreign_ident +/lib/modules/Sql.pmod/postgres.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 @@ -124,6 +125,7 @@ testfont binary /src/modules/Postgres/configure.in foreign_ident /src/modules/Postgres/pgres_config.h.in foreign_ident /src/modules/Postgres/postgres.c foreign_ident +/src/modules/Postgres/version.h foreign_ident /src/modules/Regexp/acconfig.h foreign_ident /src/modules/Ssleay/ssleay.c foreign_ident /src/modules/Yp/acconfig.h foreign_ident diff --git a/lib/modules/Sql.pmod/postgres.pike b/lib/modules/Sql.pmod/postgres.pike index 09a5ff83401ce5a2f2c6094076d5c7520218fc64..062ace927323bec02db57b5a3e0547755ffbd42e 100644 --- a/lib/modules/Sql.pmod/postgres.pike +++ b/lib/modules/Sql.pmod/postgres.pike @@ -2,6 +2,8 @@ * This is part of the Postgres module for Pike. * (C) 1997 Francesco Chemolli <kinkie@comedia.it> * + * $Id: postgres.pike,v 1.2 1997/11/25 20:58:17 grubba Exp $ + * */ #define ERROR(X) throw (({X,backtrace()})) @@ -9,32 +11,27 @@ inherit Postgres.postgres: mo; private static mixed callout; +private static string glob_to_regexp (string glob) { + if (!glob||!sizeof(glob)) + return 0; + return "^"+replace(glob,({"*","?","'","\\"}),({".*",".","\\'","\\\\"}))+"$"; +} + +static private int mkbool(string s) { + if (s=="f") + return 0; + return 1; +} + void create(void|string host, void|string database, void|string user, void|string pass) { string real_host=host, real_db=database; int port=0; if (stringp(host)&&(search(host,":")>=0)) if (sscanf(host,"%s:%d",real_host,port)!=2) - ERROR("Error in parsing the hostname!\n"); + ERROR("Error in parsing the hostname argument.\n"); - //postgres docs say that PGHOST, PGPORT, PGDATABASE are used to - //determine defaults if not otherwise availible. Since on my system - //this doesn't work, I'll do it myself - if (!real_host && getenv("PGHOST")) - real_host=getenv("PGHOST"); - if (!port && getenv("PGPORT")) - port=(int)getenv("PGPORT"); - if (!real_db && getenv("PGDATABASE")) - real_db=getenv("PGDATABASE"); - if (!real_host) - real_host="localhost"; - if (!real_db) - real_db="template1"; - //this allows to connect, since template1 is shipped with Postgres... - if (port) - mo::create(real_host,real_db,port); - else - mo::create(real_host,real_db); //should use the default port. + mo::create(real_host||"",real_db||"",port); } static void poll (int delay) @@ -71,10 +68,12 @@ string server_info () { array(string) list_dbs (void|string wild) { array name,ret=({}); - object res=big_query("Select datname from pg_database"); + object res= + big_query( + "SELECT datname from pg_database"+ + ((wild&&sizeof(wild))? " WHERE datname ~ '"+glob_to_regexp(wild)+"'" : "") + ); while (name=res->fetch_row()) { - if (wild && !glob(wild,name)) - continue; ret += ({name[0]}); } return sort(ret); @@ -84,23 +83,20 @@ array(string) list_tables (void|string wild) { array name,ret=({}); object res; res=big_query( - "select relname,relkind FROM pg_class WHERE " - "(relkind = 'r' or relkind = 'i')"); + "SELECT relname, relkind FROM pg_class, pg_user " + "WHERE ( relkind = 'r' OR relkind = 'i' OR relkind = 'S') " + "AND relname !~ '^pg_' " + "AND usesysid = relowner " + + ((wild && sizeof(wild)) ? "AND relname ~ '"+glob_to_regexp(wild)+"' " : "") + + "ORDER BY relname" + ); while (name=res->fetch_row()) { - if (wild && !glob(wild,name[0])||glob("pg_*",name[0])) - continue; - ret += ({name[0]}); + ret += ({name[0]}); } - return sort(ret); -} - -int mkbool(string s) { - if (s=="f") - return 0; - return 1; + return ret; } -mapping(string:array(mixed)) list_fields (string table) { +mapping(string:array(mixed)) list_fields (string table, void|string wild) { array row; mapping ret=([]); object res=big_query( @@ -119,5 +115,10 @@ mapping(string:array(mixed)) list_fields (string table) { ,"has_rules","default"}),row); ret[name]=m; } + if (wild && strlen (wild)) { + array a=glob(wild,indices(ret)); + return mkmapping(a,Array.map(a,lambda(string s, mapping m) + {return m[s];},ret)); + } return ret; } diff --git a/src/modules/Postgres/ChangeLog b/src/modules/Postgres/ChangeLog index 3aa1cca1ce63d1a1d96e921b74f451545d9da812..9188a0fba49f80121828966027da57ad6efedc77 100644 --- a/src/modules/Postgres/ChangeLog +++ b/src/modules/Postgres/ChangeLog @@ -1,9 +1,108 @@ +Tue Nov 25 13:42:25 1997 Francesco Chemolli <kinkie@ai-chan> + + * version.h: Released version 1.0 (hopefully) + + * doc/Attic/raw_postgres, doc/sql_postgres, doc/sql_postgres_result, + doc/Attic/postgres, doc/Attic/postgres_result, doc/postgres_postgres, + doc/postgres_postgres_result: + Made some order, to make the documentation better understandable and + complete. + + * doc/Attic/postgres, doc/Attic/postgres_result, doc/Attic/raw_postgres: + Fixed and completed the documentation. + + * lib/postgres.pike: Fixed a typo. + +Mon Nov 24 14:34:31 1997 Francesco Chemolli <kinkie@ai-chan> + + * lib/postgres.h: + Now it's mainly a placeholder, since the 'real' module is in Sql only, + and importing the whole Sql family of modules wouldn't help much... + + * ChangeLog: Updated. + + * version.h: Version 1.0pre2. + + * lib/postgres.pike: Added interface compliancy for list_fields. + + * doc/Attic/postgres, doc/Attic/postgres_result: + Documentation. Lots of it (I hope). + + * lib/postgres.h: *** empty log message *** + +Mon Nov 24 14:32:49 1997 Francesco Chemolli <kinkie@ai-chan> + + * lib/postgres.pike: Added interface compliancy for list_fields. + + * doc/postgres, doc/postgres_result: + Documentation. Lots of it (I hope). + + * lib/Attic/postgres.h: *** empty log message *** + +Thu Nov 13 10:53:39 1997 Francesco Chemolli <kinkie@ai-chan> + + * ChangeLog: *** empty log message *** + + * version.h: Released version 1.0pre1 + + * postgres.c: Added versioning information. + +Sun Oct 12 13:11:37 1997 Francesco Chemolli <kinkie@ai-chan> + + * ChangeLog: Released version 0.7 + + * lib/postgres.pike: Removed some redundant code for create(). + + * postgres.c: + Better argument handling for create(). Now portnumber 0 is a special + case which means "default port" and leaves to the pglib the burden + of determining the port to connect to. + Now finally 'object o=Sql.postgres()' works (previously it misbehaved + if the database argument was missing). + + Stronger typechecking for create(). + +Sun Oct 12 13:10:08 1997 Francesco Chemolli <kinkie@ai-chan> + + * lib/postgres.pike: Removed some redundant code for create(). + + * postgres.c: + Better argument handling for create(). Now portnumber 0 is a special + case which means "default port" and leaves to the pglib the burden + of determining the port to connect to. + Now finally 'object o=Sql.postgres()' works (previously it misbehaved + if the database argument was missing). + + Stronger typechecking for create(). + + * lib/postgres.pike: + Changes were made to use better SQL queries instead of + filtering the results by hand. + + * Released version 0.7 + +Mon Oct 6 17:55:15 1997 Francesco Chemolli <kinkie@ai-chan> + + * postgres.c: Adopted xalloc in lieu of malloc for increased safety + Added a "version" constant to the postgres pike module to identify + the vesion with more ease. I'll leave it undocumented elsewhere though. + + * Released version 0.6 + +Sat Sep 6 11:26:53 1997 Francesco Chemolli <kinkie@ai-chan> + + * postgres.c, pgresult.c: + Fixed some problems which could result in deadlocks in the Pike driver. + Thanks to Henrik Grubbstroem for signaling me. + Tue Jul 8 20:23:06 1997 Francesco Chemolli <kinkie@ai-chan> * postgres.c: Corrected a small bug which manifested itself when building in a non_threaded environment. + * Released version 0.5 + Mon Jun 30 13:57:08 1997 Francesco Chemolli <kinkie@ai-chan> * configure.in, postgres.c, configure: @@ -39,6 +138,8 @@ Fri Jun 27 09:55:51 1997 Francesco Chemolli <kinkie@ai-chan> proprietaria ma semplice. Ci pensera` poi il modulo di interfaccia a gestire la traduzione e a ottenere la compliancy. + * Released version 0.4 + Thu Jun 19 12:35:12 1997 Francesco Chemolli <kinkie@ai-chan> * lib/postgres.pike: Corretto un baco in lib/postgres.pike @@ -54,6 +155,8 @@ Thu Jun 19 12:35:12 1997 Francesco Chemolli <kinkie@ai-chan> Ora la classe in Sql.pmod puo` ereditare. Piu` efficiente, e migliore controllo degli errori. + * Released version 0.3 + Wed Apr 2 11:56:14 1997 Francesco Chemolli <kinkie@ai-chan> * Makefile.in, configure, configure.in, extras/test_notify.pike, extras/test_schema.pike, lib/postgres.h, pg_types.h, pgres_config.h.in, pgresult.c, postgres.c, quickmanual.txt, testsuite.in: diff --git a/src/modules/Postgres/configure.in b/src/modules/Postgres/configure.in index 702e6c6817f63f5a9f9aafdf81114516b0caa790..2631277db75e2346cb5766e90679b43b1c7067cc 100644 --- a/src/modules/Postgres/configure.in +++ b/src/modules/Postgres/configure.in @@ -1,4 +1,4 @@ -dnl $Id: configure.in,v 1.2 1997/11/07 19:34:34 grubba Exp $ +dnl $Id: configure.in,v 1.3 1997/11/25 20:57:56 grubba Exp $ dnl (C) 1997 Francesco Chemolli <kinkie@comedia.it> AC_INIT(postgres.c) diff --git a/src/modules/Postgres/doc/postgres_postgres b/src/modules/Postgres/doc/postgres_postgres new file mode 100644 index 0000000000000000000000000000000000000000..55bf95c1ecc5230cf2b1d1d855353e04c12516a2 --- /dev/null +++ b/src/modules/Postgres/doc/postgres_postgres @@ -0,0 +1,266 @@ +NAME + Postgres.postgres - Postgres (Postgres95, PgSQL) _RAW_ Server interface + +AUTHOR + Francesco Chemolli <kinkie@comedia.it> + +DESCRIPTION + This is an interface to the Postgres (Postgres95, pgsql) database server. + This module may or may not be availible on your Pike, depending + whether the appropriate include and library files + could be found at compile-time. Note that you DO NOT + need to have a Postgres server running on your host to use this module: + you can connect to the database over a TCP/IP socket + + Please notice that unless you wish to specifically connect to a Postgres + server, you'd better use the Sql.sql program instead. + I and Henrik Grubbstr�m have (hopefully) designed a server-independent + sql-server-class. The interfaces to all existing sql-classes + are consistent. Using Sql.sql ensures that your Pike + applications will run with any supported SQL server without changing + a single line of code, at least for most common (and simple) operations. + + The program Postgres.postgres provides the _RAW_ interface + to the database. Many functions are _NOT_ availible + for this program. Therefore, its use is DEPRECATED. + It is included in this documentation only for completeness' sake. + Use Sql.postgres instead, or even better Sql.sql + +SEE ALSO + Sql.sql, Sql.postgres, Sql.postgres_result + +============================================================================ +NAME + create - (re)inititalize connection and select database + +SYNTAX + object Postgres.postgres (); + or + object Postgres.postgres (string host, void|string database, void|int port); + +DESCRIPTION + With no arguments, this function initializes (reinitializes if a connection + had been previously set up) a connection to the Postgres backend. + Since Postgres requires a database to be selected, it will try + to connect to the default database. The connection may fail however for a + variety of reasons, in this case the most likely of all is because + you don't have enough authority to connect to that database. + So use of this particular syntax is discouraged. + + The host argument allows you to connect to databases residing on different + hosts. If it is 0 or "", it will try to connect to localhost. + + The database argument specifies the database to connect to. If 0 or "", it + will try to connect to the default database. + +NOTA BENE + You need to have a database selected before using the sql-object, + otherwise you'll get exceptions when you try to query it. + Also notice that this function CAN raise exceptions if the db + server doesn't respond, if the database doesn't exist or is not accessible + by you. + + You don't need bothering about syncronizing the connection to the database: + it is automatically closed (and the database is sync-ed) when the + object is destroyed. + +SEE ALSO + Sql.postgres, Sql.sql, postgres->select_db + +============================================================================ +NAME + select_db - connect to a database + +SYNTAX + void select_db (string dbname); + +DESCRIPTION + This function allows you to connect to a database. Due to restrictions + of the Postgres frontend-backend protocol, you always have to be connected + to a database, so in fact this function just allows you to connect + to a different database on the same server. + +NOTA BENE + This function CAN raise exceptions if something goes wrong (backend process + not running, not enough permissions..) + +SEE ALSO + postgres->create + +============================================================================ +NAME + big_query - Query the database + +SYNTAX + object (Sql.postgres_result) big_query (string sqlquery); + +DESCRIPTION + This is the only provided interface which allows you to query the + database. If you wish to use the simpler "query" function, you need to + use the Sql.sql generic sql-object. + + It returns a postgres_result object (which conforms to the Sql.sql_result + standard interface for accessing data). I recommend using query() for + simpler queries (because it is easier to handle, but stores all the result + in memory), and big_query for queries you expect to return huge amounts + of data (it's harder to handle, but fectches results on demand). + +NOTA BENE + This function _CAN_ raise exceptions. + + The program Sql.postgres_result is exactly + the same as Postgres.postgres_result. + +SEE ALSO + Sql.sql, Sql.sql_result + +============================================================================ +NAME + error - tell what the last server error was. + +SYNTAX + string error(); + +DESCRIPTION + This function returns the textual description of the last server-related + error. Returns 0 if no error has occurred yet. It is not cleared upon + reading (can be invoked multiple times, will return the same result + until a new error occurs). + +SEE ALSO + postgres->big_query + +============================================================================ +NAME + host_info - describe the connection we're using + +SYNTAX + string host_info(); + +DESCRIPTION + This function returns a string describing what host are we talking to, + and how (TCP/IP or UNIX sockets). + +============================================================================ +NAME + reset - resets a connection + +SYNTAX + void reset(); + +DESCRIPTION + This function resets the connection to the backend. Can be used for + a variety of reasons, for example to detect the status of a connection. + +NOTA BENE + This function is Postgres-specific, and thus it is not availible + through the generic SQL-interface. + +============================================================================ +NAME + _set_notify_callback - sets a notification callback for SQL events + +SYNTAX + void _set_notify_callback (); + or + void _set_notify_callback (function f); + +DESCRIPTION + With Postgres you can associate events and notifications to tables. + This function allows you to detect and handle such events. + + With no arguments, resets and removes any callback you might have + put previously, and any polling cycle. + + With one argument, sets the notification callback (there can be only + one for each sqlobject). + + The callback function must return no value, and takes a string argument, + which will be the name of the table on which the notification event + has occured. In future versions, support for user-specified arguments + will be added. + +NOTA BENE + The Sql.postgres program adds support for automatic delivery of + messages (see it for explanation on the inner workings of this feature. + + This function is Postgres-specific, and thus it is not availible + through the generic SQL-interface. + +SEE ALSO + Sql.postgres + +============================================================================ +NAME + version - show the version of the Postgres driver. + +SYNTAX + string Postgres.version; + +DESCRIPTION + Should you need to report a bug to the author, please submit along with + the report the driver version number, as returned by this call. + +============================================================================ +EXTERNAL INFLUENCES on the module. + These ones do not depend on my implementation really, they're just part + of the Postgres C API. They take the form of certain environment variables + which, if defined in the environment of the pike interpreter, influence + the interface's behavior. + + PGHOST: sets the name of the default host to connect to. It defaults + to "localhost" + + PGOPTIONS: sets some extra flags for the frontend-backend connection. + DO NOT SET unless you're sure of what you're doing. + + PGPORT: sets the default port to connect to, otherwise it will use + compile-time defaults (that is: the time you compiled the postgres + library, not the Pike driver). + + PGTTY: sets the file to be used for Postgres frontend debugging. + Do not use, unless you're sure of what you're doing. + + PGDATABASE: sets the default database to connect to. + + PGREALM: sets the default realm for Kerberos authentication. I never used + this, so I can't help you. + + Refer to the Postgres documentation for further details. + +NOTES + I didn't make any testsuite for this module, since to test anything it would + require a working Postgres server, and I can't make any assumption + on those... You can try to use the included scripts (they're in the + "pike/src/modules/Postgres/extras" directory + but you'll probably have to patch them to reflect your site's settings. + + Also note that THIS MODULE USES BLOCKING I/O to connect to the server. + Postgres is quite slow, and so you might want to consider this + particular aspect. It is (at least should be) thread-safe, and so it can be used + in a multithread environment. + +THANKS + Many thanks to Henrik Grubbstr�m, without whose help this piece of + code couldn't be nearly as complete as it is. + Also thanks to Frederik Hubinette, for designing such a nice language + as Pike. + +COPYRIGHT + This code and documentation are copyright 1997 Francesco Chemolli + <kinkie@comedia.it>. + It may be copied, modified, redistributed under the terms of the + GNU General Public License, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Pike source. If not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The Pike programming language is copyright Frederik Hubinette, and is + distributed under the terms of the GNU General Public License. For furhter + information, please consult the Pike WWW site, at http://pike.idonex.se/ diff --git a/src/modules/Postgres/doc/postgres_postgres_result b/src/modules/Postgres/doc/postgres_postgres_result new file mode 100644 index 0000000000000000000000000000000000000000..159716b027e32b8e3ab83008a35b0b9b1a9e7336 --- /dev/null +++ b/src/modules/Postgres/doc/postgres_postgres_result @@ -0,0 +1,42 @@ +NAME + Postgres.postgres_result - result of a Postgres query + +AUTHOR + Francesco Chemolli <kinkie@comedia.it> + +DESCRIPTION + Postgres.postgres_result contains the result of a Postgres-query. + See Sql.postgres for a description of this program's functions. + +KEYWORDS + sql, database + +SEE ALSO + Sql.postgres, Postgres.postgres, Sql.sql, Sql.sql_result + + +============================================================================ +THANKS + Many thanks to Henrik Grubbstr�m, without whose help this piece of + code couldn't be nearly as complete as it is. + Also thanks to Frederik Hubinette, for designing such a nice language + as Pike. + +COPYRIGHT + This code and documentation are copyright 1997 Francesco Chemolli + <kinkie@comedia.it>. + It may be copied, modified, redistributed under the terms of the + GNU General Public License, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Pike source. If not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The Pike programming language is copyright Frederik Hubinette, and is + distributed under the terms of the GNU General Public License. For furhter + information, please consult the Pike WWW site, at http://pike.idonex.se/ diff --git a/src/modules/Postgres/doc/sql_postgres b/src/modules/Postgres/doc/sql_postgres new file mode 100644 index 0000000000000000000000000000000000000000..34a5290e2438959b825bf6e95cd5a4c5b29d00ab --- /dev/null +++ b/src/modules/Postgres/doc/sql_postgres @@ -0,0 +1,382 @@ +NAME + Sql.postgres - Postgres (Postgres95, PgSQL) Server interface + +AUTHOR + Francesco Chemolli <kinkie@comedia.it> + +DESCRIPTION + This is an interface to the Postgres (Postgres95, pgsql) database server. + This module may or may not be availible on your Pike, depending + whether the appropriate include and library files + could be found at compile-time. Note that you DO NOT + need to have a Postgres server running on your host to use this module: + you can connect to the database over a TCP/IP socket + + Please notice that unless you wish to specifically connect to a Postgres + server, you'd better use the Sql.sql program instead. + I and Henrik Grubbstr�m have (hopefully) designed a server-independent + sql-server-class. The interfaces to all existing sql-classes + are consistent. Using Sql.sql ensures that your Pike + applications will run with any supported SQL server without changing + a single line of code (well, except server-specific SQL extensions). + + The program Postgres.postgres provides the _RAW_ interface + to the database. Many functions are _NOT_ availible + for that program. Therefore, its use is DEPRECATED. + +SEE ALSO + Sql.sql, Postgres.postgres, Sql.postgres_result + +============================================================================ +NAME + create - (re)inititalize connection and select database + +SYNTAX + object Sql.postgres (); + or + object Sql.postgres (void|string host, void|string database, void|string username, void|string password); + or + void Sql.postgres->create(void|string host, void|string database, void|string username, void|string password); + +DESCRIPTION + With no arguments, this function initializes (reinitializes if a connection + had been previously set up) a connection to the Postgres backend. + Since Postgres requires a database to be selected, it will try + to connect to the default database. The connection may fail however for a + variety of reasons, in this case the most likely of all is because + you don't have enough authority to connect to that database. + So use of this particular syntax is discouraged. + + The host argument can have the syntax "hostname" or "hostname:portname". + This allows to specify the TCP/IP port to connect to. If it is 0 or "", it + will try to connect to localhost, default port. + + The database argument specifies the database to connect to. If 0 or "", it + will try to connect to the specified database. + + The username and password arguments are silently ignored, since the Postgres + C API doesn't allow to connect to the server as any user different than the + user running the interface. + +NOTA BENE + You need to have a database selected before using the sql-object, + otherwise you'll get exceptions when you try to query it. + Also notice that this function CAN raise exceptions if the db + server doesn't respond, if the database doesn't exist or is not accessible + by you. + + You don't need bothering about syncronizing the connection to the database: + it is automatically closed (and the database is sync-ed) when the + object is destroyed. + +SEE ALSO + Postgres.postgres, Sql.sql, postgres->select_db + +============================================================================ +NAME + select_db - connect to a database + +SYNTAX + void select_db (string dbname); + +DESCRIPTION + This function allows you to connect to a database. Due to restrictions + of the Postgres frontend-backend protocol, you always have to be connected + to a database, so in fact this function just allows you to connect + to a different database on the same server. + +NOTA BENE + This function CAN raise exceptions if something goes wrong (backend process + not running, not enough permissions..) + +SEE ALSO + postgres->create + +============================================================================ +NAME + big_query - Query the database + +SYNTAX + object (Sql.postgres_result) big_query (string sqlquery); + +DESCRIPTION + This is the only provided interface which allows you to query the + database. If you wish to use the simpler "query" function, you need to + use the Sql.sql generic sql-object. + + It returns a postgres_result object (which conforms to the Sql.sql_result + standard interface for accessing data). I recommend using query() for + simpler queries (because it is easier to handle, but stores all the result + in memory), and big_query for queries you expect to return huge amounts + of data (it's harder to handle, but fectches results on demand). + +NOTA BENE + This function _CAN_ raise exceptions. + +SEE ALSO + Sql.sql, Sql.sql_result + +============================================================================ +NAME + error - tell what the last server error was. + +SYNTAX + string error(); + +DESCRIPTION + This function returns the textual description of the last server-related + error. Returns 0 if no error has occurred yet. It is not cleared upon + reading (can be invoked multiple times, will return the same result + until a new error occurs). + +SEE ALSO + postgres->big_query + +============================================================================ +NAME + list_dbs - list all databases availible on the server + +SYNTAX + string * list_dbs (); + or + string * list_dbs (string glob); + +DESCRIPTION + Lists all the databases availible on the server. + If glob is specified, lists only those databases matching it. + +============================================================================ +NAME + list_tables - lists all the tables of the current database + +SYNTAX + string * list_tables (); + or + string * list_tables (string glob); + +DESCRIPTION + Returns an array containing the names of all the tables in the currently + selected database. + If a glob is specified, it will return only those tables + whose name matches it. + +============================================================================ +NAME + list_fields - describe the fields of a table in the database + +SYNTAX + mapping(string:mapping(string:mixed)) list_fields(string table); + or + mapping(string:mapping(string:mixed)) list_fields(string table, string glob); + +DESCRIPTION + Returns a mapping, indexed on the column name, of mappings describing the + attributes of a table of the current database. + If a glob is specified, will return descriptions only of the columns matching + it. + + The current fields are (but WILL change for better manageability and interface + compliancy): + + int "has_rules" + + int "is_shared" + + string "expires" : a string representing an internal date. + + string "owner" : it's the textual representation of a Postgres uid. + + string "length" : don't know really why it's a string... this is how it's + internally represented though.. + + string "text": a textual description of the internal (to the server) type-name + + mixed "default" + +============================================================================ +NAME + server_info - returns information on the type of connection + +SYNTAX + string server_info(); + +DESCRIPTION + This function returns a string describing the server we are talking + to. It has the form "servername/serverversion" (like the HTTP protocol + description) and is most useful in conjunction with the generic SQL-server + module. + +SEE ALSO + Sql.sql + +============================================================================ +NAME + host_info - describe the connection we're using + +SYNTAX + string host_info(); + +DESCRIPTION + This function returns a string describing what host are we talking to, + and how (TCP/IP or UNIX sockets). + +============================================================================ +NAME + create_db - create a new database + +SYNTAX + void create_db(string dbname); + +DESCRIPTION + This function creates a new database with the given name (assuming we + have enough permissions to do this). + +SEE ALSO + postgres->drop_db + +============================================================================ +NAME + drop_db - destroy a database + +SYNTAX + void drop_db(string dbname); + +DESCRIPTION + This function destroys a database and all the data it contains (assuming + we have enough permissions to do so). USE WITH CAUTION! + +SEE ALSO + postgres->create_db + +============================================================================ +NAME + reset - resets a connection + +SYNTAX + void reset(); + +DESCRIPTION + This function resets the connection to the backend. Can be used for + a variety of reasons, for example to detect the status of a connection. + +NOTA BENE + This function is Postgres-specific, and thus it is not availible + through the generic SQL-interface. + +============================================================================ +NAME + set_notify_callback - sets a notification callback for SQL events + +SYNTAX + void set_notify_callback (); + or + void set_notify_callback (function f); + or + void set_notify_callback (function f, int|float polling_interval); + +DESCRIPTION + With Postgres you can associate events and notifications to tables. + This function allows you to detect and handle such events. + + With no arguments, resets and removes any callback you might have + put previously, and any polling cycle. + + With one argument, sets the notification callback (there can be only + one for each sqlobject). + + With two arguments, sets a notification callback and sets a polling + cycle. + + The polling cycle is necessary because of the way notifications are + delivered, that is piggyback with a query result. This means that + if you don't do any query, you'll receive no notification. The polling + cycle starts a call_out cycle which will do an empty query when + the specified interval expires, so that pending notifications + may be delivered. + + The callback function must return no value, and takes a string argument, + which will be the name of the table on which the notification event + has occured. In future versions, support for user-specified arguments + will be added. + +NOTA BENE + The polling cycle can be run only if your process is in "event-driven mode" + (that is, if 'main' has returned a negative number). + + This function is Postgres-specific, and thus it is not availible + through the generic SQL-interface. + +============================================================================ +NAME + version - show the version of the Postgres driver. + +SYNTAX + string Postgres.version; + +DESCRIPTION + Should you need to report a bug to the author, please submit along with + the report the driver version number, as returned by this call. + +============================================================================ +EXTERNAL INFLUENCES on the module. + These ones do not depend on my implementation really, they're just part + of the Postgres C API. They take the form of certain environment variables + which, if defined in the environment of the pike interpreter, influence + the interface's behavior. + + PGHOST: sets the name of the default host to connect to. It defaults + to "localhost" + + PGOPTIONS: sets some extra flags for the frontend-backend connection. + DO NOT SET unless you're sure of what you're doing. + + PGPORT: sets the default port to connect to, otherwise it will use + compile-time defaults (that is: the time you compiled the postgres + library, not the Pike driver). + + PGTTY: sets the file to be used for Postgres frontend debugging. + Do not use, unless you're sure of what you're doing. + + PGDATABASE: sets the default database to connect to. + + PGREALM: sets the default realm for Kerberos authentication. I never used + this, so I can't help you. + + Refer to the Postgres documentation for further details. + +NOTES + I didn't make any testsuite for this module, since to test anything it would + require a working Postgres server, and I can't make any assumption + on those... You can try to use the included scripts (they're in the + "pike/src/modules/Postgres/extras" directory + but you'll probably have to patch them to reflect your site's settings. + + Also note that THIS MODULE USES BLOCKING I/O to connect to the server. + Postgres is quite slow, and so you might want to consider this + particular aspect. It is (at least should be) thread-safe, and so it can be used + in a multithread environment. + +THANKS + Many thanks to Henrik Grubbstr�m, without whose help this piece of + code couldn't be nearly as complete as it is. + Also thanks to Frederik Hubinette, for designing such a nice language + as Pike. + +COPYRIGHT + This code and documentation are copyright 1997 Francesco Chemolli + <kinkie@comedia.it>. + It may be copied, modified, redistributed under the terms of the + GNU General Public License, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Pike source. If not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The Pike programming language is copyright Frederik Hubinette, and is + distributed under the terms of the GNU General Public License. For furhter + information, please consult the Pike WWW site, at http://pike.idonex.se/ diff --git a/src/modules/Postgres/doc/sql_postgres_result b/src/modules/Postgres/doc/sql_postgres_result new file mode 100644 index 0000000000000000000000000000000000000000..8533fb5a60352319b8b99d5f7264f1c951ff31aa --- /dev/null +++ b/src/modules/Postgres/doc/sql_postgres_result @@ -0,0 +1,150 @@ +NAME + Sql.postgres_result - result of a Postgres query + +AUTHOR + Francesco Chemolli <kinkie@comedia.it> + +DESCRIPTION + Sql.postgres_result contains the result of a Postgres-query. + +KEYWORDS + sql, database + +SEE ALSO + Sql.postgres, Postgres.postgres, Sql.sql, Sql.sql_result + + +============================================================================ +NAME + create - make a new postgres_result object + +SYNTAX + object(postgres_result) postgres->big_query(string q); + or + object(postgres_result) sql->big_query(string q); + +DESCRIPTION + Notice that you can't create istances of this object yourself. + The only way to create it is via a big_query to a Postgres + database. + +SEE ALSO + postgres->big_query, Sql.postgres + +============================================================================ +NAME + num_rows - number of rows in the result + +SYNTAX + int postgres_result->num_rows(); + +DESCRIPTION + Returns the number of rows in the result. + +SEE ALSO + postgres_result->num_fields + +============================================================================ +NAME + num_fields - number of fields in the result + +SYNTAX + int postgres_result->num_fields(); + +DESCRIPTION + Returns the number of fields in the result. + +SEE ALSO + postgres_result->num_rows + +============================================================================ +NAME + fetch_fields - get informations on the fields of the current result set + +SYNTAX + array(mapping(string:mixed)) postgres_result->fetch_fields(); + +DESCRIPTION + Returns an array with an entry for each field, each entry is + a mapping with the following fields: + + string "name": name of the column + + int "type": the type ID of the field. This is the database's internal + representation type ID. + + int|string "length": can be an integer (the size of the contents in + bytes) or the word "variable". + +NOTA BENE + For char() fields, length is to be intended as the MAXIMUM length + of the field. This is not part of the interface specifications in fact, + but a driver-choice. In fact char() fields are for Postgres _FIXED_ + length fields, and are space-padded. If CUT_TRAILING_SPACES is defined + when the driver is compiled (default behavior) it will cut such spaces. + +SEE ALSO + sql->list_fields + +============================================================================ +NAME + seek - seek the results cursor position + +SYNTAX + void postgres_result->seek(int r); + +DESCRIPTION + Moves the result cursor (ahead or backwards) the specified number of + rows. Notice that when you fetch a row, the cursor is automatically + moved forward one slot. + +SEE ALSO + postgres_result->fetch_row + + +============================================================================ +NAME + fetch_row - fetch the next row from the result + +SYNTAX + #include <postgres.h> + + array(string) postgres_result->fetch_row(); + +DESCRIPTION + Returns an array with the contents of the next row in the result. + Advances the row cursor to the next row. Returns 0 at end of table. + +BUGS + Since there's no generic way to know whether a type is numeric + or not in Postgres, all results are returned as strings. + You can typecast them in Pike to get the numeric value. + +SEE ALSO + postgres_result->seek + +============================================================================ +THANKS + Many thanks to Henrik Grubbstr�m, without whose help this piece of + code couldn't be nearly as complete as it is. + Also thanks to Frederik Hubinette, for designing such a nice language + as Pike. + +COPYRIGHT + This code and documentation are copyright 1997 Francesco Chemolli + <kinkie@comedia.it>. + It may be copied, modified, redistributed under the terms of the + GNU General Public License, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Pike source. If not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The Pike programming language is copyright Frederik Hubinette, and is + distributed under the terms of the GNU General Public License. For furhter + information, please consult the Pike WWW site, at http://pike.idonex.se/ diff --git a/src/modules/Postgres/pgres_config.h.in b/src/modules/Postgres/pgres_config.h.in index e3e2cf876d8fdd99dc518ed251a904509d20e026..b3564808a53c355fb445823490a5adcb88c86eba 100644 --- a/src/modules/Postgres/pgres_config.h.in +++ b/src/modules/Postgres/pgres_config.h.in @@ -1,4 +1,4 @@ -/* $Id: pgres_config.h.in,v 1.1.1.1 1997/10/14 22:07:21 grubba Exp $ */ +/* $Id: pgres_config.h.in,v 1.2 1997/11/25 20:57:57 grubba Exp $ */ #undef STDC_HEADERS #undef HAVE_POSTGRES_H diff --git a/src/modules/Postgres/pgresult.c b/src/modules/Postgres/pgresult.c index e6613ce3bca9aec98ab35127c9d566ac22151287..edf842d6cd02a836b3bc53b679050bb0d0cf2aa8 100644 --- a/src/modules/Postgres/pgresult.c +++ b/src/modules/Postgres/pgresult.c @@ -65,11 +65,9 @@ MUTEX_T pike_postgres_result_mutex; #define PQ_LOCK() mt_lock(&pike_postgres_mutex) #define PQ_UNLOCK() mt_unlock(&pike_postgres_mutex) -#define THREAD() THREADS_ALLOW();PQ_LOCK() -#define UNTHREAD() THREADS_DISQLLOW(); PQ_UNLOCK() #else -#define THREAD() /**/ -#define UNTHREAD() /**/ +#define PQ_LOCK() /**/ +#define PQ_UNLOCK() /**/ #endif #include "pg_types.h" @@ -98,13 +96,6 @@ static void f_create (INT32 args) char *storage; check_all_args("postgres_result->create",args,BIT_OBJECT,0); pgdebug("result->f_create(%d).\n",args); -#if OLD - if (sp[-args].u.object->prog != postgres_program) - error ("Need a postgres type object.\n"); - THIS->result= - ((struct pgres_object_data *)sp[-args].u.object->storage)->last_result; - ((struct pgres_object_data *) sp[-args].u.object->storage)->last_result=NULL; -#endif storage=get_storage(sp[-args].u.object,postgres_program); if (!storage) diff --git a/src/modules/Postgres/postgres.c b/src/modules/Postgres/postgres.c index b96059c6fecafb94a39772246f95b5f42e796c73..4bde4e87e627290859d8b52612ab248f11c90e4b 100644 --- a/src/modules/Postgres/postgres.c +++ b/src/modules/Postgres/postgres.c @@ -1,5 +1,5 @@ /* - * Postgres95 support for pike/0.5 and up + * Postgres95 and PostgreSQL support for pike/0.5 and up * * (C) 1997 Francesco Chemolli <kinkie@comedia.it> * @@ -10,18 +10,20 @@ #include "pgres_config.h" #ifdef HAVE_POSTGRES +#include "version.h" + /* #define PGDEBUG */ /* System includes */ #include <stdlib.h> #include <stdio.h> /* Needed or libpq-fe.h pukes :( */ -#include <malloc.h> #include <string.h> /* Pike includes */ #include <global.h> #include <las.h> #include <machine.h> +#include <pike_memory.h> #include <svalue.h> #include <threads.h> #include <stralloc.h> @@ -34,6 +36,7 @@ #ifdef DEBUG #undef DEBUG #endif + #include <postgres.h> #include <libpq-fe.h> @@ -59,7 +62,7 @@ static void pgdebug (char * a, ...) {} struct program * postgres_program; -RCSID("$Id: postgres.c,v 1.1.1.1 1997/10/14 22:07:21 grubba Exp $"); +RCSID("$Id: postgres.c,v 1.2 1997/11/25 20:57:59 grubba Exp $"); #define THIS ((struct pgres_object_data *) fp->current_storage) @@ -76,9 +79,7 @@ static void pgres_create (struct object * o) { pgdebug ("pgres_create().\n"); THIS->dblink=NULL; THIS->last_error=NULL; - THIS->notify_callback=malloc(sizeof(struct svalue)); - if (!THIS->notify_callback) - error ("Memory allocation error.\n"); + THIS->notify_callback=(struct svalue*)xalloc(sizeof(struct svalue)); THIS->notify_callback->type=T_INT; } @@ -87,11 +88,11 @@ static void pgres_destroy (struct object * o) PGconn * conn; pgdebug ("pgres_destroy().\n"); if ((conn=THIS->dblink)) { - PQ_LOCK(); THREADS_ALLOW(); + PQ_LOCK(); PQfinish(conn); - THREADS_DISALLOW(); PQ_UNLOCK(); + THREADS_DISALLOW(); THIS->dblink=NULL; } if(THIS->last_error) { @@ -110,47 +111,54 @@ static void f_create (INT32 args) char * host=NULL, *db=NULL, *port=NULL; PGconn * conn; - check_all_args("Postgres->create",args, + check_all_args("postgres->create",args, BIT_STRING|BIT_VOID,BIT_STRING|BIT_VOID, BIT_INT|BIT_VOID,0); if (THIS->dblink) { conn=THIS->dblink; - PQ_LOCK(); THREADS_ALLOW(); + PQ_LOCK(); PQfinish(conn); - THREADS_DISALLOW(); PQ_UNLOCK(); + THREADS_DISALLOW(); } if (args>=1) - if(sp[-args].u.string->len) + if(sp[-args].type==T_STRING && sp[-args].u.string->len) host=sp[-args].u.string->str; /* postgres docs say they use hardwired defaults if no variable is found*/ if (args>=2) - if (sp[1-args].u.string->len) + if (sp[1-args].type==T_STRING && sp[1-args].u.string->len) db=sp[1-args].u.string->str; + /* This is not beautiful code, but it works: + * it specifies the port to connect to if there is a third + * argument greater than 0. It accepts integer arguments >= 0 + * to allow simpler code in pike wrappers part. + */ if (args==3) - if (sp[2-args].u.integer <=65535 && sp[2-args].u.integer>0) { - port=malloc(10*sizeof(char)); /*it's enough, we need only 6*/ - sprintf(port,"%d",sp[2-args].u.integer); + if (sp[2-args].type==T_INT && sp[2-args].u.integer <=65535 && sp[2-args].u.integer >= 0) { + if (sp[2-args].u.integer>0) { + port=xalloc(10*sizeof(char)); /*it's enough, we need only 6*/ + sprintf(port,"%d",sp[2-args].u.integer); + } } else - error ("You must specify a TCP/IP port number as argument 5 to postgres->create().\n"); - PQ_LOCK(); + error ("You must specify a TCP/IP port number as argument 5 to Sql.postgres->create().\n"); THREADS_ALLOW(); - pgdebug("f_create(%s,%s,%s).\n",host,port,db); + PQ_LOCK(); + pgdebug("f_create(host: %s, port: %s, db: %s).\n",host,port,db); conn=PQsetdb(host,port,NULL,NULL,db); - THREADS_DISALLOW(); PQ_UNLOCK(); + THREADS_DISALLOW(); if (!conn) - error ("Internal error: PQserdb returned NULL!\n"); + error ("Could not conneect to server\n"); if (PQstatus(conn)!=CONNECTION_OK) { set_error(PQerrorMessage(conn)); - PQ_LOCK(); THREADS_ALLOW(); + PQ_LOCK(); PQfinish(conn); - THREADS_DISALLOW(); PQ_UNLOCK(); + THREADS_DISALLOW(); error("Could not connect to database.\n"); } THIS->dblink=conn; @@ -170,15 +178,15 @@ static void f_select_db (INT32 args) error ("Internal error. How can you possibly not be linked to a " "database already?\n"); conn=THIS->dblink; - PQ_LOCK(); THREADS_ALLOW(); + PQ_LOCK(); host=PQhost(conn); port=PQport(conn); options=PQoptions(conn); tty=PQtty(conn); db=PQdb(conn); - THREADS_DISALLOW(); PQ_UNLOCK(); + THREADS_DISALLOW(); #if 0 /* This is an optimization, but people may want to reset a connection * re-selecting its database. @@ -191,8 +199,8 @@ static void f_select_db (INT32 args) db=sp[-args].u.string->str; /* This could be really done calling f_create, but it's more efficient this * way */ - PQ_LOCK(); THREADS_ALLOW(); + PQ_LOCK(); /* using newconn is necessary or otherwise the datastructures I use * as arguments get freed by PQfinish. Could be a problem under extreme * situations (i.e. if the temporary use of _one_ more filedescriptor @@ -201,8 +209,8 @@ static void f_select_db (INT32 args) newconn=PQsetdb(host,port,options,tty,db); PQfinish(conn); conn=newconn; - THREADS_DISALLOW(); PQ_UNLOCK(); + THREADS_DISALLOW(); if (PQstatus(conn)==CONNECTION_BAD) { set_error(PQerrorMessage(conn)); PQfinish(conn); @@ -229,13 +237,13 @@ static void f_big_query(INT32 args) else query=" "; - PQ_LOCK(); THREADS_ALLOW(); + PQ_LOCK(); pgdebug("f_big_query(\"%s\")\n",query); res=PQexec(conn,query); notification=PQnotifies(conn); - THREADS_DISALLOW(); PQ_UNLOCK(); + THREADS_DISALLOW(); pop_n_elems(args); if (notification!=NULL) { @@ -307,11 +315,11 @@ static void f_reset (INT32 args) if (!THIS->dblink) error ("Not connected.\n"); conn=THIS->dblink; - PQ_LOCK(); THREADS_ALLOW(); + PQ_LOCK(); PQreset(conn); - THREADS_DISALLOW(); PQ_UNLOCK(); + THREADS_DISALLOW(); if (PQstatus(conn)==CONNECTION_BAD) { set_error(PQerrorMessage(conn)); error("Bad connection.\n"); @@ -340,9 +348,10 @@ static void f_trace (INT32 args) } #endif -/* I hope I'm doing this right... */ static void f_callback(INT32 args) { + check_all_args("postgres->_set_notify_callback()",BIT_INT|BIT_FUNCTION,0); + if (sp[-args].type==T_INT) { if (THIS->notify_callback->type!=T_INT) { free_svalue(THIS->notify_callback); @@ -414,6 +423,9 @@ void pike_module_init (void) postgres_program = end_program(); add_program_constant("postgres",postgres_program,0); postgres_program->refs++; + + add_string_constant("version",PGSQL_VERSION,0); + pgresult_init(); } diff --git a/src/modules/Postgres/version.h b/src/modules/Postgres/version.h new file mode 100644 index 0000000000000000000000000000000000000000..ea9649d07094997ddd37e0bb0c5f6ea948e97206 --- /dev/null +++ b/src/modules/Postgres/version.h @@ -0,0 +1,8 @@ +/* + * $Id: version.h,v 1.1 1997/11/25 20:58:00 grubba Exp $ + * + * This file is provided for CVS's sake, and to define a simple string to be + * used as the module's release version + */ + +#define PGSQL_VERSION "Postgres/1.0"