DBD-SQLite-Amalgamation

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

t/00basic.t
t/01logon.t
t/02cr_table.t
t/03insert.t
t/04select.t
t/05tran.t
t/06error.t
t/08create_function.t
t/09create_aggregate.t
t/10dsnlist.t
t/11unicode.t
t/12create_collation.t
t/13progress_handler.t
t/20createdrop.t
t/30insertfetch.t
t/40bindparam.t
t/40blobs.t
t/40blobtext.t
t/40listfields.t
t/40nulls.t
t/40numrows.t

dbdimp.c  view on Meta::CPAN

            dbname, sqlite3_version);
    }

    if (sqlite3_open(dbname, &(imp_dbh->db)) != SQLITE_OK) {
        sqlite_error(dbh, (imp_xxh_t*)imp_dbh, 1, (char*)sqlite3_errmsg(imp_dbh->db));
        return FALSE;
    }
    DBIc_IMPSET_on(imp_dbh);

    imp_dbh->in_tran = FALSE;
    imp_dbh->unicode = FALSE;
    imp_dbh->functions = newAV();
    imp_dbh->aggregates = newAV();
    imp_dbh->timeout = SQL_TIMEOUT;
    
    imp_dbh->handle_binary_nulls = FALSE;

    sqlite3_busy_timeout(imp_dbh->db, SQL_TIMEOUT);

    if ((retval = sqlite3_exec(imp_dbh->db, "PRAGMA empty_result_callbacks = ON",
        NULL, NULL, &errmsg))

dbdimp.c  view on Meta::CPAN

                val = (char*)sqlite3_column_text(imp_sth->stmt, i);
                len = sqlite3_column_bytes(imp_sth->stmt, i);
                if (chopBlanks) {
                    val = savepv(val);
                    while((len > 0) && (val[len-1] == ' ')) {
                       len--;
                    }
                    val[len] = '\0';
                }
                sv_setpvn(AvARRAY(av)[i], val, len);
                if (imp_dbh->unicode) {
                  SvUTF8_on(AvARRAY(av)[i]);
                } else {
                  SvUTF8_off(AvARRAY(av)[i]);
                }
                if (chopBlanks) Safefree(val);
                break;
            case SQLITE_BLOB:
                len = sqlite3_column_bytes(imp_sth->stmt, i);
                sv_setpvn(AvARRAY(av)[i], sqlite3_column_blob(imp_sth->stmt, i), len);
                SvUTF8_off(AvARRAY(av)[i]);

dbdimp.c  view on Meta::CPAN

                {
                    sqlite_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
                    return TRUE;
                }
                imp_dbh->in_tran = FALSE;
            }
        }
        DBIc_set(imp_dbh, DBIcf_AutoCommit, SvTRUE(valuesv));
        return TRUE;
    }
    if (strEQ(key, "unicode")) {
      imp_dbh->unicode = !(! SvTRUE(valuesv));
      return TRUE;
    }
    return FALSE;
}

SV *
sqlite_db_FETCH_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)
{
    dTHR;
    char *key = SvPV_nolen(keysv);

    if (strEQ(key, "sqlite_version")) {
        return newSVpv(sqlite3_version,0);
    }
   if (strEQ(key, "unicode")) {
     return newSViv(imp_dbh->unicode ? 1 : 0);
   }

    return NULL;
}

int
sqlite_st_STORE_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv)
{
    char *key = SvPV_nolen(keysv);
    return FALSE;

dbdimp.c  view on Meta::CPAN

      warn("improper collation function: '%s' is not symmetric", name); 
    }

    /* Copy the func reference so that it can be deallocated at disconnect */
    av_push( imp_dbh->functions, func_sv );

    /* Register the func within sqlite3 */
    rv = sqlite3_create_collation( 
      imp_dbh->db, name, SQLITE_UTF8,
      func_sv, 
      imp_dbh->unicode ? sqlite_db_collation_dispatcher_utf8 
                       : sqlite_db_collation_dispatcher
      );

    if ( rv != SQLITE_OK )
    {
        croak( "sqlite_create_collation failed with error %s", 
               sqlite3_errmsg(imp_dbh->db) );
    }
}

dbdimp.h  view on Meta::CPAN

    dbih_drc_t com;
    /* sqlite specific bits */
};

/* Database Handle */
struct imp_dbh_st {
    dbih_dbc_t com;
    /* sqlite specific bits */
    sqlite3 *db;
    bool in_tran;
    bool unicode;
    bool handle_binary_nulls;
    int timeout;
    AV *functions;
    AV *aggregates;
};

/* Statement Handle */
struct imp_sth_st {
    dbih_stc_t com;
    /* sqlite specific bits */

lib/DBD/SQLite.pm  view on Meta::CPAN


=head2 Database Handle Attributes

=over 4

=item sqlite_version

Returns the version of the SQLite library which DBD::SQLite is using,
e.g., "2.8.0". Can only be read.

=item unicode

If set to a true value, DBD::SQLite will turn the UTF-8 flag on for all text
strings coming out of the database. For more details on the UTF-8 flag see
L<perlunicode>. The default is for the UTF-8 flag to be turned off.

Also note that due to some bizareness in SQLite's type system (see
http://www.sqlite.org/datatype3.html), if you want to retain
blob-style behavior for B<some> columns under C<< $dbh->{unicode} = 1
>> (say, to store images in the database), you have to state so
explicitely using the 3-argument form of L<DBI/bind_param> when doing
updates:

    use DBI qw(:sql_types);
    $dbh->{unicode} = 1;
    my $sth = $dbh->prepare
         ("INSERT INTO mytable (blobcolumn) VALUES (?)");
    $sth->bind_param(1, $binary_data, SQL_BLOB); # binary_data will
    # be stored as-is.

Defining the column type as BLOB in the DDL is B<not> sufficient.

=back

=head1 DRIVER PRIVATE METHODS

lib/DBD/SQLite.pm  view on Meta::CPAN

Collations C<binary> and C<nocase> are builtin within Sqlite.
Collations C<perl> and C<perllocale> are builtin within 
the C<DBD::SQLite> driver, and correspond to the 
Perl C<cmp> operator with or without the L<locale> pragma; 
so you can write for example 

  CREATE TABLE foo(txt1 COLLATE perl,
                   txt2 COLLATE perllocale,
                   txt3 COLLATE nocase)

If the attribute C<< $dbh->{unicode} >> is set, strings coming from
the database and passed to the collation function will be properly
tagged with the utf8 flag; but this only works if the 
C<unicode> attribute is set B<before> the call to 
C<create_collation>. The recommended way to activate unicode
is to set the parameter at connection time :

  my $dbh = DBI->connect("dbi:SQLite:dbname=foo", "", "", 
                          { RaiseError => 1,
                            unicode    => 1} );


=head2 $dbh->func( $n_opcodes, $handler, 'progress_handler' )

This method registers a handler to be invoked 
periodically during long running calls to SQLite.
An example use for this interface is to keep a GUI 
updated during a large query.
The parameters are:

ppport.h  view on Meta::CPAN

pad_new|||
pad_peg|||n
pad_push|||
pad_reset|||
pad_setsv|||
pad_sv||5.009005|
pad_swipe|||
pad_tidy|||
pad_undef|||
parse_body|||
parse_unicode_opts|||
parser_dup|||
parser_free|||
path_is_absolute|||n
peep|||
pending_Slabs_to_ro|||
perl_alloc_using|||n
perl_alloc|||n
perl_clone_using|||n
perl_clone|||n
perl_construct|||n

sqlite-amalgamation.c  view on Meta::CPAN

  char *zMalloc;      /* Dynamic buffer allocated by sqlite3_malloc() */
};

/* One or more of the following flags are set to indicate the validOK
** representations of the value stored in the Mem struct.
**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** No other flags may be set in this case.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.
** Usually this is encoded in the same unicode encoding as the main
** database (see below for exceptions). If the MEM_Term flag is also
** set, then the string is nul terminated. The MEM_Int and MEM_Real 
** flags may coexist with the MEM_Str flag.
**
** Multiple of these values can appear in Mem.flags.  But only one
** at a time can appear in Mem.type.
*/
#define MEM_Null      0x0001   /* Value is NULL */
#define MEM_Str       0x0002   /* Value is a string */
#define MEM_Int       0x0004   /* Value is an integer */

sqlite-amalgamation.c  view on Meta::CPAN

  c += (*zIn++);                                                      \
  if( c>=0xD800 && c<0xE000 ){                                       \
    int c2 = ((*zIn++)<<8);                                           \
    c2 += (*zIn++);                                                   \
    c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);   \
    if( (c & 0xFFFF0000)==0 ) c = 0xFFFD;                             \
  }                                                                   \
}

/*
** Translate a single UTF-8 character.  Return the unicode value.
**
** During translation, assume that the byte that zTerm points
** is a 0x00.
**
** Write a pointer to the next unread byte back into *pzNext.
**
** Notes On Invalid UTF-8:
**
**  *  This routine never allows a 7-bit character (0x00 through 0x7f) to
**     be encoded as a multi-byte character.  Any multi-byte character that

sqlite-amalgamation.c  view on Meta::CPAN

**  *  This routine never allows a UTF16 surrogate value to be encoded.
**     If a multi-byte character attempts to encode a value between
**     0xd800 and 0xe000 then it is rendered as 0xfffd.
**
**  *  Bytes in the range of 0x80 through 0xbf which occur as the first
**     byte of a character are interpreted as single-byte characters
**     and rendered as themselves even though they are technically
**     invalid characters.
**
**  *  This routine accepts an infinite number of different UTF8 encodings
**     for unicode values 0x80 and greater.  It do not change over-length
**     encodings to 0xfffd as some systems recommend.
*/
#define READ_UTF8(zIn, zTerm, c)                           \
  c = *(zIn++);                                            \
  if( c>=0xc0 ){                                           \
    c = sqlite3UtfTrans1[c-0xc0];                          \
    while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){            \
      c = (c<<6) + (0x3f & *(zIn++));                      \
    }                                                      \
    if( c<0x80                                             \

sqlite-amalgamation.c  view on Meta::CPAN

      pMem->z[pMem->n+1] = '\0';
      pMem->flags |= MEM_Term;
      pMem->enc = bom;
    }
  }
  return rc;
}
#endif /* SQLITE_OMIT_UTF16 */

/*
** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
** return the number of unicode characters in pZ up to (but not including)
** the first 0x00 byte. If nByte is not less than zero, return the
** number of unicode characters in the first nByte of pZ (or up to 
** the first 0x00, whichever comes first).
*/
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){
  int r = 0;
  const u8 *z = (const u8*)zIn;
  const u8 *zTerm;
  if( nByte>=0 ){
    zTerm = &z[nByte];
  }else{
    zTerm = (const u8*)(-1);

sqlite-amalgamation.c  view on Meta::CPAN

  if( db->mallocFailed ){
    sqlite3VdbeMemRelease(&m);
    m.z = 0;
  }
  assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
  assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
  return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3DbStrDup(db, m.z);
}

/*
** pZ is a UTF-16 encoded unicode string. If nChar is less than zero,
** return the number of bytes up to (but not including), the first pair
** of consecutive 0x00 bytes in pZ. If nChar is not less than zero,
** then return the number of bytes in the first nChar unicode characters
** in pZ (or up until the first pair of 0x00 bytes, whichever comes first).
*/
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
  unsigned int c = 1;
  char const *z = zIn;
  int n = 0;
  if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
    /* Using an "if (SQLITE_UTF16NATIVE==SQLITE_UTF16BE)" construct here
    ** and in other parts of this file means that at one branch will
    ** not be covered by coverage testing on any single host. But coverage

sqlite-amalgamation.c  view on Meta::CPAN

      OSVERSIONINFO sInfo;
      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
      GetVersionEx(&sInfo);
      sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
    }
    return sqlite3_os_type==2;
  }
#endif /* SQLITE_OS_WINCE */

/*
** Convert a UTF-8 string to microsoft unicode (UTF-16?). 
**
** Space to hold the returned string is obtained from malloc.
*/
static WCHAR *utf8ToUnicode(const char *zFilename){
  int nChar;
  WCHAR *zWideFilename;

  nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
  zWideFilename = malloc( nChar*sizeof(zWideFilename[0]) );
  if( zWideFilename==0 ){

sqlite-amalgamation.c  view on Meta::CPAN

  }
  nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar);
  if( nChar==0 ){
    free(zWideFilename);
    zWideFilename = 0;
  }
  return zWideFilename;
}

/*
** Convert microsoft unicode to UTF-8.  Space to hold the returned string is
** obtained from malloc().
*/
static char *unicodeToUtf8(const WCHAR *zWideFilename){
  int nByte;
  char *zFilename;

  nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
  zFilename = malloc( nByte );
  if( zFilename==0 ){
    return 0;
  }
  nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
                              0, 0);
  if( nByte == 0 ){
    free(zFilename);
    zFilename = 0;
  }
  return zFilename;
}

/*
** Convert an ansi string to microsoft unicode, based on the
** current codepage settings for file apis.
** 
** Space to hold the returned string is obtained
** from malloc.
*/
static WCHAR *mbcsToUnicode(const char *zFilename){
  int nByte;
  WCHAR *zMbcsFilename;
  int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;

sqlite-amalgamation.c  view on Meta::CPAN

  }
  nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte);
  if( nByte==0 ){
    free(zMbcsFilename);
    zMbcsFilename = 0;
  }
  return zMbcsFilename;
}

/*
** Convert microsoft unicode to multibyte character string, based on the
** user's Ansi codepage.
**
** Space to hold the returned string is obtained from
** malloc().
*/
static char *unicodeToMbcs(const WCHAR *zWideFilename){
  int nByte;
  char *zFilename;
  int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;

  nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
  zFilename = malloc( nByte );
  if( zFilename==0 ){
    return 0;
  }
  nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte,

sqlite-amalgamation.c  view on Meta::CPAN

** returned string is obtained from malloc().
*/
static char *mbcsToUtf8(const char *zFilename){
  char *zFilenameUtf8;
  WCHAR *zTmpWide;

  zTmpWide = mbcsToUnicode(zFilename);
  if( zTmpWide==0 ){
    return 0;
  }
  zFilenameUtf8 = unicodeToUtf8(zTmpWide);
  free(zTmpWide);
  return zFilenameUtf8;
}

/*
** Convert UTF-8 to multibyte character string.  Space to hold the 
** returned string is obtained from malloc().
*/
static char *utf8ToMbcs(const char *zFilename){
  char *zFilenameMbcs;
  WCHAR *zTmpWide;

  zTmpWide = utf8ToUnicode(zFilename);
  if( zTmpWide==0 ){
    return 0;
  }
  zFilenameMbcs = unicodeToMbcs(zTmpWide);
  free(zTmpWide);
  return zFilenameMbcs;
}

#if SQLITE_OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
*/
/*
** WindowsCE does not have a localtime() function.  So create a

sqlite-amalgamation.c  view on Meta::CPAN

    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  size_t i, j;
  char zTempPath[MAX_PATH+1];
  if( sqlite3_temp_directory ){
    sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
  }else if( isNT() ){
    char *zMulti;
    WCHAR zWidePath[MAX_PATH];
    GetTempPathW(MAX_PATH-30, zWidePath);
    zMulti = unicodeToUtf8(zWidePath);
    if( zMulti ){
      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
      free(zMulti);
    }else{
      return SQLITE_NOMEM;
    }
  }else{
    char *zUtf8;
    char zMbcsPath[MAX_PATH];
    GetTempPathA(MAX_PATH-30, zMbcsPath);

sqlite-amalgamation.c  view on Meta::CPAN

  if( isNT() ){
    WCHAR *zTemp;
    nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3;
    zTemp = malloc( nByte*sizeof(zTemp[0]) );
    if( zTemp==0 ){
      free(zConverted);
      return SQLITE_NOMEM;
    }
    GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0);
    free(zConverted);
    zOut = unicodeToUtf8(zTemp);
    free(zTemp);
  }else{
    char *zTemp;
    nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3;
    zTemp = malloc( nByte*sizeof(zTemp[0]) );
    if( zTemp==0 ){
      free(zConverted);
      return SQLITE_NOMEM;
    }
    GetFullPathNameA((char*)zConverted, nByte, zTemp, 0);

sqlite-amalgamation.c  view on Meta::CPAN

    return SQLITE_MISUSE;
  }
  sqlite3_mutex_enter(db->mutex);
  zSql8 = sqlite3Utf16to8(db, zSql, nBytes);
  if( zSql8 ){
    rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, ppStmt, &zTail8);
  }

  if( zTail8 && pzTail ){
    /* If sqlite3_prepare returns a tail pointer, we calculate the
    ** equivalent pointer into the UTF-16 string by counting the unicode
    ** characters between zSql8 and zTail8, and then returning a pointer
    ** the same number of characters into the UTF-16 string.
    */
    int chars_parsed = sqlite3Utf8CharLen(zSql8, zTail8-zSql8);
    *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
  }
  sqlite3DbFree(db, zSql8); 
  rc = sqlite3ApiExit(db, rc);
  sqlite3_mutex_leave(db->mutex);
  return rc;

sqlite-amalgamation.c  view on Meta::CPAN

  sqlite3_mutex_leave(db->mutex);
  return z;
}

#ifndef SQLITE_OMIT_UTF16
/*
** Return UTF-16 encoded English language explanation of the most recent
** error.
*/
SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){
  /* Because all the characters in the string are in the unicode
  ** range 0x00-0xFF, if we pad the big-endian string with a 
  ** zero byte, we can obtain the little-endian string with
  ** &big_endian[1].
  */
  static const char outOfMemBe[] = {
    0, 'o', 0, 'u', 0, 't', 0, ' ', 
    0, 'o', 0, 'f', 0, ' ', 
    0, 'm', 0, 'e', 0, 'm', 0, 'o', 0, 'r', 0, 'y', 0, 0, 0
  };
  static const char misuseBe [] = {

sqlite-amalgamation.c  view on Meta::CPAN

**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $
**
** This file implements an integration between the ICU library 
** ("International Components for Unicode", an open-source library 
** for handling unicode data) and SQLite. The integration uses 
** ICU to provide the following to SQLite:
**
**   * An implementation of the SQL regexp() function (and hence REGEXP
**     operator) using the ICU uregex_XX() APIs.
**
**   * Implementations of the SQL scalar upper() and lower() functions
**     for case mapping.
**
**   * Integration of ICU and SQLite collation seqences.
**
**   * An implementation of the LIKE operator that uses ICU to 
**     provide case-independent matching.
*/

#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)

/* Include ICU headers */
#include <unicode/utypes.h>
#include <unicode/uregex.h>
#include <unicode/ustring.h>
#include <unicode/ucol.h>


#ifndef SQLITE_CORE
  #include "sqlite3ext.h"
  SQLITE_EXTENSION_INIT1
#else
  #include "sqlite3.h"
#endif

/*

t/11unicode.t  view on Meta::CPAN

#!/usr/local/bin/perl
#
#   $Id: 40blobs.t,v 1.5 2004/07/21 20:50:45 matt Exp $
#
#   This is a test for correct handling of the "unicode" database
#   handle parameter.
#

$^W = 1;
use strict;

#
#   Include std stuff
#

t/11unicode.t  view on Meta::CPAN

    database_roundtrip($bytestring, $bytestring);

Test(! is_utf8($bytesback), "Reading blob gives binary");
Test(! is_utf8($textback), "Reading text gives binary too (for now)");
Test($bytesback eq $bytestring, "No blob corruption");
Test($textback eq $bytestring, "Same text, different encoding");

# Start over but now activate Unicode support.

if ($ENV{DBI_AUTOPROXY}) {
    # for testing DBD::Gofer we have to create a new dbh with unicode enabled
    # because we can't change the attribute for an existing dbh
    $dbh = DBI->connect($test_dsn, $test_user, $test_password, {
        RaiseError => 1,
        unicode => 1,
    })
}
else {
    $dbh->{unicode} = 1;
}

($textback, $bytesback) =
    database_roundtrip($utfstring, $bytestring);

Test(! is_utf8($bytesback), "Reading blob still gives binary");
Test(is_utf8($textback), "Reading text returns UTF-8");
Test($bytesback eq $bytestring, "Still no blob corruption");
Test($textback eq $utfstring, "Same text");

t/12create_collation.t  view on Meta::CPAN

is_deeply(\@sorted, $db_sorted, "collate perllocale (@sorted // @$db_sorted)");

@sorted    = sort no_accents @words;
$db_sorted = $dbh->selectcol_arrayref("$sql COLLATE no_accents");
is_deeply(\@sorted, $db_sorted, "collate no_accents (@sorted // @$db_sorted)");
$dbh->disconnect;


$dbh = DBI->connect("dbi:SQLite:dbname=foo", "", "", 
                    { RaiseError => 1,
                      unicode    => 1} );
ok($dbh);
$dbh->func( "no_accents", \&no_accents, "create_collation" );
$dbh->do( 'CREATE TEMP TABLE collate_test ( txt )' );
$dbh->do( "INSERT INTO collate_test VALUES ( '$_' )" ) foreach @words_utf8;

@sorted    = sort @words_utf8;
$db_sorted = $dbh->selectcol_arrayref("$sql COLLATE perl");
is_deeply(\@sorted, $db_sorted, "collate perl (@sorted // @$db_sorted)");

{use locale; @sorted    = sort @words_utf8;}

t/40bindparam.t  view on Meta::CPAN

#
while (Testing()) {
    #
    #   Connect to the database
    Test($state or $dbh = DBI->connect($test_dsn, $test_user, $test_password),
	 'connect')
	or ServerError();
    
    # For some reason this test is fscked with the utf8 flag on.
    # It seems to be because the string "K\x{00f6}nig" which to
    # me looks like unicode, should set the UTF8 flag on that
    # scalar. But no. It doesn't. Stupid fscking piece of crap.
    # (the test works if I manually set that flag with utf8::upgrade())
    # $dbh->{NoUTF8Flag} = 1 if $] > 5.007;

    #
    #   Find a possible new table name
    #
    Test($state or $table = FindNewTable($dbh), 'FindNewTable')
	or DbiError($dbh->err, $dbh->errstr);



( run in 0.551 second using v1.01-cache-2.11-cpan-88abd93f124 )