Author: timbo
Date: Tue Nov 24 05:07:10 2009
New Revision: 13591
Modified:
dbi/trunk/Changes
dbi/trunk/DBI.pm
dbi/trunk/DBI.xs
dbi/trunk/DBIXS.h
dbi/trunk/dbixs_rev.h
Log:
Added DBI::sql_type_cast() and corresponding internal sql_type_cast_svpv()
Added DBIstcf_DISCARD_STRING and DBIstcf_STRICT constants.
Bumped DBISTATE_VERSION from 94 to 95.
XXX Needs tests.
Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes (original)
+++ dbi/trunk/Changes Tue Nov 24 05:07:10 2009
@@ -8,13 +8,12 @@
=head2 Changes in DBI 1.611 (svn rXXX)
-XXX needs to be redone to convert ReadOnly to an internal flag:
-
- Fixes DBI->trace(0, *STDERR); (H.Merijn Brand)
+ Fixed DBI->trace(0, *STDERR); (H.Merijn Brand)
which tried to open a file named "*main::STDERR" in perl-5.10.x
Bumped required perl version to 5.8.1 (as announced in DBI 1.607)
+XXX needs to be redone to convert ReadOnly to an internal flag:
Changed "Issuing rollback() due to DESTROY without explicit disconnect"
warning to not be issued if ReadOnly set for that dbh.
Updated dbipport.h to Devel::PPPort 3.19 (H.Merijn Brand)
@@ -24,7 +23,16 @@
Added ChildCallbacks => { ... } to Callbacks as a way to
specify Callbacks for child handles.
With tests and docs thanks to David E. Wheeler.
-XXX awaiting docs
+XXX awaiting docs for ChildCallbacks from David.
+
+ Added DBI::sql_type_cast($value, $type, $flags) to cast a string value
+ to an SQL type. e.g. SQL_INTEGER effectively does $value += 0;
+ Has other options plus an internal interface for drivers.
+
+ Added specification of type casting behaviour for bind_column()
+ based on DBI::sql_type_cast() and two new bind_column attributes
+ StrictlyTyped and DiscardString. Thanks to Martin Evans.
+XXX awaiting docs for sql_type_cast & bind_column from Martin Evans.
=head2 Changes in DBI 1.609 (svn r12816) 8th June 2009
Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm (original)
+++ dbi/trunk/DBI.pm Tue Nov 24 05:07:10 2009
@@ -223,6 +223,8 @@
SQL_INTERVAL_HOUR_TO_MINUTE
SQL_INTERVAL_HOUR_TO_SECOND
SQL_INTERVAL_MINUTE_TO_SECOND
+ DBIstcf_DISCARD_STRING
+ DBIstcf_STRICT
) ],
sql_cursor_types => [ qw(
SQL_CURSOR_FORWARD_ONLY
@@ -233,7 +235,7 @@
) ], # for ODBC cursor types
utils => [ qw(
neat neat_list $neat_maxlen dump_results looks_like_number
- data_string_diff data_string_desc data_diff
+ data_string_diff data_string_desc data_diff sql_type_cast
) ],
profile => [ qw(
dbi_profile dbi_profile_merge dbi_profile_merge_nodes dbi_time
Modified: dbi/trunk/DBI.xs
==============================================================================
--- dbi/trunk/DBI.xs (original)
+++ dbi/trunk/DBI.xs Tue Nov 24 05:07:10 2009
@@ -78,6 +78,7 @@
static int set_err_char _((SV *h, imp_xxh_t *imp_xxh, const char *err_c,
IV err_i, const char *errstr, const char *state, const char *method));
static int set_err_sv _((SV *h, imp_xxh_t *imp_xxh, SV *err, SV
*errstr, SV *state, SV *method));
static int quote_type _((int sql_type, int p, int s, int *base_type, void
*v));
+static int sql_type_cast_svpv _((pTHX_ SV *sv, int sql_type, U32 flags,
void *v));
static I32 dbi_hash _((const char *string, long i));
static void dbih_dumphandle _((pTHX_ SV *h, const char *msg, int level));
static int dbih_dumpcom _((pTHX_ imp_xxh_t *imp_xxh, const char *msg, int
level));
@@ -434,11 +435,12 @@
DBIS->get_fbav = dbih_get_fbav;
DBIS->make_fdsv = dbih_make_fdsv;
DBIS->neat_svpv = neatsvpv;
- DBIS->bind_as_num = quote_type;
+ DBIS->bind_as_num = quote_type; /* XXX deprecated */
DBIS->hash = dbi_hash;
DBIS->set_err_sv = set_err_sv;
DBIS->set_err_char= set_err_char;
DBIS->bind_col = dbih_sth_bind_col;
+ DBIS->sql_type_cast_svpv = sql_type_cast_svpv;
/* Remember the last handle used. BEWARE! Sneaky stuff here! */
@@ -1696,6 +1698,8 @@
(void)s;
(void)t;
(void)v;
+ /* looks like it's never been used, and doesn't make much sense anyway */
+ warn("Use of DBI internal bind_as_num/quote_type function is deprecated");
switch(sql_type) {
case SQL_INTEGER:
case SQL_SMALLINT:
@@ -1714,6 +1718,107 @@
}
+/* Convert a simple string representation of a value into a more specific
+ * perl type based on an sql_type value.
+ * The semantics of SQL standard TYPE values are interpreted _very_ loosely
+ * on the basis of "be liberal in what you accept and let's throw in some
+ * extra semantics while we're here" :)
+ * Returns:
+ * -2: sql_type isn't handled, value unchanged
+ * -1: sv is undef, value unchanged
+ * 0: sv couldn't be cast cleanly and DBIstcf_STRICT was used
+ * 1: sv couldn't be cast cleanly and DBIstcf_STRICT was not used
+ * 2: sv was cast ok
+ */
+
+int
+sql_type_cast_svpv(pTHX_ SV *sv, int sql_type, U32 flags, void *v)
+{
+ int cast_ok = 0;
+ int grok_flags;
+ UV uv;
+
+ /* do nothing for undef (NULL) or non-string values */
+ if (!sv || !SvOK(sv))
+ return -1;
+
+ switch(sql_type) {
+
+ default:
+ return -2; /* not a recognised SQL TYPE, value unchanged */
+
+ case SQL_INTEGER:
+ /* sv_2iv is liberal, may return SvIV, SvUV, or SvNV */
+ sv_2iv(sv);
+ /* SvNOK will be set if value is out of range for IV/UV.
+ * SvIOK should be set but won't if sv is not numeric (in which
+ * case perl would have warn'd already if -w or warnings are in effect)
+ */
+ cast_ok = (SvIOK(sv) && !SvNOK(sv));
+ break;
+
+ case SQL_DOUBLE:
+ sv_2nv(sv);
+ /* SvNOK should be set but won't if sv is not numeric (in which
+ * case perl would have warn'd already if -w or warnings are in effect)
+ */
+ cast_ok = SvNOK(sv);
+ break;
+
+ /* caller would like IV else UV else NV */
+ /* else no error and sv is untouched */
+ case SQL_NUMERIC:
+ /* based on the code in perl's toke.c */
+ uv = 0;
+ grok_flags = grok_number(SvPVX(sv), SvCUR(sv), &uv);
+ cast_ok = 1;
+ if (flags == IS_NUMBER_IN_UV) { /* +ve int */
+ if (uv <= IV_MAX) /* prefer IV over UV */
+ sv_2iv(sv);
+ else sv_2uv(sv);
+ }
+ else if (flags == (IS_NUMBER_IN_UV | IS_NUMBER_NEG)
+ && uv <= IV_MAX
+ ) {
+ sv_2iv(sv);
+ }
+ else if (flags) { /* is numeric */
+ sv_2nv(sv);
+ }
+ else if (flags & DBIstcf_STRICT)
+ cast_ok = 0;
+ break;
+
+#if 0 /* XXX future possibilities */
+ case SQL_BIGINT: /* use Math::BigInt if too large for IV/UV */
+#endif
+ }
+
+ if (cast_ok) {
+
+ if (flags & DBIstcf_DISCARD_STRING
+ && SvNIOK(sv) /* we set a numeric value */
+ && SvPVX(sv) /* we have a buffer to discard */
+ ) {
+ SvOOK_off(sv);
+ if (SvLEN(sv)) {
+ Safefree(SvPVX(sv));
+ SvLEN(sv) = 0;
+ }
+ SvPVX(sv) = NULL;
+ SvPOK_off(sv);
+ }
+ }
+
+ if (cast_ok)
+ return 2;
+ else if (flags & DBIstcf_STRICT)
+ return 0;
+ else return 1;
+}
+
+
+
/* --- Generic Handle Attributes (for all handle types) --- */
static int
@@ -4007,7 +4112,7 @@
SQL_ALL_TYPES = SQL_ALL_TYPES
SQL_ARRAY = SQL_ARRAY
SQL_ARRAY_LOCATOR = SQL_ARRAY_LOCATOR
- SQL_BIGINT = SQL_BIGINT
+ SQL_BIGINT = SQL_BIGINT
SQL_BINARY = SQL_BINARY
SQL_BIT = SQL_BIT
SQL_BLOB = SQL_BLOB
@@ -4081,6 +4186,8 @@
DBIpp_st_qq = DBIpp_st_qq
DBIpp_st_bs = DBIpp_st_bs
DBIpp_st_XX = DBIpp_st_XX
+ DBIstcf_DISCARD_STRING = DBIstcf_DISCARD_STRING
+ DBIstcf_STRICT = DBIstcf_STRICT
CODE:
RETVAL = ix;
OUTPUT:
@@ -4438,7 +4545,15 @@
RETVAL
-
+int
+sql_type_cast(sv, sql_type, flags=0)
+ SV * sv
+ int sql_type
+ U32 flags
+ CODE:
+ RETVAL = sql_type_cast_svpv(aTHX_ sv, sql_type, flags, 0);
+ OUTPUT:
+ RETVAL
Modified: dbi/trunk/DBIXS.h
==============================================================================
--- dbi/trunk/DBIXS.h (original)
+++ dbi/trunk/DBIXS.h Tue Nov 24 05:07:10 2009
@@ -342,6 +342,10 @@
#define neatsvpv(sv,len) (DBIS->neat_svpv(sv,len))
#endif
+/* --- For sql_type_cast_svpv() --- */
+
+#define DBIstcf_DISCARD_STRING 0x0001
+#define DBIstcf_STRICT 0x0002
/* --- Implementors Private Data Support --- */
@@ -392,7 +396,7 @@
struct dbistate_st {
-#define DBISTATE_VERSION 94 /* Must change whenever dbistate_t does */
+#define DBISTATE_VERSION 95 /* Must change whenever dbistate_t does */
/* this must be the first member in structure */
void (*check_version) _((const char *name,
@@ -417,7 +421,7 @@
SV * (*get_attr_k) _((SV *h, SV *keysv, int dbikey));
AV * (*get_fbav) _((imp_sth_t *imp_sth));
SV * (*make_fdsv) _((SV *sth, const char *imp_class, STRLEN
imp_size, const char *col_name));
- int (*bind_as_num) _((int sql_type, int p, int s, int *t, void
*v));
+ int (*bind_as_num) _((int sql_type, int p, int s, int *t, void
*v)); /* XXX deprecated */
I32 (*hash) _((const char *string, long i));
SV * (*preparse) _((SV *sth, char *statement, IV ps_return, IV
ps_accept, void *foo));
@@ -430,11 +434,13 @@
int (*set_err_char) _((SV *h, imp_xxh_t *imp_xxh, const char *err,
IV err_i, const char *errstr, const char *state, const char *method));
int (*bind_col) _((SV *sth, SV *col, SV *ref, SV *attribs));
- IO *logfp_ref; /* DAA keep ptr to filehandle for refcounting */
+ IO *logfp_ref; /* keep ptr to filehandle for refcounting */
+
+ int (*sql_type_cast_svpv) _((pTHX_ SV *sv, int sql_type, U32
flags, void *v));
/* WARNING: Only add new structure members here, and reduce pad2 to keep */
/* the memory footprint exactly the same */
- void *pad2[4];
+ void *pad2[3];
};
/* macros for backwards compatibility */
Modified: dbi/trunk/dbixs_rev.h
==============================================================================
--- dbi/trunk/dbixs_rev.h (original)
+++ dbi/trunk/dbixs_rev.h Tue Nov 24 05:07:10 2009
@@ -1,4 +1,3 @@
-/* Mon Nov 2 22:44:58 2009 */
-/* Mixed revision working copy (13455M:13465) */
+/* Tue Nov 24 12:53:00 2009 */
/* Code modified since last checkin */
-#define DBIXS_REVISION 13455
+#define DBIXS_REVISION 13590