aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pgtclsh
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pgtclsh')
-rw-r--r--src/bin/pgtclsh/Makefile46
-rw-r--r--src/bin/pgtclsh/README21
-rw-r--r--src/bin/pgtclsh/pgtclAppInit.c114
-rw-r--r--src/bin/pgtclsh/pgtclUtils.tcl16
-rw-r--r--src/bin/pgtclsh/pgtkAppInit.c117
-rw-r--r--src/bin/pgtclsh/updateStats.tcl71
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
+}
+