[DBD::Pg] Quick partial implmentation of the new UTF-8 plan.
dbdpg-commits-gENoVmVU/[email protected] Wed, 29 Jun 2011 02:50:08 +0000
| Newsgroups | gmane.comp.db.postgresql.dbdpg.cvs |
|---|---|
| Message-ID | <[email protected]> |
Committed by Greg Sabino Mullane <greg-O9fzpki4YnJWk0Htik3J/[email protected]> Quick partial implmentation of the new UTF-8 plan. --- dbdimp.c | 95 ++++++++++++++++++++++++++++++++++++-------------------- dbdimp.h | 2 +- testme.tmp.pl | 6 +++ 3 files changed, 68 insertions(+), 35 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 30567d0..076bcbc 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -108,7 +108,9 @@ int dbd_db_login6 (SV * dbh, imp_dbh_t * imp_dbh, char * dbname, char * uid, cha bool inquote = DBDPG_FALSE; STRLEN connect_string_size; ConnStatusType connstatus; - int utf8int; + int unicode; + const char * server_encoding; + const char * client_encoding; if (TSTART) TRC(DBILOGFP, "%sBegin dbd_db_login\n", THEADER); @@ -211,28 +213,32 @@ int dbd_db_login6 (SV * dbh, imp_dbh_t * imp_dbh, char * dbname, char * uid, cha TRACE_PQPROTOCOLVERSION; imp_dbh->pg_protocol = PQprotocolVersion(imp_dbh->conn); - /* Check the value of the pg_utf8_strings attribute. Default to not set (-1) */ - utf8int = -1; - DBD_ATTRIB_GET_IV(attr, "pg_utf8_strings", 15, svp, utf8int); + /* Check the value of the pg_unicode attribute. Default to not set (-1) */ + unicode = -1; + DBD_ATTRIB_GET_IV(attr, "pg_unicode", 10, svp, unicode); /* We need to see if we are treating things with utf8 respect, or as byte soup The rules are: - - pg_utf8_strings trumps everything else - - SQL_ASCII is always byte soup - - Everything else is not + - An explicit pg_unicode setting trumps everything else + - A server_encoding of SQL_ASCII is always byte soup + - If the client_encoding matches the server_encoding, set unicode on + - Otherwise, we leave things alone */ - if (utf8int > 1) { /* Force it on, no matter what */ - imp_dbh->utf8_strings = DBDPG_TRUE; + client_encoding = PQparameterStatus(imp_dbh->conn, "client_encoding"); + + if (unicode > 1) { /* Force it on, no matter what */ + imp_dbh->unicode = DBDPG_TRUE; } else { - if (utf8int == 0) { /* Force it off, no matter what */ - imp_dbh->utf8_strings = DBDPG_FALSE; + if (unicode == 0) { /* Force it off, no matter what */ + imp_dbh->unicode = DBDPG_FALSE; } - else { /* Neither is set, so use the server_encoding */ - imp_dbh->utf8_strings = - (0 == strncmp(PQparameterStatus(imp_dbh->conn, "server_encoding"), "SQL_ASCII", 9)) - ? DBDPG_FALSE : DBDPG_TRUE; + else { /* Neither is set, so check the encodings */ + server_encoding = PQparameterStatus(imp_dbh->conn, "server_encoding"); + /* If they match, set unicode to true, otherwise, false */ + imp_dbh->unicode = (0==strcmp(server_encoding, client_encoding)) + ? DBDPG_TRUE : DBDPG_FALSE; } } @@ -271,7 +277,6 @@ int dbd_db_login6 (SV * dbh, imp_dbh_t * imp_dbh, char * dbname, char * uid, cha /* Deprecated: */ imp_dbh->pg_enable_utf8 = DBDPG_FALSE; - /* If using server version 7.4, switch to "smart" */ imp_dbh->server_prepare = PGLIBVERSION >= 80000 ? 1 : 2; @@ -281,6 +286,12 @@ int dbd_db_login6 (SV * dbh, imp_dbh_t * imp_dbh, char * dbname, char * uid, cha /* Tell DBI that we should call disconnect when the handle dies */ DBIc_ACTIVE_on(imp_dbh); + /* If needed, set the client_encoding to UTF-8 */ + if (imp_dbh->unicode && + (0 == strncmp(client_encoding, "UTF-8", 5))) { + PQexec(imp_dbh->conn, "SET client_encoding = 'UTF-8'"); + } + if (TEND) TRC(DBILOGFP, "%sEnd dbd_db_login\n", THEADER); return 1; @@ -312,7 +323,7 @@ static void pg_error (pTHX_ SV * h, int error_num, const char * error_msg) sv_setpv(DBIc_STATE(imp_xxh), (char*)imp_dbh->sqlstate); /* Set as utf-8 */ - if (imp_dbh->utf8_strings) + if (imp_dbh->unicode) SvUTF8_on(DBIc_ERRSTR(imp_xxh)); if (TEND) TRC(DBILOGFP, "%sEnd pg_error\n", THEADER); @@ -375,6 +386,11 @@ static ExecStatusType _result(pTHX_ imp_dbh_t * imp_dbh, const char * sql) if (TSQL) TRC(DBILOGFP, "%s;\n\n", sql); + /* Upgrade to a true UTF-8 string in place as needed */ + if (imp_dbh->unicode) { + // upgrade_utf8 magic on 'sql' + } + TRACE_PQEXEC; result = PQexec(imp_dbh->conn, sql); @@ -733,7 +749,7 @@ SV * dbd_db_FETCH_attrib (SV * dbh, imp_dbh_t * imp_dbh, SV * keysv) } break; - case 10: /* AutoCommit pg_bool_tf pg_pid_number pg_options */ + case 10: /* AutoCommit pg_bool_tf pg_pid_number pg_options pg_unicode */ if (strEQ("AutoCommit", key)) retsv = boolSV(DBIc_has(imp_dbh, DBIcf_AutoCommit)); @@ -745,6 +761,8 @@ SV * dbd_db_FETCH_attrib (SV * dbh, imp_dbh_t * imp_dbh, SV * keysv) TRACE_PQOPTIONS; retsv = newSVpv(PQoptions(imp_dbh->conn),0); } + else if (strEQ("pg_unicode", key)) + retsv = newSViv((IV)imp_dbh->unicode); break; case 11: /* pg_INV_READ pg_protocol */ @@ -777,7 +795,7 @@ SV * dbd_db_FETCH_attrib (SV * dbh, imp_dbh_t * imp_dbh, SV * keysv) retsv = newSViv((IV)imp_dbh->pg_enable_utf8); break; - case 15: /* pg_default_port pg_async_status pg_expand_array pg_utf8_strings */ + case 15: /* pg_default_port pg_async_status pg_expand_array */ if (strEQ("pg_default_port", key)) retsv = newSViv((IV) PGDEFPORT ); @@ -785,8 +803,6 @@ SV * dbd_db_FETCH_attrib (SV * dbh, imp_dbh_t * imp_dbh, SV * keysv) retsv = newSViv((IV)imp_dbh->async_status); else if (strEQ("pg_expand_array", key)) retsv = newSViv((IV)imp_dbh->expand_array); - else if (strEQ("pg_utf8_strings", key)) - retsv = newSViv((IV)imp_dbh->utf8_strings); break; case 17: /* pg_server_prepare pg_server_version */ @@ -854,7 +870,7 @@ int dbd_db_STORE_attrib (SV * dbh, imp_dbh_t * imp_dbh, SV * keysv, SV * valuesv } break; - case 10: /* AutoCommit pg_bool_tf */ + case 10: /* AutoCommit pg_bool_tf pg_unicode*/ if (strEQ("AutoCommit", key)) { if (newval != DBIc_has(imp_dbh, DBIcf_AutoCommit)) { @@ -866,10 +882,18 @@ int dbd_db_STORE_attrib (SV * dbh, imp_dbh_t * imp_dbh, SV * keysv, SV * valuesv } retval = 1; } + else if (strEQ("pg_bool_tf", key)) { imp_dbh->pg_bool_tf = newval!=0 ? DBDPG_TRUE : DBDPG_FALSE; retval = 1; } + + else if (strEQ("pg_unicode", key)) { + imp_dbh->unicode = newval!=0 ? DBDPG_TRUE : DBDPG_FALSE; + retval = 1; + } + + break; case 13: /* pg_errorlevel */ @@ -902,18 +926,13 @@ int dbd_db_STORE_attrib (SV * dbh, imp_dbh_t * imp_dbh, SV * keysv, SV * valuesv break; - case 15: /* pg_expand_array pg_utf8_strings */ + case 15: /* pg_expand_array */ if (strEQ("pg_expand_array", key)) { imp_dbh->expand_array = newval ? DBDPG_TRUE : DBDPG_FALSE; retval = 1; } - else if (strEQ("pg_utf8_strings", key)) { - imp_dbh->utf8_strings = newval!=0 ? DBDPG_TRUE : DBDPG_FALSE; - retval = 1; - } - break; case 17: /* pg_server_prepare */ @@ -1120,7 +1139,7 @@ SV * dbd_st_FETCH_attrib (SV * sth, imp_sth_t * imp_sth, SV * keysv) TRACE_PQFNAME; fieldname = PQfname(imp_sth->result, fields); sv_fieldname = newSVpv(fieldname,0); - if (imp_dbh->utf8_strings) + if (imp_dbh->unicode) SvUTF8_on(sv_fieldname); (void)av_store(av, fields, sv_fieldname); } @@ -2694,7 +2713,7 @@ static SV * pg_destringify_array(pTHX_ imp_dbh_t *imp_dbh, unsigned char * input av_push(currentav, newSViv('t' == *string ? 1 : 0)); else { SV *sv = newSVpvn(string, section_size); - if (imp_dbh->utf8_strings) + if (imp_dbh->unicode) SvUTF8_on(sv); av_push(currentav, sv); } @@ -2822,6 +2841,11 @@ int pg_quickexec (SV * dbh, const char * sql, const int asyncflag) if (TSQL) TRC(DBILOGFP, "%s;\n\n", sql); + /* Upgrade to a true UTF-8 string in place as needed */ + if (imp_dbh->unicode) { + // upgrade_utf8 magic on 'sql' + } + TRACE_PQEXEC; result = PQexec(imp_dbh->conn, sql); status = _sqlstate(aTHX_ imp_dbh, result); @@ -3145,6 +3169,7 @@ int dbd_st_execute (SV * sth, imp_sth_t * imp_sth) } else { TRACE_PQEXECPREPARED; + // upgrade utf8 magic: prepare_name, PQvals imp_sth->result = PQexecPrepared (imp_dbh->conn, imp_sth->prepare_name, imp_sth->numphs, imp_sth->PQvals, imp_sth->PQlens, imp_sth->PQfmts, 0); } @@ -3224,6 +3249,7 @@ int dbd_st_execute (SV * sth, imp_sth_t * imp_sth) } else { TRACE_PQEXECPARAMS; + // upgrade utf8 magic: statement, PQvals imp_sth->result = PQexecParams (imp_dbh->conn, statement, imp_sth->numphs, imp_sth->PQoids, imp_sth->PQvals, imp_sth->PQlens, imp_sth->PQfmts, 0); } @@ -3263,6 +3289,7 @@ int dbd_st_execute (SV * sth, imp_sth_t * imp_sth) } else { TRACE_PQEXEC; + // upgrade utf8 magic: statement imp_sth->result = PQexec(imp_dbh->conn, statement); } @@ -3468,7 +3495,7 @@ AV * dbd_st_fetch (SV * sth, imp_sth_t * imp_sth) break; default: sv_setpvn(sv, (char *)value, value_len); - if (imp_dbh->utf8_strings) + if (imp_dbh->unicode) SvUTF8_on(sv); } } @@ -3476,7 +3503,7 @@ AV * dbd_st_fetch (SV * sth, imp_sth_t * imp_sth) value_len = strlen((char *)value); sv_setpvn(sv, (char *)value, value_len); /* Check for specific types here? */ - if (imp_dbh->utf8_strings) + if (imp_dbh->unicode) SvUTF8_on(sv); } @@ -3506,7 +3533,7 @@ AV * dbd_st_fetch (SV * sth, imp_sth_t * imp_sth) */ const char * const s = SvPV(AvARRAY(av)[i],len); sv_setpvn(currph->inout, s, len); - if (imp_dbh->utf8_strings) + if (imp_dbh->unicode) SvUTF8_on(currph->inout); } } @@ -3852,7 +3879,7 @@ int pg_db_getcopydata (SV * dbh, SV * dataline, int async) if (copystatus > 0) { sv_setpv(dataline, tempbuf); - if (imp_dbh->utf8_strings) + if (imp_dbh->unicode) SvUTF8_on(dataline); TRACE_PQFREEMEM; PQfreemem(tempbuf); diff --git a/dbdimp.h b/dbdimp.h index 6310514..b30ceaf 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -31,7 +31,7 @@ struct imp_dbh_st { char *sqlstate; /* from the last result */ bool pg_bool_tf; /* do bools return 't'/'f'? Set by user, default is 0 */ - bool utf8_strings; /* so we set the utf8 flag on data from the database? */ + bool unicode; /* do we force client_encoding to UTF-8 and set the Perl utf8 string on returned data? */ bool pg_enable_utf8; /* (DEPRECATED) should we attempt to make utf8 strings? Set by user, default is 0 */ 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?) */ diff --git a/testme.tmp.pl b/testme.tmp.pl index 713f5f8..d540714 100755 --- a/testme.tmp.pl +++ b/testme.tmp.pl @@ -19,6 +19,7 @@ my $tracelevel = shift || 0; $ENV{DBI_TRACE} = $tracelevel; my $dbname = 'latin'; +$dbname = 'greg'; my $DSN = "DBI:Pg:dbname=$dbname"; my $dbh = DBI->connect($DSN, '', '', {AutoCommit=>0,RaiseError=>1,PrintError=>0}) @@ -27,6 +28,11 @@ my $dbh = DBI->connect($DSN, '', '', {AutoCommit=>0,RaiseError=>1,PrintError=>0} my $me = $dbh->{Driver}{Name}; print "DBI is version $DBI::VERSION, I am $me, version of DBD::Pg is $DBD::Pg::VERSION\n"; +my $SQL = 'SHOW client_encoding'; +my $enc = $dbh->selectall_arrayref($SQL)->[0][0]; +print "Client encoding: $enc\n"; +$dbh->commit(); + exit; sub memory_leak_test_bug_65734 { -- 1.7.0.5