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