diff options
Diffstat (limited to 'src/bin/pgtclsh')
-rw-r--r-- | src/bin/pgtclsh/Makefile | 46 | ||||
-rw-r--r-- | src/bin/pgtclsh/README | 21 | ||||
-rw-r--r-- | src/bin/pgtclsh/pgtclAppInit.c | 114 | ||||
-rw-r--r-- | src/bin/pgtclsh/pgtclUtils.tcl | 16 | ||||
-rw-r--r-- | src/bin/pgtclsh/pgtkAppInit.c | 117 | ||||
-rw-r--r-- | src/bin/pgtclsh/updateStats.tcl | 71 |
6 files changed, 385 insertions, 0 deletions
diff --git a/src/bin/pgtclsh/Makefile b/src/bin/pgtclsh/Makefile new file mode 100644 index 00000000000..a99ab39f082 --- /dev/null +++ b/src/bin/pgtclsh/Makefile @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------- +# +# Makefile +# Makefile for a tclsh workalike with pgtcl commands installed +# +# Copyright (c) 1994, Regents of the University of California +# +# +# IDENTIFICATION +# $Header: /cvsroot/pgsql/src/bin/pgtclsh/Attic/Makefile,v 1.1.1.1 1996/07/09 06:22:15 scrappy Exp $ +# +#------------------------------------------------------------------------- + +MKDIR= ../../mk +include $(MKDIR)/postgres.mk +include ../Makefile.global + +CFLAGS+= -I$(TCL_INCDIR) -I$(TK_INCDIR) + +# try to find libpgtcl.a in either directory +LIBPGTCL= -L$(srcdir)/libpgtcl/$(objdir) -L$(LIBDIR) -lpgtcl + +pgtclsh: $(objdir)/pgtclAppInit.o + $(CC) $(CDEBUG) -o $(objdir)/$(@F) $(objdir)/pgtclAppInit.o\ + $(LIBPGTCL) $(LIBPQ) -L$(TCL_LIBDIR) $(TCL_LIB) -lm $(LD_ADD) + +pgtksh: $(objdir)/pgtkAppInit.o + $(CC) $(CDEBUG) -o $(objdir)/$(@F) $(objdir)/pgtkAppInit.o \ + $(LIBPGTCL) $(LIBPQ) -L$(TCL_LIBDIR) -L$(TK_LIBDIR) \ + $(TK_LIB) $(TCL_LIB) -lX11 -lm $(LD_ADD) + +install:: localobj pgtclsh pgtksh + $(INSTALL) $(INSTL_EXE_OPTS) $(objdir)/pgtclsh $(DESTDIR)$(BINDIR)/pgtclsh + $(INSTALL) $(INSTL_EXE_OPTS) $(objdir)/pgtksh $(DESTDIR)$(BINDIR)/pgtksh + +CLEANFILES = pgtclAppInit.o pgtkAppInit.o pgtclsh pgtksh + +PROG=pgtclsh + +all:: pgtclsh pgtksh + +# don't use the default template for generating executables since we have +# two executable targets +# include $(MKDIR)/postgres.prog.mk + + diff --git a/src/bin/pgtclsh/README b/src/bin/pgtclsh/README new file mode 100644 index 00000000000..bbd89e012f9 --- /dev/null +++ b/src/bin/pgtclsh/README @@ -0,0 +1,21 @@ +pgtclsh is an example of a tclsh extended with the new Tcl +commands provided by the libpgtcl library. By using pgtclsh, one can +write front-end applications to Postgres95 in Tcl without having to +deal with any libpq programming at all. + +The pgtclsh is an enhanced version of tclsh. Similarly, pgtksh is a +wish replacement with postgres95 bindings. The Makefile is also set up +so that you can choose "pgtksh" as a target. + +pgtclsh has been tested with the official releases of + Tcl version 7.4 +and Tk version 4.0 + +and will probably not work with versions older than those (including +earlier beta releases). + +For details of the libpgtcl interface, please see the file +src/doc/libpgtcl.doc. + +If you have any questions or bug reports, please send them to +Jolly Chen at jolly@cs.berkeley.edu. diff --git a/src/bin/pgtclsh/pgtclAppInit.c b/src/bin/pgtclsh/pgtclAppInit.c new file mode 100644 index 00000000000..cc38ca34a70 --- /dev/null +++ b/src/bin/pgtclsh/pgtclAppInit.c @@ -0,0 +1,114 @@ +/* + * pgtclAppInit.c -- + * + * a skeletal Tcl_AppInit that provides pgtcl initialization + * to create a tclsh that can talk to pglite backends + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#ifndef lint +static char sccsid[] = "@(#) tclAppInit.c 1.11 94/12/17 16:14:03"; +#endif /* not lint */ + +#include "tcl.h" + +#include "libpgtcl.h" + +/* + * The following variable is a special hack that is needed in order for + * Sun shared libraries to be used for Tcl. + */ + +#ifdef NEED_MATHERR +extern int matherr(); +int *tclDummyMathPtr = (int *) matherr; +#endif + +/* + *---------------------------------------------------------------------- + * + * main -- + * + * This is the main program for the application. + * + * Results: + * None: Tcl_Main never returns here, so this procedure never + * returns either. + * + * Side effects: + * Whatever the application does. + * + *---------------------------------------------------------------------- + */ + +int +main(argc, argv) + int argc; /* Number of command-line arguments. */ + char **argv; /* Values of command-line arguments. */ +{ + Tcl_Main(argc, argv, Tcl_AppInit); + return 0; /* Needed only to prevent compiler warning. */ +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppInit -- + * + * This procedure performs application-specific initialization. + * Most applications, especially those that incorporate additional + * packages, will have their own version of this procedure. + * + * Results: + * Returns a standard Tcl completion code, and leaves an error + * message in interp->result if an error occurs. + * + * Side effects: + * Depends on the startup script. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_AppInit(interp) + Tcl_Interp *interp; /* Interpreter for application. */ +{ + if (Tcl_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * Call the init procedures for included packages. Each call should + * look like this: + * + * if (Mod_Init(interp) == TCL_ERROR) { + * return TCL_ERROR; + * } + * + * where "Mod" is the name of the module. + */ + + if (Pg_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * Call Tcl_CreateCommand for application-specific commands, if + * they weren't already created by the init procedures called above. + */ + + /* + * Specify a user-specific startup file to invoke if the application + * is run interactively. Typically the startup file is "~/.apprc" + * where "app" is the name of the application. If this line is deleted + * then no user-specific startup file will be run under any conditions. + */ + + tcl_RcFileName = "~/.tclshrc"; + return TCL_OK; +} diff --git a/src/bin/pgtclsh/pgtclUtils.tcl b/src/bin/pgtclsh/pgtclUtils.tcl new file mode 100644 index 00000000000..dff87a484f4 --- /dev/null +++ b/src/bin/pgtclsh/pgtclUtils.tcl @@ -0,0 +1,16 @@ +# getDBs : +# get the names of all the databases at a given host and port number +# with the defaults being the localhost and port 5432 +# return them in alphabetical order +proc getDBs { {host "localhost"} {port "5432"} } { + # datnames is the list to be result + set conn [pg_connect template1 -host $host -port $port] + set res [pg_exec $conn "SELECT datname FROM pg_database ORDER BY datname"] + set ntups [pg_result $res -numTuples] + for {set i 0} {$i < $ntups} {incr i} { + lappend datnames [pg_result $res -getTuple $i] + } + pg_disconnect $conn + return $datnames +} + diff --git a/src/bin/pgtclsh/pgtkAppInit.c b/src/bin/pgtclsh/pgtkAppInit.c new file mode 100644 index 00000000000..33763458b51 --- /dev/null +++ b/src/bin/pgtclsh/pgtkAppInit.c @@ -0,0 +1,117 @@ +/* + * pgtkAppInit.c -- + * + * a skeletal Tcl_AppInit that provides pgtcl initialization + * to create a tclsh that can talk to pglite backends + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#ifndef lint +static char sccsid[] = "@(#) tkAppInit.c 1.12 94/12/17 16:30:56"; +#endif /* not lint */ + +#include "tk.h" +#include "libpgtcl.h" + +/* + * The following variable is a special hack that is needed in order for + * Sun shared libraries to be used for Tcl. + */ + +#ifdef NEED_MATHERR +extern int matherr(); +int *tclDummyMathPtr = (int *) matherr; +#endif + +/* + *---------------------------------------------------------------------- + * + * main -- + * + * This is the main program for the application. + * + * Results: + * None: Tk_Main never returns here, so this procedure never + * returns either. + * + * Side effects: + * Whatever the application does. + * + *---------------------------------------------------------------------- + */ + +int +main(argc, argv) + int argc; /* Number of command-line arguments. */ + char **argv; /* Values of command-line arguments. */ +{ + Tk_Main(argc, argv, Tcl_AppInit); + return 0; /* Needed only to prevent compiler warning. */ +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppInit -- + * + * This procedure performs application-specific initialization. + * Most applications, especially those that incorporate additional + * packages, will have their own version of this procedure. + * + * Results: + * Returns a standard Tcl completion code, and leaves an error + * message in interp->result if an error occurs. + * + * Side effects: + * Depends on the startup script. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_AppInit(interp) + Tcl_Interp *interp; /* Interpreter for application. */ +{ + Tk_Window main; + + if (Tcl_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + if (Tk_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * Call the init procedures for included packages. Each call should + * look like this: + * + * if (Mod_Init(interp) == TCL_ERROR) { + * return TCL_ERROR; + * } + * + * where "Mod" is the name of the module. + */ + + if (Pg_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + /* + * Call Tcl_CreateCommand for application-specific commands, if + * they weren't already created by the init procedures called above. + */ + + /* + * Specify a user-specific startup file to invoke if the application + * is run interactively. Typically the startup file is "~/.apprc" + * where "app" is the name of the application. If this line is deleted + * then no user-specific startup file will be run under any conditions. + */ + + tcl_RcFileName = "~/.wishrc"; + return TCL_OK; +} diff --git a/src/bin/pgtclsh/updateStats.tcl b/src/bin/pgtclsh/updateStats.tcl new file mode 100644 index 00000000000..62c9564fea1 --- /dev/null +++ b/src/bin/pgtclsh/updateStats.tcl @@ -0,0 +1,71 @@ +# +# updateStats +# updates the statistic of number of distinct attribute values +# (this should really be done by the vacuum command) +# this is kind of brute force and slow, but it works +# since we use SELECT DISTINCT to calculate the number of distinct values +# and that does a sort, you need to have plenty of disk space for the +# intermediate sort files. +# +# - jolly 6/8/95 + +# +# update_attnvals +# takes in a table and updates the attnvals columns for the attributes +# of that table +# +# conn is the database connection +# rel is the table name +proc update_attnvals {conn rel} { + + # first, get the oid of the rel + set res [pg_exec $conn "SELECT oid FROM pg_class where relname = '$rel'"] + if { [pg_result $res -numTuples] == "0"} { + puts stderr "update_attnvals: Relation named $rel was not found" + return + } + set oid [pg_result $res -getTuple 0] + pg_result $res -clear + + # use this query to find the names of the attributes + set res [pg_exec $conn "SELECT * FROM $rel WHERE 'f'::bool"] + set attrNames [pg_result $res -attributes] + + puts "attrNames = $attrNames" + foreach att $attrNames { + # find how many distinct values there are for this attribute + # this may fail if the user-defined type doesn't have + # comparison operators defined + set res2 [pg_exec $conn "SELECT DISTINCT $att FROM $rel"] + set NVALS($att) [pg_result $res2 -numTuples] + puts "NVALS($att) is $NVALS($att)" + pg_result $res2 -clear + } + pg_result $res -clear + + # now, update the pg_attribute table + foreach att $attrNames { + # first find the oid of the row to change + set res [pg_exec $conn "SELECT oid FROM pg_attribute a WHERE a.attname = '$att' and a.attrelid = '$oid'"] + set attoid [pg_result $res -getTuple 0] + set res2 [pg_exec $conn "UPDATE pg_attribute SET attnvals = $NVALS($att) where pg_attribute.oid = '$attoid'::oid"] + } +} + +# updateStats +# takes in a database name +# and updates the attnval stat for all the user-defined tables +# in the database +proc updateStats { dbName } { + # datnames is the list to be result + set conn [pg_connect $dbName] + set res [pg_exec $conn "SELECT relname FROM pg_class WHERE relkind = 'r' and relname !~ '^pg_' and relname !~ '^Xinv'"] + set ntups [pg_result $res -numTuples] + for {set i 0} {$i < $ntups} {incr i} { + set rel [pg_result $res -getTuple $i] + puts "updating attnvals stats on table $rel" + update_attnvals $conn $rel + } + pg_disconnect $conn +} + |