aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-01-25 01:58:40 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2010-01-25 01:58:40 +0000
commit00ef17eb7ffe2b7991adc2db2154947d2d4efbda (patch)
tree77ff0455ae330654e4f96e61803368cd8eed0605
parentd5d0a67b22bfdbdac254a059b2d2a0a9547fc285 (diff)
downloadpostgresql-00ef17eb7ffe2b7991adc2db2154947d2d4efbda.tar.gz
postgresql-00ef17eb7ffe2b7991adc2db2154947d2d4efbda.zip
Apply Tcl_Init() to the "hold" interpreter created by pltcl.
You might think this is unnecessary since that interpreter is never used to run code --- but it turns out that's wrong. As of Tcl 8.5, the "clock" command (alone among builtin Tcl commands) is partially implemented by loaded-on-demand Tcl code, which means that it fails if there's not unknown-command support, and also that it's impossible to run it directly in a safe interpreter. The way they get around the latter is that Tcl_CreateSlave() automatically sets up an alias command that forwards any execution of "clock" in a safe slave interpreter to its parent interpreter. Thus, when attempting to execute "clock" in trusted pltcl, the command actually executes in the "hold" interpreter, where it will fail if unknown-command support hasn't been introduced by sourcing the standard init.tcl script, which is done by Tcl_Init(). (This is a pretty dubious design decision on the Tcl boys' part, if you ask me ... but they didn't.) Back-patch all the way. It's not clear that anyone would try to use ancient versions of pltcl with a recent Tcl, but it's not clear they wouldn't, either. Also add a regression test using "clock", in branches that have regression test support for pltcl. Per recent trouble report from Kyle Bateman.
-rw-r--r--src/pl/tcl/expected/pltcl_setup.out20
-rw-r--r--src/pl/tcl/pltcl.c7
-rw-r--r--src/pl/tcl/sql/pltcl_setup.sql11
3 files changed, 36 insertions, 2 deletions
diff --git a/src/pl/tcl/expected/pltcl_setup.out b/src/pl/tcl/expected/pltcl_setup.out
index e168b121b86..7923ef5cdaf 100644
--- a/src/pl/tcl/expected/pltcl_setup.out
+++ b/src/pl/tcl/expected/pltcl_setup.out
@@ -402,3 +402,23 @@ create operator @< (
rightarg = int4,
procedure = tcl_int4lt
);
+--
+-- Test usage of Tcl's "clock" command. In recent Tcl versions this
+-- command fails without working "unknown" support, so it's a good canary
+-- for initialization problems.
+--
+create function tcl_date_week(int4,int4,int4) returns text as '
+ return [clock format [clock scan "$2/$3/$1"] -format "%U"]
+' language pltcl immutable;
+select tcl_date_week(2010,1,24);
+ tcl_date_week
+---------------
+ 04
+(1 row)
+
+select tcl_date_week(2001,10,24);
+ tcl_date_week
+---------------
+ 42
+(1 row)
+
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 3d118938a84..77e2b6b8d71 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -31,7 +31,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.98.2.3 2008/06/17 00:53:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.98.2.4 2010/01/25 01:58:40 tgl Exp $
*
**********************************************************************/
@@ -244,9 +244,12 @@ pltcl_init(void)
************************************************************/
if ((pltcl_hold_interp = Tcl_CreateInterp()) == NULL)
elog(ERROR, "could not create \"hold\" interpreter");
+ if (Tcl_Init(pltcl_hold_interp) == TCL_ERROR)
+ elog(ERROR, "could not initialize \"hold\" interpreter");
/************************************************************
- * Create the two interpreters
+ * Create the two slave interpreters. Note: Tcl automatically does
+ * Tcl_Init on the normal slave, and it's not wanted for the safe slave.
************************************************************/
if ((pltcl_norm_interp =
Tcl_CreateSlave(pltcl_hold_interp, "norm", 0)) == NULL)
diff --git a/src/pl/tcl/sql/pltcl_setup.sql b/src/pl/tcl/sql/pltcl_setup.sql
index 78ddd867eb4..17e09babb30 100644
--- a/src/pl/tcl/sql/pltcl_setup.sql
+++ b/src/pl/tcl/sql/pltcl_setup.sql
@@ -436,3 +436,14 @@ create operator @< (
procedure = tcl_int4lt
);
+--
+-- Test usage of Tcl's "clock" command. In recent Tcl versions this
+-- command fails without working "unknown" support, so it's a good canary
+-- for initialization problems.
+--
+create function tcl_date_week(int4,int4,int4) returns text as '
+ return [clock format [clock scan "$2/$3/$1"] -format "%U"]
+' language pltcl immutable;
+
+select tcl_date_week(2010,1,24);
+select tcl_date_week(2001,10,24);