Author: turnstep
Date: Sat Jul 21 21:25:35 2007
New Revision: 9787

Added:
   DBD-Pg/trunk/t/09arrays.t
Modified:
   DBD-Pg/trunk/Pg.pm
   DBD-Pg/trunk/Pg.xs
   DBD-Pg/trunk/dbdimp.c
   DBD-Pg/trunk/dbdimp.h
   DBD-Pg/trunk/types.c

Log:
First swing at array support.
Converts arrayref to Postgres arrays for quote() and execute().
Who needs Harry Potter when you can spend the day writing XS code? :)


Modified: DBD-Pg/trunk/Pg.pm
==============================================================================
--- DBD-Pg/trunk/Pg.pm  (original)
+++ DBD-Pg/trunk/Pg.pm  Sat Jul 21 21:25:35 2007
@@ -111,9 +111,6 @@
 
        use strict;
 
-       our $CATALOG = 123; ## Set later on, this is to catch seriously 
misplaced code
-
-
        ## Returns an array of formatted database names from the pg_database 
table
        sub data_sources {
                my $drh = shift;
@@ -2549,7 +2546,8 @@
 
 This module implements its own C<quote> method. In addition to the DBI method 
it
 also doubles the backslash, because PostgreSQL treats a backslash as an escape
-character.
+character. You may also quote arrayrefs and received a string suitable for 
+passing into Postgres array columns.
 
 B<NOTE:> The undocumented (and invalid) support for the C<SQL_BINARY> data
 type is officially deprecated. Use C<PG_BYTEA> with C<bind_param()> instead:
@@ -2842,6 +2840,9 @@
 option will force server-side prepares off until such time as PostgreSQL 
 supports using DEFAULT in prepared statements.
 
+DBD::Pg also supports passing in arrays to execute: simply pass in an 
arrayref, 
+and DBD::Pg will flatten it into a string suitable for input on the backend.
+
 =item B<execute_array>
 
 Supported by this driver as proposed by DBI.
@@ -3280,6 +3281,20 @@
     $count = $sth2->fetchall_arrayref()->[0][0];
   }
 
+=head2 Array support
+
+DBD::Pg allows arrays (as arrayrefs) to be passed in to both 
+the quote() and the execute() functions. In both cases, the array is 
+flattened into a string representing a Postgres array.
+
+When fetching rows from a table that contains a column with an 
+array type, the result will be passed back to your script as an arrayref.
+
+To turn off the automatic parsing of returned arrays into arrayrefs, 
+you can set the variable "pg_expand_array", which is true by default.
+
+  $dbh->{pg_expand_array} = 0;
+
 
 =head2 COPY support
 

Modified: DBD-Pg/trunk/Pg.xs
==============================================================================
--- DBD-Pg/trunk/Pg.xs  (original)
+++ DBD-Pg/trunk/Pg.xs  Sat Jul 21 21:25:35 2007
@@ -61,6 +61,8 @@
        PG_OID       = 26
        PG_TID       = 27
 
+       PG_INT4ARRAY = 1007
+
        PG_ASYNC           = PG_ASYNC
        PG_OLDQUERY_CANCEL = PG_OLDQUERY_CANCEL
        PG_OLDQUERY_WAIT   = PG_OLDQUERY_WAIT
@@ -89,24 +91,31 @@
 
 SV*
 quote(dbh, to_quote_sv, type_sv=Nullsv)
+    SV* dbh
        SV* to_quote_sv
        SV* type_sv
 
        CODE:
        {
+               D_imp_dbh(dbh);
                sql_type_info_t *type_info;
                char *to_quote;
                char *quoted;
                STRLEN len=0;
                STRLEN retlen=0;
                SV **svp;
-                       
+
                SvGETMAGIC(to_quote_sv);
 
                /* Null is always returned as "NULL", so we can ignore any type 
given */
                if (!SvOK(to_quote_sv)) {
                        RETVAL = newSVpvn("NULL", 4);
                }
+               else if (SvROK(to_quote_sv)) {
+                       if (SvTYPE(SvRV(to_quote_sv)) != SVt_PVAV)
+                               croak("Cannot quote a reference");
+                       RETVAL = pg_stringify_array(to_quote_sv, ",", 
imp_dbh->pg_server_version);
+               }
                else {
 
                        /* If no valid type is given, we default to varchar */

Modified: DBD-Pg/trunk/dbdimp.c
==============================================================================
--- DBD-Pg/trunk/dbdimp.c       (original)
+++ DBD-Pg/trunk/dbdimp.c       Sat Jul 21 21:25:35 2007
@@ -218,6 +218,7 @@
        imp_dbh->prepare_now    = DBDPG_FALSE;
        imp_dbh->done_begin     = DBDPG_FALSE;
        imp_dbh->dollaronly     = DBDPG_FALSE;
+       imp_dbh->expand_array   = DBDPG_TRUE;
        imp_dbh->pid_number     = getpid();
        imp_dbh->prepare_number = 1;
        imp_dbh->copystate      = 0;
@@ -644,12 +645,14 @@
 #endif
                break;
 
-       case 15: /* pg_default_port pg_async_status */
+       case 15: /* pg_default_port pg_async_status pg_expand_array */
 
                if (strEQ("pg_default_port", key))
                        retsv = newSViv((IV) PGDEFPORT );
                else if (strEQ("pg_async_status", key))
                        retsv = newSViv((IV)imp_dbh->async_status);
+               else if (strEQ("pg_expand_array", key))
+                       retsv = newSViv((IV)imp_dbh->expand_array);
                break;
 
        case 17: /* pg_server_prepare  pg_server_version */
@@ -738,6 +741,13 @@
                }
 #endif
 
+       case 15: /* pg_expand_array */
+
+               if (strEQ("pg_expand_array", key)) {
+                       imp_dbh->expand_array = newval ? DBDPG_TRUE : 
DBDPG_FALSE;
+                       return 1;
+               }
+
        case 17: /* pg_server_prepare */
 
                if (strEQ("pg_server_prepare", key)) {
@@ -1929,6 +1939,7 @@
 int dbd_bind_ph (SV * sth, imp_sth_t * imp_sth, SV * ph_name, SV * newvalue, 
IV sql_type, SV * attribs, int is_inout, IV maxlen)
 {
 
+       D_imp_dbh_from_sth;
        char * name = Nullch;
        STRLEN name_len;
        ph_t * currph = NULL;
@@ -1937,6 +1948,7 @@
        bool   reprepare = DBDPG_FALSE;
        int    pg_type = 0;
        char * value_string = NULL;
+       bool   is_array = DBDPG_FALSE;
 
        maxlen = 0; /* not used, this makes the compiler happy */
 
@@ -2015,9 +2027,17 @@
                        currph->iscurrent = DBDPG_TRUE;
                        imp_sth->has_current = DBDPG_TRUE;
                }
+               else if (SvTYPE(SvRV(newvalue)) == SVt_PVAV) {
+                       SV * quotedval;
+                       quotedval = 
pg_stringify_array(newvalue,",",imp_dbh->pg_server_version);
+                       currph->valuelen = sv_len(quotedval);
+                       Renew(currph->value, currph->valuelen+1, char); /* 
freed in dbd_st_destroy */
+                       currph->value = SvPVutf8_nolen(quotedval);
+                       currph->bind_type = pg_type_data(CSTRINGARRAYOID);
+                       is_array = DBDPG_TRUE;
+               }
                else {
-                       croak("Cannot bind a reference (%s) (%s) (%d) type=%d 
%d %d %d", neatsvpv(newvalue,0), SvAMAGIC(newvalue),
-                                 SvTYPE(SvRV(newvalue)) == SVt_PVAV ? 1 : 0, 
SvTYPE(newvalue), SVt_PVAV, SVt_PV, 0);
+                       croak("Cannot bind a reference\n");
                }
        }
        if (dbis->debug >= 5) {
@@ -2026,7 +2046,16 @@
                        (void)PerlIO_printf(DBILOGFP, "dbdpg: Bind attribs 
(%s)", neatsvpv(attribs,0));
                }
        }
-       
+
+       /* We ignore attribs for these special cases */
+       if (currph->isdefault || currph->iscurrent || is_array) {
+               if (NULL == currph->bind_type) {
+                       imp_sth->numbound++;
+                       currph->bind_type = pg_type_data(UNKNOWNOID);
+               }
+               return 1;
+       }
+
        /* Check for a pg_type argument (sql_type already handled) */
        if (attribs) {
                if((svp = hv_fetch((HV*)SvRV(attribs),"pg_type", 7, 0)) != NULL)
@@ -2080,9 +2109,6 @@
                        imp_sth->has_binary = DBDPG_TRUE;
        }
 
-       if (currph->isdefault || currph->iscurrent)
-               return 1;
-
        /* convert to a string ASAP */
        if (!SvPOK(newvalue) && SvOK(newvalue)) {
                (void)sv_2pv(newvalue, &na);
@@ -2126,6 +2152,134 @@
 
 } /* end of dbd_bind_ph */
 
+/* ================================================================== */
+SV * pg_stringify_array(SV *input, const char * array_delim, int 
server_version) {
+
+       AV * toparr;
+       AV * currarr;
+       AV * lastarr;
+       int done;
+       int array_depth = 0;
+       int array_items;
+       int inner_arrays = 0;
+       int xy, yz;
+       SV * svitem;
+       char * string;
+       STRLEN svlen;
+       SV * value;
+
+       if (dbis->debug >= 4)
+               (void)PerlIO_printf(DBILOGFP, "dbdpg: pg_stringify_array\n");
+
+       toparr = (AV *) SvRV(input);
+       value = newSVpv("{", 1);
+
+       /* Empty arrays are easy */
+       if (av_len(toparr) < 0) {
+               av_clear(toparr);
+               sv_catpv(value, "}");
+               return value;
+       }
+
+       done = 0;
+       currarr = lastarr = toparr;
+       while (!done) {
+               /* Grab the first item of the current array */
+               svitem = *av_fetch(currarr, 0, 0);
+
+               /* If a ref, die if not an array, else keep descending */
+               if (SvROK(svitem)) {
+                       if (SvTYPE(SvRV(svitem)) != SVt_PVAV)
+                               croak("Arrays must contain only scalars and 
other arrays");
+                       array_depth++;
+
+                       /* Squirrel away this level before we leave it */
+                       lastarr = currarr;
+
+                       /* Set the current array to this item */
+                       currarr = (AV *)SvRV(svitem);
+
+                       /* If this is an empty array, stop here */
+                       if (av_len(currarr) < 0)
+                               done = 1;
+               }
+               else
+                       done = 1;
+       }
+
+       inner_arrays = array_depth ? 1+av_len(lastarr) : 0;
+
+       /* How many items are in each inner array? */
+       array_items = array_depth ? 
(1+av_len((AV*)SvRV(*av_fetch(lastarr,0,0)))) : 1+av_len(lastarr);
+
+       for (xy=1; xy < array_depth; xy++) {
+               sv_catpv(value, "{");
+       }
+
+       for (xy=0; xy < inner_arrays || !array_depth; xy++) {
+               if (array_depth) {
+                       svitem = *av_fetch(lastarr, xy, 0);
+                       if (!SvROK(svitem))
+                               croak ("Not a valid array!");
+                       currarr = (AV*)SvRV(svitem);
+                       if (SvTYPE(currarr) != SVt_PVAV)
+                               croak("Arrays must contain only scalars and 
other arrays!");
+                       if (1+av_len(currarr) != array_items)
+                               croak("Invalid array - all arrays must be of 
equal size");
+                       sv_catpv(value, "{");
+               }
+               for (yz=0; yz < array_items; yz++) {
+                       svitem = *av_fetch(currarr, yz, 0);
+
+                       if (SvROK(svitem))
+                               croak("Arrays must contain only scalars and 
other arrays");
+
+                       if (!SvOK(svitem)) { /* Insert NULL if we can */
+                               /* Only version 8.2 and up can handle NULLs in 
arrays */
+                               if (server_version < 80200)
+                                       croak("Cannot use NULLs in arrays until 
version 8.2");
+                               sv_catpv(value, "NULL"); /* Beware of 
array_nulls config param! */
+                       }
+                       else {
+                               sv_catpv(value, "\"");
+                               string = SvPV(svitem, svlen);
+                               while (svlen--) {
+                                       sv_catpvf(value, "%s%c", /* upgrades to 
utf8 for us */
+                                                         '\"'==*string ? "\\" 
: 
+                                                         '\\'==*string ? 
"\\\\" :
+                                                         "", *string);
+                                       string++;
+                               }
+                               sv_catpv(value, "\"");
+                       }
+
+                       if (yz < array_items-1)
+                               sv_catpv(value, array_delim);
+               }
+
+               if (!array_items) {
+                       sv_catpv(value, "\"\"");
+               }
+
+               sv_catpv(value, "}");
+               if (xy < inner_arrays-1)
+                       sv_catpv(value, array_delim);
+               if (!array_depth)
+                       break;
+       }
+
+       for (xy=0; xy<array_depth; xy++) {
+               sv_catpv(value, "}");
+       }
+
+       if (dbis->debug >= 4)
+               (void)PerlIO_printf(DBILOGFP, "dbdpg: pg_stringify_array 
returns %s\n", neatsvpv(value,0));
+
+       return value;
+
+} /* end of pg_stringify_array */
+
+
 
 /* ================================================================== */
 int pg_quickexec (SV * dbh, const char * sql, int asyncflag)

Modified: DBD-Pg/trunk/dbdimp.h
==============================================================================
--- DBD-Pg/trunk/dbdimp.h       (original)
+++ DBD-Pg/trunk/dbdimp.h       Sat Jul 21 21:25:35 2007
@@ -25,6 +25,7 @@
        bool    prepare_now;       /* force immediate prepares, even with 
placeholders. Set by user, default is 0 */
        bool    done_begin;        /* have we done a begin? (e.g. are we in a 
transaction?) */
        bool    dollaronly;        /* Only consider $1, $2 ... as valid 
placeholders */
+       bool    expand_array;      /* Transform arrays from the db into Perl 
arrays? Default is 1 */
 
        int     pg_protocol;       /* value of PQprotocolVersion, usually 0, 2, 
or 3 */
        int     pg_server_version; /* Server version e.g. 80100 */
@@ -131,6 +132,7 @@
 int dbdpg_result (SV *dbh, imp_dbh_t *imp_dbh);
 int dbdpg_cancel (SV *h, imp_dbh_t *imp_dbh);
 int dbdpg_cancel_sth (SV *sth, imp_sth_t *imp_sth);
+SV * pg_stringify_array(SV * input, const char * array_delim, int 
server_version);
 
 /* end of dbdimp.h */
 

Added: DBD-Pg/trunk/t/09arrays.t
==============================================================================
--- (empty file)
+++ DBD-Pg/trunk/t/09arrays.t   Sat Jul 21 21:25:35 2007
@@ -0,0 +1,223 @@
+#!perl -w
+
+# Test array stuff - currently not working!
+
+use Test::More qw/no_plan/;
+use DBI qw/:sql_types/;
+use DBD::Pg qw/:pg_types/;
+use strict;
+use Data::Dumper;
+$|=1;
+
+my ($sth,$result);
+
+if (defined $ENV{DBI_DSN}) {
+#      plan tests => 18;
+} else {
+       plan skip_all => 'Cannot run test unless DBI_DSN is defined. See the 
README file';
+}
+
+my $dbh = DBI->connect($ENV{DBI_DSN}, $ENV{DBI_USER}, $ENV{DBI_PASS},
+                       {RaiseError => 1, PrintError => 0, AutoCommit => 0});
+ok( defined $dbh, "Connect to database for array testing");
+
+if (DBD::Pg::_pg_use_catalog($dbh)) {
+       $dbh->do("SET search_path TO " . $dbh->quote_identifier
+                                        (exists $ENV{DBD_SCHEMA} ? 
$ENV{DBD_SCHEMA} : 'public'));
+}
+my $pgversion = $dbh->{pg_server_version};
+
+my $SQL = "DELETE FROM dbd_pg_test WHERE pname = 'Array Testing'";
+my $cleararray = $dbh->prepare($SQL);
+
+$SQL = "INSERT INTO dbd_pg_test(id,pname,testarray) VALUES (99,'Array 
Testing',?)";
+my $addarray = $dbh->prepare($SQL);
+
+$dbh->{pg_flatten_arrays} = 0;
+$SQL = "SELECT testarray FROM dbd_pg_test WHERE pname= 'Array Testing'";
+my $getarray = $dbh->prepare($SQL);
+
+my $array_tests = 
+q![]
+{}
+Empty array
+
+[[]]
+{{""}}
+Empty array with two levels
+
+[[[]]]
+{{{""}}}
+Empty array with three levels
+
+[[],[]]
+{{""},{""}}
+Two empty arrays
+
+[[[],[],[]]]
+{{{""},{""},{""}}}
+Three empty arrays at second level
+
+[[],[[]]]
+ERROR: must be of equal size
+Unbalanced empty arrays
+
+{}
+ERROR: Cannot bind a reference
+Bare hashref
+
+[{}]
+ERROR: only scalars and other arrays
+Hashref at top level
+
+[1,2,{3,4},5]
+ERROR: only scalars and other arrays
+Hidden hashref
+
+[[1,2],[3]]
+ERROR: must be of equal size
+Unbalanced array
+
+[[1,2],[3,4,5]]
+ERROR: must be of equal size
+Unbalanced array
+
+[[1,2],[]]
+ERROR: must be of equal size
+Unbalanced array
+
+[[],[3]]
+ERROR: must be of equal size
+Unbalanced array
+
+[123]
+{123} quote: {"123"}
+Simple 1-D numeric array
+
+['abc']
+{abc} quote: {"abc"}
+Simple 1-D text array
+
+[1,2]
+{1,2} quote: {"1","2"}
+Simple 1-D numeric array
+
+[[1]]
+{{1}} quote: {{"1"}}
+Simple 2-D numeric array
+
+[[1,2]]
+{{1,2}} quote: {{"1","2"}}
+Simple 2-D numeric array
+
+[[[1]]]
+{{{1}}} quote: {{{"1"}}}
+Simple 3-D numeric array
+
+[[["alpha",2],[23,"pop"]]]
+{{{alpha,2},{23,pop}}} quote: {{{"alpha","2"},{"23","pop"}}}
+3-D mixed array
+
+[[[1,2,3],[4,5,"6"],["seven","8","9"]]]
+{{{1,2,3},{4,5,6},{seven,8,9}}} quote: 
{{{"1","2","3"},{"4","5","6"},{"seven","8","9"}}}
+3-D mixed array
+
+[q{O'RLY?}]
+{O'RLY?} quote: {"O'RLY?"}
+Simple single quote
+
+[q{O"RLY?}]
+{"O\"RLY?"}
+Simple double quote
+
+[[q{O"RLY?}],[q|'Ya' - "really"|],[123]]
+{{"O\"RLY?"},{"'Ya' - \"really\""},{123}} quote: {{"O\"RLY?"},{"'Ya' - 
\"really\""},{"123"}}
+Many quotes
+
+["Test\\\\nRun"]
+{"Test\\\\nRun"} quote: {"Test\\\\\\nRun"}
+Simple backslash
+
+[["Test\\\\nRun","Quite \"so\""],["back\\\\\\\\slashes are a 
\"pa\\\\in\"",123] ]
+{{"Test\\\\nRun","Quite \"so\""},{"back\\\\\\\\\\\\slashes are a 
\"pa\\\\in\"",123}} quote: {{"Test\\\\\\nRun","Quite 
\"so\""},{"back\\\\\\\\\\\\slashes are a \"pa\\\\\\in\"","123"}}
+Escape party
+
+[undef]
+{NULL}
+NEED 80200: Simple undef test
+
+[[undef]]
+{{NULL}}
+NEED 80200: Simple undef test
+
+[[1,2],[undef,3],["four",undef],[undef,undef]]
+{{1,2},{NULL,3},{four,NULL},{NULL,NULL}} quote: 
{{"1","2"},{NULL,"3"},{"four",NULL},{NULL,NULL}}
+MEED 80200: Multiple undef test
+
+!;
+
+## Note: We silently allow things like this: [[[]],[]]
+
+for my $test (split /\n\n/ => $array_tests) {
+       next unless $test =~ /\w/;
+       my ($input,$expected,$msg) = split /\n/ => $test;
+       my $qexpected = $expected;
+       if ($expected =~ s/\s*quote:\s*(.+)//) {
+               $qexpected = $1;
+       }
+
+       if ($msg =~ s/NEED (\d+):\s*//) {
+               my $ver = $1;
+               if ($pgversion < $ver) {
+                 SKIP: {
+                               skip 'Cannot test NULL arrays unless version 
8.2 or better', 4;
+                       }
+                       next;
+               }
+       }
+
+
+       $cleararray->execute();
+       eval {
+               $addarray->execute(eval $input);
+       };
+       if ($expected =~ /error:\s+(.+)/i) {
+               like($@, qr{$1}, "Array failed : $msg : $input");
+       }
+       else {
+               is($@, q{}, "Array worked : $msg : $input");
+               $getarray->execute();
+               $result = $getarray->fetchall_arrayref()->[0][0];
+               is($result, $expected, "Correct array inserted: $msg : $input");
+       }
+
+       eval {
+               $result = $dbh->quote(eval $input);
+       };
+       if ($qexpected =~ /error:\s+(.+)/i) {
+               my $errmsg = $1;
+               $errmsg =~ s/bind/quote/;
+               like($@, qr{$errmsg}, "Array quote failed : $msg : $input");
+       }
+       else {
+               is($@, q{}, "Array quote worked : $msg : $input");
+               is($result, $qexpected, "Correct array quote: $msg : $input");
+       }
+
+}
+
+
+$cleararray->execute();
+$addarray->execute([123]);
+$SQL = "SELECT testarray FROM dbd_pg_test WHERE pname = 'Array Testing'";
+$sth = $dbh->prepare($SQL);
+$sth->execute();
+$result = $sth->fetchall_arrayref()->[0][0];
+
+#is($result, [123], qq{Arrays rock});
+
+
+
+## Now the other direction!
+
+ok ($dbh->disconnect, "Disconnect from database");

Modified: DBD-Pg/trunk/types.c
==============================================================================
--- DBD-Pg/trunk/types.c        (original)
+++ DBD-Pg/trunk/types.c        Sat Jul 21 21:25:35 2007
@@ -35,7 +35,7 @@
        {CIDOID, "cid", null_quote, null_dequote, {SQL_INTEGER}, DBDPG_TRUE},
        {CIDROID, "IP - cidr", null_quote, null_dequote, {0}, DBDPG_TRUE},
        {CIRCLEOID, "circle", quote_circle, dequote_string, {0}, DBDPG_TRUE},
-       {CSTRINGARRAYOID, "cstringarray", 0, 0, {0}, DBDPG_FALSE},
+       {CSTRINGARRAYOID, "cstringarray", null_quote, null_dequote, {0}, 
DBDPG_TRUE},
        {CSTRINGOID, "cstring", null_quote, null_dequote, {0}, DBDPG_TRUE},
        {DATEOID, "date", null_quote, null_dequote, {SQL_TYPE_DATE}, 
DBDPG_TRUE},
        {FLOAT4ARRAYOID, "float4array", 0, 0, {0}, DBDPG_FALSE},
@@ -172,6 +172,7 @@
 }
 
 static sql_type_info_t sql_types[] = {
+       {SQL_ARRAY, "SQL_ARRAY", null_quote, null_dequote, {ANYARRAYOID}, 
DBDPG_TRUE},
        {SQL_BIT, "SQL_BIT", null_quote, null_dequote, {BITOID}, DBDPG_TRUE},
        {SQL_BOOLEAN, "SQL_BOOLEAN", quote_bool, dequote_bool, {BOOLOID}, 
DBDPG_TRUE},
        {SQL_CHAR, "SQL_CHAR", quote_string, dequote_char, {BPCHAROID}, 
DBDPG_TRUE},
@@ -187,6 +188,7 @@
        {SQL_BIGINT, "SQL_BIGINT", null_quote, null_dequote, {INT8OID}, 
DBDPG_TRUE},
        {SQL_INTERVAL, "SQL_INTERVAL", quote_string, dequote_string, 
{INTERVALOID}, DBDPG_TRUE},
        {SQL_DECIMAL, "SQL_DECIMAL", null_quote, null_dequote, {NUMERICOID}, 
DBDPG_TRUE},
+       {SQL_LONGVARCHAR, "SQL_LONGVARCHAR", quote_string, dequote_string, 
{TEXTOID}, DBDPG_TRUE},
        {SQL_TYPE_TIME, "SQL_TYPE_TIME", null_quote, null_dequote, {TIMEOID}, 
DBDPG_TRUE},
        {SQL_TIMESTAMP, "SQL_TIMESTAMP", quote_string, dequote_string, 
{TIMESTAMPOID}, DBDPG_TRUE},
        {SQL_TYPE_TIMESTAMP, "SQL_TYPE_TIMESTAMP", quote_string, 
dequote_string, {TIMESTAMPOID}, DBDPG_TRUE},
@@ -198,27 +200,29 @@
 sql_type_info_t* sql_type_data(sql_type)
        int sql_type;
 {      switch(sql_type) {
-               case SQL_BIT:                          return &sql_types[0];
-               case SQL_BOOLEAN:                      return &sql_types[1];
-               case SQL_CHAR:                         return &sql_types[2];
-               case SQL_VARBINARY:                    return &sql_types[3];
-               case SQL_TYPE_DATE:                    return &sql_types[4];
-               case SQL_REAL:                         return &sql_types[5];
-               case SQL_NUMERIC:                      return &sql_types[6];
-               case SQL_FLOAT:                        return &sql_types[7];
-               case SQL_DOUBLE:                       return &sql_types[8];
-               case SQL_SMALLINT:                     return &sql_types[9];
-               case SQL_TINYINT:                      return &sql_types[10];
-               case SQL_INTEGER:                      return &sql_types[11];
-               case SQL_BIGINT:                       return &sql_types[12];
-               case SQL_INTERVAL:                     return &sql_types[13];
-               case SQL_DECIMAL:                      return &sql_types[14];
-               case SQL_TYPE_TIME:                    return &sql_types[15];
-               case SQL_TIMESTAMP:                    return &sql_types[16];
-               case SQL_TYPE_TIMESTAMP:               return &sql_types[17];
-               case SQL_TYPE_TIMESTAMP_WITH_TIMEZONE: return &sql_types[18];
-               case SQL_UNKNOWN_TYPE:                 return &sql_types[19];
-               case SQL_VARCHAR:                      return &sql_types[20];
+               case SQL_ARRAY:                        return &sql_types[0];
+               case SQL_BIT:                          return &sql_types[1];
+               case SQL_BOOLEAN:                      return &sql_types[2];
+               case SQL_CHAR:                         return &sql_types[3];
+               case SQL_VARBINARY:                    return &sql_types[4];
+               case SQL_TYPE_DATE:                    return &sql_types[5];
+               case SQL_REAL:                         return &sql_types[6];
+               case SQL_NUMERIC:                      return &sql_types[7];
+               case SQL_FLOAT:                        return &sql_types[8];
+               case SQL_DOUBLE:                       return &sql_types[9];
+               case SQL_SMALLINT:                     return &sql_types[10];
+               case SQL_TINYINT:                      return &sql_types[11];
+               case SQL_INTEGER:                      return &sql_types[12];
+               case SQL_BIGINT:                       return &sql_types[13];
+               case SQL_INTERVAL:                     return &sql_types[14];
+               case SQL_DECIMAL:                      return &sql_types[15];
+               case SQL_LONGVARCHAR:                  return &sql_types[16];
+               case SQL_TYPE_TIME:                    return &sql_types[17];
+               case SQL_TIMESTAMP:                    return &sql_types[18];
+               case SQL_TYPE_TIMESTAMP:               return &sql_types[19];
+               case SQL_TYPE_TIMESTAMP_WITH_TIMEZONE: return &sql_types[20];
+               case SQL_UNKNOWN_TYPE:                 return &sql_types[21];
+               case SQL_VARCHAR:                      return &sql_types[22];
                default: return NULL;
        }
 }
@@ -415,7 +419,7 @@
 VARCHAROID, varchar, quote_string, dequote_string, SQL_VARCHAR, 1
 BPCHAROID, bpchar, quote_string, dequote_char, SQL_CHAR, 1
 NAMEOID, name, null_quote, null_dequote, SQL_VARCHAR, 0
-TEXTOID, text, quote_string, dequote_string, SQL_LONGVARCHAR, 0
+TEXTOID, text, quote_string, dequote_string, SQL_LONGVARCHAR, 1
 
 ## Geometric types
 POINTOID, point, quote_geom, dequote_string, 0, 0
@@ -447,7 +451,7 @@
 ## Others
 ABSTIMEOID, abstime, null_quote, null_dequote, 0, 0
 ACLITEMOID, aclitem, null_quote, null_dequote, 0, 0
-ANYARRAYOID, anyarray, null_quote, null_dequote, SQL_ARRAY, 0
+ANYARRAYOID, anyarray, null_quote, null_dequote, SQL_ARRAY, 1
 ANYELEMENTOID, anyelement, 0, 0, 0, 0
 ANYENUMOID, anyenum, 0, 0, 0, 0
 ANYNONARRAYOID, anynonarray, 0, 0, 0, 0
@@ -456,7 +460,7 @@
 CASHOID, money, null_quote, null_dequote, 0, 0
 CIDROID, IP - cidr, null_quote, null_dequote, 0, 0
 CSTRINGOID, cstring, null_quote, null_dequote, 0, 0
-CSTRINGARRAYOID, cstringarray, 0, 0, 0, 0
+CSTRINGARRAYOID, cstringarray, null_quote, null_dequote, 0, 0
 FLOAT4ARRAYOID, float4array, 0, 0, 0, 0
 INETOID, IP address, null_quote, null_dequote, 0, 0
 INT2VECTOROID, int28, null_quote, null_dequote, 0, 0

Reply via email to