Thread: libpgtcl doesn't use UTF encoding of TCL

libpgtcl doesn't use UTF encoding of TCL

From
pgsql-bugs@postgresql.org
Date:
Eugene Faukin (elf@solvo.ru) reports a bug with a severity of 2
The lower the number the more severe it is.

Short Description
libpgtcl doesn't use UTF encoding of TCL

Long Description
Modern versions of the TCL (8.2 at least) use UTF encoding to internal
storage of the text. libpgtcl uses TCL functions to insert strings directly
into TCL internal structure without any conversion.


Sample Code
I can suggest you next patch I use for myself:

diff -uNr postgresql-7.0.2.orig/src/interfaces/libpgtcl/pgtclCmds.c
postgresql-7.0.2/src/interfaces/libpgtcl/pgtclCmds.c
--- postgresql-7.0.2.orig/src/interfaces/libpgtcl/pgtclCmds.c   Wed Apr 12 21:17:11 2000
+++ postgresql-7.0.2/src/interfaces/libpgtcl/pgtclCmds.c        Thu Nov 16 20:26:37 2000
@@ -431,6 +431,7 @@
        Pg_ConnectionId *connid;
        PGconn     *conn;
        PGresult   *result;
+       Tcl_DString putString;

        if (argc != 3)
        {
@@ -449,7 +450,9 @@
                return TCL_ERROR;
        }

-       result = PQexec(conn, argv[2]);
+       Tcl_UtfToExternalDString(NULL, argv[2], -1, &putString);
+       result = PQexec(conn, Tcl_DStringValue(&putString));
+       Tcl_DStringFree(&putString);

        /* Transfer any notify events from libpq to Tcl event queue. */
        PgNotifyTransferEvents(connid);
@@ -535,6 +538,7 @@
        char       *arrVar;
        char            nameBuffer[256];
        const char *appendstr;
+       Tcl_DString retString;

        if (argc < 3 || argc > 5)
        {
@@ -685,11 +689,24 @@
                }
 #ifdef TCL_ARRAYS
                for (i = 0; i < PQnfields(result); i++)
-                       Tcl_AppendElement(interp, tcl_value(PQgetvalue(result, tupno, i)));
+               {
+                   Tcl_ExternalToUtfDString(NULL,
+                                            tcl_value(PQgetvalue(result,
+                                                                 tupno, i)),
+                                            -1, &retString);
+                   Tcl_AppendElement(interp, Tcl_DStringValue(&retString));
+               }
 #else
                for (i = 0; i < PQnfields(result); i++)
-                       Tcl_AppendElement(interp, PQgetvalue(result, tupno, i));
+               {
+                   Tcl_ExternalToUtfDString(NULL,
+                                            PQgetvalue(result, tupno, i),
+                                            -1, &retString);
+
+                   Tcl_AppendElement(interp, Tcl_DStringValue(&retString));
+               }
 #endif
+               Tcl_DStringFree(&retString);
                return TCL_OK;
        }
        else if (strcmp(opt, "-tupleArray") == 0)
@@ -707,21 +724,35 @@
                }
                for (i = 0; i < PQnfields(result); i++)
                {
-                       if (Tcl_SetVar2(interp, argv[4], PQfname(result, i),
+                   Tcl_ExternalToUtfDString(NULL,
 #ifdef TCL_ARRAYS
-                                                       tcl_value(PQgetvalue(result, tupno, i)),
+                                            tcl_value(PQgetvalue(result,
+                                                                 tupno, i)),
 #else
-                                                       PQgetvalue(result, tupno, i),
+                                            PQgetvalue(result, tupno, i),
 #endif
-                                                       TCL_LEAVE_ERR_MSG) == NULL)
-                               return TCL_ERROR;
+                                            -1, &retString);
+
+                   if (Tcl_SetVar2(interp, argv[4], PQfname(result, i),
+                                   Tcl_DStringValue(&retString),
+                                   TCL_LEAVE_ERR_MSG) == NULL)
+                   {
+                       Tcl_DStringFree(&retString);
+                       return TCL_ERROR;
+                   }
                }
+               Tcl_DStringFree(&retString);
                return TCL_OK;
        }
        else if (strcmp(opt, "-attributes") == 0)
        {
                for (i = 0; i < PQnfields(result); i++)
-                       Tcl_AppendElement(interp, PQfname(result, i));
+               {
+                   Tcl_ExternalToUtfDString(NULL, PQfname(result, i),
+                                            -1, &retString);
+                   Tcl_AppendElement(interp, Tcl_DStringValue(&retString));
+                   Tcl_DStringFree(&retString);
+               }
                return TCL_OK;
        }
        else if (strcmp(opt, "-lAttributes") == 0)
@@ -1274,6 +1305,8 @@
                                column,
                                ncols;
        Tcl_DString headers;
+       Tcl_DString retString;
+       Tcl_DString putString;
        char            buffer[2048];
        struct info_s
        {
@@ -1292,7 +1325,11 @@
        if (conn == (PGconn *) NULL)
                return TCL_ERROR;

-       if ((result = PQexec(conn, argv[2])) == 0)
+       Tcl_UtfToExternalDString(NULL, argv[2], -1, &putString);
+       result = PQexec(conn, Tcl_DStringValue(&putString));
+       Tcl_DStringFree(&putString);
+
+       if (result == 0)
        {
                /* error occurred sending the query */
                Tcl_SetResult(interp, PQerrorMessage(conn), TCL_VOLATILE);
@@ -1340,13 +1377,21 @@
                Tcl_SetVar2(interp, argv[3], ".tupno", buffer, 0);

                for (column = 0; column < ncols; column++)
-                       Tcl_SetVar2(interp, argv[3], info[column].cname,
+               {
+                   Tcl_ExternalToUtfDString(NULL,
 #ifdef TCL_ARRAYS
-                                               tcl_value(PQgetvalue(result, tupno, column)),
+                                            tcl_value(PQgetvalue(result,
+                                                                 tupno,
+                                                                 column)),
 #else
-                                               PQgetvalue(result, tupno, column),
+                                            PQgetvalue(result, tupno, column),
 #endif
-                                               0);
+                                            -1, &retString);
+
+                   Tcl_SetVar2(interp, argv[3], info[column].cname,
+                               Tcl_DStringValue(&retString), 0);
+                   Tcl_DStringFree(&retString);
+               }

                Tcl_SetVar2(interp, argv[3], ".command", "update", 0);



No file was uploaded with this report

Re: libpgtcl doesn't use UTF encoding of TCL

From
Bruce Momjian
Date:
Do you have any idea how this will work with earlier TCL versions?  When
was Tcl_UtfToExternalDString added to TCL?

> Eugene Faukin (elf@solvo.ru) reports a bug with a severity of 2
> The lower the number the more severe it is.
>
> Short Description
> libpgtcl doesn't use UTF encoding of TCL
>
> Long Description
> Modern versions of the TCL (8.2 at least) use UTF encoding to internal
> storage of the text. libpgtcl uses TCL functions to insert strings directly
> into TCL internal structure without any conversion.
>
>
> Sample Code
> I can suggest you next patch I use for myself:
>
> diff -uNr postgresql-7.0.2.orig/src/interfaces/libpgtcl/pgtclCmds.c
postgresql-7.0.2/src/interfaces/libpgtcl/pgtclCmds.c
> --- postgresql-7.0.2.orig/src/interfaces/libpgtcl/pgtclCmds.c   Wed Apr 12 21:17:11 2000
> +++ postgresql-7.0.2/src/interfaces/libpgtcl/pgtclCmds.c        Thu Nov 16 20:26:37 2000
> @@ -431,6 +431,7 @@
>         Pg_ConnectionId *connid;
>         PGconn     *conn;
>         PGresult   *result;
> +       Tcl_DString putString;
>
>         if (argc != 3)
>         {
> @@ -449,7 +450,9 @@
>                 return TCL_ERROR;
>         }
>
> -       result = PQexec(conn, argv[2]);
> +       Tcl_UtfToExternalDString(NULL, argv[2], -1, &putString);
> +       result = PQexec(conn, Tcl_DStringValue(&putString));
> +       Tcl_DStringFree(&putString);
>
>         /* Transfer any notify events from libpq to Tcl event queue. */
>         PgNotifyTransferEvents(connid);
> @@ -535,6 +538,7 @@
>         char       *arrVar;
>         char            nameBuffer[256];
>         const char *appendstr;
> +       Tcl_DString retString;
>
>         if (argc < 3 || argc > 5)
>         {
> @@ -685,11 +689,24 @@
>                 }
>  #ifdef TCL_ARRAYS
>                 for (i = 0; i < PQnfields(result); i++)
> -                       Tcl_AppendElement(interp, tcl_value(PQgetvalue(result, tupno, i)));
> +               {
> +                   Tcl_ExternalToUtfDString(NULL,
> +                                            tcl_value(PQgetvalue(result,
> +                                                                 tupno, i)),
> +                                            -1, &retString);
> +                   Tcl_AppendElement(interp, Tcl_DStringValue(&retString));
> +               }
>  #else
>                 for (i = 0; i < PQnfields(result); i++)
> -                       Tcl_AppendElement(interp, PQgetvalue(result, tupno, i));
> +               {
> +                   Tcl_ExternalToUtfDString(NULL,
> +                                            PQgetvalue(result, tupno, i),
> +                                            -1, &retString);
> +
> +                   Tcl_AppendElement(interp, Tcl_DStringValue(&retString));
> +               }
>  #endif
> +               Tcl_DStringFree(&retString);
>                 return TCL_OK;
>         }
>         else if (strcmp(opt, "-tupleArray") == 0)
> @@ -707,21 +724,35 @@
>                 }
>                 for (i = 0; i < PQnfields(result); i++)
>                 {
> -                       if (Tcl_SetVar2(interp, argv[4], PQfname(result, i),
> +                   Tcl_ExternalToUtfDString(NULL,
>  #ifdef TCL_ARRAYS
> -                                                       tcl_value(PQgetvalue(result, tupno, i)),
> +                                            tcl_value(PQgetvalue(result,
> +                                                                 tupno, i)),
>  #else
> -                                                       PQgetvalue(result, tupno, i),
> +                                            PQgetvalue(result, tupno, i),
>  #endif
> -                                                       TCL_LEAVE_ERR_MSG) == NULL)
> -                               return TCL_ERROR;
> +                                            -1, &retString);
> +
> +                   if (Tcl_SetVar2(interp, argv[4], PQfname(result, i),
> +                                   Tcl_DStringValue(&retString),
> +                                   TCL_LEAVE_ERR_MSG) == NULL)
> +                   {
> +                       Tcl_DStringFree(&retString);
> +                       return TCL_ERROR;
> +                   }
>                 }
> +               Tcl_DStringFree(&retString);
>                 return TCL_OK;
>         }
>         else if (strcmp(opt, "-attributes") == 0)
>         {
>                 for (i = 0; i < PQnfields(result); i++)
> -                       Tcl_AppendElement(interp, PQfname(result, i));
> +               {
> +                   Tcl_ExternalToUtfDString(NULL, PQfname(result, i),
> +                                            -1, &retString);
> +                   Tcl_AppendElement(interp, Tcl_DStringValue(&retString));
> +                   Tcl_DStringFree(&retString);
> +               }
>                 return TCL_OK;
>         }
>         else if (strcmp(opt, "-lAttributes") == 0)
> @@ -1274,6 +1305,8 @@
>                                 column,
>                                 ncols;
>         Tcl_DString headers;
> +       Tcl_DString retString;
> +       Tcl_DString putString;
>         char            buffer[2048];
>         struct info_s
>         {
> @@ -1292,7 +1325,11 @@
>         if (conn == (PGconn *) NULL)
>                 return TCL_ERROR;
>
> -       if ((result = PQexec(conn, argv[2])) == 0)
> +       Tcl_UtfToExternalDString(NULL, argv[2], -1, &putString);
> +       result = PQexec(conn, Tcl_DStringValue(&putString));
> +       Tcl_DStringFree(&putString);
> +
> +       if (result == 0)
>         {
>                 /* error occurred sending the query */
>                 Tcl_SetResult(interp, PQerrorMessage(conn), TCL_VOLATILE);
> @@ -1340,13 +1377,21 @@
>                 Tcl_SetVar2(interp, argv[3], ".tupno", buffer, 0);
>
>                 for (column = 0; column < ncols; column++)
> -                       Tcl_SetVar2(interp, argv[3], info[column].cname,
> +               {
> +                   Tcl_ExternalToUtfDString(NULL,
>  #ifdef TCL_ARRAYS
> -                                               tcl_value(PQgetvalue(result, tupno, column)),
> +                                            tcl_value(PQgetvalue(result,
> +                                                                 tupno,
> +                                                                 column)),
>  #else
> -                                               PQgetvalue(result, tupno, column),
> +                                            PQgetvalue(result, tupno, column),
>  #endif
> -                                               0);
> +                                            -1, &retString);
> +
> +                   Tcl_SetVar2(interp, argv[3], info[column].cname,
> +                               Tcl_DStringValue(&retString), 0);
> +                   Tcl_DStringFree(&retString);
> +               }
>
>                 Tcl_SetVar2(interp, argv[3], ".command", "update", 0);
>
>
>
> No file was uploaded with this report
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: libpgtcl doesn't use UTF encoding of TCL

From
Bruce Momjian
Date:
> On Wed, 18 Jul 2001, Bruce Momjian wrote:
>
> > Do you have any idea how this will work with earlier TCL versions?
>
> It won't. If pgtcl is supposed to still be able to compile with older
> versions of Tcl, the changes have to be made a compile time option.

Can't we probe the TCL version in the code and handle it that way?

> > When was Tcl_UtfToExternalDString added to TCL?
>
> According to Tcl's changelog files, it was added in 1997 for Tcl 8.1
> wich was released in 1999.

Shame.  I think we could have required Tcl 8.X but clearly we can't be
requring >= 8.1.  I have 8.0 here and I am sure many do as well.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: libpgtcl doesn't use UTF encoding of TCL

From
Reinhard Max
Date:
On Wed, 18 Jul 2001, Bruce Momjian wrote:

> Do you have any idea how this will work with earlier TCL versions?

It won't. If pgtcl is supposed to still be able to compile with older
versions of Tcl, the changes have to be made a compile time option.

> When was Tcl_UtfToExternalDString added to TCL?

According to Tcl's changelog files, it was added in 1997 for Tcl 8.1
wich was released in 1999.

cu
    Reinhard Max

Maintainer of the Tcl/Tk and PostgreSQL packages for SuSE Linux

Re: libpgtcl doesn't use UTF encoding of TCL

From
Tom Lane
Date:
Reinhard Max <max@suse.de> writes:
> On Wed, 18 Jul 2001, Bruce Momjian wrote:
>> Do you have any idea how this will work with earlier TCL versions?

> It won't. If pgtcl is supposed to still be able to compile with older
> versions of Tcl, the changes have to be made a compile time option.

Please do that and resubmit the patch.  We really don't want to give up
backwards compatibility just yet.

            regards, tom lane

Re: libpgtcl doesn't use UTF encoding of TCL

From
Bruce Momjian
Date:
> On Wed, Jul 18, 2001 at 02:53:22PM -0400, Tom Lane wrote:
>
> > > It won't. If pgtcl is supposed to still be able to compile with older
> > > versions of Tcl, the changes have to be made a compile time option.
> >
> > Please do that and resubmit the patch.  We really don't want to give up
> > backwards compatibility just yet.
> >
>
> Thank you, gentlemans :-)
> I will be interest with this result too.

I believe $tcl_version is what you want to use to test.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: libpgtcl doesn't use UTF encoding of TCL

From
Reinhard Max
Date:
On Wed, 18 Jul 2001, Tom Lane wrote:

> Reinhard Max <max@suse.de> writes:
> > On Wed, 18 Jul 2001, Bruce Momjian wrote:
> >> Do you have any idea how this will work with earlier TCL versions?
>
> > It won't. If pgtcl is supposed to still be able to compile with older
> > versions of Tcl, the changes have to be made a compile time option.
>
> Please do that and resubmit the patch.

OK, I'll pack the new stuff inside #ifdef TCL_UTF8 and define that if
the Tcl version is 8.1 or greater.

Can anybody tell me, if that TCL_ARRAYS stuff is still good for
something? If I could remove it, TCL_UTF8 would be less complex at
some places, because I'd only have to cover two instead of four cases.

BTW, I think the proposed Patch doesn't go far enough as it assumes
the database (client) encoding is identical to the system encoding by
using NULL as the first argument for Tcl_UtfToExternalDString and
Tcl_ExternalToUtfDString. I think it should instead either use the
database's encoding for the conversion to be correct or set
PostgreSQL's client encoding to UNICODE so that no conversion would be
needed. Unfortunately, I don't have the time to do that at the moment.

> We really don't want to give up backwards compatibility just yet.

How far do you want it to be backwards compatible? If >= 8.0 is OK,
I'll possibly overwork libpq later this year to use Tcl's object
interface. I expect at least some performance gain out of this.

cu
    Reinhard

Re: libpgtcl doesn't use UTF encoding of TCL

From
Reinhard Max
Date:
On Wed, 18 Jul 2001, Tom Lane wrote:

> Reinhard Max <max@suse.de> writes:
> > On Wed, 18 Jul 2001, Bruce Momjian wrote:
> >> Do you have any idea how this will work with earlier TCL versions?
>
> > It won't. If pgtcl is supposed to still be able to compile with older
> > versions of Tcl, the changes have to be made a compile time option.
>
> Please do that and resubmit the patch.

Here it is, but I consider it still incomplete and I have not done
exhaustive testing. Some more occurrences of PQexec and PQgetvalue
need to be wrapped up with UTF8 conversion, but I'll not have the time
to do it for the next 1-2 weeks.

cu
    Reinhard

Re: libpgtcl doesn't use UTF encoding of TCL

From
Bruce Momjian
Date:
> On Wed, 18 Jul 2001, Tom Lane wrote:
>
> > Reinhard Max <max@suse.de> writes:
> > > On Wed, 18 Jul 2001, Bruce Momjian wrote:
> > >> Do you have any idea how this will work with earlier TCL versions?
> >
> > > It won't. If pgtcl is supposed to still be able to compile with older
> > > versions of Tcl, the changes have to be made a compile time option.
> >
> > Please do that and resubmit the patch.
>
> OK, I'll pack the new stuff inside #ifdef TCL_UTF8 and define that if
> the Tcl version is 8.1 or greater.

Is the TCL_UTF8 some variable that gets set at tcl runtime?  I hope so.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: libpgtcl doesn't use UTF encoding of TCL

From
Peter Eisentraut
Date:
Reinhard Max writes:

> OK, I'll pack the new stuff inside #ifdef TCL_UTF8 and define that if
> the Tcl version is 8.1 or greater.

No, please add a configure check for Tcl_UtfToExternalDString or some
other function representative of this interface..

--
Peter Eisentraut   peter_e@gmx.net   http://funkturm.homeip.net/~peter

Re: libpgtcl doesn't use UTF encoding of TCL

From
Bruce Momjian
Date:
> On Fri, 20 Jul 2001, Peter Eisentraut wrote:
>
> > Reinhard Max writes:
> >
> > > OK, I'll pack the new stuff inside #ifdef TCL_UTF8 and define that if
> > > the Tcl version is 8.1 or greater.
> >
> > No, please add a configure check for Tcl_UtfToExternalDString or
> > some other function representative of this interface..
>
> Why make simple things complicated?
> Tcl changed it's internal string representation starting with release
> 8.1 . It is not an interface one can decide whether to use it or not.
> Every extension that imports or exports strings and gets compiled for
> Tcl >= 8.1 has to make sure that they are UTF8 regardless, if it uses
> the Tcl_*Utf*DString functions or something else. So I consider it
> sufficient to define TCL_UTF8 if Tcl's Version is >= 8.1 as I did in
> the patch that was attached to my last mail.

I think he is OK checking the TCL version.  It is pretty common to check
the TCL include file for symbols and handle things that way.  Do we test
any other TCL include defines from configure?

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: libpgtcl doesn't use UTF encoding of TCL

From
Reinhard Max
Date:
On Fri, 20 Jul 2001, Peter Eisentraut wrote:

> Reinhard Max writes:
>
> > OK, I'll pack the new stuff inside #ifdef TCL_UTF8 and define that if
> > the Tcl version is 8.1 or greater.
>
> No, please add a configure check for Tcl_UtfToExternalDString or
> some other function representative of this interface..

Why make simple things complicated?
Tcl changed it's internal string representation starting with release
8.1 . It is not an interface one can decide whether to use it or not.
Every extension that imports or exports strings and gets compiled for
Tcl >= 8.1 has to make sure that they are UTF8 regardless, if it uses
the Tcl_*Utf*DString functions or something else. So I consider it
sufficient to define TCL_UTF8 if Tcl's Version is >= 8.1 as I did in
the patch that was attached to my last mail.

cu
    Reinhard

Re: libpgtcl doesn't use UTF encoding of TCL

From
Bruce Momjian
Date:
> > On Wed, 18 Jul 2001, Tom Lane wrote:
> >
> > > Reinhard Max <max@suse.de> writes:
> > > > On Wed, 18 Jul 2001, Bruce Momjian wrote:
> > > >> Do you have any idea how this will work with earlier TCL versions?
> > >
> > > > It won't. If pgtcl is supposed to still be able to compile with older
> > > > versions of Tcl, the changes have to be made a compile time option.
> > >
> > > Please do that and resubmit the patch.
> >
> > OK, I'll pack the new stuff inside #ifdef TCL_UTF8 and define that if
> > the Tcl version is 8.1 or greater.
>
> Is the TCL_UTF8 some variable that gets set at tcl runtime?  I hope so.

I now realize we can't have this configure at runtime.  It has to read
the tcl include file for the version it is about to be linked to.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: libpgtcl doesn't use UTF encoding of TCL

From
Eugene Fokin
Date:
On Wed, Jul 18, 2001 at 02:53:22PM -0400, Tom Lane wrote:

> > It won't. If pgtcl is supposed to still be able to compile with older
> > versions of Tcl, the changes have to be made a compile time option.
>
> Please do that and resubmit the patch.  We really don't want to give up
> backwards compatibility just yet.
>

Thank you, gentlemans :-)
I will be interest with this result too.

--
Eugene Faukin
SOLVO Ltd. Company

Re: libpgtcl doesn't use UTF encoding of TCL

From
Tatsuo Ishii
Date:
Hum. Why don't you enable --enable-multibyte and
--enable-unicode-conversion and set client_encoding to UNICODE? That
would do a conversion from/to UTF-8 for Tcl 8.x (x > 9) clients?
--
Tatsuo Ishii

> Eugene Faukin (elf@solvo.ru) reports a bug with a severity of 2
> The lower the number the more severe it is.
> 
> Short Description
> libpgtcl doesn't use UTF encoding of TCL
> 
> Long Description
> Modern versions of the TCL (8.2 at least) use UTF encoding to internal
> storage of the text. libpgtcl uses TCL functions to insert strings directly
> into TCL internal structure without any conversion.
> 
> 
> Sample Code
> I can suggest you next patch I use for myself:
> 
> diff -uNr postgresql-7.0.2.orig/src/interfaces/libpgtcl/pgtclCmds.c
postgresql-7.0.2/src/interfaces/libpgtcl/pgtclCmds.c
> --- postgresql-7.0.2.orig/src/interfaces/libpgtcl/pgtclCmds.c   Wed Apr 12 21:17:11 2000
> +++ postgresql-7.0.2/src/interfaces/libpgtcl/pgtclCmds.c        Thu Nov 16 20:26:37 2000
> @@ -431,6 +431,7 @@
>         Pg_ConnectionId *connid;
>         PGconn     *conn;
>         PGresult   *result;
> +       Tcl_DString putString;
>  
>         if (argc != 3)
>         {
> @@ -449,7 +450,9 @@
>                 return TCL_ERROR;
>         }
>  
> -       result = PQexec(conn, argv[2]);
> +       Tcl_UtfToExternalDString(NULL, argv[2], -1, &putString);
> +       result = PQexec(conn, Tcl_DStringValue(&putString));
> +       Tcl_DStringFree(&putString);
>  
>         /* Transfer any notify events from libpq to Tcl event queue. */
>         PgNotifyTransferEvents(connid);
> @@ -535,6 +538,7 @@
>         char       *arrVar;
>         char            nameBuffer[256];
>         const char *appendstr;
> +       Tcl_DString retString;
>  
>         if (argc < 3 || argc > 5)
>         {
> @@ -685,11 +689,24 @@
>                 }
>  #ifdef TCL_ARRAYS
>                 for (i = 0; i < PQnfields(result); i++)
> -                       Tcl_AppendElement(interp, tcl_value(PQgetvalue(result, tupno, i)));
> +               {
> +                   Tcl_ExternalToUtfDString(NULL,
> +                                            tcl_value(PQgetvalue(result,
> +                                                                 tupno, i)),
> +                                            -1, &retString);
> +                   Tcl_AppendElement(interp, Tcl_DStringValue(&retString));
> +               }
>  #else
>                 for (i = 0; i < PQnfields(result); i++)
> -                       Tcl_AppendElement(interp, PQgetvalue(result, tupno, i));
> +               {
> +                   Tcl_ExternalToUtfDString(NULL,
> +                                            PQgetvalue(result, tupno, i),
> +                                            -1, &retString);
> +               
> +                   Tcl_AppendElement(interp, Tcl_DStringValue(&retString));
> +               }
>  #endif
> +               Tcl_DStringFree(&retString);
>                 return TCL_OK;
>         }
>         else if (strcmp(opt, "-tupleArray") == 0)
> @@ -707,21 +724,35 @@
>                 }
>                 for (i = 0; i < PQnfields(result); i++)
>                 {
> -                       if (Tcl_SetVar2(interp, argv[4], PQfname(result, i),
> +                   Tcl_ExternalToUtfDString(NULL, 
>  #ifdef TCL_ARRAYS
> -                                                       tcl_value(PQgetvalue(result, tupno, i)),
> +                                            tcl_value(PQgetvalue(result,
> +                                                                 tupno, i)),
>  #else
> -                                                       PQgetvalue(result, tupno, i),
> +                                            PQgetvalue(result, tupno, i),
>  #endif
> -                                                       TCL_LEAVE_ERR_MSG) == NULL)
> -                               return TCL_ERROR;
> +                                            -1, &retString);
> +
> +                   if (Tcl_SetVar2(interp, argv[4], PQfname(result, i),
> +                                   Tcl_DStringValue(&retString),
> +                                   TCL_LEAVE_ERR_MSG) == NULL)
> +                   {
> +                       Tcl_DStringFree(&retString);
> +                       return TCL_ERROR;
> +                   }
>                 }
> +               Tcl_DStringFree(&retString);
>                 return TCL_OK;
>         }
>         else if (strcmp(opt, "-attributes") == 0)
>         {
>                 for (i = 0; i < PQnfields(result); i++)
> -                       Tcl_AppendElement(interp, PQfname(result, i));
> +               {
> +                   Tcl_ExternalToUtfDString(NULL, PQfname(result, i),
> +                                            -1, &retString);
> +                   Tcl_AppendElement(interp, Tcl_DStringValue(&retString));
> +                   Tcl_DStringFree(&retString);
> +               }
>                 return TCL_OK;
>         }
>         else if (strcmp(opt, "-lAttributes") == 0)
> @@ -1274,6 +1305,8 @@
>                                 column,
>                                 ncols;
>         Tcl_DString headers;
> +       Tcl_DString retString;
> +       Tcl_DString putString;
>         char            buffer[2048];
>         struct info_s
>         {
> @@ -1292,7 +1325,11 @@
>         if (conn == (PGconn *) NULL)
>                 return TCL_ERROR;
>  
> -       if ((result = PQexec(conn, argv[2])) == 0)
> +       Tcl_UtfToExternalDString(NULL, argv[2], -1, &putString);
> +       result = PQexec(conn, Tcl_DStringValue(&putString));
> +       Tcl_DStringFree(&putString);
> +
> +       if (result == 0)
>         {
>                 /* error occurred sending the query */
>                 Tcl_SetResult(interp, PQerrorMessage(conn), TCL_VOLATILE);
> @@ -1340,13 +1377,21 @@
>                 Tcl_SetVar2(interp, argv[3], ".tupno", buffer, 0);
>  
>                 for (column = 0; column < ncols; column++)
> -                       Tcl_SetVar2(interp, argv[3], info[column].cname,
> +               {
> +                   Tcl_ExternalToUtfDString(NULL,
>  #ifdef TCL_ARRAYS
> -                                               tcl_value(PQgetvalue(result, tupno, column)),
> +                                            tcl_value(PQgetvalue(result,
> +                                                                 tupno,
> +                                                                 column)),
>  #else
> -                                               PQgetvalue(result, tupno, column),
> +                                            PQgetvalue(result, tupno, column),
>  #endif
> -                                               0);
> +                                            -1, &retString);
> +
> +                   Tcl_SetVar2(interp, argv[3], info[column].cname,
> +                               Tcl_DStringValue(&retString), 0);
> +                   Tcl_DStringFree(&retString);
> +               }
>  
>                 Tcl_SetVar2(interp, argv[3], ".command", "update", 0);
>  
> 
> 
> No file was uploaded with this report
> 
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster
> 


Re: libpgtcl doesn't use UTF encoding of TCL

From
Eugene Fokin
Date:
On Sun, Jul 22, 2001 at 08:10:32PM +0900, Tatsuo Ishii wrote:
> Hum. Why don't you enable --enable-multibyte and
> --enable-unicode-conversion and set client_encoding to UNICODE? That
> would do a conversion from/to UTF-8 for Tcl 8.x (x > 9) clients?

You're right. Probably, this way correct enough too :-)
Thank you for suggest.
But, I think, patching the libpgtcl has not to be superfluous.

-- 
Eugene Faukin
SOLVO Ltd. Company


Re: libpgtcl doesn't use UTF encoding of TCL

From
Bruce Momjian
Date:
> On Wed, 18 Jul 2001, Tom Lane wrote:
>
> > Reinhard Max <max@suse.de> writes:
> > > On Wed, 18 Jul 2001, Bruce Momjian wrote:
> > >> Do you have any idea how this will work with earlier TCL versions?
> >
> > > It won't. If pgtcl is supposed to still be able to compile with older
> > > versions of Tcl, the changes have to be made a compile time option.
> >
> > Please do that and resubmit the patch.
>
> Here it is, but I consider it still incomplete and I have not done
> exhaustive testing. Some more occurrences of PQexec and PQgetvalue
> need to be wrapped up with UTF8 conversion, but I'll not have the time
> to do it for the next 1-2 weeks.
>
> cu
>     Reinhard

I have a patch here that handles all the TCL/UTF issues.  Would you let
me know if it is OK?

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
Index: configure.in
===================================================================
RCS file: /junk/pgsql/repo/pgsql/configure.in,v
retrieving revision 1.132
diff -u -r1.132 configure.in
--- configure.in    2001/08/01 23:52:50    1.132
+++ configure.in    2001/08/23 15:18:30
@@ -411,6 +411,21 @@


 #
+# If Tcl is enabled (above) then check for pltcl_utf
+#
+AC_MSG_CHECKING([whether to build with PL/Tcl with UTF support])
+if test "$with_tcl" = yes; then
+  PGAC_ARG_BOOL(enable, pltcl-utf, no,
+                [  --enable-pltcl-utf      build PL/Tcl UTF support (if Tcl is enabled)],
+                [AC_DEFINE([ENABLE_PLTCL_UTF])])
+else
+  enable_pltcl_utf=no
+fi
+AC_MSG_RESULT([$enable_pltcl_utf])
+AC_SUBST([enable_pltcl_utf])
+
+
+#
 # Optionally build Perl modules (Pg.pm and PL/Perl)
 #
 AC_MSG_CHECKING([whether to build Perl modules])
Index: doc/src/sgml/installation.sgml
===================================================================
RCS file: /junk/pgsql/repo/pgsql/doc/src/sgml/installation.sgml,v
retrieving revision 1.50
diff -u -r1.50 installation.sgml
--- doc/src/sgml/installation.sgml    2001/06/02 18:25:16    1.50
+++ doc/src/sgml/installation.sgml    2001/08/24 12:39:53
@@ -674,6 +674,17 @@
       </varlistentry>

       <varlistentry>
+       <term>--enable-pltcl-utf</term>
+       <listitem>
+        <para>
+         Enables enables PL/Tcl Tcl_UtfToExternal and Tcl_ExternalToUtf
+         conversion support. These functions needed for Tcl versions 8.1
+         and above for proper handling of 8-bit characters.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
        <term>--enable-odbc</term>
        <listitem>
         <para>
Index: src/include/config.h.in
===================================================================
RCS file: /junk/pgsql/repo/pgsql/src/include/config.h.in,v
retrieving revision 1.170
diff -u -r1.170 config.h.in
--- src/include/config.h.in    2001/08/01 23:52:50    1.170
+++ src/include/config.h.in    2001/08/23 15:01:41
@@ -84,6 +84,9 @@
 /* --enable-pltcl-unknown */
 #undef ENABLE_PLTCL_UNKNOWN

+/* --enable-pltcl-utf */
+#undef ENABLE_PLTCL_UTF
+
 /* --enable-nls */
 #undef ENABLE_NLS

Index: src/pl/tcl/pltcl.c
===================================================================
RCS file: /junk/pgsql/repo/pgsql/src/pl/tcl/pltcl.c,v
retrieving revision 1.38
diff -u -r1.38 pltcl.c
--- src/pl/tcl/pltcl.c    2001/08/02 15:45:55    1.38
+++ src/pl/tcl/pltcl.c    2001/08/24 12:43:06
@@ -59,6 +59,18 @@
 #include "catalog/pg_language.h"
 #include "catalog/pg_type.h"

+#if defined(ENABLE_PLTCL_UTF) && TCL_MAJOR_VERSION == 8 \
+    && TCL_MINOR_VERSION > 0
+#    define UTF_BEGIN    do { Tcl_DString _pltcl_ds_tmp
+#       define UTF_END        Tcl_DStringFree(&_pltcl_ds_tmp); } while (0)
+#       define UTF_U2E(x)    (Tcl_UtfToExternalDString(NULL,(x),-1,&_pltcl_ds_tmp))
+#    define UTF_E2U(x)    (Tcl_ExternalToUtfDString(NULL,(x),-1,&_pltcl_ds_tmp))
+#else /* ENABLE_PLTCL_UTF */
+#    define    UTF_BEGIN
+#    define    UTF_END
+#    define    UTF_U2E(x)    (x)
+#    define    UTF_E2U(x)    (x)
+#endif /* ENABLE_PLTCL_UTF */

 /**********************************************************************
  * The information we cache about loaded procedures
@@ -333,7 +345,9 @@
                             SPI_tuptable->tupdesc, fno);
         if (part != NULL)
         {
-            Tcl_DStringAppend(&unknown_src, part, -1);
+            UTF_BEGIN;
+            Tcl_DStringAppend(&unknown_src, UTF_E2U(part), -1);
+            UTF_END;
             pfree(part);
         }
     }
@@ -613,7 +627,9 @@
         }
         proc_source = DatumGetCString(DirectFunctionCall1(textout,
                                   PointerGetDatum(&procStruct->prosrc)));
-        Tcl_DStringAppend(&proc_internal_body, proc_source, -1);
+        UTF_BEGIN;
+        Tcl_DStringAppend(&proc_internal_body, UTF_E2U(proc_source), -1);
+        UTF_END;
         pfree(proc_source);
         Tcl_DStringAppendElement(&proc_internal_def,
                                  Tcl_DStringValue(&proc_internal_body));
@@ -715,7 +731,9 @@
                                                     fcinfo->arg[i],
                               ObjectIdGetDatum(prodesc->arg_out_elem[i]),
                                 Int32GetDatum(prodesc->arg_out_len[i])));
-                Tcl_DStringAppendElement(&tcl_cmd, tmp);
+                UTF_BEGIN;
+                Tcl_DStringAppendElement(&tcl_cmd, UTF_E2U(tmp));
+                UTF_END;
                 pfree(tmp);
             }
         }
@@ -777,13 +795,15 @@
     if (SPI_finish() != SPI_OK_FINISH)
         elog(ERROR, "pltcl: SPI_finish() failed");

+    UTF_BEGIN;
     if (fcinfo->isnull)
         retval = (Datum) 0;
     else
         retval = FunctionCall3(&prodesc->result_in_func,
-                               PointerGetDatum(interp->result),
+                               PointerGetDatum(UTF_U2E(interp->result)),
                                ObjectIdGetDatum(prodesc->result_in_elem),
                                Int32GetDatum(-1));
+    UTF_END;

     /************************************************************
      * Finally we may restore normal error handling.
@@ -929,7 +949,9 @@

         proc_source = DatumGetCString(DirectFunctionCall1(textout,
                                   PointerGetDatum(&procStruct->prosrc)));
-        Tcl_DStringAppend(&proc_internal_body, proc_source, -1);
+        UTF_BEGIN;
+        Tcl_DStringAppend(&proc_internal_body, UTF_E2U(proc_source), -1);
+        UTF_END;
         pfree(proc_source);
         Tcl_DStringAppendElement(&proc_internal_def,
                                  Tcl_DStringValue(&proc_internal_body));
@@ -1230,11 +1252,13 @@
          ************************************************************/
         modnulls[attnum - 1] = ' ';
         fmgr_info(typinput, &finfo);
+        UTF_BEGIN;
         modvalues[attnum - 1] =
             FunctionCall3(&finfo,
-                          CStringGetDatum(ret_values[i++]),
+                          CStringGetDatum(UTF_U2E(ret_values[i++])),
                           ObjectIdGetDatum(typelem),
                    Int32GetDatum(tupdesc->attrs[attnum - 1]->atttypmod));
+        UTF_END;
     }

     rettup = SPI_modifytuple(trigdata->tg_relation, rettup, tupdesc->natts,
@@ -1558,7 +1582,9 @@
     /************************************************************
      * Execute the query and handle return codes
      ************************************************************/
-    spi_rc = SPI_exec(argv[query_idx], count);
+    UTF_BEGIN;
+    spi_rc = SPI_exec(UTF_U2E(argv[query_idx]), count);
+    UTF_END;
     memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));

     switch (spi_rc)
@@ -1794,7 +1820,9 @@
     /************************************************************
      * Prepare the plan and check for errors
      ************************************************************/
-    plan = SPI_prepare(argv[1], nargs, qdesc->argtypes);
+    UTF_BEGIN;
+    plan = SPI_prepare(UTF_U2E(argv[1]), nargs, qdesc->argtypes);
+    UTF_END;

     if (plan == NULL)
     {
@@ -2078,11 +2106,13 @@
          ************************************************************/
         for (j = 0; j < callnargs; j++)
         {
+            UTF_BEGIN;
             qdesc->argvalues[j] =
                 FunctionCall3(&qdesc->arginfuncs[j],
-                              CStringGetDatum(callargs[j]),
+                              CStringGetDatum(UTF_U2E(callargs[j])),
                               ObjectIdGetDatum(qdesc->argtypelems[j]),
                               Int32GetDatum(qdesc->arglen[j]));
+            UTF_END;
         }

         /************************************************************
@@ -2377,7 +2407,9 @@
                                                          attr,
                                                ObjectIdGetDatum(typelem),
                               Int32GetDatum(tupdesc->attrs[i]->attlen)));
-            Tcl_SetVar2(interp, *arrptr, *nameptr, outputstr, 0);
+            UTF_BEGIN;
+            Tcl_SetVar2(interp, *arrptr, *nameptr, UTF_E2U(outputstr), 0);
+            UTF_END;
             pfree(outputstr);
         }
         else
@@ -2448,7 +2480,9 @@
                                                ObjectIdGetDatum(typelem),
                               Int32GetDatum(tupdesc->attrs[i]->attlen)));
             Tcl_DStringAppendElement(retval, attname);
-            Tcl_DStringAppendElement(retval, outputstr);
+            UTF_BEGIN;
+            Tcl_DStringAppendElement(retval, UTF_E2U(outputstr));
+            UTF_END;
             pfree(outputstr);
         }
     }

Re: libpgtcl doesn't use UTF encoding of TCL

From
Reinhard Max
Date:
Hi Bruce,

On Wed, 5 Sep 2001, Bruce Momjian wrote:

> I have a patch here that handles all the TCL/UTF issues.
> Would you let me know if it is OK?

I think, it isn't really a clean fix. It only works, if your
database's encoding and Tcl's system encoding are identical. If the
database uses a different encoding than Tcl, you still end up with
wrong characters. Also, the configure switch (if needed at all)
should IMHO be a disable switch, because the conversion is mandatory
for Tcl >= 8.1 unless someone really knows that he won't have any
8-Bit characters in his database. So less people would get bitten, if
UTF conversion was enabled by default for Tcl >= 8.1 .

Besides these flaws, I think the patch could be simpler and avoid the
UTF_BEGIN and UTF_END macros if UTF_U2E and UTF_E2U were (maybe
inlined) functions and defined like this (untested):

char* UTF_U2E(CONST char * source)
{
    static Tcl_DString *destPtr = NULL;

    if (destPtr == NULL) {
        destPtr = (Tcl_DString *) malloc(sizeof(Tcl_DString));
    } else {
        Tcl_DStringFree(destPtr);
    }
    return Tcl_UtfToExternalDString(NULL, source, -1, destPtr);
}


See also the mail, I sent to pgsql-patches last Tuesday on the same
topic.

In addition to my suggestion there to require the database to be
UNICODE for Tcl >= 8.1, I just had another Idea how it could be solved
cleanly:

What about making --enable-unicode-conversion mandatory when
PostgreSQL gets compiled with Tcl support and changing PgTcl and
PL/Tcl to set their client encoding to UNICODE at _runtime_ when they
find themselfes running with a Tcl interpreter that needs UTF-8 (i.e.
Tcl >= 8.1)?

Going this way, we could even retain binary compatibility for PgTcl
and PL/Tcl with Tcl versions prior and after Tcl's move to UTF-8.

One Question remains here: Do --enable-multibyte and
--enable-unicode-conversion have any downsides (besides a larger
executable), if they are compiled in, but not used?

cu
    Reinhard