[Bast-commits] r7865 - in DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond: . lib/DBIx lib/DBIx/Class lib/DBIx/Class/Manual lib/DBIx/Class/Storage lib/DBIx/Class/Storage/DBI lib/DBIx/Class/Storage/DBI/ODBC lib/DBIx/Class/Storage/DBI/Oracle lib/DBIx/Class/Storage/DBI/Sybase lib/SQL/Translator/Parser/DBIx t t/inflate t/lib t/relationship t/resultset t/storage

ribasushi at dev.catalyst.perl.org ribasushi at dev.catalyst.perl.org
Thu Nov 12 01:24:46 GMT 2009


Author: ribasushi
Date: 2009-11-12 01:24:44 +0000 (Thu, 12 Nov 2009)
New Revision: 7865

Added:
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Common.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/NoBindVars.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/inflate/datetime_sybase.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/resultset/is_paged.t
Removed:
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Base.pm
Modified:
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/Changes
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/Makefile.PL
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Manual/FAQ.pod
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Manual/Troubleshooting.pod
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Ordered.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/ResultSet.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/ResultSource.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Row.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/AutoCast.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Pg.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/SQLite.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Microsoft_SQL_Server.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/SQL/Translator/Parser/DBIx/Class.pm
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/100populate.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/60core.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/71mysql.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/72pg.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/73oracle.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/746mssql.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/746sybase.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/74mssql.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/79aliasing.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/80unique.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/94versioning.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/inflate/hri.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/lib/sqlite.sql
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/relationship/core.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/storage/on_connect_call.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/storage/replication.t
   DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/zzzzzzz_sqlite_deadlock.t
Log:
 r7765 at Thesaurus (orig r7753):  ribasushi | 2009-10-03 15:49:14 +0200
 Test reorg (no changes)
 r7766 at Thesaurus (orig r7754):  ribasushi | 2009-10-03 15:55:25 +0200
 Add failing tests for RT#50003
 r7767 at Thesaurus (orig r7755):  caelum | 2009-10-03 16:09:45 +0200
 fix on_connect_ with coderef connect_info
 r7771 at Thesaurus (orig r7759):  ribasushi | 2009-10-04 13:17:53 +0200
 Fix AutoCast's POD
 r7782 at Thesaurus (orig r7770):  ribasushi | 2009-10-09 06:57:20 +0200
  r7777 at Thesaurus (orig r7765):  frew | 2009-10-07 20:05:05 +0200
  add method to check if an rs is paginated
  r7778 at Thesaurus (orig r7766):  frew | 2009-10-07 20:31:02 +0200
  is_paginated method and test
  r7780 at Thesaurus (orig r7768):  frew | 2009-10-09 06:45:36 +0200
  change name of method
  r7781 at Thesaurus (orig r7769):  frew | 2009-10-09 06:47:31 +0200
  add message to changelog for is_paged
 
 r7785 at Thesaurus (orig r7773):  ribasushi | 2009-10-09 11:00:36 +0200
 Ugh CRLF
 r7786 at Thesaurus (orig r7774):  ribasushi | 2009-10-09 11:04:35 +0200
 Skip versioning test on really old perls lacking Time::HiRes
 r7787 at Thesaurus (orig r7775):  ribasushi | 2009-10-09 11:04:50 +0200
 Changes
 r7788 at Thesaurus (orig r7776):  triode | 2009-10-09 22:32:04 +0200
 added troubleshooting case of excessive memory allocation involving TEXT/BLOB/etc
 columns and large LongReadLen
 
 r7789 at Thesaurus (orig r7777):  triode | 2009-10-09 22:44:21 +0200
 added my name to contributors list
 
 r7790 at Thesaurus (orig r7778):  ribasushi | 2009-10-10 18:49:15 +0200
 Whoops, this isn't right
 r7791 at Thesaurus (orig r7779):  ribasushi | 2009-10-11 15:44:18 +0200
 More ordered fixes
 r7793 at Thesaurus (orig r7781):  norbi | 2009-10-13 11:27:18 +0200
  r7982 at vger:  mendel | 2009-10-13 11:26:11 +0200
  Fixed a typo and a POD error.
 
 r7805 at Thesaurus (orig r7793):  ribasushi | 2009-10-16 14:28:35 +0200
 Fix test to stop failing when DT-support is not present
 r7811 at Thesaurus (orig r7799):  caelum | 2009-10-18 11:13:29 +0200
  r20728 at hlagh (orig r7703):  ribasushi | 2009-09-20 18:51:16 -0400
  Another try at a clean sybase branch
  r20730 at hlagh (orig r7705):  ribasushi | 2009-09-20 18:58:09 -0400
  Part one of the sybase work by Caelum (mostly reviewed)
  r20731 at hlagh (orig r7706):  ribasushi | 2009-09-20 19:18:40 -0400
  main sybase branch ready
  r21051 at hlagh (orig r7797):  caelum | 2009-10-18 04:57:43 -0400
   r20732 at hlagh (orig r7707):  ribasushi | 2009-09-20 19:20:00 -0400
   Branch for bulk insert
   r20733 at hlagh (orig r7708):  ribasushi | 2009-09-20 20:06:21 -0400
   All sybase bulk-insert code by Caelum
   r20750 at hlagh (orig r7725):  caelum | 2009-09-24 02:47:39 -0400
   clean up set_identity stuff
   r20751 at hlagh (orig r7726):  caelum | 2009-09-24 05:21:18 -0400
   minor cleanups, test update of blob to NULL
   r20752 at hlagh (orig r7727):  caelum | 2009-09-24 08:45:04 -0400
   remove some duplicate code
   r20753 at hlagh (orig r7728):  caelum | 2009-09-24 09:57:58 -0400
   fix insert with all defaults
   r20786 at hlagh (orig r7732):  caelum | 2009-09-25 21:17:16 -0400
   some cleanups
   r20804 at hlagh (orig r7736):  caelum | 2009-09-28 05:31:38 -0400
   minor changes
   r20805 at hlagh (orig r7737):  caelum | 2009-09-28 06:25:48 -0400
   fix DT stuff
   r20809 at hlagh (orig r7741):  caelum | 2009-09-28 22:25:55 -0400
   removed some dead code, added fix and test for _execute_array_empty
   r20811 at hlagh (orig r7743):  caelum | 2009-09-29 13:36:20 -0400
   minor changes after review
   r20812 at hlagh (orig r7744):  caelum | 2009-09-29 14:16:03 -0400
   do not clobber $rv from execute_array
   r20813 at hlagh (orig r7745):  caelum | 2009-09-29 14:38:14 -0400
   make insert_bulk atomic
   r20815 at hlagh (orig r7747):  caelum | 2009-09-29 20:35:26 -0400
   remove _exhaaust_statements
   r20816 at hlagh (orig r7748):  caelum | 2009-09-29 21:48:38 -0400
   fix insert_bulk when not using bulk api inside a txn
   r20831 at hlagh (orig r7749):  caelum | 2009-09-30 02:53:42 -0400
   added test for populate being atomic
   r20832 at hlagh (orig r7750):  caelum | 2009-09-30 03:00:59 -0400
   factor out subclass-specific _execute_array callback
   r20833 at hlagh (orig r7751):  caelum | 2009-10-01 11:59:30 -0400
   remove a piece of dead code
   r20840 at hlagh (orig r7758):  caelum | 2009-10-03 15:46:56 -0400
   remove _pretty_print
   r20842 at hlagh (orig r7760):  caelum | 2009-10-04 16:19:56 -0400
   minor optimization for insert_bulk
   r21050 at hlagh (orig r7796):  caelum | 2009-10-18 04:56:54 -0400
   error checking related to literal SQL for insert_bulk
  
 
 r7820 at Thesaurus (orig r7808):  caelum | 2009-10-21 03:10:39 +0200
 add test for populate with literal sql mixed with binds, improve error messages
 r7823 at Thesaurus (orig r7811):  ribasushi | 2009-10-21 16:33:45 +0200
 Show what's wrong with the current populate code
 r7824 at Thesaurus (orig r7812):  caelum | 2009-10-22 11:10:38 +0200
 stringify values passed to populate/insert_bulk
 r7825 at Thesaurus (orig r7813):  ribasushi | 2009-10-22 13:17:41 +0200
 Some smoker run the suite for 30 *minutes* - the timeout seems to be too short for them (boggle)
 r7826 at Thesaurus (orig r7814):  caelum | 2009-10-22 14:41:37 +0200
 a few extra tests can never hurt, right? :)
 r7827 at Thesaurus (orig r7815):  ribasushi | 2009-10-23 10:51:05 +0200
 Prevent sqlt from failing silently
 r7828 at Thesaurus (orig r7816):  ribasushi | 2009-10-23 10:52:49 +0200
 { is_foreign_key_constraint => 0, on_delete => undef } is a valid construct - no need to carp
 r7832 at Thesaurus (orig r7820):  robkinyon | 2009-10-26 20:11:22 +0100
 Fixed bad if-check in columns()
 r7840 at Thesaurus (orig r7828):  caelum | 2009-10-31 14:01:56 +0100
 change repository in meta to point to real svn url rather than svnweb
 r7842 at Thesaurus (orig r7830):  caelum | 2009-10-31 21:04:39 +0100
 pass sqlite_version to SQLT
 r7843 at Thesaurus (orig r7831):  caelum | 2009-10-31 21:22:37 +0100
 fix regex to numify sqlite_version
 r7844 at Thesaurus (orig r7832):  caelum | 2009-10-31 23:59:19 +0100
 work-around disconnect bug with DBD::Pg 2.15.1
 r7855 at Thesaurus (orig r7843):  ribasushi | 2009-11-04 10:55:51 +0100
  r7817 at Thesaurus (orig r7805):  rbuels | 2009-10-21 02:37:28 +0200
  making a branch, here we go again with the pg_unqualified_schema
  r7818 at Thesaurus (orig r7806):  rbuels | 2009-10-21 02:38:59 +0200
  more pg unqualified schema tests, which expose a gap in the coverage
  r7819 at Thesaurus (orig r7807):  rbuels | 2009-10-21 03:10:38 +0200
  gutted Pg storage driver's sequence discovery to just rely on DBD::Pg's last_insert_id.  this needs testing with older versions of DBD::Pg
  r7821 at Thesaurus (orig r7809):  rbuels | 2009-10-21 04:00:39 +0200
  more coverage in Pg sequence-discovery tests.  i think this shows why last_insert_id cannot be used.
  r7822 at Thesaurus (orig r7810):  rbuels | 2009-10-21 04:07:05 +0200
  reverted [7807], and just changed code to use the custom pg_catalog query, which is the only thing that works in the pathological case where DBIC is told a different primary key from the primary key that is set on the table in the DB ([7809] added testing for this)
  r7852 at Thesaurus (orig r7840):  rbuels | 2009-11-03 18:47:05 +0100
  added Changes line mentioning tweak to Pg auto-inc fix
  r7854 at Thesaurus (orig r7842):  ribasushi | 2009-11-04 10:55:35 +0100
  Cleanup exceptions
 
 r7858 at Thesaurus (orig r7846):  caelum | 2009-11-06 16:01:30 +0100
 transactions for MSSQL over DBD::Sybase
 r7861 at Thesaurus (orig r7849):  caelum | 2009-11-10 13:16:18 +0100
 made commit/rollback when disconnected an exception
 r7862 at Thesaurus (orig r7850):  robkinyon | 2009-11-10 17:19:57 +0100
 Added a note about select
 r7863 at Thesaurus (orig r7851):  ribasushi | 2009-11-10 18:23:10 +0100
 Changes
 r7867 at Thesaurus (orig r7855):  frew | 2009-11-11 21:56:37 +0100
 RT50874
 r7868 at Thesaurus (orig r7856):  frew | 2009-11-11 23:50:43 +0100
 RT50828
 r7869 at Thesaurus (orig r7857):  frew | 2009-11-11 23:54:15 +0100
 clearer test message
 r7870 at Thesaurus (orig r7858):  frew | 2009-11-12 00:37:27 +0100
 some cleanup for $rs->populate
 r7872 at Thesaurus (orig r7860):  ribasushi | 2009-11-12 01:35:36 +0100
 Fix find on resultset with custom result_class
 r7873 at Thesaurus (orig r7861):  ribasushi | 2009-11-12 01:40:14 +0100
 Fix return value of in_storage
 r7874 at Thesaurus (orig r7862):  ribasushi | 2009-11-12 01:43:48 +0100
 Extra FAQ entry
 r7875 at Thesaurus (orig r7863):  ribasushi | 2009-11-12 02:11:25 +0100
 Sanify _determine_driver handling in ::Storage::DBI
 r7876 at Thesaurus (orig r7864):  ribasushi | 2009-11-12 02:14:37 +0100
 Add mysql determine_driver test by Pedro Melo



Property changes on: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond
___________________________________________________________________
Name: svk:merge
   - 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/cookbook_fixes:7657
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond:7959
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/resultsetcolumn_custom_columns:5160
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/sqla_1.50_compat:5414
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/trunk:7237
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_column_attr:10946
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_trunk:11788
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:2798
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/_abandoned_but_possibly_useful/table_name_ref:7266
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/autocast:7418
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/belongs_to_null_col_fix:5244
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/column_attr:5074
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/connect_info_hash:7435
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cookbook_fixes:7479
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/count_distinct:6218
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/count_rs:6741
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/diamond_relationships:6310
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/discard_changes_replication_fix:7252
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/fix-update-and-delete-as_query:6162
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/grouped_has_many_join:7382
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/grouped_prefetch:6885
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/joined_count:6323
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mc_fixes:6645
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mssql_money_type:7096
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mssql_storage_minor_refactor:7210
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mssql_top_fixes:6971
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/multi_stuff:5565
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/multicreate_fixes:7275
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mysql_ansi:7175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mystery_join:6589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/new_replication_transaction_fixup:7058
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_connect_call:6854
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle-tweaks:6222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/order_by_refactor:6475
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/pg_unqualified_schema:7566
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/prefetch:5699
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/prefetch_limit:6724
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/prefetch_redux:7206
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/reduce_pings:7261
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/rsrc_in_storage:6577
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/rt_bug_41083:5437
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/search_related_prefetch:6818
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sqla_1.50_compat:5321
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-tweaks:6262
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subclassed_rsset:5930
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subquery:5617
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/syb_connected:6919
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase:7682
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase_bulk_insert:7679
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase_mssql:6125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/table_name_ref:7132
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/top_limit_altfix:6429
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/type_aware_update:6619
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/unresolvable_prefetch:6949
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/views:5585
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/tags/0.08108_prerelease_please_do_not_pull_into_it:7008
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/tags/pre_0.08109_please_do_not_merge:7336
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/trunk:7731
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510
   + 168d5346-440b-0410-b799-f706be625ff1:/DBIx-Class-current:2207
462d4d0c-b505-0410-bf8e-ce8f877b3390:/local/bast/DBIx-Class:3159
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/cookbook_fixes:7657
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond:7959
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/resultsetcolumn_custom_columns:5160
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/branches/sqla_1.50_compat:5414
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/trunk:7982
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class:32260
9c88509d-e914-0410-b01c-b9530614cbfe:/local/DBIx-Class-CDBICompat:54993
9c88509d-e914-0410-b01c-b9530614cbfe:/vendor/DBIx-Class:31122
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_column_attr:10946
ab17426e-7cd3-4704-a2a2-80b7c0a611bb:/local/dbic_trunk:11788
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:2798
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/_abandoned_but_possibly_useful/table_name_ref:7266
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/autocast:7418
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/belongs_to_null_col_fix:5244
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cdbicompat_integration:4160
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/column_attr:5074
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/connect_info_hash:7435
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/cookbook_fixes:7479
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/count_distinct:6218
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/count_rs:6741
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/diamond_relationships:6310
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/discard_changes_replication_fix:7252
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/fix-update-and-delete-as_query:6162
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/grouped_has_many_join:7382
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/grouped_prefetch:6885
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/is_resultset_paginated:7769
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/joined_count:6323
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mc_fixes:6645
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mssql_money_type:7096
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mssql_storage_minor_refactor:7210
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mssql_top_fixes:6971
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/multi_stuff:5565
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/multicreate_fixes:7275
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mysql_ansi:7175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/mystery_join:6589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/new_replication_transaction_fixup:7058
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_connect_call:6854
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/on_disconnect_do:3694
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle-tweaks:6222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/oracle_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/order_by_refactor:6475
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/pg_unqualified_schema:7842
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/prefetch:5699
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/prefetch_limit:6724
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/prefetch_redux:7206
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/reduce_pings:7261
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/rsrc_in_storage:6577
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/rt_bug_41083:5437
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/search_related_prefetch:6818
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sqla_1.50_compat:5321
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-tweaks:6262
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subclassed_rsset:5930
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/subquery:5617
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/syb_connected:6919
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase:7682
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase_bulk_insert:7679
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase_bulkinsert_support:7796
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase_mssql:6125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/sybase_support:7797
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/table_name_ref:7132
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/top_limit_altfix:6429
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/type_aware_update:6619
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/unresolvable_prefetch:6949
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/views:5585
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/tags/0.08108_prerelease_please_do_not_pull_into_it:7008
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/tags/pre_0.08109_please_do_not_merge:7336
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/trunk:7864
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-C3:318
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-current:2222
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-joins:173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class-resultset:570
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/datetime:1716
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_compat:1855
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/find_unique_query_fixes:2142
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/inflate:1988
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/many_to_many:2025
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/re_refactor_bugfix:1944
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/reorganize_tests:1827
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset-new-refactor:1766
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_2_electric_boogaloo:2175
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/resultset_cleanup:2102
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/branches/DBIx-Class/sqlt_tests_refactor:2043
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/trunk/DBIx-Class:3606
fe160bb6-dc1c-0410-9f2b-d64a711b54a5:/local/DBIC-trunk-0.08:10510

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/Changes
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/Changes	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/Changes	2009-11-12 01:24:44 UTC (rev 7865)
@@ -1,5 +1,42 @@
 Revision history for DBIx::Class
 
+        - Fix populate with has_many bug
+          (RT #50828)
+        - Fix Oracle autoincrement broken for Resultsets with scalar refs
+          (RT #50874)
+        - Complete Sybase RDBMS support including:
+          - Support for TEXT/IMAGE columns
+          - Support for the 'money' datatype
+          - Transaction savepoints support
+          - DateTime inflation support
+          - Support for bind variables when connecting to a newer Sybase with
+             OpenClient libraries
+          - Support for connections via FreeTDS with CASTs for bind variables
+             when needed
+          - Support for interpolated variables with proper quoting when
+             connecting to an older Sybase and/or via FreeTDS
+          - bulk API support for populate()
+        - Transaction support for MSSQL via DBD::Sybase
+        - Add is_paged method to DBIx::Class::ResultSet so that we can
+          check that if we want a pager
+        - Skip versioning test on really old perls lacking Time::HiRes
+          (RT #50209)
+        - Fixed on_connect_do/call regression when used with a coderef
+          connector (RT #50003)
+        - A couple of fixes to Ordered to remedy subclassing issues
+        - Fixed another lingering problem with PostgreSQL
+          auto-increment support and its interaction with multiple
+          schemas
+        - Remove some IN workarounds, and require a recent version of
+          SQLA instead
+        - Improvements to populate's handling of mixed scalarref values
+        - Fixed regression losing result_class after $rs->find (introduced
+          in 0.08108)
+        - Fix in_storage() to return 1|0 as per existing documentation
+        - Centralize handling of _determine_driver calls prior to certain
+          ::Storage::DBI methods
+        - POD improvements
+
 0.08112 2009-09-21 10:57:00 (UTC)
         - Remove the recommends from Makefile.PL, DBIx::Class is not
           supposed to have optional dependencies. ever.
@@ -102,7 +139,7 @@
           nonexisting prefetch
         - make_column_dirty() now overwrites the deflated value with an
           inflated one if such exists
-        - Fixed set_$rel with where restriction deleting rows outside 
+        - Fixed set_$rel with where restriction deleting rows outside
           the restriction
         - populate() returns the created objects or an arrayref of the
           created objects depending on scalar vs. list context
@@ -154,7 +191,7 @@
           side of the relation, to avoid duplicates
         - DBIC now properly handles empty inserts (invoking all default
           values from the DB, normally via INSERT INTO tbl DEFAULT VALUES
-        - Fix find_or_new/create to stop returning random rows when 
+        - Fix find_or_new/create to stop returning random rows when
           default value insert is requested (RT#28875)
         - Make IC::DT extra warning state the column name too
         - It is now possible to transparrently search() on columns
@@ -176,9 +213,9 @@
         - Change ->count code to work correctly with DISTINCT (distinct => 1)
           via GROUP BY
         - Removed interpolation of bind vars for as_query - placeholders
-          are preserved and nested query bind variables are properly 
+          are preserved and nested query bind variables are properly
           merged in the correct order
-        - Refactor DBIx::Class::Storage::DBI::Sybase to automatically 
+        - Refactor DBIx::Class::Storage::DBI::Sybase to automatically
           load a subclass, namely Microsoft_SQL_Server.pm
           (similar to DBIx::Class::Storage::DBI::ODBC)
         - Refactor InflateColumn::DateTime to allow components to
@@ -241,7 +278,7 @@
           - not try and insert things tagged on via new_related unless required
         - Possible to set locale in IC::DateTime extra => {} config
         - Calling the accessor of a belongs_to when the foreign_key
-          was NULL and the row was not stored would unexpectedly fail 
+          was NULL and the row was not stored would unexpectedly fail
         - Split sql statements for deploy only if SQLT::Producer returned a scalar
           containing all statements to be executed
         - Add as_query() for ResultSet and ResultSetColumn. This makes subqueries
@@ -269,8 +306,8 @@
         - new order_by => { -desc => 'colname' } syntax supported
         - PG array datatype supported
         - insert should use store_column, not set_column to avoid marking
-          clean just-stored values as dirty. New test for this 
-        - regression test for source_name 
+          clean just-stored values as dirty. New test for this
+        - regression test for source_name
 
 0.08099_05 2008-10-30 21:30:00 (UTC)
         - Rewrite of Storage::DBI::connect_info(), extended with an
@@ -284,7 +321,7 @@
         - Fixed up related resultsets and multi-create
         - Fixed superfluous connection in ODBC::_rebless
         - Fixed undef PK for first insert in ODBC::Microsoft_SQL_Server
-        - Added virtual method to Versioned so a user can create upgrade 
+        - Added virtual method to Versioned so a user can create upgrade
           path across multiple versions (jgoulah)
         - Better (and marginally faster) implementation of the HashRefInflator
           hash construction algorithm
@@ -293,7 +330,7 @@
 
 0.08099_04 2008-07-24 01:00:00
         - Functionality to storage to enable a sub to be run without FK checks
-        - Fixed $schema->clone bug which caused clone and source to share 
+        - Fixed $schema->clone bug which caused clone and source to share
           internal hash refs
         - Added register_extra_source methods for additional sources
         - Added datetime_undef_if_invalid for InflateColumn::DateTime to
@@ -319,11 +356,11 @@
         - Add warnings for non-unique ResultSet::find queries
         - Changed Storage::DBI::Replication to Storage::DBI::Replicated and
           refactored support.
-        - By default now deploy/diff et al. will ignore constraint and index 
+        - By default now deploy/diff et al. will ignore constraint and index
           names
         - Add ResultSet::_is_deterministic_value, make new_result filter the
           values passed to new to drop values that would generate invalid SQL.
-        - Use Sub::Name to name closures before installing them. Fixes 
+        - Use Sub::Name to name closures before installing them. Fixes
           incompatibility with Moose method modifiers on generated methods.
 
 0.08010 2008-03-01 10:30
@@ -332,7 +369,7 @@
 0.08009 2008-01-20 13:30
         - Made search_rs smarter about when to preserve the cache to fix
           mm prefetch usage
-        - Added Storage::DBI subclass for MSSQL over ODBC. 
+        - Added Storage::DBI subclass for MSSQL over ODBC.
         - Added freeze, thaw and dclone methods to Schema so that thawed
           objects will get re-attached to the schema.
         - Moved dbicadmin to JSON::Any wrapped JSON.pm for a sane API
@@ -346,20 +383,20 @@
           foreign and self parts the wrong way round in the condition
         - ResultSetColumn::func() now returns all results if called in list
           context; this makes things like func('DISTINCT') work as expected
-        - Many-to-many relationships now warn if the utility methods would 
+        - Many-to-many relationships now warn if the utility methods would
           clash
         - InflateColumn::DateTime now accepts an extra parameter of timezone
           to set timezone on the DT object (thanks Sergio Salvi)
-        - Added sqlt_deploy_hook to result classes so that indexes can be 
+        - Added sqlt_deploy_hook to result classes so that indexes can be
           added.
-        - Added startup checks to warn loudly if we appear to be running on 
+        - Added startup checks to warn loudly if we appear to be running on
           RedHat systems from perl-5.8.8-10 and up that have the bless/overload
           patch applied (badly) which causes 2x -> 100x performance penalty.
           (Jon Schutz)
-        - ResultSource::reverse_relationship_info can distinguish between 
+        - ResultSource::reverse_relationship_info can distinguish between
           sources using the same table
         - Row::insert will now not fall over if passed duplicate related objects
-        - Row::copy will not fall over if you have two relationships to the 
+        - Row::copy will not fall over if you have two relationships to the
           same source with a unique constraint on it
 
 0.08007 2007-09-04 19:36:00
@@ -371,7 +408,7 @@
         - Move to using Class::C3::Componentised
         - Remove warn statement from DBIx::Class::Row
 
-0.08005 2007-08-06 
+0.08005 2007-08-06
         - add timestamp fix re rt.cpan 26978 - no test yet but change
           clearly should cause no regressions
         - provide alias for related_resultset via local() so it's set
@@ -386,7 +423,7 @@
           (original fix from diz)
 
 0.08004 2007-08-06 19:00:00
-        - fix storage connect code to not trigger bug via auto-viv 
+        - fix storage connect code to not trigger bug via auto-viv
           (test from aherzog)
         - fixup cursor_class to be an 'inherited' attr for per-package defaults
         - add default_resultset_attributes entry to Schema

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/Makefile.PL
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/Makefile.PL	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/Makefile.PL	2009-11-12 01:24:44 UTC (rev 7865)
@@ -45,6 +45,7 @@
 requires 'SQL::Abstract'            => '1.60';
 requires 'SQL::Abstract::Limit'     => '0.13';
 requires 'Sub::Name'                => '0.04';
+requires 'Data::Dumper::Concise'    => '1.000';
 
 my %replication_requires = (
   'Moose',                    => '0.87',
@@ -114,6 +115,12 @@
       'DateTime::Format::Oracle' => '0',
     ) : ()
   ,
+
+  $ENV{DBICTEST_SYBASE_DSN}
+    ? (
+      'DateTime::Format::Sybase' => 0,
+    ) : ()
+  ,
 );
 #************************************************************************#
 # Make ABSOLUTELY SURE that nothing on the list above is a real require, #
@@ -132,10 +139,10 @@
 
 resources 'IRC'         => 'irc://irc.perl.org/#dbix-class';
 resources 'license'     => 'http://dev.perl.org/licenses/';
-resources 'repository'  => 'http://dev.catalyst.perl.org/svnweb/bast/browse/DBIx-Class/';
+resources 'repository'  => 'http://dev.catalyst.perl.org/repos/bast/DBIx-Class/';
 resources 'MailingList' => 'http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class';
 
-no_index 'DBIx::Class::Storage::DBI::Sybase::Base';
+no_index 'DBIx::Class::Storage::DBI::Sybase::Common';
 no_index 'DBIx::Class::SQLAHacks';
 no_index 'DBIx::Class::SQLAHacks::MSSQL';
 no_index 'DBIx::Class::Storage::DBI::AmbiguousGlob';

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Manual/FAQ.pod
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Manual/FAQ.pod	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Manual/FAQ.pod	2009-11-12 01:24:44 UTC (rev 7865)
@@ -371,6 +371,9 @@
 
 =item .. insert many rows of data efficiently?
 
+The C<populate> method in L<DBIx::Class::ResultSet> provides
+efficient bulk inserts.
+
 =item .. update a collection of rows at the same time?
 
 Create a resultset using a search, to filter the rows of data you

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Manual/Troubleshooting.pod
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Manual/Troubleshooting.pod	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Manual/Troubleshooting.pod	2009-11-12 01:24:44 UTC (rev 7865)
@@ -156,5 +156,16 @@
 L<https://bugzilla.redhat.com/show_bug.cgi?id=460308> and
 L<http://rhn.redhat.com/errata/RHBA-2008-0876.html>
 
+=head2 Excessive Memory Allocation with TEXT/BLOB/etc. Columns and Large LongReadLen
+
+It has been observed, using L<DBD::ODBC>, that a creating a L<DBIx::Class::Row> 
+object which includes a column of data type TEXT/BLOB/etc. will allocate 
+LongReadLen bytes.  This allocation does not leak, but if LongReadLen 
+is large in size, and many such row objects are created, e.g. as the 
+output of a ResultSet query, the memory footprint of the Perl interpreter 
+can grow very large.
+
+The solution is to use the smallest practical value for LongReadLen.
+
 =cut
 

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Ordered.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Ordered.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Ordered.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -501,7 +501,7 @@
     }
     else {
       my $bumped_pos_val = $self->_position_value ($to_position);
-      my @between = ($to_position, $new_group_last_position);
+      my @between = map { $self->_position_value ($_) } ($to_position, $new_group_last_position);
       $self->_shift_siblings (1, @between);   #shift right
       $self->set_column( $position_column => $bumped_pos_val );
     }
@@ -682,27 +682,9 @@
 if you are working with preexisting non-normalised position data,
 or if you need to work with materialized path columns.
 
-=head2 _position
-
-  my $num_pos = $item->_position;
-
-Returns the B<absolute numeric position> of the current object, with the
-first object being at position 1, its sibling at position 2 and so on.
-By default simply returns the value of L</position_column>.
-
-=cut
-sub _position {
-    my $self = shift;
-
-#    #the right way to do this
-#    return $self->previous_siblings->count + 1;
-
-    return $self->get_column ($self->position_column);
-}
-
 =head2 _position_from_value
 
-  my $num_pos = $item->_position_of_value ( $pos_value )
+  my $num_pos = $item->_position_from_value ( $pos_value )
 
 Returns the B<absolute numeric position> of an object with a B<position
 value> set to C<$pos_value>. By default simply returns C<$pos_value>.
@@ -864,6 +846,19 @@
     );
 }
 
+=head2 _position
+
+  my $num_pos = $item->_position;
+
+Returns the B<absolute numeric position> of the current object, with the
+first object being at position 1, its sibling at position 2 and so on.
+
+=cut
+sub _position {
+    my $self = shift;
+    return $self->_position_from_value ($self->get_column ($self->position_column) );
+}
+
 =head2 _grouping_clause
 
 This method returns one or more name=>value pairs for limiting a search

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/ResultSet.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/ResultSet.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/ResultSet.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -357,9 +357,9 @@
   }
 
   my $rs = (ref $self)->new($self->result_source, $new_attrs);
-  if ($rows) {
-    $rs->set_cache($rows);
-  }
+
+  $rs->set_cache($rows) if ($rows);
+
   return $rs;
 }
 
@@ -519,7 +519,7 @@
     # in ::Relationship::Base::search_related (the row method), and furthermore
     # the relationship is of the 'single' type. This means that the condition
     # provided by the relationship (already attached to $self) is sufficient,
-    # as there can be only one row in the databse that would satisfy the 
+    # as there can be only one row in the databse that would satisfy the
     # relationship
   }
   else {
@@ -530,7 +530,7 @@
   }
 
   # Run the query
-  my $rs = $self->search ($query, $attrs);
+  my $rs = $self->search ($query, {result_class => $self->result_class, %$attrs});
   if (keys %{$rs->_resolved_attrs->{collapse}}) {
     my $row = $rs->next;
     carp "Query returned more than one row" if $rs->next;
@@ -1240,7 +1240,7 @@
 
   my $tmp_attrs = { %$attrs };
 
-  # take off any limits, record_filter is cdbi, and no point of ordering a count 
+  # take off any limits, record_filter is cdbi, and no point of ordering a count
   delete $tmp_attrs->{$_} for (qw/select as rows offset order_by record_filter/);
 
   # overwrite the selector (supplied by the storage)
@@ -1794,10 +1794,19 @@
     }
     return wantarray ? @created : \@created;
   } else {
-    my ($first, @rest) = @$data;
+    my $first = $data->[0];
 
-    my @names = grep {!ref $first->{$_}} keys %$first;
-    my @rels = grep { $self->result_source->has_relationship($_) } keys %$first;
+    # if a column is a registered relationship, and is a non-blessed hash/array, consider
+    # it relationship data
+    my (@rels, @columns);
+    for (keys %$first) {
+      my $ref = ref $first->{$_};
+      $self->result_source->has_relationship($_) && ($ref eq 'ARRAY' or $ref eq 'HASH')
+        ? push @rels, $_
+        : push @columns, $_
+      ;
+    }
+
     my @pks = $self->result_source->primary_columns;
 
     ## do the belongs_to relationships
@@ -1826,17 +1835,15 @@
         delete $data->[$index]->{$rel};
         $data->[$index] = {%{$data->[$index]}, %$related};
 
-        push @names, keys %$related if $index == 0;
+        push @columns, keys %$related if $index == 0;
       }
     }
 
     ## do bulk insert on current row
-    my @values = map { [ @$_{@names} ] } @$data;
-
     $self->result_source->storage->insert_bulk(
       $self->result_source,
-      \@names,
-      \@values,
+      \@columns,
+      [ map { [ @$_{@columns} ] } @$data ],
     );
 
     ## do the has_many relationships
@@ -1845,7 +1852,7 @@
       foreach my $rel (@rels) {
         next unless $item->{$rel} && ref $item->{$rel} eq "ARRAY";
 
-        my $parent = $self->find(map {{$_=>$item->{$_}} } @pks)
+        my $parent = $self->find({map { $_ => $item->{$_} } @pks})
      || $self->throw_exception('Cannot find the relating object.');
 
         my $child = $parent->$rel;
@@ -2564,6 +2571,23 @@
   shift->set_cache(undef);
 }
 
+=head2 is_paged
+
+=over 4
+
+=item Arguments: none
+
+=item Return Value: true, if the resultset has been paginated
+
+=back
+
+=cut
+
+sub is_paged {
+  my ($self) = @_;
+  return !!$self->{attrs}{page};
+}
+
 =head2 related_resultset
 
 =over 4
@@ -2711,8 +2735,8 @@
   }];
 
   my $seen = { %{$attrs->{seen_join} || {} } };
-  my $jpath = ($attrs->{seen_join} && keys %{$attrs->{seen_join}}) 
-    ? $from->[-1][0]{-join_path} 
+  my $jpath = ($attrs->{seen_join} && keys %{$attrs->{seen_join}})
+    ? $from->[-1][0]{-join_path}
     : [];
 
 
@@ -2948,7 +2972,7 @@
   # even though it doesn't make much sense, this is what pre 081xx has
   # been doing
   if (my $page = delete $attrs->{page}) {
-    $attrs->{offset} = 
+    $attrs->{offset} =
       ($attrs->{rows} * ($page - 1))
             +
       ($attrs->{offset} || 0)
@@ -3143,7 +3167,7 @@
 
 =back
 
-Which column(s) to order the results by. 
+Which column(s) to order the results by.
 
 [The full list of suitable values is documented in
 L<SQL::Abstract/"ORDER BY CLAUSES">; the following is a summary of
@@ -3238,6 +3262,9 @@
 attribute, the column names returned are storage-dependent. E.g. MySQL would
 return a column named C<count(employeeid)> in the above example.
 
+B<NOTE:> You will almost always need a corresponding 'as' entry when you use
+'select'.
+
 =head2 +select
 
 =over 4
@@ -3435,12 +3462,12 @@
 
 =over 4
 
-=item * 
+=item *
 
 Prefetch uses the L</cache> to populate the prefetched relationships. This
 may or may not be what you want.
 
-=item * 
+=item *
 
 If you specify a condition on a prefetched relationship, ONLY those
 rows that match the prefetched condition will be fetched into that relationship.
@@ -3552,8 +3579,8 @@
   # only return rows WHERE deleted IS NULL for all searches
   __PACKAGE__->resultset_attributes({ where => { deleted => undef } }); )
 
-Can be overridden by passing C<{ where => undef }> as an attribute
-to a resulset.
+Can be overridden by passing C<< { where => undef } >> as an attribute
+to a resultset.
 
 =back
 

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/ResultSource.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/ResultSource.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/ResultSource.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -389,7 +389,7 @@
   my $self = shift;
   $self->throw_exception(
     "columns() is a read-only accessor, did you mean add_columns()?"
-  ) if (@_ > 1);
+  ) if @_;
   return @{$self->{_ordered_columns}||[]};
 }
 

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Row.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Row.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Row.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -424,7 +424,7 @@
 sub in_storage {
   my ($self, $val) = @_;
   $self->{_in_storage} = $val if @_ > 1;
-  return $self->{_in_storage};
+  return $self->{_in_storage} ? 1 : 0;
 }
 
 =head2 update

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/AutoCast.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/AutoCast.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/AutoCast.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -10,7 +10,7 @@
 
 =head1 NAME
 
-DBIx::Class::Storage::DBI::AutoCast
+DBIx::Class::Storage::DBI::AutoCast - Storage component for RDBMS requiring explicit placeholder typing
 
 =head1 SYNOPSIS
 
@@ -29,6 +29,10 @@
 
   CAST(? as $mapped_type)
 
+This option can also be enabled in L<DBIx::Class::Storage::DBI/connect_info> as:
+
+  on_connect_call => ['set_auto_cast']
+
 =cut
 
 sub _prep_for_execute {
@@ -60,7 +64,27 @@
   return ($sql, $bind);
 }
 
+=head2 connect_call_set_auto_cast
 
+Executes:
+
+  $schema->storage->auto_cast(1);
+
+on connection.
+
+Used as:
+
+    on_connect_call => ['set_auto_cast']
+
+in L<DBIx::Class::Storage::DBI/connect_info>.
+
+=cut
+
+sub connect_call_set_auto_cast {
+  my $self = shift;
+  $self->auto_cast(1);
+}
+
 =head1 AUTHOR
 
 See L<DBIx::Class/CONTRIBUTORS>

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -61,7 +61,7 @@
   my $self = shift;
 
   if (ref($self->_dbi_connect_info->[0]) eq 'CODE') {
-    $self->throw_exception ('cannot set DBI attributes on a CODE ref connect_info');
+    $self->throw_exception ('Cannot set DBI attributes on a CODE ref connect_info');
   }
 
   my $dbi_attrs = $self->_dbi_connect_info->[-1];

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -53,8 +53,16 @@
 
   my $sth;
 
+  my $source_name;
+  if ( ref $source->name ne 'SCALAR' ) {
+      $source_name = $source->name;
+  }
+  else {
+      $source_name = ${$source->name};
+  }
+
   # check for fully-qualified name (eg. SCHEMA.TABLENAME)
-  if ( my ( $schema, $table ) = $source->name =~ /(\w+)\.(\w+)/ ) {
+  if ( my ( $schema, $table ) = $source_name =~ /(\w+)\.(\w+)/ ) {
     $sql = q{
       SELECT trigger_body FROM ALL_TRIGGERS t
       WHERE t.owner = ? AND t.table_name = ?
@@ -66,7 +74,7 @@
   }
   else {
     $sth = $dbh->prepare($sql);
-    $sth->execute( uc( $source->name ) );
+    $sth->execute( uc( $source_name ) );
   }
   while (my ($insert_trigger) = $sth->fetchrow_array) {
     return uc($1) if $insert_trigger =~ m!(\w+)\.nextval!i; # col name goes here???
@@ -223,7 +231,7 @@
 
 =cut
 
-sub source_bind_attributes 
+sub source_bind_attributes
 {
 	require DBD::Oracle;
 	my $self = shift;

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Pg.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Pg.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Pg.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -26,11 +26,11 @@
 
   for my $col (@cols) {
     my $seq = ( $source->column_info($col)->{sequence} ||= $self->dbh_do('_dbh_get_autoinc_seq', $source, $col) )
-      or $self->throw_exception( "could not determine sequence for "
-                                 . $source->name
-                                 . ".$col, please consider adding a "
-                                 . "schema-qualified sequence to its column info"
-                               );
+      or $self->throw_exception( sprintf(
+        'could not determine sequence for column %s.%s, please consider adding a schema-qualified sequence to its column info',
+          $source->name,
+          $col,
+      ));
 
     push @values, $self->_dbh_last_insert_id ($self->_dbh, $seq);
   }
@@ -61,22 +61,22 @@
     ( $schema, $table ) = ( $1, $2 );
   }
 
-  # use DBD::Pg to fetch the column info if it is recent enough to
-  # work. otherwise, use custom SQL
-  my $seq_expr =  $DBD::Pg::VERSION >= 2.015001
-      ? eval{ $dbh->column_info(undef,$schema,$table,$col)->fetchrow_hashref->{COLUMN_DEF} }
-      : $self->_dbh_get_column_default( $dbh, $schema, $table, $col );
+  # get the column default using a Postgres-specific pg_catalog query
+  my $seq_expr = $self->_dbh_get_column_default( $dbh, $schema, $table, $col );
 
   # if no default value is set on the column, or if we can't parse the
   # default value as a sequence, throw.
-  unless ( defined $seq_expr and $seq_expr =~ /^nextval\(+'([^']+)'::(?:text|regclass)\)/i ){
+  unless ( defined $seq_expr and $seq_expr =~ /^nextval\(+'([^']+)'::(?:text|regclass)\)/i ) {
     $seq_expr = '' unless defined $seq_expr;
     $schema = "$schema." if defined $schema && length $schema;
-    $self->throw_exception( "no sequence found for $schema$table.$col, check table definition, "
-                            . "or explicitly set the 'sequence' for this column in the "
-                            . $source->source_name
-                            . " class"
-                          );
+    $self->throw_exception( sprintf (
+      'no sequence found for %s%s.%s, check the RDBMS table definition or explicitly set the '.
+      "'sequence' for this column in %s",
+        $schema ? "$schema." : '',
+        $table,
+        $col,
+        $source->source_name,
+    ));
   }
 
   return $1;

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/SQLite.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/SQLite.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/SQLite.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -47,6 +47,22 @@
   return $backupfile;
 }
 
+sub deployment_statements {
+  my $self = shift;;
+  my ($schema, $type, $version, $dir, $sqltargs, @rest) = @_;
+
+  $sqltargs ||= {};
+
+  my $sqlite_version = $self->_get_dbh->{sqlite_version};
+
+  # numify, SQLT does a numeric comparison
+  $sqlite_version =~ s/^(\d+) \. (\d+) (?: \. (\d+))? .*/${1}.${2}/x;
+
+  $sqltargs->{producer_args}{sqlite_version} = $sqlite_version;
+
+  $self->next::method($schema, $type, $version, $dir, $sqltargs, @rest);
+}
+
 sub datetime_parser_type { return "DateTime::Format::SQLite"; } 
 
 1;

Deleted: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Base.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Base.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Base.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -1,54 +0,0 @@
-package # hide from PAUSE
-    DBIx::Class::Storage::DBI::Sybase::Base;
-
-use strict;
-use warnings;
-
-use base qw/DBIx::Class::Storage::DBI/;
-use mro 'c3';
-
-=head1 NAME
-
-DBIx::Class::Storage::DBI::Sybase::Base - Common functionality for drivers using
-DBD::Sybase
-
-=cut
-
-sub _ping {
-  my $self = shift;
-
-  my $dbh = $self->_dbh or return 0;
-
-  local $dbh->{RaiseError} = 1;
-  eval {
-    $dbh->do('select 1');
-  };
-
-  return $@ ? 0 : 1;
-}
-
-sub _placeholders_supported {
-  my $self = shift;
-  my $dbh  = $self->_get_dbh;
-
-  return eval {
-# There's also $dbh->{syb_dynamic_supported} but it can be inaccurate for this
-# purpose.
-    local $dbh->{PrintError} = 0;
-    local $dbh->{RaiseError} = 1;
-# this specifically tests a bind that is NOT a string
-    $dbh->selectrow_array('select 1 where 1 = ?', {}, 1);
-  };
-}
-
-1;
-
-=head1 AUTHORS
-
-See L<DBIx::Class/CONTRIBUTORS>.
-
-=head1 LICENSE
-
-You may distribute this code under the same terms as Perl itself.
-
-=cut

Added: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Common.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Common.pm	                        (rev 0)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Common.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -0,0 +1,111 @@
+package DBIx::Class::Storage::DBI::Sybase::Common;
+
+use strict;
+use warnings;
+
+use base qw/DBIx::Class::Storage::DBI/;
+use mro 'c3';
+
+=head1 NAME
+
+DBIx::Class::Storage::DBI::Sybase::Common - Common functionality for drivers using
+DBD::Sybase
+
+=head1 DESCRIPTION
+
+This is the base class for L<DBIx::Class::Storage::DBI::Sybase> and
+L<DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server>. It provides some
+utility methods related to L<DBD::Sybase> and the supported functions of the
+database you are connecting to.
+
+=head1 METHODS
+
+=cut
+
+sub _ping {
+  my $self = shift;
+
+  my $dbh = $self->_dbh or return 0;
+
+  local $dbh->{RaiseError} = 1;
+  local $dbh->{PrintError} = 0;
+
+  if ($dbh->{syb_no_child_con}) {
+# ping is impossible with an active statement, we return false if so
+    my $ping = eval { $dbh->ping };
+    return $@ ? 0 : $ping;
+  }
+
+  eval {
+# XXX if the main connection goes stale, does opening another for this statement
+# really determine anything?
+    $dbh->do('select 1');
+  };
+
+  return $@ ? 0 : 1;
+}
+
+sub _set_max_connect {
+  my $self = shift;
+  my $val  = shift || 256;
+
+  my $dsn = $self->_dbi_connect_info->[0];
+
+  return if ref($dsn) eq 'CODE';
+
+  if ($dsn !~ /maxConnect=/) {
+    $self->_dbi_connect_info->[0] = "$dsn;maxConnect=$val";
+    my $connected = defined $self->_dbh;
+    $self->disconnect;
+    $self->ensure_connected if $connected;
+  }
+}
+
+=head2 using_freetds
+
+Whether or not L<DBD::Sybase> was compiled against FreeTDS. If false, it means
+the Sybase OpenClient libraries were used.
+
+=cut
+
+sub using_freetds {
+  my $self = shift;
+
+  return $self->_get_dbh->{syb_oc_version} =~ /freetds/i;
+}
+
+=head2 set_textsize
+
+When using FreeTDS and/or MSSQL, C<< $dbh->{LongReadLen} >> is not available,
+use this function instead. It does:
+
+  $dbh->do("SET TEXTSIZE $bytes");
+
+Takes the number of bytes, or uses the C<LongReadLen> value from your
+L<DBIx::Class/connect_info> if omitted, lastly falls back to the C<32768> which
+is the L<DBD::Sybase> default.
+
+=cut
+
+sub set_textsize {
+  my $self = shift;
+  my $text_size = shift ||
+    eval { $self->_dbi_connect_info->[-1]->{LongReadLen} } ||
+    32768; # the DBD::Sybase default
+
+  return unless defined $text_size;
+
+  $self->_dbh->do("SET TEXTSIZE $text_size");
+}
+
+1;
+
+=head1 AUTHORS
+
+See L<DBIx::Class/CONTRIBUTORS>.
+
+=head1 LICENSE
+
+You may distribute this code under the same terms as Perl itself.
+
+=cut

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Microsoft_SQL_Server.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Microsoft_SQL_Server.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/Microsoft_SQL_Server.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -4,7 +4,7 @@
 use warnings;
 
 use base qw/
-  DBIx::Class::Storage::DBI::Sybase::Base
+  DBIx::Class::Storage::DBI::Sybase::Common
   DBIx::Class::Storage::DBI::MSSQL
 /;
 use mro 'c3';
@@ -18,16 +18,37 @@
       'DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server::NoBindVars';
     $self->_rebless;
   }
+}
 
-# LongReadLen doesn't work with MSSQL through DBD::Sybase, and the default is
-# huge on some versions of SQL server and can cause memory problems, so we
-# fix it up here.
-  my $text_size = eval { $self->_dbi_connect_info->[-1]->{LongReadLen} } ||
-    32768; # the DBD::Sybase default
+sub _init {
+  my $self = shift;
 
-  $dbh->do("set textsize $text_size");
+  # LongReadLen doesn't work with MSSQL through DBD::Sybase, and the default is
+  # huge on some versions of SQL server and can cause memory problems, so we
+  # fix it up here (see Sybase/Common.pm)
+  $self->set_textsize;
 }
 
+sub _dbh_begin_work {
+  my $self = shift;
+
+  $self->_get_dbh->do('BEGIN TRAN');
+}
+
+sub _dbh_commit {
+  my $self = shift;
+  my $dbh  = $self->_dbh
+    or $self->throw_exception('cannot COMMIT on a disconnected handle');
+  $dbh->do('COMMIT');
+}
+
+sub _dbh_rollback {
+  my $self = shift;
+  my $dbh  = $self->_dbh
+    or $self->throw_exception('cannot ROLLBACK on a disconnected handle');
+  $dbh->do('ROLLBACK');
+}
+
 1;
 
 =head1 NAME

Added: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/NoBindVars.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/NoBindVars.pm	                        (rev 0)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase/NoBindVars.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -0,0 +1,102 @@
+package DBIx::Class::Storage::DBI::Sybase::NoBindVars;
+
+use base qw/
+  DBIx::Class::Storage::DBI::NoBindVars
+  DBIx::Class::Storage::DBI::Sybase
+/;
+use mro 'c3';
+use List::Util ();
+use Scalar::Util ();
+
+sub _init {
+  my $self = shift;
+  $self->disable_sth_caching(1);
+  $self->_identity_method('@@IDENTITY');
+  $self->next::method (@_);
+}
+
+sub _fetch_identity_sql { 'SELECT ' . $_[0]->_identity_method }
+
+my $number = sub { Scalar::Util::looks_like_number($_[0]) };
+
+my $decimal = sub { $_[0] =~ /^ [-+]? \d+ (?:\.\d*)? \z/x };
+
+my %noquote = (
+    int => sub { $_[0] =~ /^ [-+]? \d+ \z/x },
+    bit => => sub { $_[0] =~ /^[01]\z/ },
+    money => sub { $_[0] =~ /^\$ \d+ (?:\.\d*)? \z/x },
+    float => $number,
+    real => $number,
+    double => $number,
+    decimal => $decimal,
+    numeric => $decimal,
+);
+
+sub interpolate_unquoted {
+  my $self = shift;
+  my ($type, $value) = @_;
+
+  return $self->next::method(@_) if not defined $value or not defined $type;
+
+  if (my $key = List::Util::first { $type =~ /$_/i } keys %noquote) {
+    return 1 if $noquote{$key}->($value);
+  }
+  elsif ($self->is_datatype_numeric($type) && $number->($value)) {
+    return 1;
+  }
+
+  return $self->next::method(@_);
+}
+
+sub _prep_interpolated_value {
+  my ($self, $type, $value) = @_;
+
+  if ($type =~ /money/i && defined $value) {
+    # change a ^ not followed by \$ to a \$
+    $value =~ s/^ (?! \$) /\$/x;
+  }
+
+  return $value;
+}
+
+1;
+
+=head1 NAME
+
+DBIx::Class::Storage::DBI::Sybase::NoBindVars - Storage::DBI subclass for Sybase
+without placeholder support
+
+=head1 DESCRIPTION
+
+If you're using this driver than your version of Sybase, or the libraries you
+use to connect to it, do not support placeholders.
+
+You can also enable this driver explicitly using:
+
+  my $schema = SchemaClass->clone;
+  $schema->storage_type('::DBI::Sybase::NoBindVars');
+  $schema->connect($dsn, $user, $pass, \%opts);
+
+See the discussion in L<< DBD::Sybase/Using ? Placeholders & bind parameters to
+$sth->execute >> for details on the pros and cons of using placeholders.
+
+One advantage of not using placeholders is that C<select @@identity> will work
+for obtainging the last insert id of an C<IDENTITY> column, instead of having to
+do C<select max(col)> in a transaction as the base Sybase driver does.
+
+When using this driver, bind variables will be interpolated (properly quoted of
+course) into the SQL query itself, without using placeholders.
+
+The caching of prepared statements is also explicitly disabled, as the
+interpolation renders it useless.
+
+=head1 AUTHORS
+
+See L<DBIx::Class/CONTRIBUTORS>.
+
+=head1 LICENSE
+
+You may distribute this code under the same terms as Perl itself.
+
+=cut
+# vim:sts=2 sw=2:

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI/Sybase.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -4,63 +4,1134 @@
 use warnings;
 
 use base qw/
-    DBIx::Class::Storage::DBI::Sybase::Base
-    DBIx::Class::Storage::DBI::NoBindVars
+    DBIx::Class::Storage::DBI::Sybase::Common
+    DBIx::Class::Storage::DBI::AutoCast
 /;
 use mro 'c3';
+use Carp::Clan qw/^DBIx::Class/;
+use List::Util();
+use Sub::Name();
+use Data::Dumper::Concise();
 
+__PACKAGE__->mk_group_accessors('simple' =>
+    qw/_identity _blob_log_on_update _writer_storage _is_extra_storage
+       _bulk_storage _is_bulk_storage _began_bulk_work
+       _bulk_disabled_due_to_coderef_connect_info_warned
+       _identity_method/
+);
+
+my @also_proxy_to_extra_storages = qw/
+  connect_call_set_auto_cast auto_cast connect_call_blob_setup
+  connect_call_datetime_setup
+
+  disconnect _connect_info _sql_maker _sql_maker_opts disable_sth_caching
+  auto_savepoint unsafe cursor_class debug debugobj schema
+/;
+
+=head1 NAME
+
+DBIx::Class::Storage::DBI::Sybase - Sybase support for DBIx::Class
+
+=head1 SYNOPSIS
+
+This subclass supports L<DBD::Sybase> for real Sybase databases.  If you are
+using an MSSQL database via L<DBD::Sybase>, your storage will be reblessed to
+L<DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server>.
+
+=head1 DESCRIPTION
+
+If your version of Sybase does not support placeholders, then your storage
+will be reblessed to L<DBIx::Class::Storage::DBI::Sybase::NoBindVars>. You can
+also enable that driver explicitly, see the documentation for more details.
+
+With this driver there is unfortunately no way to get the C<last_insert_id>
+without doing a C<SELECT MAX(col)>. This is done safely in a transaction
+(locking the table.) See L</INSERTS WITH PLACEHOLDERS>.
+
+A recommended L<DBIx::Class::Storage::DBI/connect_info> setting:
+
+  on_connect_call => [['datetime_setup'], ['blob_setup', log_on_update => 0]]
+
+=head1 METHODS
+
+=cut
+
 sub _rebless {
-    my $self = shift;
+  my $self = shift;
 
+  if (ref($self) eq 'DBIx::Class::Storage::DBI::Sybase') {
     my $dbtype = eval {
-      @{$self->_get_dbh
-        ->selectrow_arrayref(qq{sp_server_info \@attribute_id=1})
-      }[2]
-    };
-    unless ( $@ ) {
-        $dbtype =~ s/\W/_/gi;
-        my $subclass = "DBIx::Class::Storage::DBI::Sybase::${dbtype}";
-        if ($self->load_optional_class($subclass) && !$self->isa($subclass)) {
-            bless $self, $subclass;
+      @{$self->_get_dbh->selectrow_arrayref(qq{sp_server_info \@attribute_id=1})}[2]
+    } || '';
+
+    my $exception = $@;
+    $dbtype =~ s/\W/_/gi;
+    my $subclass = "DBIx::Class::Storage::DBI::Sybase::${dbtype}";
+
+    if (!$exception && $dbtype && $self->load_optional_class($subclass)) {
+      bless $self, $subclass;
+      $self->_rebless;
+    } else { # real Sybase
+      my $no_bind_vars = 'DBIx::Class::Storage::DBI::Sybase::NoBindVars';
+
+      if ($self->using_freetds) {
+        carp <<'EOF' unless $ENV{DBIC_SYBASE_FREETDS_NOWARN};
+
+You are using FreeTDS with Sybase.
+
+We will do our best to support this configuration, but please consider this
+support experimental.
+
+TEXT/IMAGE columns will definitely not work.
+
+You are encouraged to recompile DBD::Sybase with the Sybase Open Client libraries
+instead.
+
+See perldoc DBIx::Class::Storage::DBI::Sybase for more details.
+
+To turn off this warning set the DBIC_SYBASE_FREETDS_NOWARN environment
+variable.
+EOF
+        if (not $self->_typeless_placeholders_supported) {
+          if ($self->_placeholders_supported) {
+            $self->auto_cast(1);
+          } else {
+            $self->ensure_class_loaded($no_bind_vars);
+            bless $self, $no_bind_vars;
             $self->_rebless;
+          }
         }
+      }
+      elsif (not $self->_get_dbh->{syb_dynamic_supported}) {
+        # not necessarily FreeTDS, but no placeholders nevertheless
+        $self->ensure_class_loaded($no_bind_vars);
+        bless $self, $no_bind_vars;
+        $self->_rebless;
+      } elsif (not $self->_typeless_placeholders_supported) {
+        # this is highly unlikely, but we check just in case
+        $self->auto_cast(1);
+      }
     }
+  }
 }
 
-sub _dbh_last_insert_id {
-    my ($self, $dbh, $source, $col) = @_;
-    return ($dbh->selectrow_array('select @@identity'))[0];
+sub _init {
+  my $self = shift;
+  $self->_set_max_connect(256);
+
+  # based on LongReadLen in connect_info
+  $self->set_textsize if $self->using_freetds;
+
+# create storage for insert/(update blob) transactions,
+# unless this is that storage
+  return if $self->_is_extra_storage;
+
+  my $writer_storage = (ref $self)->new;
+
+  $writer_storage->_is_extra_storage(1);
+  $writer_storage->connect_info($self->connect_info);
+  $writer_storage->auto_cast($self->auto_cast);
+
+  $self->_writer_storage($writer_storage);
+
+# create a bulk storage unless connect_info is a coderef
+  return
+    if (Scalar::Util::reftype($self->_dbi_connect_info->[0])||'') eq 'CODE';
+
+  my $bulk_storage = (ref $self)->new;
+
+  $bulk_storage->_is_extra_storage(1);
+  $bulk_storage->_is_bulk_storage(1); # for special ->disconnect acrobatics
+  $bulk_storage->connect_info($self->connect_info);
+
+# this is why
+  $bulk_storage->_dbi_connect_info->[0] .= ';bulkLogin=1';
+
+  $self->_bulk_storage($bulk_storage);
 }
 
+for my $method (@also_proxy_to_extra_storages) {
+  no strict 'refs';
+  no warnings 'redefine';
+
+  my $replaced = __PACKAGE__->can($method);
+
+  *{$method} = Sub::Name::subname $method => sub {
+    my $self = shift;
+    $self->_writer_storage->$replaced(@_) if $self->_writer_storage;
+    $self->_bulk_storage->$replaced(@_)   if $self->_bulk_storage;
+    return $self->$replaced(@_);
+  };
+}
+
+sub disconnect {
+  my $self = shift;
+
+# Even though we call $sth->finish for uses off the bulk API, there's still an
+# "active statement" warning on disconnect, which we throw away here.
+# This is due to the bug described in insert_bulk.
+# Currently a noop because 'prepare' is used instead of 'prepare_cached'.
+  local $SIG{__WARN__} = sub {
+    warn $_[0] unless $_[0] =~ /active statement/i;
+  } if $self->_is_bulk_storage;
+
+# so that next transaction gets a dbh
+  $self->_began_bulk_work(0) if $self->_is_bulk_storage;
+
+  $self->next::method;
+}
+
+# Make sure we have CHAINED mode turned on if AutoCommit is off in non-FreeTDS
+# DBD::Sybase (since we don't know how DBD::Sybase was compiled.) If however
+# we're using FreeTDS, CHAINED mode turns on an implicit transaction which we
+# only want when AutoCommit is off.
+sub _populate_dbh {
+  my $self = shift;
+
+  $self->next::method(@_);
+  
+  if ($self->_is_bulk_storage) {
+# this should be cleared on every reconnect
+    $self->_began_bulk_work(0);
+    return;
+  }
+
+  if (not $self->using_freetds) {
+    $self->_dbh->{syb_chained_txn} = 1;
+  } else {
+    if ($self->_dbh_autocommit) {
+      $self->_dbh->do('SET CHAINED OFF');
+    } else {
+      $self->_dbh->do('SET CHAINED ON');
+    }
+  }
+}
+
+=head2 connect_call_blob_setup
+
+Used as:
+
+  on_connect_call => [ [ 'blob_setup', log_on_update => 0 ] ]
+
+Does C<< $dbh->{syb_binary_images} = 1; >> to return C<IMAGE> data as raw binary
+instead of as a hex string.
+
+Recommended.
+
+Also sets the C<log_on_update> value for blob write operations. The default is
+C<1>, but C<0> is better if your database is configured for it.
+
+See
+L<DBD::Sybase/Handling_IMAGE/TEXT_data_with_syb_ct_get_data()/syb_ct_send_data()>.
+
+=cut
+
+sub connect_call_blob_setup {
+  my $self = shift;
+  my %args = @_;
+  my $dbh = $self->_dbh;
+  $dbh->{syb_binary_images} = 1;
+
+  $self->_blob_log_on_update($args{log_on_update})
+    if exists $args{log_on_update};
+}
+
+sub _is_lob_type {
+  my $self = shift;
+  my $type = shift;
+  $type && $type =~ /(?:text|image|lob|bytea|binary|memo)/i;
+}
+
+sub _is_lob_column {
+  my ($self, $source, $column) = @_;
+
+  return $self->_is_lob_type($source->column_info($column)->{data_type});
+}
+
+sub _prep_for_execute {
+  my $self = shift;
+  my ($op, $extra_bind, $ident, $args) = @_;
+
+  my ($sql, $bind) = $self->next::method (@_);
+
+  my $table = Scalar::Util::blessed($ident) ? $ident->from : $ident;
+
+  my $bind_info = $self->_resolve_column_info(
+    $ident, [map $_->[0], @{$bind}]
+  );
+  my $bound_identity_col = List::Util::first
+    { $bind_info->{$_}{is_auto_increment} }
+    (keys %$bind_info)
+  ;
+  my $identity_col = Scalar::Util::blessed($ident) &&
+    List::Util::first
+    { $ident->column_info($_)->{is_auto_increment} }
+    $ident->columns
+  ;
+
+  if (($op eq 'insert' && $bound_identity_col) ||
+      ($op eq 'update' && exists $args->[0]{$identity_col})) {
+    $sql = join ("\n",
+      $self->_set_table_identity_sql($op => $table, 'on'),
+      $sql,
+      $self->_set_table_identity_sql($op => $table, 'off'),
+    );
+  }
+
+  if ($op eq 'insert' && (not $bound_identity_col) && $identity_col &&
+      (not $self->{insert_bulk})) {
+    $sql =
+      "$sql\n" .
+      $self->_fetch_identity_sql($ident, $identity_col);
+  }
+
+  return ($sql, $bind);
+}
+
+sub _set_table_identity_sql {
+  my ($self, $op, $table, $on_off) = @_;
+
+  return sprintf 'SET IDENTITY_%s %s %s',
+    uc($op), $self->sql_maker->_quote($table), uc($on_off);
+}
+
+# Stolen from SQLT, with some modifications. This is a makeshift
+# solution before a sane type-mapping library is available, thus
+# the 'our' for easy overrides.
+our %TYPE_MAPPING  = (
+    number    => 'numeric',
+    money     => 'money',
+    varchar   => 'varchar',
+    varchar2  => 'varchar',
+    timestamp => 'datetime',
+    text      => 'varchar',
+    real      => 'double precision',
+    comment   => 'text',
+    bit       => 'bit',
+    tinyint   => 'smallint',
+    float     => 'double precision',
+    serial    => 'numeric',
+    bigserial => 'numeric',
+    boolean   => 'varchar',
+    long      => 'varchar',
+);
+
+sub _native_data_type {
+  my ($self, $type) = @_;
+
+  $type = lc $type;
+  $type =~ s/\s* identity//x;
+
+  return uc($TYPE_MAPPING{$type} || $type);
+}
+
+sub _fetch_identity_sql {
+  my ($self, $source, $col) = @_;
+
+  return sprintf ("SELECT MAX(%s) FROM %s",
+    map { $self->sql_maker->_quote ($_) } ($col, $source->from)
+  );
+}
+
+sub _execute {
+  my $self = shift;
+  my ($op) = @_;
+
+  my ($rv, $sth, @bind) = $self->dbh_do($self->can('_dbh_execute'), @_);
+
+  if ($op eq 'insert') {
+    $self->_identity($sth->fetchrow_array);
+    $sth->finish;
+  }
+
+  return wantarray ? ($rv, $sth, @bind) : $rv;
+}
+
+sub last_insert_id { shift->_identity }
+
+# handles TEXT/IMAGE and transaction for last_insert_id
+sub insert {
+  my $self = shift;
+  my ($source, $to_insert) = @_;
+
+  my $identity_col = (List::Util::first
+    { $source->column_info($_)->{is_auto_increment} }
+    $source->columns) || '';
+
+  # check for empty insert
+  # INSERT INTO foo DEFAULT VALUES -- does not work with Sybase
+  # try to insert explicit 'DEFAULT's instead (except for identity)
+  if (not %$to_insert) {
+    for my $col ($source->columns) {
+      next if $col eq $identity_col;
+      $to_insert->{$col} = \'DEFAULT';
+    }
+  }
+
+  my $blob_cols = $self->_remove_blob_cols($source, $to_insert);
+
+  # do we need the horrific SELECT MAX(COL) hack?
+  my $dumb_last_insert_id =
+       $identity_col
+    && (not exists $to_insert->{$identity_col})
+    && ($self->_identity_method||'') ne '@@IDENTITY';
+
+  my $next = $self->next::can;
+
+  # we are already in a transaction, or there are no blobs
+  # and we don't need the PK - just (try to) do it
+  if ($self->{transaction_depth}
+        || (!$blob_cols && !$dumb_last_insert_id) 
+  ) {
+    return $self->_insert (
+      $next, $source, $to_insert, $blob_cols, $identity_col
+    );
+  }
+
+  # otherwise use the _writer_storage to do the insert+transaction on another
+  # connection
+  my $guard = $self->_writer_storage->txn_scope_guard;
+
+  my $updated_cols = $self->_writer_storage->_insert (
+    $next, $source, $to_insert, $blob_cols, $identity_col
+  );
+
+  $self->_identity($self->_writer_storage->_identity);
+
+  $guard->commit;
+
+  return $updated_cols;
+}
+
+sub _insert {
+  my ($self, $next, $source, $to_insert, $blob_cols, $identity_col) = @_;
+
+  my $updated_cols = $self->$next ($source, $to_insert);
+
+  my $final_row = {
+    ($identity_col ?
+      ($identity_col => $self->last_insert_id($source, $identity_col)) : ()),
+    %$to_insert,
+    %$updated_cols,
+  };
+
+  $self->_insert_blobs ($source, $blob_cols, $final_row) if $blob_cols;
+
+  return $updated_cols;
+}
+
+sub update {
+  my $self = shift;
+  my ($source, $fields, $where, @rest) = @_;
+
+  my $wantarray = wantarray;
+
+  my $blob_cols = $self->_remove_blob_cols($source, $fields);
+
+  my $table = $source->name;
+
+  my $identity_col = List::Util::first
+    { $source->column_info($_)->{is_auto_increment} }
+    $source->columns;
+
+  my $is_identity_update = $identity_col && defined $fields->{$identity_col};
+
+  return $self->next::method(@_) unless $blob_cols;
+
+# If there are any blobs in $where, Sybase will return a descriptive error
+# message.
+# XXX blobs can still be used with a LIKE query, and this should be handled.
+
+# update+blob update(s) done atomically on separate connection
+  $self = $self->_writer_storage;
+
+  my $guard = $self->txn_scope_guard;
+
+# First update the blob columns to be updated to '' (taken from $fields, where
+# it is originally put by _remove_blob_cols .)
+  my %blobs_to_empty = map { ($_ => delete $fields->{$_}) } keys %$blob_cols;
+
+# We can't only update NULL blobs, because blobs cannot be in the WHERE clause.
+
+  $self->next::method($source, \%blobs_to_empty, $where, @rest);
+
+# Now update the blobs before the other columns in case the update of other
+# columns makes the search condition invalid.
+  $self->_update_blobs($source, $blob_cols, $where);
+
+  my @res;
+  if (%$fields) {
+    if ($wantarray) {
+      @res    = $self->next::method(@_);
+    }
+    elsif (defined $wantarray) {
+      $res[0] = $self->next::method(@_);
+    }
+    else {
+      $self->next::method(@_);
+    }
+  }
+
+  $guard->commit;
+
+  return $wantarray ? @res : $res[0];
+}
+
+sub insert_bulk {
+  my $self = shift;
+  my ($source, $cols, $data) = @_;
+
+  my $identity_col = List::Util::first
+    { $source->column_info($_)->{is_auto_increment} }
+    $source->columns;
+
+  my $is_identity_insert = (List::Util::first
+    { $_ eq $identity_col }
+    @{$cols}
+  ) ? 1 : 0;
+
+  my @source_columns = $source->columns;
+
+  my $use_bulk_api =
+    $self->_bulk_storage &&
+    $self->_get_dbh->{syb_has_blk};
+
+  if ((not $use_bulk_api) &&
+      (Scalar::Util::reftype($self->_dbi_connect_info->[0])||'') eq 'CODE' &&
+      (not $self->_bulk_disabled_due_to_coderef_connect_info_warned)) {
+    carp <<'EOF';
+Bulk API support disabled due to use of a CODEREF connect_info. Reverting to
+regular array inserts.
+EOF
+    $self->_bulk_disabled_due_to_coderef_connect_info_warned(1);
+  }
+
+  if (not $use_bulk_api) {
+    my $blob_cols = $self->_remove_blob_cols_array($source, $cols, $data);
+
+# _execute_array uses a txn anyway, but it ends too early in case we need to
+# select max(col) to get the identity for inserting blobs.
+    ($self, my $guard) = $self->{transaction_depth} == 0 ? 
+      ($self->_writer_storage, $self->_writer_storage->txn_scope_guard)
+      :
+      ($self, undef);
+
+    local $self->{insert_bulk} = 1;
+
+    $self->next::method(@_);
+
+    if ($blob_cols) {
+      if ($is_identity_insert) {
+        $self->_insert_blobs_array ($source, $blob_cols, $cols, $data);
+      }
+      else {
+        my @cols_with_identities = (@$cols, $identity_col);
+
+        ## calculate identities
+        # XXX This assumes identities always increase by 1, which may or may not
+        # be true.
+        my ($last_identity) =
+          $self->_dbh->selectrow_array (
+            $self->_fetch_identity_sql($source, $identity_col)
+          );
+        my @identities = (($last_identity - @$data + 1) .. $last_identity);
+
+        my @data_with_identities = map [@$_, shift @identities], @$data;
+
+        $self->_insert_blobs_array (
+          $source, $blob_cols, \@cols_with_identities, \@data_with_identities
+        );
+      }
+    }
+
+    $guard->commit if $guard;
+
+    return;
+  }
+
+# otherwise, use the bulk API
+
+# rearrange @$data so that columns are in database order
+  my %orig_idx;
+  @orig_idx{@$cols} = 0..$#$cols;
+
+  my %new_idx;
+  @new_idx{@source_columns} = 0..$#source_columns;
+
+  my @new_data;
+  for my $datum (@$data) {
+    my $new_datum = [];
+    for my $col (@source_columns) {
+# identity data will be 'undef' if not $is_identity_insert
+# columns with defaults will also be 'undef'
+      $new_datum->[ $new_idx{$col} ] =
+        exists $orig_idx{$col} ? $datum->[ $orig_idx{$col} ] : undef;
+    }
+    push @new_data, $new_datum;
+  }
+
+# bcp identity index is 1-based
+  my $identity_idx = exists $new_idx{$identity_col} ?
+    $new_idx{$identity_col} + 1 : 0;
+
+## Set a client-side conversion error handler, straight from DBD::Sybase docs.
+# This ignores any data conversion errors detected by the client side libs, as
+# they are usually harmless.
+  my $orig_cslib_cb = DBD::Sybase::set_cslib_cb(
+    Sub::Name::subname insert_bulk => sub {
+      my ($layer, $origin, $severity, $errno, $errmsg, $osmsg, $blkmsg) = @_;
+
+      return 1 if $errno == 36;
+
+      carp
+        "Layer: $layer, Origin: $origin, Severity: $severity, Error: $errno" .
+        ($errmsg ? "\n$errmsg" : '') .
+        ($osmsg  ? "\n$osmsg"  : '')  .
+        ($blkmsg ? "\n$blkmsg" : '');
+
+      return 0;
+  });
+
+  eval {
+    my $bulk = $self->_bulk_storage;
+
+    my $guard = $bulk->txn_scope_guard;
+
+## XXX get this to work instead of our own $sth
+## will require SQLA or *Hacks changes for ordered columns
+#    $bulk->next::method($source, \@source_columns, \@new_data, {
+#      syb_bcp_attribs => {
+#        identity_flag   => $is_identity_insert,
+#        identity_column => $identity_idx,
+#      }
+#    });
+    my $sql = 'INSERT INTO ' .
+      $bulk->sql_maker->_quote($source->name) . ' (' .
+# colname list is ignored for BCP, but does no harm
+      (join ', ', map $bulk->sql_maker->_quote($_), @source_columns) . ') '.
+      ' VALUES ('.  (join ', ', ('?') x @source_columns) . ')';
+
+## XXX there's a bug in the DBD::Sybase bulk support that makes $sth->finish for
+## a prepare_cached statement ineffective. Replace with ->sth when fixed, or
+## better yet the version above. Should be fixed in DBD::Sybase .
+    my $sth = $bulk->_get_dbh->prepare($sql,
+#      'insert', # op
+      {
+        syb_bcp_attribs => {
+          identity_flag   => $is_identity_insert,
+          identity_column => $identity_idx,
+        }
+      }
+    );
+
+    my @bind = do {
+      my $idx = 0;
+      map [ $_, $idx++ ], @source_columns;
+    };
+
+    $self->_execute_array(
+      $source, $sth, \@bind, \@source_columns, \@new_data, sub {
+        $guard->commit
+      }
+    );
+
+    $bulk->_query_end($sql);
+  };
+
+  my $exception = $@;
+  DBD::Sybase::set_cslib_cb($orig_cslib_cb);
+
+  if ($exception =~ /-Y option/) {
+    carp <<"EOF";
+
+Sybase bulk API operation failed due to character set incompatibility, reverting
+to regular array inserts:
+
+*** Try unsetting the LANG environment variable.
+
+$exception
+EOF
+    $self->_bulk_storage(undef);
+    unshift @_, $self;
+    goto \&insert_bulk;
+  }
+  elsif ($exception) {
+# rollback makes the bulkLogin connection unusable
+    $self->_bulk_storage->disconnect;
+    $self->throw_exception($exception);
+  }
+}
+
+sub _dbh_execute_array {
+  my ($self, $sth, $tuple_status, $cb) = @_;
+
+  my $rv = $self->next::method($sth, $tuple_status);
+  $cb->() if $cb;
+
+  return $rv;
+}
+
+# Make sure blobs are not bound as placeholders, and return any non-empty ones
+# as a hash.
+sub _remove_blob_cols {
+  my ($self, $source, $fields) = @_;
+
+  my %blob_cols;
+
+  for my $col (keys %$fields) {
+    if ($self->_is_lob_column($source, $col)) {
+      my $blob_val = delete $fields->{$col};
+      if (not defined $blob_val) {
+        $fields->{$col} = \'NULL';
+      }
+      else {
+        $fields->{$col} = \"''";
+        $blob_cols{$col} = $blob_val unless $blob_val eq '';
+      }
+    }
+  }
+
+  return %blob_cols ? \%blob_cols : undef;
+}
+
+# same for insert_bulk
+sub _remove_blob_cols_array {
+  my ($self, $source, $cols, $data) = @_;
+
+  my @blob_cols;
+
+  for my $i (0..$#$cols) {
+    my $col = $cols->[$i];
+
+    if ($self->_is_lob_column($source, $col)) {
+      for my $j (0..$#$data) {
+        my $blob_val = delete $data->[$j][$i];
+        if (not defined $blob_val) {
+          $data->[$j][$i] = \'NULL';
+        }
+        else {
+          $data->[$j][$i] = \"''";
+          $blob_cols[$j][$i] = $blob_val
+            unless $blob_val eq '';
+        }
+      }
+    }
+  }
+
+  return @blob_cols ? \@blob_cols : undef;
+}
+
+sub _update_blobs {
+  my ($self, $source, $blob_cols, $where) = @_;
+
+  my (@primary_cols) = $source->primary_columns;
+
+  $self->throw_exception('Cannot update TEXT/IMAGE column(s) without a primary key')
+    unless @primary_cols;
+
+# check if we're updating a single row by PK
+  my $pk_cols_in_where = 0;
+  for my $col (@primary_cols) {
+    $pk_cols_in_where++ if defined $where->{$col};
+  }
+  my @rows;
+
+  if ($pk_cols_in_where == @primary_cols) {
+    my %row_to_update;
+    @row_to_update{@primary_cols} = @{$where}{@primary_cols};
+    @rows = \%row_to_update;
+  } else {
+    my $cursor = $self->select ($source, \@primary_cols, $where, {});
+    @rows = map {
+      my %row; @row{@primary_cols} = @$_; \%row
+    } $cursor->all;
+  }
+
+  for my $row (@rows) {
+    $self->_insert_blobs($source, $blob_cols, $row);
+  }
+}
+
+sub _insert_blobs {
+  my ($self, $source, $blob_cols, $row) = @_;
+  my $dbh = $self->_get_dbh;
+
+  my $table = $source->name;
+
+  my %row = %$row;
+  my (@primary_cols) = $source->primary_columns;
+
+  $self->throw_exception('Cannot update TEXT/IMAGE column(s) without a primary key')
+    unless @primary_cols;
+
+  $self->throw_exception('Cannot update TEXT/IMAGE column(s) without primary key values')
+    if ((grep { defined $row{$_} } @primary_cols) != @primary_cols);
+
+  for my $col (keys %$blob_cols) {
+    my $blob = $blob_cols->{$col};
+
+    my %where = map { ($_, $row{$_}) } @primary_cols;
+
+    my $cursor = $self->select ($source, [$col], \%where, {});
+    $cursor->next;
+    my $sth = $cursor->sth;
+
+    if (not $sth) {
+
+      $self->throw_exception(
+          "Could not find row in table '$table' for blob update:\n"
+        . Data::Dumper::Concise::Dumper (\%where)
+      );
+    }
+
+    eval {
+      do {
+        $sth->func('CS_GET', 1, 'ct_data_info') or die $sth->errstr;
+      } while $sth->fetch;
+
+      $sth->func('ct_prepare_send') or die $sth->errstr;
+
+      my $log_on_update = $self->_blob_log_on_update;
+      $log_on_update    = 1 if not defined $log_on_update;
+
+      $sth->func('CS_SET', 1, {
+        total_txtlen => length($blob),
+        log_on_update => $log_on_update
+      }, 'ct_data_info') or die $sth->errstr;
+
+      $sth->func($blob, length($blob), 'ct_send_data') or die $sth->errstr;
+
+      $sth->func('ct_finish_send') or die $sth->errstr;
+    };
+    my $exception = $@;
+    $sth->finish if $sth;
+    if ($exception) {
+      if ($self->using_freetds) {
+        $self->throw_exception (
+          'TEXT/IMAGE operation failed, probably because you are using FreeTDS: '
+          . $exception
+        );
+      } else {
+        $self->throw_exception($exception);
+      }
+    }
+  }
+}
+
+sub _insert_blobs_array {
+  my ($self, $source, $blob_cols, $cols, $data) = @_;
+
+  for my $i (0..$#$data) {
+    my $datum = $data->[$i];
+
+    my %row;
+    @row{ @$cols } = @$datum;
+
+    my %blob_vals;
+    for my $j (0..$#$cols) {
+      if (exists $blob_cols->[$i][$j]) {
+        $blob_vals{ $cols->[$j] } = $blob_cols->[$i][$j];
+      }
+    }
+
+    $self->_insert_blobs ($source, \%blob_vals, \%row);
+  }
+}
+
+=head2 connect_call_datetime_setup
+
+Used as:
+
+  on_connect_call => 'datetime_setup'
+
+In L<DBIx::Class::Storage::DBI/connect_info> to set:
+
+  $dbh->syb_date_fmt('ISO_strict'); # output fmt: 2004-08-21T14:36:48.080Z
+  $dbh->do('set dateformat mdy');   # input fmt:  08/13/1979 18:08:55.080
+
+On connection for use with L<DBIx::Class::InflateColumn::DateTime>, using
+L<DateTime::Format::Sybase>, which you will need to install.
+
+This works for both C<DATETIME> and C<SMALLDATETIME> columns, although
+C<SMALLDATETIME> columns only have minute precision.
+
+=cut
+
+{
+  my $old_dbd_warned = 0;
+
+  sub connect_call_datetime_setup {
+    my $self = shift;
+    my $dbh = $self->_get_dbh;
+
+    if ($dbh->can('syb_date_fmt')) {
+      # amazingly, this works with FreeTDS
+      $dbh->syb_date_fmt('ISO_strict');
+    } elsif (not $old_dbd_warned) {
+      carp "Your DBD::Sybase is too old to support ".
+      "DBIx::Class::InflateColumn::DateTime, please upgrade!";
+      $old_dbd_warned = 1;
+    }
+
+    $dbh->do('SET DATEFORMAT mdy');
+
+    1;
+  }
+}
+
+sub datetime_parser_type { "DateTime::Format::Sybase" }
+
+# ->begin_work and such have no effect with FreeTDS but we run them anyway to
+# let the DBD keep any state it needs to.
+#
+# If they ever do start working, the extra statements will do no harm (because
+# Sybase supports nested transactions.)
+
+sub _dbh_begin_work {
+  my $self = shift;
+
+# bulkLogin=1 connections are always in a transaction, and can only call BEGIN
+# TRAN once. However, we need to make sure there's a $dbh.
+  return if $self->_is_bulk_storage && $self->_dbh && $self->_began_bulk_work;
+
+  $self->next::method(@_);
+
+  if ($self->using_freetds) {
+    $self->_get_dbh->do('BEGIN TRAN');
+  }
+
+  $self->_began_bulk_work(1) if $self->_is_bulk_storage;
+}
+
+sub _dbh_commit {
+  my $self = shift;
+  if ($self->using_freetds) {
+    $self->_dbh->do('COMMIT');
+  }
+  return $self->next::method(@_);
+}
+
+sub _dbh_rollback {
+  my $self = shift;
+  if ($self->using_freetds) {
+    $self->_dbh->do('ROLLBACK');
+  }
+  return $self->next::method(@_);
+}
+
+# savepoint support using ASE syntax
+
+sub _svp_begin {
+  my ($self, $name) = @_;
+
+  $self->_get_dbh->do("SAVE TRANSACTION $name");
+}
+
+# A new SAVE TRANSACTION with the same name releases the previous one.
+sub _svp_release { 1 }
+
+sub _svp_rollback {
+  my ($self, $name) = @_;
+
+  $self->_get_dbh->do("ROLLBACK TRANSACTION $name");
+}
+
 1;
 
-=head1 NAME
+=head1 Schema::Loader Support
 
-DBIx::Class::Storage::DBI::Sybase - Storage::DBI subclass for Sybase
+There is an experimental branch of L<DBIx::Class::Schema::Loader> that will
+allow you to dump a schema from most (if not all) versions of Sybase.
 
-=head1 SYNOPSIS
+It is available via subversion from:
 
-This subclass supports L<DBD::Sybase> for real Sybase databases.  If
-you are using an MSSQL database via L<DBD::Sybase>, see
-L<DBIx::Class::Storage::DBI::Sybase::MSSQL>.
+  http://dev.catalyst.perl.org/repos/bast/branches/DBIx-Class-Schema-Loader/current/
 
-=head1 CAVEATS
+=head1 FreeTDS
 
-This storage driver uses L<DBIx::Class::Storage::DBI::NoBindVars> as a base.
-This means that bind variables will be interpolated (properly quoted of course)
-into the SQL query itself, without using bind placeholders.
+This driver supports L<DBD::Sybase> compiled against FreeTDS
+(L<http://www.freetds.org/>) to the best of our ability, however it is
+recommended that you recompile L<DBD::Sybase> against the Sybase Open Client
+libraries. They are a part of the Sybase ASE distribution:
 
-More importantly this means that caching of prepared statements is explicitly
-disabled, as the interpolation renders it useless.
+The Open Client FAQ is here:
+L<http://www.isug.com/Sybase_FAQ/ASE/section7.html>.
 
-=head1 AUTHORS
+Sybase ASE for Linux (which comes with the Open Client libraries) may be
+downloaded here: L<http://response.sybase.com/forms/ASE_Linux_Download>.
 
-Brandon L Black <blblack at gmail.com>
+To see if you're using FreeTDS check C<< $schema->storage->using_freetds >>, or run:
 
-Justin Hunter <justin.d.hunter at gmail.com>
+  perl -MDBI -le 'my $dbh = DBI->connect($dsn, $user, $pass); print $dbh->{syb_oc_version}'
 
+Some versions of the libraries involved will not support placeholders, in which
+case the storage will be reblessed to
+L<DBIx::Class::Storage::DBI::Sybase::NoBindVars>.
+
+In some configurations, placeholders will work but will throw implicit type
+conversion errors for anything that's not expecting a string. In such a case,
+the C<auto_cast> option from L<DBIx::Class::Storage::DBI::AutoCast> is
+automatically set, which you may enable on connection with
+L<DBIx::Class::Storage::DBI::AutoCast/connect_call_set_auto_cast>. The type info
+for the C<CAST>s is taken from the L<DBIx::Class::ResultSource/data_type>
+definitions in your Result classes, and are mapped to a Sybase type (if it isn't
+already) using a mapping based on L<SQL::Translator>.
+
+In other configurations, placeholers will work just as they do with the Sybase
+Open Client libraries.
+
+Inserts or updates of TEXT/IMAGE columns will B<NOT> work with FreeTDS.
+
+=head1 INSERTS WITH PLACEHOLDERS
+
+With placeholders enabled, inserts are done in a transaction so that there are
+no concurrency issues with getting the inserted identity value using
+C<SELECT MAX(col)>, which is the only way to get the C<IDENTITY> value in this
+mode.
+
+In addition, they are done on a separate connection so that it's possible to
+have active cursors when doing an insert.
+
+When using C<DBIx::Class::Storage::DBI::Sybase::NoBindVars> transactions are
+disabled, as there are no concurrency issues with C<SELECT @@IDENTITY> as it's a
+session variable.
+
+=head1 TRANSACTIONS
+
+Due to limitations of the TDS protocol, L<DBD::Sybase>, or both; you cannot
+begin a transaction while there are active cursors; nor can you use multiple
+active cursors within a transaction. An active cursor is, for example, a
+L<ResultSet|DBIx::Class::ResultSet> that has been executed using C<next> or
+C<first> but has not been exhausted or L<reset|DBIx::Class::ResultSet/reset>.
+
+For example, this will not work:
+
+  $schema->txn_do(sub {
+    my $rs = $schema->resultset('Book');
+    while (my $row = $rs->next) {
+      $schema->resultset('MetaData')->create({
+        book_id => $row->id,
+        ...
+      });
+    }
+  });
+
+This won't either:
+
+  my $first_row = $large_rs->first;
+  $schema->txn_do(sub { ... });
+
+Transactions done for inserts in C<AutoCommit> mode when placeholders are in use
+are not affected, as they are done on an extra database handle.
+
+Some workarounds:
+
+=over 4
+
+=item * use L<DBIx::Class::Storage::DBI::Replicated>
+
+=item * L<connect|DBIx::Class::Schema/connect> another L<Schema|DBIx::Class::Schema>
+
+=item * load the data from your cursor with L<DBIx::Class::ResultSet/all>
+
+=back
+
+=head1 MAXIMUM CONNECTIONS
+
+The TDS protocol makes separate connections to the server for active statements
+in the background. By default the number of such connections is limited to 25,
+on both the client side and the server side.
+
+This is a bit too low for a complex L<DBIx::Class> application, so on connection
+the client side setting is set to C<256> (see L<DBD::Sybase/maxConnect>.) You
+can override it to whatever setting you like in the DSN.
+
+See
+L<http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.ase_15.0.sag1/html/sag1/sag1272.htm>
+for information on changing the setting on the server side.
+
+=head1 DATES
+
+See L</connect_call_datetime_setup> to setup date formats
+for L<DBIx::Class::InflateColumn::DateTime>.
+
+=head1 TEXT/IMAGE COLUMNS
+
+L<DBD::Sybase> compiled with FreeTDS will B<NOT> allow you to insert or update
+C<TEXT/IMAGE> columns.
+
+Setting C<< $dbh->{LongReadLen} >> will also not work with FreeTDS use either:
+
+  $schema->storage->dbh->do("SET TEXTSIZE $bytes");
+
+or
+
+  $schema->storage->set_textsize($bytes);
+
+instead.
+
+However, the C<LongReadLen> you pass in
+L<DBIx::Class::Storage::DBI/connect_info> is used to execute the equivalent
+C<SET TEXTSIZE> command on connection.
+
+See L</connect_call_blob_setup> for a L<DBIx::Class::Storage::DBI/connect_info>
+setting you need to work with C<IMAGE> columns.
+
+=head1 BULK API
+
+The experimental L<DBD::Sybase> Bulk API support is used for
+L<populate|DBIx::Class::ResultSet/populate> in B<void> context, in a transaction
+on a separate connection.
+
+To use this feature effectively, use a large number of rows for each
+L<populate|DBIx::Class::ResultSet/populate> call, eg.:
+
+  while (my $rows = $data_source->get_100_rows()) {
+    $rs->populate($rows);
+  }
+
+B<NOTE:> the L<add_columns|DBIx::Class::ResultSource/add_columns>
+calls in your C<Result> classes B<must> list columns in database order for this
+to work. Also, you may have to unset the C<LANG> environment variable before
+loading your app, if it doesn't match the character set of your database.
+
+When inserting IMAGE columns using this method, you'll need to use
+L</connect_call_blob_setup> as well.
+
+=head1 TODO
+
+=over
+
+=item *
+
+Transitions to AutoCommit=0 (starting a transaction) mode by exhausting
+any active cursors, using eager cursors.
+
+=item *
+
+Real limits and limited counts using stored procedures deployed on startup.
+
+=item *
+
+Adaptive Server Anywhere (ASA) support, with possible SQLA::Limit support.
+
+=item *
+
+Blob update with a LIKE query on a blob, without invalidating the WHERE condition.
+
+=item *
+
+bulk_insert using prepare_cached (see comments.)
+
+=back
+
+=head1 AUTHOR
+
+See L<DBIx::Class/CONTRIBUTORS>.
+
 =head1 LICENSE
 
 You may distribute this code under the same terms as Perl itself.
 
 =cut
+# vim:sts=2 sw=2:

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class/Storage/DBI.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -13,6 +13,7 @@
 use DBIx::Class::Storage::Statistics;
 use Scalar::Util();
 use List::Util();
+use Data::Dumper::Concise();
 
 # what version of sqlt do we require if deploy() without a ddl_dir is invoked
 # when changing also adjust the corresponding author_require in Makefile.PL
@@ -40,6 +41,38 @@
 __PACKAGE__->sql_maker_class('DBIx::Class::SQLAHacks');
 
 
+# Each of these methods need _determine_driver called before itself
+# in order to function reliably. This is a purely DRY optimization
+my @rdbms_specific_methods = qw/
+  sqlt_type
+  build_datetime_parser
+  datetime_parser_type
+
+  insert
+  insert_bulk
+  update
+  delete
+  select
+  select_single
+/;
+
+for my $meth (@rdbms_specific_methods) {
+
+  my $orig = __PACKAGE__->can ($meth)
+    or next;
+
+  no strict qw/refs/;
+  no warnings qw/redefine/;
+  *{__PACKAGE__ ."::$meth"} = sub {
+    if (not $_[0]->_driver_determined) {
+      $_[0]->_determine_driver;
+      goto $_[0]->can($meth);
+    }
+    $orig->(@_);
+  };
+}
+
+
 =head1 NAME
 
 DBIx::Class::Storage::DBI - DBI storage handler
@@ -712,7 +745,6 @@
 # Storage subclasses should override this
 sub with_deferred_fk_checks {
   my ($self, $sub) = @_;
-
   $sub->();
 }
 
@@ -878,13 +910,14 @@
   my ($self) = @_;
 
   if ((not $self->_driver_determined) && (not $self->{_in_determine_driver})) {
-    my $started_unconnected = 0;
+    my $started_connected = 0;
     local $self->{_in_determine_driver} = 1;
 
     if (ref($self) eq __PACKAGE__) {
       my $driver;
       if ($self->_dbh) { # we are connected
         $driver = $self->_dbh->{Driver}{Name};
+        $started_connected = 1;
       } else {
         # if connect_info is a CODEREF, we have no choice but to connect
         if (ref $self->_dbi_connect_info->[0] &&
@@ -896,7 +929,6 @@
           # try to use dsn to not require being connected, the driver may still
           # force a connection in _rebless to determine version
           ($driver) = $self->_dbi_connect_info->[0] =~ /dbi:([^:]+):/i;
-          $started_unconnected = 1;
         }
       }
 
@@ -913,7 +945,7 @@
     $self->_init; # run driver-specific initializations
 
     $self->_run_connection_actions
-        if $started_unconnected && defined $self->_dbh;
+        if !$started_connected && defined $self->_dbh;
   }
 }
 
@@ -1144,7 +1176,6 @@
 sub txn_commit {
   my $self = shift;
   if ($self->{transaction_depth} == 1) {
-    my $dbh = $self->_dbh;
     $self->debugobj->txn_commit()
       if ($self->debug);
     $self->_dbh_commit;
@@ -1160,7 +1191,9 @@
 
 sub _dbh_commit {
   my $self = shift;
-  $self->_dbh->commit;
+  my $dbh  = $self->_dbh
+    or $self->throw_exception('cannot COMMIT on a disconnected handle');
+  $dbh->commit;
 }
 
 sub txn_rollback {
@@ -1197,7 +1230,9 @@
 
 sub _dbh_rollback {
   my $self = shift;
-  $self->_dbh->rollback;
+  my $dbh  = $self->_dbh
+    or $self->throw_exception('cannot ROLLBACK on a disconnected handle');
+  $dbh->rollback;
 }
 
 # This used to be the top-half of _execute.  It was split out to make it
@@ -1300,12 +1335,6 @@
 sub insert {
   my ($self, $source, $to_insert) = @_;
 
-# redispatch to insert method of storage we reblessed into, if necessary
-  if (not $self->_driver_determined) {
-    $self->_determine_driver;
-    goto $self->can('insert');
-  }
-
   my $ident = $source->from;
   my $bind_attributes = $self->source_bind_attributes($source);
 
@@ -1337,22 +1366,103 @@
 sub insert_bulk {
   my ($self, $source, $cols, $data) = @_;
 
-# redispatch to insert_bulk method of storage we reblessed into, if necessary
-  if (not $self->_driver_determined) {
-    $self->_determine_driver;
-    goto $self->can('insert_bulk');
-  }
-
   my %colvalues;
-  my $table = $source->from;
   @colvalues{@$cols} = (0..$#$cols);
-  my ($sql, @bind) = $self->sql_maker->insert($table, \%colvalues);
 
-  $self->_query_start( $sql, @bind );
+  for my $i (0..$#$cols) {
+    my $first_val = $data->[0][$i];
+    next unless ref $first_val eq 'SCALAR';
+
+    $colvalues{ $cols->[$i] } = $first_val;
+  }
+
+  # check for bad data and stringify stringifiable objects
+  my $bad_slice = sub {
+    my ($msg, $col_idx, $slice_idx) = @_;
+    $self->throw_exception(sprintf "%s for column '%s' in populate slice:\n%s",
+      $msg,
+      $cols->[$col_idx],
+      do {
+        local $Data::Dumper::Maxdepth = 1; # don't dump objects, if any
+        Data::Dumper::Concise::Dumper({
+          map { $cols->[$_] => $data->[$slice_idx][$_] } (0 .. $#$cols)
+        }),
+      }
+    );
+  };
+
+  for my $datum_idx (0..$#$data) {
+    my $datum = $data->[$datum_idx];
+
+    for my $col_idx (0..$#$cols) {
+      my $val            = $datum->[$col_idx];
+      my $sqla_bind      = $colvalues{ $cols->[$col_idx] };
+      my $is_literal_sql = (ref $sqla_bind) eq 'SCALAR';
+
+      if ($is_literal_sql) {
+        if (not ref $val) {
+          $bad_slice->('bind found where literal SQL expected', $col_idx, $datum_idx);
+        }
+        elsif ((my $reftype = ref $val) ne 'SCALAR') {
+          $bad_slice->("$reftype reference found where literal SQL expected",
+            $col_idx, $datum_idx);
+        }
+        elsif ($$val ne $$sqla_bind){
+          $bad_slice->("inconsistent literal SQL value, expecting: '$$sqla_bind'",
+            $col_idx, $datum_idx);
+        }
+      }
+      elsif (my $reftype = ref $val) {
+        require overload;
+        if (overload::Method($val, '""')) {
+          $datum->[$col_idx] = "".$val;
+        }
+        else {
+          $bad_slice->("$reftype reference found where bind expected",
+            $col_idx, $datum_idx);
+        }
+      }
+    }
+  }
+
+  my ($sql, $bind) = $self->_prep_for_execute (
+    'insert', undef, $source, [\%colvalues]
+  );
+  my @bind = @$bind;
+
+  my $empty_bind = 1 if (not @bind) &&
+    (grep { ref $_ eq 'SCALAR' } values %colvalues) == @$cols;
+
+  if ((not @bind) && (not $empty_bind)) {
+    $self->throw_exception(
+      'Cannot insert_bulk without support for placeholders'
+    );
+  }
+
+  $self->_query_start( $sql, ['__BULK__'] );
   my $sth = $self->sth($sql);
 
-#  @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
+  my $rv = do {
+    if ($empty_bind) {
+      # bind_param_array doesn't work if there are no binds
+      $self->_dbh_execute_inserts_with_no_binds( $sth, scalar @$data );
+    }
+    else {
+#      @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
+      $self->_execute_array( $source, $sth, \@bind, $cols, $data );
+    }
+  };
 
+  $self->_query_end( $sql, ['__BULK__'] );
+
+  return (wantarray ? ($rv, $sth, @bind) : $rv);
+}
+
+sub _execute_array {
+  my ($self, $source, $sth, $bind, $cols, $data, @extra) = @_;
+
+  my $guard = $self->txn_scope_guard unless $self->{transaction_depth} != 0;
+
   ## This must be an arrayref, else nothing works!
   my $tuple_status = [];
 
@@ -1362,7 +1472,7 @@
   ## Bind the values and execute
   my $placeholder_index = 1;
 
-  foreach my $bound (@bind) {
+  foreach my $bound (@$bind) {
 
     my $attributes = {};
     my ($column_name, $data_index) = @$bound;
@@ -1377,43 +1487,70 @@
     $sth->bind_param_array( $placeholder_index, [@data], $attributes );
     $placeholder_index++;
   }
-  my $rv = eval { $sth->execute_array({ArrayTupleStatus => $tuple_status}) };
-  if (my $err = $@) {
+
+  my $rv = eval {
+    $self->_dbh_execute_array($sth, $tuple_status, @extra);
+  };
+  my $err = $@ || $sth->errstr;
+
+# Statement must finish even if there was an exception.
+  eval { $sth->finish };
+  $err = $@ unless $err;
+
+  if ($err) {
     my $i = 0;
     ++$i while $i <= $#$tuple_status && !ref $tuple_status->[$i];
 
-    $self->throw_exception($sth->errstr || "Unexpected populate error: $err")
+    $self->throw_exception("Unexpected populate error: $err")
       if ($i > $#$tuple_status);
 
-    require Data::Dumper;
-    local $Data::Dumper::Terse = 1;
-    local $Data::Dumper::Indent = 1;
-    local $Data::Dumper::Useqq = 1;
-    local $Data::Dumper::Quotekeys = 0;
-    local $Data::Dumper::Sortkeys = 1;
-
     $self->throw_exception(sprintf "%s for populate slice:\n%s",
-      $tuple_status->[$i][1],
-      Data::Dumper::Dumper(
-        { map { $cols->[$_] => $data->[$i][$_] } (0 .. $#$cols) }
-      ),
+      ($tuple_status->[$i][1] || $err),
+      Data::Dumper::Concise::Dumper({
+        map { $cols->[$_] => $data->[$i][$_] } (0 .. $#$cols)
+      }),
     );
   }
-  $self->throw_exception($sth->errstr) if !$rv;
 
-  $self->_query_end( $sql, @bind );
-  return (wantarray ? ($rv, $sth, @bind) : $rv);
+  $guard->commit if $guard;
+
+  return $rv;
 }
 
+sub _dbh_execute_array {
+    my ($self, $sth, $tuple_status, @extra) = @_;
+
+    return $sth->execute_array({ArrayTupleStatus => $tuple_status});
+}
+
+sub _dbh_execute_inserts_with_no_binds {
+  my ($self, $sth, $count) = @_;
+
+  my $guard = $self->txn_scope_guard unless $self->{transaction_depth} != 0;
+
+  eval {
+    my $dbh = $self->_get_dbh;
+    local $dbh->{RaiseError} = 1;
+    local $dbh->{PrintError} = 0;
+
+    $sth->execute foreach 1..$count;
+  };
+  my $exception = $@;
+
+# Make sure statement is finished even if there was an exception.
+  eval { $sth->finish };
+  $exception = $@ unless $exception;
+
+  $self->throw_exception($exception) if $exception;
+
+  $guard->commit if $guard;
+
+  return $count;
+}
+
 sub update {
   my ($self, $source, @args) = @_; 
 
-# redispatch to update method of storage we reblessed into, if necessary
-  if (not $self->_driver_determined) {
-    $self->_determine_driver;
-    goto $self->can('update');
-  }
-
   my $bind_attributes = $self->source_bind_attributes($source);
 
   return $self->_execute('update' => [], $source, $bind_attributes, @args);
@@ -1421,12 +1558,11 @@
 
 
 sub delete {
-  my $self = shift @_;
-  my $source = shift @_;
-  $self->_determine_driver;
+  my ($self, $source, @args) = @_; 
+
   my $bind_attrs = $self->source_bind_attributes($source);
 
-  return $self->_execute('delete' => [], $source, $bind_attrs, @_);
+  return $self->_execute('delete' => [], $source, $bind_attrs, @args);
 }
 
 # We were sent here because the $rs contains a complex search
@@ -1993,7 +2129,6 @@
   return @pcols ? \@pcols : [ 1 ];
 }
 
-
 sub source_bind_attributes {
   my ($self, $source) = @_;
 
@@ -2227,14 +2362,7 @@
 =cut
 
 sub sqlt_type {
-  my ($self) = @_;
-
-  if (not $self->_driver_determined) {
-    $self->_determine_driver;
-    goto $self->can ('sqlt_type');
-  }
-
-  $self->_get_dbh->{Driver}->{Name};
+  shift->_get_dbh->{Driver}->{Name};
 }
 
 =head2 bind_attribute_by_data_type
@@ -2508,7 +2636,11 @@
     parser => 'SQL::Translator::Parser::DBIx::Class',
     data => $schema,
   );
-  return $tr->translate;
+
+  my $ret = $tr->translate
+    or $self->throw_exception( 'Unable to produce deployment statements: ' . $tr->error);
+
+  return $ret;
 }
 
 sub deploy {
@@ -2574,11 +2706,6 @@
 =cut
 
 sub build_datetime_parser {
-  if (not $_[0]->_driver_determined) {
-    $_[0]->_determine_driver;
-    goto $_[0]->can('build_datetime_parser');
-  }
-
   my $self = shift;
   my $type = $self->datetime_parser_type(@_);
   $self->ensure_class_loaded ($type);
@@ -2611,10 +2738,10 @@
     return;
 }
 
-# SQLT version handling 
+# SQLT version handling
 {
-  my $_sqlt_version_ok;     # private 
-  my $_sqlt_version_error;  # private 
+  my $_sqlt_version_ok;     # private
+  my $_sqlt_version_error;  # private
 
   sub _sqlt_version_ok {
     if (!defined $_sqlt_version_ok) {

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/DBIx/Class.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -341,6 +341,8 @@
 
 Tom Hukins
 
+triode: Pete Gamache <gamache at cpan.org>
+
 typester: Daisuke Murase <typester at cpan.org>
 
 victori: Victor Igumnov <victori at cpan.org>

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/SQL/Translator/Parser/DBIx/Class.pm
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/SQL/Translator/Parser/DBIx/Class.pm	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/lib/SQL/Translator/Parser/DBIx/Class.pm	2009-11-12 01:24:44 UTC (rev 7865)
@@ -184,7 +184,7 @@
                     if ($fk_constraint) {
                         $cascade->{$c} = $rel_info->{attrs}{"on_$c"};
                     }
-                    else {
+                    elsif ( $rel_info->{attrs}{"on_$c"} ) {
                         carp "SQLT attribute 'on_$c' was supplied for relationship '$moniker/$rel', which does not appear to be a foreign constraint. "
                             . "If you are sure that SQLT must generate a constraint for this relationship, add 'is_foreign_key_constraint => 1' to the attributes.\n";
                     }

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/100populate.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/100populate.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/100populate.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -5,9 +5,8 @@
 use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
+use Path::Class::File ();
 
-plan tests => 23;
-
 my $schema = DBICTest->init_schema();
 
 # The map below generates stuff like:
@@ -116,3 +115,205 @@
 is($link7->url, undef, 'Link 7 url');
 is($link7->title, 'gtitle', 'Link 7 title');
 
+my $rs = $schema->resultset('Artist');
+$rs->delete;
+
+# test _execute_array_empty (insert_bulk with all literal sql)
+
+$rs->populate([
+    (+{
+        name => \"'DT'",
+        rank => \500,
+        charfield => \"'mtfnpy'",
+    }) x 5
+]);
+
+is((grep {
+  $_->name eq 'DT' &&
+  $_->rank == 500  &&
+  $_->charfield eq 'mtfnpy'
+} $rs->all), 5, 'populate with all literal SQL');
+
+$rs->delete;
+
+# test mixed binds with literal sql
+
+$rs->populate([
+    (+{
+        name => \"'DT'",
+        rank => 500,
+        charfield => \"'mtfnpy'",
+    }) x 5
+]);
+
+is((grep {
+  $_->name eq 'DT' &&
+  $_->rank == 500  &&
+  $_->charfield eq 'mtfnpy'
+} $rs->all), 5, 'populate with all literal SQL');
+
+$rs->delete;
+
+###
+
+throws_ok {
+    $rs->populate([
+        {
+            artistid => 1,
+            name => 'foo1',
+        },
+        {
+            artistid => 'foo', # this dies
+            name => 'foo2',
+        },
+        {
+            artistid => 3,
+            name => 'foo3',
+        },
+    ]);
+} qr/slice/, 'bad slice';
+
+is($rs->count, 0, 'populate is atomic');
+
+# Trying to use a column marked as a bind in the first slice with literal sql in
+# a later slice should throw.
+
+throws_ok {
+  $rs->populate([
+    {
+      artistid => 1,
+      name => \"'foo'",
+    },
+    {
+      artistid => \2,
+      name => \"'foo'",
+    }
+  ]);
+} qr/bind expected/, 'literal sql where bind expected throws';
+
+# ... and vice-versa.
+
+throws_ok {
+  $rs->populate([
+    {
+      artistid => \1,
+      name => \"'foo'",
+    },
+    {
+      artistid => 2,
+      name => \"'foo'",
+    }
+  ]);
+} qr/literal SQL expected/i, 'bind where literal sql expected throws';
+
+throws_ok {
+  $rs->populate([
+    {
+      artistid => 1,
+      name => \"'foo'",
+    },
+    {
+      artistid => 2,
+      name => \"'bar'",
+    }
+  ]);
+} qr/inconsistent/, 'literal sql must be the same in all slices';
+
+# the stringification has nothing to do with the artist name
+# this is solely for testing consistency
+my $fn = Path::Class::File->new ('somedir/somefilename.tmp');
+my $fn2 = Path::Class::File->new ('somedir/someotherfilename.tmp');
+
+lives_ok {
+  $rs->populate([
+    {
+      name => 'supplied before stringifying object',
+    },
+    {
+      name => $fn,
+    }
+  ]);
+} 'stringifying objects pass through';
+
+# ... and vice-versa.
+
+lives_ok {
+  $rs->populate([
+    {
+      name => $fn2,
+    },
+    {
+      name => 'supplied after stringifying object',
+    },
+  ]);
+} 'stringifying objects pass through';
+
+for (
+  $fn,
+  $fn2,
+  'supplied after stringifying object',
+  'supplied before stringifying object'
+) {
+  my $row = $rs->find ({name => $_});
+  ok ($row, "Stringification test row '$_' properly inserted");
+}
+
+$rs->delete;
+
+# test stringification with ->create rather than Storage::insert_bulk as well
+
+lives_ok {
+  my @dummy = $rs->populate([
+    {
+      name => 'supplied before stringifying object',
+    },
+    {
+      name => $fn,
+    }
+  ]);
+} 'stringifying objects pass through';
+
+# ... and vice-versa.
+
+lives_ok {
+  my @dummy = $rs->populate([
+    {
+      name => $fn2,
+    },
+    {
+      name => 'supplied after stringifying object',
+    },
+  ]);
+} 'stringifying objects pass through';
+
+for (
+  $fn,
+  $fn2,
+  'supplied after stringifying object',
+  'supplied before stringifying object'
+) {
+  my $row = $rs->find ({name => $_});
+  ok ($row, "Stringification test row '$_' properly inserted");
+}
+
+lives_ok {
+   $schema->resultset('TwoKeys')->populate([{
+      artist => 1,
+      cd     => 5,
+      fourkeys_to_twokeys => [{
+            f_foo => 1,
+            f_bar => 1,
+            f_hello => 1,
+            f_goodbye => 1,
+            autopilot => 'a',
+      },{
+            f_foo => 2,
+            f_bar => 2,
+            f_hello => 2,
+            f_goodbye => 2,
+            autopilot => 'b',
+      }]
+   }])
+} 'multicol-PK has_many populate works';
+
+done_testing;

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/60core.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/60core.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/60core.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -65,7 +65,7 @@
 
 is(@art, 2, 'And then there were two');
 
-ok(!$art->in_storage, "It knows it's dead");
+is($art->in_storage, 0, "It knows it's dead");
 
 dies_ok ( sub { $art->delete }, "Can't delete twice");
 
@@ -144,7 +144,7 @@
   });
 
   is($new_obj->name, 'find_or_new', 'find_or_new: instantiated a new artist');
-  ok(! $new_obj->in_storage, 'new artist is not in storage');
+  is($new_obj->in_storage, 0, 'new artist is not in storage');
 }
 
 my $cd = $schema->resultset("CD")->find(1);

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/71mysql.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/71mysql.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/71mysql.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -227,4 +227,14 @@
       => 'Nothing Found!';
 }
 
+
+## If find() is the first query after connect()
+## DBI::Storage::sql_maker() will be called before
+## _determine_driver() and so the ::SQLHacks class for MySQL
+## will not be used
+
+my $schema2 = DBICTest::Schema->connect($dsn, $user, $pass);
+$schema2->resultset("Artist")->find(4);
+isa_ok($schema2->storage->sql_maker, 'DBIx::Class::SQLAHacks::MySQL');
+
 done_testing;

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/72pg.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/72pg.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/72pg.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -472,6 +472,7 @@
 
 my @eapk_schemas;
 BEGIN{ @eapk_schemas = map "dbic_apk_$_", 0..5 }
+my %seqs; #< hash of schema.table.col => currval of its (DBIC) primary key sequence
 
 sub run_extended_apk_tests {
   my $schema = shift;
@@ -489,10 +490,18 @@
         for @eapk_schemas;
 
     $dbh->do("CREATE SEQUENCE $eapk_schemas[5].fooseq");
+    $dbh->do("SELECT setval('$eapk_schemas[5].fooseq',400)");
+    $seqs{"$eapk_schemas[1].apk.id2"} = 400;
+
     $dbh->do("CREATE SEQUENCE $eapk_schemas[4].fooseq");
+    $dbh->do("SELECT setval('$eapk_schemas[4].fooseq',300)");
+    $seqs{"$eapk_schemas[3].apk.id2"} = 300;
+
     $dbh->do("CREATE SEQUENCE $eapk_schemas[3].fooseq");
+    $dbh->do("SELECT setval('$eapk_schemas[3].fooseq',200)");
+    $seqs{"$eapk_schemas[4].apk.id2"} = 200;
 
-    $dbh->do("SET search_path = ".join ',', @eapk_schemas );
+    $dbh->do("SET search_path = ".join ',', reverse @eapk_schemas );
   });
 
   # clear our search_path cache
@@ -519,12 +528,14 @@
                qualify_table => 4,
              );
 
+  eapk_poke( $schema );
   eapk_poke( $schema, 0 );
   eapk_poke( $schema, 2 );
   eapk_poke( $schema, 4 );
   eapk_poke( $schema, 1 );
   eapk_poke( $schema, 0 );
   eapk_poke( $schema, 1 );
+  eapk_poke( $schema );
   eapk_poke( $schema, 4 );
   eapk_poke( $schema, 3 );
   eapk_poke( $schema, 1 );
@@ -538,8 +549,6 @@
 # do a DBIC create on the apk table in the given schema number (which is an
 # index of @eapk_schemas)
 
-my %seqs; #< sanity-check hash of schema.table.col => currval of its sequence
-
 sub eapk_poke {
   my ($s, $schema_num) = @_;
 
@@ -547,7 +556,7 @@
       ? $eapk_schemas[$schema_num]
       : '';
 
-  my $schema_name_actual = $schema_name || eapk_get_search_path($s)->[0];
+  my $schema_name_actual = $schema_name || eapk_find_visible_schema($s);
 
   $s->source('ExtAPK')->name($schema_name ? $schema_name.'.apk' : 'apk');
   #< clear sequence name cache
@@ -558,12 +567,13 @@
   lives_ok {
     my $new;
     for my $inc (1,2,3) {
-      $new = $schema->resultset('ExtAPK')->create({});
+      $new = $schema->resultset('ExtAPK')->create({ id1 => 1});
       my $proper_seqval = ++$seqs{"$schema_name_actual.apk.id2"};
       is( $new->id2, $proper_seqval, "$schema_name_actual.apk.id2 correct inc $inc" )
           or eapk_seq_diag($s,$schema_name);
       $new->discard_changes;
-      for my $id (grep $_ ne 'id2', @eapk_id_columns) {
+      is( $new->id1, 1 );
+      for my $id ('id3','id4') {
         my $proper_seqval = ++$seqs{"$schema_name_actual.apk.$id"};
         is( $new->$id, $proper_seqval, "$schema_name_actual.apk.$id correct inc $inc" )
             or eapk_seq_diag($s,$schema_name);
@@ -577,7 +587,7 @@
 # class
 sub eapk_seq_diag {
     my $s = shift;
-    my $schema = shift || eapk_get_search_path($s)->[0];
+    my $schema = shift || eapk_find_visible_schema($s);
 
     diag "$schema.apk sequences: ",
         join(', ',
@@ -633,13 +643,13 @@
         local $_[1]->{Warn} = 0;
 
         my $id_def = $a{nextval}
-            ? "integer primary key not null default nextval('$a{nextval}'::regclass)"
-            : 'serial primary key';
+            ? "integer not null default nextval('$a{nextval}'::regclass)"
+            : 'serial';
         $dbh->do(<<EOS);
 CREATE TABLE $table_name (
   id1 serial
   , id2 $id_def
-  , id3 serial
+  , id3 serial primary key
   , id4 serial
 )
 EOS
@@ -667,3 +677,19 @@
 
     });
 }
+
+sub eapk_find_visible_schema {
+    my ($s) = @_;
+
+    my ($schema) =
+        $s->storage->dbh_do(sub {
+            $_[1]->selectrow_array(<<EOS);
+SELECT n.nspname
+FROM pg_catalog.pg_namespace n
+JOIN pg_catalog.pg_class c ON c.relnamespace = n.oid
+WHERE c.relname = 'apk'
+  AND pg_catalog.pg_table_is_visible(c.oid)
+EOS
+        });
+    return $schema;
+}

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/73oracle.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/73oracle.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/73oracle.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -26,7 +26,7 @@
 }
 
 use strict;
-use warnings;  
+use warnings;
 
 use Test::Exception;
 use Test::More;
@@ -40,7 +40,7 @@
   ' as well as following sequences: \'pkid1_seq\', \'pkid2_seq\' and \'nonpkid_seq\''
   unless ($dsn && $user && $pass);
 
-plan tests => 35;
+plan tests => 36;
 
 DBICTest::Schema->load_classes('ArtistFQN');
 my $schema = DBICTest::Schema->connect($dsn, $user, $pass);
@@ -49,6 +49,7 @@
 
 eval {
   $dbh->do("DROP SEQUENCE artist_seq");
+  $dbh->do("DROP SEQUENCE cd_seq");
   $dbh->do("DROP SEQUENCE pkid1_seq");
   $dbh->do("DROP SEQUENCE pkid2_seq");
   $dbh->do("DROP SEQUENCE nonpkid_seq");
@@ -58,6 +59,7 @@
   $dbh->do("DROP TABLE track");
 };
 $dbh->do("CREATE SEQUENCE artist_seq START WITH 1 MAXVALUE 999999 MINVALUE 0");
+$dbh->do("CREATE SEQUENCE cd_seq START WITH 1 MAXVALUE 999999 MINVALUE 0");
 $dbh->do("CREATE SEQUENCE pkid1_seq START WITH 1 MAXVALUE 999999 MINVALUE 0");
 $dbh->do("CREATE SEQUENCE pkid2_seq START WITH 10 MAXVALUE 999999 MINVALUE 0");
 $dbh->do("CREATE SEQUENCE nonpkid_seq START WITH 20 MAXVALUE 999999 MINVALUE 0");
@@ -67,6 +69,7 @@
 $dbh->do("CREATE TABLE track (trackid NUMBER(12), cd NUMBER(12), position NUMBER(12), title VARCHAR(255), last_updated_on DATE, last_updated_at DATE, small_dt DATE)");
 
 $dbh->do("ALTER TABLE artist ADD (CONSTRAINT artist_pk PRIMARY KEY (artistid))");
+$dbh->do("ALTER TABLE cd ADD (CONSTRAINT cd_pk PRIMARY KEY (cdid))");
 $dbh->do("ALTER TABLE sequence_test ADD (CONSTRAINT sequence_test_constraint PRIMARY KEY (pkid1, pkid2))");
 $dbh->do(qq{
   CREATE OR REPLACE TRIGGER artist_insert_trg
@@ -80,6 +83,18 @@
     END IF;
   END;
 });
+$dbh->do(qq{
+  CREATE OR REPLACE TRIGGER cd_insert_trg
+  BEFORE INSERT ON cd
+  FOR EACH ROW
+  BEGIN
+    IF :new.cdid IS NULL THEN
+      SELECT cd_seq.nextval
+      INTO :new.cdid
+      FROM DUAL;
+    END IF;
+  END;
+});
 
 {
     # Swiped from t/bindtype_columns.t to avoid creating my own Resultset.
@@ -88,7 +103,7 @@
     eval { $dbh->do('DROP TABLE bindtype_test') };
 
     $dbh->do(qq[
-        CREATE TABLE bindtype_test 
+        CREATE TABLE bindtype_test
         (
             id              integer      NOT NULL   PRIMARY KEY,
             bytea           integer      NULL,
@@ -108,13 +123,15 @@
 my $new = $schema->resultset('Artist')->create({ name => 'foo' });
 is($new->artistid, 1, "Oracle Auto-PK worked");
 
+my $cd = $schema->resultset('CD')->create({ artist => 1, title => 'EP C', year => '2003' });
+is($new->artistid, 1, "Oracle Auto-PK worked - using scalar ref as table name");
+
 # test again with fully-qualified table name
 $new = $schema->resultset('ArtistFQN')->create( { name => 'bar' } );
 is( $new->artistid, 2, "Oracle Auto-PK worked with fully-qualified tablename" );
 
 # test join with row count ambiguity
 
-my $cd = $schema->resultset('CD')->create({ cdid => 1, artist => 1, title => 'EP C', year => '2003' });
 my $track = $schema->resultset('Track')->create({ trackid => 1, cd => 1,
     position => 1, title => 'Track1' });
 my $tjoin = $schema->resultset('Track')->search({ 'me.title' => 'Track1'},
@@ -149,7 +166,7 @@
 
 $tcount = $schema->resultset('Track')->search(
   {},
-  { 
+  {
      group_by => [ qw/position title/ ]
   }
 );
@@ -212,6 +229,7 @@
 END {
     if($schema && ($dbh = $schema->storage->dbh)) {
         $dbh->do("DROP SEQUENCE artist_seq");
+        $dbh->do("DROP SEQUENCE cd_seq");
         $dbh->do("DROP SEQUENCE pkid1_seq");
         $dbh->do("DROP SEQUENCE pkid2_seq");
         $dbh->do("DROP SEQUENCE nonpkid_seq");

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/746mssql.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/746mssql.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/746mssql.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -143,14 +143,11 @@
     my ($storage, $dbh) = @_;
     eval { $dbh->do("DROP TABLE money_test") };
     $dbh->do(<<'SQL');
-
 CREATE TABLE money_test (
    id INT IDENTITY PRIMARY KEY,
    amount MONEY NULL
 )
-
 SQL
-
 });
 
 my $rs = $schema->resultset('Money');

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/746sybase.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/746sybase.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/746sybase.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -1,91 +1,589 @@
 use strict;
-use warnings;
+use warnings;  
+no warnings 'uninitialized';
 
 use Test::More;
 use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
 
+require DBIx::Class::Storage::DBI::Sybase;
+require DBIx::Class::Storage::DBI::Sybase::NoBindVars;
+
 my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_SYBASE_${_}" } qw/DSN USER PASS/};
 
-plan skip_all => 'Set $ENV{DBICTEST_SYBASE_DSN}, _USER and _PASS to run this test'
-  unless ($dsn && $user);
+my $TESTS = 63 + 2;
 
-plan tests => 13;
+if (not ($dsn && $user)) {
+  plan skip_all =>
+    'Set $ENV{DBICTEST_SYBASE_DSN}, _USER and _PASS to run this test' .
+    "\nWarning: This test drops and creates the tables " .
+    "'artist', 'money_test' and 'bindtype_test'";
+} else {
+  plan tests => $TESTS*2 + 1;
+}
 
-my $schema = DBICTest::Schema->connect($dsn, $user, $pass, {AutoCommit => 1});
+my @storage_types = (
+  'DBI::Sybase',
+  'DBI::Sybase::NoBindVars',
+);
+my $schema;
+my $storage_idx = -1;
 
-# start disconnected to test reconnection
-$schema->storage->ensure_connected;
-$schema->storage->_dbh->disconnect;
+sub get_schema {
+  DBICTest::Schema->connect($dsn, $user, $pass, {
+    on_connect_call => [
+      [ blob_setup => log_on_update => 1 ], # this is a safer option
+    ],
+  });
+}
 
-isa_ok( $schema->storage, 'DBIx::Class::Storage::DBI::Sybase' );
+my $ping_count = 0;
+{
+  my $ping = DBIx::Class::Storage::DBI::Sybase->can('_ping');
+  *DBIx::Class::Storage::DBI::Sybase::_ping = sub {
+    $ping_count++;
+    goto $ping;
+  };
+}
 
-my $dbh;
-lives_ok (sub {
-  $dbh = $schema->storage->dbh;
-}, 'reconnect works');
+for my $storage_type (@storage_types) {
+  $storage_idx++;
 
-$schema->storage->dbh_do (sub {
-    my ($storage, $dbh) = @_;
-    eval { $dbh->do("DROP TABLE artist") };
-    $dbh->do(<<'SQL');
+  unless ($storage_type eq 'DBI::Sybase') { # autodetect
+    DBICTest::Schema->storage_type("::$storage_type");
+  }
 
+  $schema = get_schema();
+
+  $schema->storage->ensure_connected;
+
+  if ($storage_idx == 0 &&
+      $schema->storage->isa('DBIx::Class::Storage::DBI::Sybase::NoBindVars')) {
+# no placeholders in this version of Sybase or DBD::Sybase (or using FreeTDS)
+      my $tb = Test::More->builder;
+      $tb->skip('no placeholders') for 1..$TESTS;
+      next;
+  }
+
+  isa_ok( $schema->storage, "DBIx::Class::Storage::$storage_type" );
+
+  $schema->storage->_dbh->disconnect;
+  lives_ok (sub { $schema->storage->dbh }, 'reconnect works');
+
+  $schema->storage->dbh_do (sub {
+      my ($storage, $dbh) = @_;
+      eval { $dbh->do("DROP TABLE artist") };
+      $dbh->do(<<'SQL');
 CREATE TABLE artist (
-   artistid INT IDENTITY NOT NULL,
+   artistid INT IDENTITY PRIMARY KEY,
    name VARCHAR(100),
    rank INT DEFAULT 13 NOT NULL,
-   charfield CHAR(10) NULL,
-   primary key(artistid)
+   charfield CHAR(10) NULL
 )
-
 SQL
+  });
 
-});
+  my %seen_id;
 
-my %seen_id;
+# so we start unconnected
+  $schema->storage->disconnect;
 
-# fresh $schema so we start unconnected
-$schema = DBICTest::Schema->connect($dsn, $user, $pass, {AutoCommit => 1});
-
 # test primary key handling
-my $new = $schema->resultset('Artist')->create({ name => 'foo' });
-ok($new->artistid > 0, "Auto-PK worked");
+  my $new = $schema->resultset('Artist')->create({ name => 'foo' });
+  ok($new->artistid > 0, "Auto-PK worked");
 
-$seen_id{$new->artistid}++;
+  $seen_id{$new->artistid}++;
 
-# test LIMIT support
-for (1..6) {
+# check redispatch to storage-specific insert when auto-detected storage
+  if ($storage_type eq 'DBI::Sybase') {
+    DBICTest::Schema->storage_type('::DBI');
+    $schema = get_schema();
+  }
+
+  $new = $schema->resultset('Artist')->create({ name => 'Artist 1' });
+  is ( $seen_id{$new->artistid}, undef, 'id for Artist 1 is unique' );
+  $seen_id{$new->artistid}++;
+
+# inserts happen in a txn, so we make sure it still works inside a txn too
+  $schema->txn_begin;
+
+  for (2..6) {
     $new = $schema->resultset('Artist')->create({ name => 'Artist ' . $_ });
     is ( $seen_id{$new->artistid}, undef, "id for Artist $_ is unique" );
     $seen_id{$new->artistid}++;
-}
+  }
 
-my $it;
+  $schema->txn_commit;
 
-$it = $schema->resultset('Artist')->search( {}, {
+# test simple count
+  is ($schema->resultset('Artist')->count, 7, 'count(*) of whole table ok');
+
+# test LIMIT support
+  my $it = $schema->resultset('Artist')->search({
+    artistid => { '>' => 0 }
+  }, {
     rows => 3,
     order_by => 'artistid',
-});
+  });
 
-TODO: {
-    local $TODO = 'Sybase is very very fucked in the limit department';
+  is( $it->count, 3, "LIMIT count ok" );
 
-    is( $it->count, 3, "LIMIT count ok" );
-}
+  is( $it->next->name, "foo", "iterator->next ok" );
+  $it->next;
+  is( $it->next->name, "Artist 2", "iterator->next ok" );
+  is( $it->next, undef, "next past end of resultset ok" );
 
-# The iterator still works correctly with rows => 3, even though the sql is
-# fucked, very interesting.
+# now try with offset
+  $it = $schema->resultset('Artist')->search({}, {
+    rows => 3,
+    offset => 3,
+    order_by => 'artistid',
+  });
 
-is( $it->next->name, "foo", "iterator->next ok" );
-$it->next;
-is( $it->next->name, "Artist 2", "iterator->next ok" );
-is( $it->next, undef, "next past end of resultset ok" );
+  is( $it->count, 3, "LIMIT with offset count ok" );
 
+  is( $it->next->name, "Artist 3", "iterator->next ok" );
+  $it->next;
+  is( $it->next->name, "Artist 5", "iterator->next ok" );
+  is( $it->next, undef, "next past end of resultset ok" );
 
+# now try a grouped count
+  $schema->resultset('Artist')->create({ name => 'Artist 6' })
+    for (1..6);
+
+  $it = $schema->resultset('Artist')->search({}, {
+    group_by => 'name'
+  });
+
+  is( $it->count, 7, 'COUNT of GROUP_BY ok' );
+
+# do an IDENTITY_INSERT
+  {
+    no warnings 'redefine';
+
+    my @debug_out;
+    local $schema->storage->{debug} = 1;
+    local $schema->storage->debugobj->{callback} = sub {
+      push @debug_out, $_[1];
+    };
+
+    my $txn_used = 0;
+    my $txn_commit = \&DBIx::Class::Storage::DBI::txn_commit;
+    local *DBIx::Class::Storage::DBI::txn_commit = sub {
+      $txn_used = 1;
+      goto &$txn_commit;
+    };
+
+    $schema->resultset('Artist')
+      ->create({ artistid => 999, name => 'mtfnpy' });
+
+    ok((grep /IDENTITY_INSERT/i, @debug_out), 'IDENTITY_INSERT used');
+
+    SKIP: {
+      skip 'not testing lack of txn on IDENTITY_INSERT with NoBindVars', 1
+        if $storage_type =~ /NoBindVars/i;
+
+      is $txn_used, 0, 'no txn on insert with IDENTITY_INSERT';
+    }
+  }
+
+# do an IDENTITY_UPDATE
+  {
+    my @debug_out;
+    local $schema->storage->{debug} = 1;
+    local $schema->storage->debugobj->{callback} = sub {
+      push @debug_out, $_[1];
+    };
+
+    lives_and {
+      $schema->resultset('Artist')
+        ->find(999)->update({ artistid => 555 });
+      ok((grep /IDENTITY_UPDATE/i, @debug_out));
+    } 'IDENTITY_UPDATE used';
+    $ping_count-- if $@;
+  }
+
+  my $bulk_rs = $schema->resultset('Artist')->search({
+    name => { -like => 'bulk artist %' }
+  });
+
+# test insert_bulk using populate.
+  SKIP: {
+    skip 'insert_bulk not supported', 4
+      unless $storage_type !~ /NoBindVars/i;
+
+    lives_ok {
+      $schema->resultset('Artist')->populate([
+        {
+          name => 'bulk artist 1',
+          charfield => 'foo',
+        },
+        {
+          name => 'bulk artist 2',
+          charfield => 'foo',
+        },
+        {
+          name => 'bulk artist 3',
+          charfield => 'foo',
+        },
+      ]);
+    } 'insert_bulk via populate';
+
+    is $bulk_rs->count, 3, 'correct number inserted via insert_bulk';
+
+    is ((grep $_->charfield eq 'foo', $bulk_rs->all), 3,
+      'column set correctly via insert_bulk');
+
+    my %bulk_ids;
+    @bulk_ids{map $_->artistid, $bulk_rs->all} = ();
+
+    is ((scalar keys %bulk_ids), 3,
+      'identities generated correctly in insert_bulk');
+
+    $bulk_rs->delete;
+  }
+
+# make sure insert_bulk works a second time on the same connection
+  SKIP: {
+    skip 'insert_bulk not supported', 3
+      unless $storage_type !~ /NoBindVars/i;
+
+    lives_ok {
+      $schema->resultset('Artist')->populate([
+        {
+          name => 'bulk artist 1',
+          charfield => 'bar',
+        },
+        {
+          name => 'bulk artist 2',
+          charfield => 'bar',
+        },
+        {
+          name => 'bulk artist 3',
+          charfield => 'bar',
+        },
+      ]);
+    } 'insert_bulk via populate called a second time';
+
+    is $bulk_rs->count, 3,
+      'correct number inserted via insert_bulk';
+
+    is ((grep $_->charfield eq 'bar', $bulk_rs->all), 3,
+      'column set correctly via insert_bulk');
+
+    $bulk_rs->delete;
+  }
+
+# test invalid insert_bulk (missing required column)
+#
+# There should be a rollback, reconnect and the next valid insert_bulk should
+# succeed.
+  throws_ok {
+    $schema->resultset('Artist')->populate([
+      {
+        charfield => 'foo',
+      }
+    ]);
+  } qr/no value or default|does not allow null|placeholders/i,
+# The second pattern is the error from fallback to regular array insert on
+# incompatible charset.
+# The third is for ::NoBindVars with no syb_has_blk.
+  'insert_bulk with missing required column throws error';
+
+# now test insert_bulk with IDENTITY_INSERT
+  SKIP: {
+    skip 'insert_bulk not supported', 3
+      unless $storage_type !~ /NoBindVars/i;
+
+    lives_ok {
+      $schema->resultset('Artist')->populate([
+        {
+          artistid => 2001,
+          name => 'bulk artist 1',
+          charfield => 'foo',
+        },
+        {
+          artistid => 2002,
+          name => 'bulk artist 2',
+          charfield => 'foo',
+        },
+        {
+          artistid => 2003,
+          name => 'bulk artist 3',
+          charfield => 'foo',
+        },
+      ]);
+    } 'insert_bulk with IDENTITY_INSERT via populate';
+
+    is $bulk_rs->count, 3,
+      'correct number inserted via insert_bulk with IDENTITY_INSERT';
+
+    is ((grep $_->charfield eq 'foo', $bulk_rs->all), 3,
+      'column set correctly via insert_bulk with IDENTITY_INSERT');
+
+    $bulk_rs->delete;
+  }
+
+# test correlated subquery
+  my $subq = $schema->resultset('Artist')->search({ artistid => { '>' => 3 } })
+    ->get_column('artistid')
+    ->as_query;
+  my $subq_rs = $schema->resultset('Artist')->search({
+    artistid => { -in => $subq }
+  });
+  is $subq_rs->count, 11, 'correlated subquery';
+
+# mostly stolen from the blob stuff Nniuq wrote for t/73oracle.t
+  SKIP: {
+    skip 'TEXT/IMAGE support does not work with FreeTDS', 22
+      if $schema->storage->using_freetds;
+
+    my $dbh = $schema->storage->_dbh;
+    {
+      local $SIG{__WARN__} = sub {};
+      eval { $dbh->do('DROP TABLE bindtype_test') };
+
+      $dbh->do(qq[
+        CREATE TABLE bindtype_test 
+        (
+          id    INT   IDENTITY PRIMARY KEY,
+          bytea IMAGE NULL,
+          blob  IMAGE NULL,
+          clob  TEXT  NULL
+        )
+      ],{ RaiseError => 1, PrintError => 0 });
+    }
+
+    my %binstr = ( 'small' => join('', map { chr($_) } ( 1 .. 127 )) );
+    $binstr{'large'} = $binstr{'small'} x 1024;
+
+    my $maxloblen = length $binstr{'large'};
+    
+    if (not $schema->storage->using_freetds) {
+      $dbh->{'LongReadLen'} = $maxloblen * 2;
+    } else {
+      $dbh->do("set textsize ".($maxloblen * 2));
+    }
+
+    my $rs = $schema->resultset('BindType');
+    my $last_id;
+
+    foreach my $type (qw(blob clob)) {
+      foreach my $size (qw(small large)) {
+        no warnings 'uninitialized';
+
+        my $created;
+        lives_ok {
+          $created = $rs->create( { $type => $binstr{$size} } )
+        } "inserted $size $type without dying";
+
+        $last_id = $created->id if $created;
+
+        lives_and {
+          ok($rs->find($last_id)->$type eq $binstr{$size})
+        } "verified inserted $size $type";
+      }
+    }
+
+    $rs->delete;
+
+    # blob insert with explicit PK
+    # also a good opportunity to test IDENTITY_INSERT
+    lives_ok {
+      $rs->create( { id => 1, blob => $binstr{large} } )
+    } 'inserted large blob without dying with manual PK';
+
+    lives_and {
+      ok($rs->find(1)->blob eq $binstr{large})
+    } 'verified inserted large blob with manual PK';
+
+    # try a blob update
+    my $new_str = $binstr{large} . 'mtfnpy';
+
+    # check redispatch to storage-specific update when auto-detected storage
+    if ($storage_type eq 'DBI::Sybase') {
+      DBICTest::Schema->storage_type('::DBI');
+      $schema = get_schema();
+    }
+
+    lives_ok {
+      $rs->search({ id => 1 })->update({ blob => $new_str })
+    } 'updated blob successfully';
+
+    lives_and {
+      ok($rs->find(1)->blob eq $new_str)
+    } 'verified updated blob';
+
+    # try a blob update with IDENTITY_UPDATE
+    lives_and {
+      $new_str = $binstr{large} . 'hlagh';
+      $rs->find(1)->update({ id => 999, blob => $new_str });
+      ok($rs->find(999)->blob eq $new_str);
+    } 'verified updated blob with IDENTITY_UPDATE';
+
+    ## try multi-row blob update
+    # first insert some blobs
+    $new_str = $binstr{large} . 'foo';
+    lives_and {
+      $rs->delete;
+      $rs->create({ blob => $binstr{large} }) for (1..2);
+      $rs->update({ blob => $new_str });
+      is((grep $_->blob eq $new_str, $rs->all), 2);
+    } 'multi-row blob update';
+
+    $rs->delete;
+
+    # now try insert_bulk with blobs and only blobs
+    $new_str = $binstr{large} . 'bar';
+    lives_ok {
+      $rs->populate([
+        {
+          bytea => 1,
+          blob => $binstr{large},
+          clob => $new_str,
+        },
+        {
+          bytea => 1,
+          blob => $binstr{large},
+          clob => $new_str,
+        },
+      ]);
+    } 'insert_bulk with blobs does not die';
+
+    is((grep $_->blob eq $binstr{large}, $rs->all), 2,
+      'IMAGE column set correctly via insert_bulk');
+
+    is((grep $_->clob eq $new_str, $rs->all), 2,
+      'TEXT column set correctly via insert_bulk');
+
+    # now try insert_bulk with blobs and a non-blob which also happens to be an
+    # identity column
+    SKIP: {
+      skip 'no insert_bulk without placeholders', 4
+        if $storage_type =~ /NoBindVars/i;
+
+      $rs->delete;
+      $new_str = $binstr{large} . 'bar';
+      lives_ok {
+        $rs->populate([
+          {
+            id => 1,
+            bytea => 1,
+            blob => $binstr{large},
+            clob => $new_str,
+          },
+          {
+            id => 2,
+            bytea => 1,
+            blob => $binstr{large},
+            clob => $new_str,
+          },
+        ]);
+      } 'insert_bulk with blobs and explicit identity does NOT die';
+
+      is((grep $_->blob eq $binstr{large}, $rs->all), 2,
+        'IMAGE column set correctly via insert_bulk with identity');
+
+      is((grep $_->clob eq $new_str, $rs->all), 2,
+        'TEXT column set correctly via insert_bulk with identity');
+
+      is_deeply [ map $_->id, $rs->all ], [ 1,2 ],
+        'explicit identities set correctly via insert_bulk with blobs';
+    }
+
+    lives_and {
+      $rs->delete;
+      $rs->create({ blob => $binstr{large} }) for (1..2);
+      $rs->update({ blob => undef });
+      is((grep !defined($_->blob), $rs->all), 2);
+    } 'blob update to NULL';
+  }
+
+# test MONEY column support (and some other misc. stuff)
+  $schema->storage->dbh_do (sub {
+      my ($storage, $dbh) = @_;
+      eval { $dbh->do("DROP TABLE money_test") };
+      $dbh->do(<<'SQL');
+CREATE TABLE money_test (
+   id INT IDENTITY PRIMARY KEY,
+   amount MONEY DEFAULT $999.99 NULL
+)
+SQL
+  });
+
+  my $rs = $schema->resultset('Money');
+
+# test insert with defaults
+  lives_and {
+    $rs->create({});
+    is((grep $_->amount == 999.99, $rs->all), 1);
+  } 'insert with all defaults works';
+  $rs->delete;
+
+# test insert transaction when there's an active cursor
+  {
+    my $artist_rs = $schema->resultset('Artist');
+    $artist_rs->first;
+    lives_ok {
+      my $row = $schema->resultset('Money')->create({ amount => 100 });
+      $row->delete;
+    } 'inserted a row with an active cursor';
+    $ping_count-- if $@; # dbh_do calls ->connected
+  }
+
+# test insert in an outer transaction when there's an active cursor
+  TODO: {
+    local $TODO = 'this should work once we have eager cursors';
+
+# clear state, or we get a deadlock on $row->delete
+# XXX figure out why this happens
+    $schema->storage->disconnect;
+
+    lives_ok {
+      $schema->txn_do(sub {
+        my $artist_rs = $schema->resultset('Artist');
+        $artist_rs->first;
+        my $row = $schema->resultset('Money')->create({ amount => 100 });
+        $row->delete;
+      });
+    } 'inserted a row with an active cursor in outer txn';
+    $ping_count-- if $@; # dbh_do calls ->connected
+  }
+
+# Now test money values.
+  my $row;
+  lives_ok {
+    $row = $rs->create({ amount => 100 });
+  } 'inserted a money value';
+
+  is eval { $rs->find($row->id)->amount }, 100, 'money value round-trip';
+
+  lives_ok {
+    $row->update({ amount => 200 });
+  } 'updated a money value';
+
+  is eval { $rs->find($row->id)->amount },
+    200, 'updated money value round-trip';
+
+  lives_ok {
+    $row->update({ amount => undef });
+  } 'updated a money value to NULL';
+
+  my $null_amount = eval { $rs->find($row->id)->amount };
+  ok(
+    (($null_amount == undef) && (not $@)),
+    'updated money value to NULL round-trip'
+  );
+  diag $@ if $@;
+}
+
+is $ping_count, 0, 'no pings';
+
 # clean up our mess
 END {
-    my $dbh = eval { $schema->storage->_dbh };
-    $dbh->do('DROP TABLE artist') if $dbh;
+  if (my $dbh = eval { $schema->storage->_dbh }) {
+    eval { $dbh->do("DROP TABLE $_") }
+      for qw/artist bindtype_test money_test/;
+  }
 }
-

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/74mssql.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/74mssql.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/74mssql.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -18,7 +18,7 @@
 plan skip_all => 'Set $ENV{DBICTEST_MSSQL_DSN}, _USER and _PASS to run this test'
   unless ($dsn);
 
-my $TESTS = 15;
+my $TESTS = 18;
 
 plan tests => $TESTS * 2;
 
@@ -145,15 +145,30 @@
     $rs->reset;
   } 'multiple active statements';
 
-  # test multiple active statements in a transaction
-  TODO: {
-    local $TODO = 'needs similar FreeTDS fixes to the ones in Sybase.pm';
-    lives_ok {
-      $schema->txn_do(sub {
-        $rs->create({ amount => 400 });
-      });
-    } 'simple transaction';
-  }
+  $rs->delete;
+
+  # test simple transaction with commit
+  lives_ok {
+    $schema->txn_do(sub {
+      $rs->create({ amount => 400 });
+    });
+  } 'simple transaction';
+
+  cmp_ok $rs->first->amount, '==', 400, 'committed';
+  $rs->reset;
+
+  $rs->delete;
+
+  # test rollback
+  throws_ok {
+    $schema->txn_do(sub {
+      $rs->create({ amount => 400 });
+      die 'mtfnpy';
+    });
+  } qr/mtfnpy/, 'simple failed txn';
+
+  is $rs->first, undef, 'rolled back';
+  $rs->reset;
 }
 
 # clean up our mess

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/79aliasing.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/79aliasing.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/79aliasing.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -52,7 +52,7 @@
   my $cd_rs = $schema->resultset('CD')->search({ 'artist.name' => 'Caterwauler McCrae' }, { join => 'artist' });
 
   my $cd = $cd_rs->find_or_new({ title => 'Huh?', year => 2006 });
-  ok(! $cd->in_storage, 'new CD not in storage yet');
+  is($cd->in_storage, 0, 'new CD not in storage yet');
   is($cd->title, 'Huh?', 'new CD title is correct');
   is($cd->year, 2006, 'new CD year is correct');
 }

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/80unique.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/80unique.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/80unique.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -195,7 +195,7 @@
       { key => 'cd_artist_title' }
     );
 
-    ok(!$cd1->in_storage, 'CD is not in storage yet after update_or_new');
+    is($cd1->in_storage, 0, 'CD is not in storage yet after update_or_new');
     $cd1->insert;
     ok($cd1->in_storage, 'CD got added to strage after update_or_new && insert');
 

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/94versioning.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/94versioning.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/94versioning.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -5,7 +5,6 @@
 use Test::More;
 use File::Spec;
 use File::Copy;
-use Time::HiRes qw/time sleep/;
 
 #warn "$dsn $user $pass";
 my ($dsn, $user, $pass);
@@ -16,6 +15,10 @@
   plan skip_all => 'Set $ENV{DBICTEST_MYSQL_DSN}, _USER and _PASS to run this test'
     unless ($dsn);
 
+  eval { require Time::HiRes }
+    || plan skip_all => 'Test needs Time::HiRes';
+  Time::HiRes->import(qw/time sleep/);
+
   require DBIx::Class::Storage::DBI;
   plan skip_all =>
       'Test needs SQL::Translator ' . DBIx::Class::Storage::DBI->_sqlt_minimum_version

Added: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/inflate/datetime_sybase.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/inflate/datetime_sybase.t	                        (rev 0)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/inflate/datetime_sybase.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -0,0 +1,85 @@
+use strict;
+use warnings;  
+
+use Test::More;
+use Test::Exception;
+use lib qw(t/lib);
+use DBICTest;
+
+my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_SYBASE_${_}" } qw/DSN USER PASS/};
+
+if (not ($dsn && $user)) {
+  plan skip_all =>
+    'Set $ENV{DBICTEST_SYBASE_DSN}, _USER and _PASS to run this test' .
+    "\nWarning: This test drops and creates a table called 'track'";
+} else {
+  eval "use DateTime; use DateTime::Format::Sybase;";
+  if ($@) {
+    plan skip_all => 'needs DateTime and DateTime::Format::Sybase for testing';
+  }
+  else {
+    plan tests => (4 * 2 * 2) + 2; # (tests * dt_types * storage_types) + storage_tests
+  }
+}
+
+my @storage_types = (
+  'DBI::Sybase',
+  'DBI::Sybase::NoBindVars',
+);
+my $schema;
+
+for my $storage_type (@storage_types) {
+  $schema = DBICTest::Schema->clone;
+
+  unless ($storage_type eq 'DBI::Sybase') { # autodetect
+    $schema->storage_type("::$storage_type");
+  }
+  $schema->connection($dsn, $user, $pass, {
+    AutoCommit => 1,
+    on_connect_call => [ 'datetime_setup' ],
+  });
+
+  $schema->storage->ensure_connected;
+
+  isa_ok( $schema->storage, "DBIx::Class::Storage::$storage_type" );
+
+# coltype, col, date
+  my @dt_types = (
+    ['DATETIME', 'last_updated_at', '2004-08-21T14:36:48.080Z'],
+# minute precision
+    ['SMALLDATETIME', 'small_dt', '2004-08-21T14:36:00.000Z'],
+  );
+  
+  for my $dt_type (@dt_types) {
+    my ($type, $col, $sample_dt) = @$dt_type;
+
+    eval { $schema->storage->dbh->do("DROP TABLE track") };
+    $schema->storage->dbh->do(<<"SQL");
+CREATE TABLE track (
+   trackid INT IDENTITY PRIMARY KEY,
+   cd INT,
+   position INT,
+   $col $type,
+)
+SQL
+    ok(my $dt = DateTime::Format::Sybase->parse_datetime($sample_dt));
+
+    my $row;
+    ok( $row = $schema->resultset('Track')->create({
+          $col => $dt,
+          cd => 1,
+        }));
+    ok( $row = $schema->resultset('Track')
+      ->search({ trackid => $row->trackid }, { select => [$col] })
+      ->first
+    );
+    is( $row->$col, $dt, 'DateTime roundtrip' );
+  }
+}
+
+# clean up our mess
+END {
+  if (my $dbh = eval { $schema->storage->_dbh }) {
+    $dbh->do('DROP TABLE track');
+  }
+}

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/inflate/hri.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/inflate/hri.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/inflate/hri.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -1,7 +1,7 @@
 use strict;
-use warnings;  
+use warnings;
 
-use Test::More qw(no_plan);
+use Test::More;
 use lib qw(t/lib);
 use DBICTest;
 my $schema = DBICTest->init_schema();
@@ -9,7 +9,7 @@
 # Under some versions of SQLite if the $rs is left hanging around it will lock
 # So we create a scope here cos I'm lazy
 {
-    my $rs = $schema->resultset('CD');
+    my $rs = $schema->resultset('CD')->search ({}, { order_by => 'cdid' });
 
     # get the defined columns
     my @dbic_cols = sort $rs->result_source->columns;
@@ -23,9 +23,11 @@
     my @hashref_cols = sort keys %$datahashref1;
 
     is_deeply( \@dbic_cols, \@hashref_cols, 'returned columns' );
+
+    my $cd1 = $rs->find ({cdid => 1});
+    is_deeply ( $cd1, $datahashref1, 'first/find return the same thing');
 }
 
-
 sub check_cols_of {
     my ($dbic_obj, $datahashref) = @_;
     
@@ -135,3 +137,5 @@
   [{ $artist->get_columns, cds => [] }],
   'nested has_many prefetch without entries'
 );
+
+done_testing;

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/lib/sqlite.sql
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/lib/sqlite.sql	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/lib/sqlite.sql	2009-11-12 01:24:44 UTC (rev 7865)
@@ -1,7 +1,5 @@
+-- Created on Tue Aug 25 12:34:34 2009
 -- 
--- Created by SQL::Translator::Producer::SQLite
--- Created on Mon Sep 21 00:11:34 2009
--- 
 
 
 BEGIN TRANSACTION;

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/relationship/core.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/relationship/core.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/relationship/core.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -133,7 +133,7 @@
   year => 2007,
 } );
 is( $cd->title, 'Greatest Hits 2: Louder Than Ever', 'find_or_new_related new record ok' );
-ok( ! $cd->in_storage, 'find_or_new_related on a new record: not in_storage' );
+is( $cd->in_storage, 0, 'find_or_new_related on a new record: not in_storage' );
 
 $cd->artist(undef);
 my $newartist = $cd->find_or_new_related( 'artist', {

Added: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/resultset/is_paged.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/resultset/is_paged.t	                        (rev 0)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/resultset/is_paged.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -0,0 +1,19 @@
+use strict;
+use warnings;
+
+use lib qw(t/lib);
+use Test::More;
+use Test::Exception;
+use DBICTest;
+
+my $schema = DBICTest->init_schema();
+
+my $tkfks = $schema->resultset('Artist');
+
+ok !$tkfks->is_paged, 'vanilla resultset is not paginated';
+
+my $paginated = $tkfks->search(undef, { page => 5 });
+ok $paginated->is_paged, 'resultset is paginated now';
+
+done_testing;
+


Property changes on: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/resultset/is_paged.t
___________________________________________________________________
Name: svn:mergeinfo
   + 
Name: svn:eol-style
   + native

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/storage/on_connect_call.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/storage/on_connect_call.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/storage/on_connect_call.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -3,67 +3,96 @@
 no warnings qw/once redefine/;
 
 use lib qw(t/lib);
+use DBI;
 use DBICTest;
+use DBICTest::Schema;
+use DBIx::Class::Storage::DBI;
 
-use Test::More tests => 9;
+# !!! do not replace this with done_testing - tests reside in the callbacks
+# !!! number of calls is important
+use Test::More tests => 16;
+# !!!
 
-use DBIx::Class::Storage::DBI;
-my $schema = DBICTest->init_schema(
-  no_connect  => 1,
-  no_deploy   => 1,
-);
+my $schema = DBICTest::Schema->clone;
 
-local *DBIx::Class::Storage::DBI::connect_call_foo = sub {
-  isa_ok $_[0], 'DBIx::Class::Storage::DBI',
-    'got storage in connect_call method';
-  is $_[1], 'bar', 'got param in connect_call method';
-};
+{
+  *DBIx::Class::Storage::DBI::connect_call_foo = sub {
+    isa_ok $_[0], 'DBIx::Class::Storage::DBI',
+      'got storage in connect_call method';
+    is $_[1], 'bar', 'got param in connect_call method';
+  };
 
-local *DBIx::Class::Storage::DBI::disconnect_call_foo = sub {
-  isa_ok $_[0], 'DBIx::Class::Storage::DBI',
-    'got storage in disconnect_call method';
-};
+  *DBIx::Class::Storage::DBI::disconnect_call_foo = sub {
+    isa_ok $_[0], 'DBIx::Class::Storage::DBI',
+      'got storage in disconnect_call method';
+  };
 
-ok $schema->connection(
-  DBICTest->_database,
-  {
-    on_connect_call => [
-        [ do_sql => 'create table test1 (id integer)' ],
-        [ do_sql => [ 'insert into test1 values (?)', {}, 1 ] ],
-        [ do_sql => sub { ['insert into test1 values (2)'] } ],
-        [ sub { $_[0]->dbh->do($_[1]) }, 'insert into test1 values (3)' ],
-        # this invokes $storage->connect_call_foo('bar') (above)
-        [ foo => 'bar' ],
-    ],
-    on_connect_do => 'insert into test1 values (4)',
-    on_disconnect_call => 'foo',
-  },
-), 'connection()';
+  ok $schema->connection(
+      DBICTest->_database,
+    {
+      on_connect_call => [
+          [ do_sql => 'create table test1 (id integer)' ],
+          [ do_sql => [ 'insert into test1 values (?)', {}, 1 ] ],
+          [ do_sql => sub { ['insert into test1 values (2)'] } ],
+          [ sub { $_[0]->dbh->do($_[1]) }, 'insert into test1 values (3)' ],
+          # this invokes $storage->connect_call_foo('bar') (above)
+          [ foo => 'bar' ],
+      ],
+      on_connect_do => 'insert into test1 values (4)',
+      on_disconnect_call => 'foo',
+    },
+  ), 'connection()';
 
-is_deeply (
-  $schema->storage->dbh->selectall_arrayref('select * from test1'),
-  [ [ 1 ], [ 2 ], [ 3 ], [ 4 ] ],
-  'on_connect_call/do actions worked'
-);
+  ok (! $schema->storage->connected, 'start disconnected');
 
-local *DBIx::Class::Storage::DBI::connect_call_foo = sub {
-  isa_ok $_[0], 'DBIx::Class::Storage::DBI',
-    'got storage in connect_call method';
-};
+  is_deeply (
+    $schema->storage->dbh->selectall_arrayref('select * from test1'),
+    [ [ 1 ], [ 2 ], [ 3 ], [ 4 ] ],
+    'on_connect_call/do actions worked'
+  );
 
-local *DBIx::Class::Storage::DBI::connect_call_bar = sub {
-  isa_ok $_[0], 'DBIx::Class::Storage::DBI',
-    'got storage in connect_call method';
-};
+  $schema->storage->disconnect;
+}
 
-$schema->storage->disconnect;
+{
+  *DBIx::Class::Storage::DBI::connect_call_foo = sub {
+    isa_ok $_[0], 'DBIx::Class::Storage::DBI',
+      'got storage in connect_call method';
+  };
 
-ok $schema->connection(
-  DBICTest->_database,
-  {
-    # method list form
-    on_connect_call => [ 'foo', sub { ok 1, "coderef in list form" }, 'bar' ],
-  },
-), 'connection()';
+  *DBIx::Class::Storage::DBI::connect_call_bar = sub {
+    isa_ok $_[0], 'DBIx::Class::Storage::DBI',
+      'got storage in connect_call method';
+  };
 
-$schema->storage->ensure_connected;
+
+  ok $schema->connection(
+    DBICTest->_database,
+    {
+      # method list form
+      on_connect_call => [ 'foo', sub { ok 1, "coderef in list form" }, 'bar' ],
+    },
+  ), 'connection()';
+
+  ok (! $schema->storage->connected, 'start disconnected');
+  $schema->storage->ensure_connected;
+  $schema->storage->disconnect; # this should not fire any tests
+}
+
+{
+  ok $schema->connection(
+    sub { DBI->connect(DBICTest->_database) },
+    {
+      # method list form
+      on_connect_call => [ sub { ok 1, "on_connect_call after DT parser" }, ],
+      on_disconnect_call => [ sub { ok 1, "on_disconnect_call after DT parser" }, ],
+    },
+  ), 'connection()';
+
+  ok (! $schema->storage->connected, 'start disconnected');
+
+  $schema->storage->_determine_driver;  # this should connect due to the coderef
+
+  ok ($schema->storage->connected, 'determine driver connects');
+  $schema->storage->disconnect;
+}

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/storage/replication.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/storage/replication.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/storage/replication.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -66,7 +66,7 @@
 
     sub init_schema {
         # current SQLT SQLite producer does not handle DROP TABLE IF EXISTS, trap warnings here
-        local $SIG{__WARN__} = sub { warn @_ unless $_[0] =~ /no such table.+DROP TABLE/ };
+        local $SIG{__WARN__} = sub { warn @_ unless $_[0] =~ /no such table.+DROP TABLE/s };
 
         my ($class, $schema_method) = @_;
 

Modified: DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/zzzzzzz_sqlite_deadlock.t
===================================================================
--- DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/zzzzzzz_sqlite_deadlock.t	2009-11-12 01:14:37 UTC (rev 7864)
+++ DBIx-Class/0.08/branches/prefetch_bug-unqualified_column_in_search_related_cond/t/zzzzzzz_sqlite_deadlock.t	2009-11-12 01:24:44 UTC (rev 7865)
@@ -10,7 +10,7 @@
 use DBICTest::Schema;
 
 plan tests => 2;
-my $wait_for = 10;  # how many seconds to wait
+my $wait_for = 30;  # how many seconds to wait
 
 for my $close (0,1) {
 




More information about the Bast-commits mailing list