[Bast-commits] r5322 - in DBIx-Class/0.08/trunk: . lib/DBIx/Class lib/DBIx/Class/Manual lib/DBIx/Class/Storage t t/lib t/lib/DBIC

norbi at dev.catalyst.perl.org norbi at dev.catalyst.perl.org
Sun Jan 18 20:28:21 GMT 2009


Author: norbi
Date: 2009-01-18 20:28:20 +0000 (Sun, 18 Jan 2009)
New Revision: 5322

Added:
   DBIx-Class/0.08/trunk/t/95sql_maker.t
   DBIx-Class/0.08/trunk/t/lib/DBIC/
   DBIx-Class/0.08/trunk/t/lib/DBIC/DebugObj.pm
   DBIx-Class/0.08/trunk/t/lib/DBIC/SqlMakerTest.pm
Modified:
   DBIx-Class/0.08/trunk/
   DBIx-Class/0.08/trunk/Makefile.PL
   DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod
   DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm
   DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm
   DBIx-Class/0.08/trunk/t/19quotes.t
   DBIx-Class/0.08/trunk/t/19quotes_newstyle.t
   DBIx-Class/0.08/trunk/t/41orrible.t
   DBIx-Class/0.08/trunk/t/72pg.t
   DBIx-Class/0.08/trunk/t/76joins.t
   DBIx-Class/0.08/trunk/t/91debug.t
   DBIx-Class/0.08/trunk/t/95sql_maker_quote.t
   DBIx-Class/0.08/trunk/t/99dbic_sqlt_parser.t
Log:
 r5416 at vger:  mendel | 2009-01-18 21:22:05 +0100
  * Merged in changes from the 'sqla_1.50_compat' branch:
    * Converted test cases to use SQL::Abstract::Test if available.
      * created DBIC::SqlMakerTest and DBIC::DebugObj helper modules
      * that way the number of extra parens does not matter
      * test cases still pass with SQLA 1.24, but also with 1.50RC
        * those tests that make no sense with older SQLA are skipped
      * Added dependency for Test::Deep (used when emulating SQL::Abstract::Test::eq_bind when SQLA is older than 1.50)
    * Removed a wrong TODO test: 95sql_maker_quote.t/"order_by with quoting needs fixing (ash/castaway)"
      * it never passed and never will (SQLA should not parse the strings in order_by)
      * asked by mst
    * Made a TODO test non-TODO: 95sql_maker_quote.t/"select attr with star needs fixing (mst/nate)"
      * this works with SQLA 1.50
    * Removed dead code from DBI::Class::Storage::DBI (sub _RowNumberOver).
      * neither DBIC, nor SQLA, nor SQLA::Limit uses this (in any version supported by DBIC)
    * Added test cases for every supported order_by syntax.
    * Made DBIC::SQL::Abstract pass on order_by hashref ({-desc => 'colname'}) to SQL::Abstract.
      * this is the blessed way of doing order by
      * new SQLA supports it
      * formerly DBIC considered this as an error
    * Documented using order_by hashref in DBIx::Class::ResultSet.
    * Added test cases to test if arrayref bind values in insert/update are passed through sql_maker intact.
    * Added test cases to test if arrayref bind values work with a PostgreSQL array type.
    * Added 'array_datatypes' parameter to the sql_maker constructor.
      * formerly SQLA considered these as literal SQL with bind values, now that is \['literal SQL', @bind]
        * the new syntax is consistent (works the same in insert/update and where conditions)
      * fortunately 'array_datatypes' was simply ignored by old SQLA (at least with current version..)
      * DBD::Pg can use arrayref bind values for PostgreSQL array types
    * Documented using PostgreSQL arrays (in Cookbook).
    * Fixed/improved a few skip and diag messages.
 
  r5092 at vger (orig r5091):  norbi | 2008-11-10 21:28:36 +0100
   * Created branch for changes required to make DBIC work with SQL::Abstract 1.50.
  r5101 at vger (orig r5094):  norbi | 2008-11-11 00:04:34 +0100
   r5094 at vger:  mendel | 2008-11-10 23:59:32 +0100
    * Converted some of the test cases to use SQL::Abstract::Test.
    * Added the parens for the join condition (SQL::Abstract::Test can't cope with it, and, besides, they help readability there; plus this gives the same output that older SQLA generated).
  
  r5102 at vger (orig r5095):  norbi | 2008-11-11 00:04:38 +0100
   r5095 at vger:  mendel | 2008-11-11 00:00:18 +0100
    * Removed a wrong TODO test: "order_by with quoting needs fixing (ash/castaway)" (asked by mst).
    * Made a TODO test non-TODO: "select attr with star needs fixing (mst/nate)" (works with SQLA 1.50).
  
  r5103 at vger (orig r5096):  norbi | 2008-11-11 00:04:43 +0100
   r5096 at vger:  mendel | 2008-11-11 00:00:44 +0100
    * Removed dead code (sub _RowNumberOver).
  
  r5128 at vger (orig r5114):  matthewt | 2008-11-12 17:43:54 +0100
   r25478 at agaton (orig r5092):  ribasushi | 2008-11-10 22:46:45 +0000
   Switch out one more reliance on connect_info
   r25483 at agaton (orig r5097):  ribasushi | 2008-11-10 23:09:23 +0000
   belongs_to relationships are explicitly flagged by default, to aid the DBIC SQLT parser (by abraxxa)
   r25484 at agaton (orig r5098):  ribasushi | 2008-11-10 23:18:01 +0000
   Clarify attributes argument of find()
   r25499 at agaton (orig r5113):  plu | 2008-11-12 16:42:44 +0000
   fixed 73oracle.t, added charfield
  
  r5131 at vger (orig r5115):  norbi | 2008-11-13 00:18:05 +0100
   r5130 at vger:  mendel | 2008-11-13 00:13:07 +0100
    * Made DBIC::SQL::Abstract pass on order_by hashref ({-desc => 'colname'}) to SQL::Abstract.
  
  r5133 at vger (orig r5116):  norbi | 2008-11-13 00:23:03 +0100
   r5132 at vger:  mendel | 2008-11-13 00:22:53 +0100
    * Bumped SQL::Abstract version dependency.
  
  r5178 at vger (orig r5148):  norbi | 2008-11-16 22:29:42 +0100
   r5177 at vger:  mendel | 2008-11-16 22:29:33 +0100
    * Added test cases to test if arrayref bind values in insert/update are passed through sql_maker intact.
    * Added 'array_datatypes' parameter to the sql_maker constructor.
  
  r5209 at vger (orig r5172):  norbi | 2008-11-21 17:34:41 +0100
   r5204 at vger:  mendel | 2008-11-21 17:11:16 +0100
    * Test cases for every supported order_by syntax.
  
  r5210 at vger (orig r5173):  norbi | 2008-11-21 17:34:51 +0100
   r5205 at vger:  mendel | 2008-11-21 17:23:05 +0100
    * Documented order_by => [ { -desc => 'col' } ] syntax.
  
  r5211 at vger (orig r5174):  norbi | 2008-11-21 17:34:57 +0100
   r5206 at vger:  mendel | 2008-11-21 17:27:42 +0100
    * Added a WHATSNEW.txt file that summarises the changes on this branch.
  
  r5212 at vger (orig r5175):  norbi | 2008-11-21 17:35:06 +0100
   r5207 at vger:  mendel | 2008-11-21 17:28:58 +0100
    * Updated svn:ignore.
  
  r5213 at vger (orig r5176):  norbi | 2008-11-21 17:35:13 +0100
   r5208 at vger:  mendel | 2008-11-21 17:34:29 +0100
    * Added tests for passing arrayrefs as bind values for PostgreSQL array values.
  
  r5243 at vger (orig r5191):  norbi | 2008-11-25 02:10:43 +0100
   r5227 at vger:  mendel | 2008-11-24 22:03:47 +0100
    * Made PostgreSQL array tests SKIP if SQLA version < 1.50.
  
  r5244 at vger (orig r5192):  norbi | 2008-11-25 02:10:49 +0100
   r5228 at vger:  mendel | 2008-11-24 22:13:10 +0100
    * Disabled stringification of arrayref bind values (used to pass values for PostgreSQL arrays).
  
  r5245 at vger (orig r5193):  norbi | 2008-11-25 02:10:54 +0100
   r5229 at vger:  mendel | 2008-11-24 22:23:16 +0100
    * Made some more tests SKIP if SQLA version < 1.50.
  
  r5246 at vger (orig r5194):  norbi | 2008-11-25 02:10:59 +0100
   r5230 at vger:  mendel | 2008-11-24 22:34:29 +0100
    * Added a test for arrayref bind values in search to match PostgreSQL array type values.
  
  r5247 at vger (orig r5195):  norbi | 2008-11-25 02:11:07 +0100
   r5231 at vger:  mendel | 2008-11-24 22:38:08 +0100
    * Fixed the test plan in 72pg.t.
    * Fixed SQLA version check in SKIP tests (it's 1.49 in current 1.50RC branch).
  
  r5248 at vger (orig r5196):  norbi | 2008-11-25 02:11:13 +0100
   r5232 at vger:  mendel | 2008-11-24 22:58:38 +0100
    * Documented using PostgreSQL arrays in Cookbook.
  
  r5249 at vger (orig r5197):  norbi | 2008-11-25 02:11:22 +0100
   r5235 at vger:  mendel | 2008-11-25 00:32:57 +0100
    * Wrapped SQL::Abstract::Test functionality in a new module (DBIC::SqlMakerTest).
    * Made a test SKIP that does not work with SQL::Abstract < 1.49 (used to be a TODO test).
  
  r5250 at vger (orig r5198):  norbi | 2008-11-25 02:11:29 +0100
   r5236 at vger:  mendel | 2008-11-25 00:34:15 +0100
    * Fixed the number of tests skipped in a SKIP block.
  
  r5251 at vger (orig r5199):  norbi | 2008-11-25 02:11:36 +0100
   r5237 at vger:  mendel | 2008-11-25 00:50:05 +0100
    * Renamed DBICTest::DBICDebugObj to DBIC::DebugObj.
  
  r5252 at vger (orig r5200):  norbi | 2008-11-25 02:11:41 +0100
   r5238 at vger:  mendel | 2008-11-25 00:52:01 +0100
    * Undid bumping of SQL::Abstract version dependency.
  
  r5253 at vger (orig r5201):  norbi | 2008-11-25 02:11:46 +0100
   r5239 at vger:  mendel | 2008-11-25 00:55:43 +0100
    * Fixed the order of args of skip().
  
  r5268 at vger (orig r5209):  norbi | 2008-11-26 22:09:07 +0100
   r5267 at vger:  mendel | 2008-11-26 22:07:01 +0100
    * Removed extra parens from the ON expression of JOIN (SQLA::Test now handles it properly - in SQLA branch '1.50_RC-extraparens' branch). That means that all the tests pass with SQLA 1.24 and SQLA 1.50RC.
  
  r5282 at vger (orig r5216):  norbi | 2008-11-27 00:04:52 +0100
   r5281 at vger:  mendel | 2008-11-27 00:04:40 +0100
    * Replaced eq_bind() implementation with the current copy from SQL::Abstract::Test.
  
  r5288 at vger (orig r5219):  norbi | 2008-11-28 09:43:48 +0100
   r5287 at vger:  mendel | 2008-11-28 09:43:36 +0100
    * Replaced eq_bind() implementation to use Test::Deep::eq_deeply().
  
  r5343 at vger (orig r5262):  norbi | 2008-12-20 22:47:16 +0100
   r5341 at vger:  mendel | 2008-12-20 22:33:26 +0100
    * Updated WHATSNEW.txt.
  
  r5345 at vger (orig r5263):  norbi | 2008-12-20 23:13:55 +0100
   r5344 at vger:  mendel | 2008-12-20 23:13:22 +0100
    * Removed hiding of packages under t/.
  
  r5347 at vger (orig r5264):  norbi | 2008-12-20 23:43:41 +0100
   r5346 at vger:  mendel | 2008-12-20 23:43:37 +0100
    * Removed hiding of packages under t/.
  
  r5349 at vger (orig r5265):  norbi | 2008-12-20 23:44:47 +0100
   r5348 at vger:  mendel | 2008-12-20 23:44:42 +0100
    * Removed an outdated comment.
  
  r5352 at vger (orig r5267):  ribasushi | 2008-12-21 09:26:19 +0100
  Fix ordering of 'use lib' and 'use' in tests
  r5353 at vger (orig r5268):  ribasushi | 2008-12-21 09:45:25 +0100
  whops
  r5356 at vger (orig r5271):  ribasushi | 2008-12-21 12:25:37 +0100
  Remove some cruft
  r5415 at vger (orig r5321):  norbi | 2009-01-18 21:15:24 +0100
   r5414 at vger:  mendel | 2009-01-18 21:15:15 +0100
    * Removed temporary notes file (WHATSNEW.txt).



Property changes on: DBIx-Class/0.08/trunk
___________________________________________________________________
Name: svn:ignore
   - _build
blib
pm_to_blib
Build
Build.bat
Makefile
inc
README
META.yml

   + _build
blib
pm_to_blib
Build
Build.bat
Makefile
Makefile.old
inc
README
META.yml

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/resultsetcolumn_custom_columns:5160
4d5fae46-8e6a-4e08-abee-817e9fb894a2:/local/bast/DBIx-Class/0.08/trunk:5391
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
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:2798
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/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
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_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/storage-ms-access:4142
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:/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/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:5416
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
bd5ac9a7-f185-4d95-9186-dbb8b392a572:/local/os/bast/DBIx-Class/0.08/trunk:2798
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/complex_join_rels:4589
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/file_column:3920
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_sequence:4173
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/parser_fk_index:4485
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/replication_dedux:4600
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/savepoints:4223
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/versioned_enhancements:4125
bd8105ee-0ff8-0310-8827-fb3f25b6796d:/DBIx-Class/0.08/branches/versioning:4578
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/trunk/Makefile.PL
===================================================================
--- DBIx-Class/0.08/trunk/Makefile.PL	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/Makefile.PL	2009-01-18 20:28:20 UTC (rev 5322)
@@ -33,6 +33,7 @@
 test_requires 'Test::Builder'       => 0.33;
 test_requires 'Test::Warn'          => 0.11;
 test_requires 'Test::Exception'     => 0;
+test_requires 'Test::Deep'          => 0;
 
 install_script 'script/dbicadmin';
 

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/Manual/Cookbook.pod	2009-01-18 20:28:20 UTC (rev 5322)
@@ -1298,6 +1298,40 @@
 The limit dialect can also be set at connect time by specifying a 
 C<limit_dialect> key in the final hash as shown above.
 
+=head2 Working with PostgreSQL array types
+
+If your SQL::Abstract version (>= 1.50) supports it, you can assign to
+PostgreSQL array values by passing array references in the C<\%columns>
+(C<\%vals>) hashref of the L<DBIx::Class::ResultSet/create> and
+L<DBIx::Class::Row/update> family of methods:
+
+  $resultset->create({
+    numbers => [1, 2, 3]
+  });
+
+  $row->update(
+    {
+      numbers => [1, 2, 3]
+    },
+    {
+      day => '2008-11-24'
+    }
+  );
+
+In conditions (eg. C<\%cond> in the L<DBIx::Class::ResultSet/search> family of
+methods) you cannot directly use array references (since this is interpreted as
+a list of values to be C<OR>ed), but you can use the following syntax to force
+passing them as bind values:
+
+  $resultset->search(
+    {
+      numbers => \[ '= ?', [1, 2, 3] ]
+    }
+  );
+
+See L<SQL::Abstract/array_datatypes> and L<SQL::Abstract/Literal SQL with
+placeholders and bind values (subqueries)> for more explanation.
+
 =head1 BOOTSTRAPPING/MIGRATING 
 
 =head2 Easy migration from class-based to schema-based setup

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/ResultSet.pm	2009-01-18 20:28:20 UTC (rev 5322)
@@ -2418,6 +2418,10 @@
 specify an order. (The scalar ref causes it to be passed as raw sql to the DB,
 so you will need to manually quote things as appropriate.)
 
+If your L<SQL::Abstract> version supports it (>=1.50), you can also use
+C<{-desc => 'year'}>, which takes care of the quoting for you. This is the
+recommended syntax.
+
 =head2 columns
 
 =over 4

Modified: DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm
===================================================================
--- DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/lib/DBIx/Class/Storage/DBI.pm	2009-01-18 20:28:20 UTC (rev 5322)
@@ -50,27 +50,6 @@
   $self;
 }
 
-sub _RowNumberOver {
-  my ($self, $sql, $order, $rows, $offset ) = @_;
-
-  $offset += 1;
-  my $last = $rows + $offset;
-  my ( $order_by ) = $self->_order_by( $order );
-
-  $sql = <<"";
-SELECT * FROM
-(
-   SELECT Q1.*, ROW_NUMBER() OVER( ) AS ROW_NUM FROM (
-      $sql
-      $order_by
-   ) Q1
-) Q2
-WHERE ROW_NUM BETWEEN $offset AND $last
-
-  return $sql;
-}
-
-
 # While we're at it, this should make LIMIT queries more efficient,
 #  without digging into things too deeply
 use Scalar::Util 'blessed';
@@ -182,6 +161,9 @@
     if (defined $_[0]->{order_by}) {
       $ret .= $self->_order_by($_[0]->{order_by});
     }
+    if (grep { $_ =~ /^-(desc|asc)/i } keys %{$_[0]}) {
+      return $self->SUPER::_order_by($_[0]);
+    }
   } elsif (ref $_[0] eq 'SCALAR') {
     $ret = $self->_sqlcase(' order by ').${ $_[0] };
   } elsif (ref $_[0] eq 'ARRAY' && @{$_[0]}) {
@@ -880,7 +862,7 @@
 sub _sql_maker_args {
     my ($self) = @_;
     
-    return ( bindtype=>'columns', limit_dialect => $self->dbh, %{$self->_sql_maker_opts} );
+    return ( bindtype=>'columns', array_datatypes => 1, limit_dialect => $self->dbh, %{$self->_sql_maker_opts} );
 }
 
 sub sql_maker {
@@ -1221,7 +1203,8 @@
     }
 
     foreach my $data (@data) {
-      $data = ref $data ? ''.$data : $data; # stringify args
+      my $ref = ref $data;
+      $data = $ref && $ref ne 'ARRAY' ? ''.$data : $data; # stringify args (except arrayrefs)
 
       $sth->bind_param($placeholder_index, $data, $attributes);
       $placeholder_index++;

Modified: DBIx-Class/0.08/trunk/t/19quotes.t
===================================================================
--- DBIx-Class/0.08/trunk/t/19quotes.t	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/t/19quotes.t	2009-01-18 20:28:20 UTC (rev 5322)
@@ -4,29 +4,28 @@
 use Test::More;
 use IO::File;
 
+use lib qw(t/lib);
+use DBIC::SqlMakerTest;
+
 BEGIN {
     eval "use DBD::SQLite";
     plan $@
         ? ( skip_all => 'needs DBD::SQLite for testing' )
-        : ( tests => 6 );
+        : ( tests => 7 );
 }
 
-use lib qw(t/lib);
 
 use_ok('DBICTest');
+use_ok('DBIC::DebugObj');
 my $schema = DBICTest->init_schema();
 
-my $orig_debugcb = $schema->storage->debugcb;
-my $orig_debug = $schema->storage->debug;
-
 diag('Testing against ' . join(' ', map { $schema->storage->dbh->get_info($_) } qw/17 18/));
 
 $schema->storage->sql_maker->quote_char('`');
 $schema->storage->sql_maker->name_sep('.');
 
-my $sql = '';
-
-$schema->storage->debugcb(sub { $sql = $_[1] });
+my ($sql, @bind) = ('');
+$schema->storage->debugobj(DBIC::DebugObj->new(\$sql, \@bind));
 $schema->storage->debug(1);
 
 my $rs;
@@ -35,7 +34,11 @@
            { 'me.year' => 2001, 'artist.name' => 'Caterwauler McCrae' },
            { join => 'artist' });
 eval { $rs->count };
-like($sql, qr/\QSELECT COUNT( * ) FROM `cd` `me`  JOIN `artist` `artist` ON ( `artist`.`artistid` = `me`.`artist` ) WHERE ( `artist`.`name` = ? AND `me`.`year` = ? )\E/, 'got correct SQL for count query with quoting');
+is_same_sql_bind(
+  $sql, \@bind,
+  "SELECT COUNT( * ) FROM `cd` `me`  JOIN `artist` `artist` ON ( `artist`.`artistid` = `me`.`artist` ) WHERE ( `artist`.`name` = ? AND `me`.`year` = ? )", ["'Caterwauler McCrae'", "'2001'"],
+  'got correct SQL for count query with quoting'
+);
 
 my $order = 'year DESC';
 $rs = $schema->resultset('CD')->search({},
@@ -55,7 +58,11 @@
            { 'me.year' => 2001, 'artist.name' => 'Caterwauler McCrae' },
            { join => 'artist' });
 eval { $rs->count };
-like($sql, qr/\QSELECT COUNT( * ) FROM [cd] [me]  JOIN [artist] [artist] ON ( [artist].[artistid] = [me].[artist] ) WHERE ( [artist].[name] = ? AND [me].[year] = ? )\E/, 'got correct SQL for count query with bracket quoting');
+is_same_sql_bind(
+  $sql, \@bind,
+  "SELECT COUNT( * ) FROM [cd] [me]  JOIN [artist] [artist] ON ( [artist].[artistid] = [me].[artist] ) WHERE ( [artist].[name] = ? AND [me].[year] = ? )", ["'Caterwauler McCrae'", "'2001'"],
+  'got correct SQL for count query with bracket quoting'
+);
 
 my %data = (
        name => 'Bill',
@@ -66,6 +73,3 @@
 $schema->storage->sql_maker->name_sep('.');
 
 is($schema->storage->sql_maker->update('group', \%data), 'UPDATE `group` SET `name` = ?, `order` = ?', 'quoted table names for UPDATE');
-
-$schema->storage->debugcb($orig_debugcb);
-$schema->storage->debug($orig_debug);

Modified: DBIx-Class/0.08/trunk/t/19quotes_newstyle.t
===================================================================
--- DBIx-Class/0.08/trunk/t/19quotes_newstyle.t	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/t/19quotes_newstyle.t	2009-01-18 20:28:20 UTC (rev 5322)
@@ -4,21 +4,21 @@
 use Test::More;
 use IO::File;
 
+use lib qw(t/lib);
+use DBIC::SqlMakerTest;
+
 BEGIN {
     eval "use DBD::SQLite";
     plan $@
         ? ( skip_all => 'needs DBD::SQLite for testing' )
-        : ( tests => 6 );
+        : ( tests => 7 );
 }
 
-use lib qw(t/lib);
+use_ok('DBICTest');
+use_ok('DBIC::DebugObj');
 
-use_ok('DBICTest');
 my $schema = DBICTest->init_schema();
 
-my $orig_debugcb = $schema->storage->debugcb;
-my $orig_debug = $schema->storage->debug;
-
 diag('Testing against ' . join(' ', map { $schema->storage->dbh->get_info($_) } qw/17 18/));
 
 my $dsn = $schema->storage->_dbi_connect_info->[0];
@@ -30,8 +30,8 @@
   { quote_char => '`', name_sep => '.' },
 );
 
-my $sql = '';
-$schema->storage->debugcb(sub { $sql = $_[1] });
+my ($sql, @bind) = ('');
+$schema->storage->debugobj(DBIC::DebugObj->new(\$sql, \@bind)),
 $schema->storage->debug(1);
 
 my $rs;
@@ -40,7 +40,11 @@
            { 'me.year' => 2001, 'artist.name' => 'Caterwauler McCrae' },
            { join => 'artist' });
 eval { $rs->count };
-like($sql, qr/\QSELECT COUNT( * ) FROM `cd` `me`  JOIN `artist` `artist` ON ( `artist`.`artistid` = `me`.`artist` ) WHERE ( `artist`.`name` = ? AND `me`.`year` = ? )\E/, 'got correct SQL for count query with quoting');
+is_same_sql_bind(
+  $sql, \@bind,
+  "SELECT COUNT( * ) FROM `cd` `me`  JOIN `artist` `artist` ON ( `artist`.`artistid` = `me`.`artist` ) WHERE ( `artist`.`name` = ? AND `me`.`year` = ? )", ["'Caterwauler McCrae'", "'2001'"],
+  'got correct SQL for count query with quoting'
+);
 
 my $order = 'year DESC';
 $rs = $schema->resultset('CD')->search({},
@@ -59,14 +63,19 @@
   undef,
   { AutoCommit => 1, quote_char => [qw/[ ]/], name_sep => '.' }
 );
-$schema->storage->debugcb(sub { $sql = $_[1] });
+
+$schema->storage->debugobj(DBIC::DebugObj->new(\$sql, \@bind)),
 $schema->storage->debug(1);
 
 $rs = $schema->resultset('CD')->search(
            { 'me.year' => 2001, 'artist.name' => 'Caterwauler McCrae' },
            { join => 'artist' });
 eval { $rs->count };
-like($sql, qr/\QSELECT COUNT( * ) FROM [cd] [me]  JOIN [artist] [artist] ON ( [artist].[artistid] = [me].[artist] ) WHERE ( [artist].[name] = ? AND [me].[year] = ? )\E/, 'got correct SQL for count query with bracket quoting');
+is_same_sql_bind(
+  $sql, \@bind,
+  "SELECT COUNT( * ) FROM [cd] [me]  JOIN [artist] [artist] ON ( [artist].[artistid] = [me].[artist] ) WHERE ( [artist].[name] = ? AND [me].[year] = ? )", ["'Caterwauler McCrae'", "'2001'"],
+  'got correct SQL for count query with bracket quoting'
+);
 
 my %data = (
        name => 'Bill',
@@ -81,6 +90,3 @@
 );
 
 is($schema->storage->sql_maker->update('group', \%data), 'UPDATE `group` SET `name` = ?, `order` = ?', 'quoted table names for UPDATE');
-
-$schema->storage->debugcb($orig_debugcb);
-$schema->storage->debug($orig_debug);

Modified: DBIx-Class/0.08/trunk/t/41orrible.t
===================================================================
--- DBIx-Class/0.08/trunk/t/41orrible.t	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/t/41orrible.t	2009-01-18 20:28:20 UTC (rev 5322)
@@ -2,9 +2,11 @@
 use warnings;
 
 use Test::More;
-#use DBIx::Class::Storage::DBI;
 use DBIx::Class::Storage::DBI::Oracle::WhereJoins;
 
+use lib qw(t/lib);
+use DBIC::SqlMakerTest;
+
 plan tests => 4;
 
 my $sa = new DBIC::SQL::Abstract::Oracle;
@@ -29,7 +31,8 @@
 # search with undefined or empty $cond
 
 #  my ($self, $table, $fields, $where, $order, @rest) = @_;
-is($sa->select([
+my ($sql, @bind) = $sa->select(
+    [
         { me => "cd" },
         [
             { "-join_type" => "LEFT", artist => "artist" },
@@ -38,10 +41,16 @@
     ],
     [ 'cd.cdid', 'cd.artist', 'cd.title', 'cd.year', 'artist.artistid', 'artist.name' ],
     undef,
-    undef),
-   'SELECT cd.cdid, cd.artist, cd.title, cd.year, artist.artistid, artist.name FROM cd me, artist artist WHERE ( artist.artistid(+) = me.artist )', 'WhereJoins search with empty where clause');
+    undef
+);
+is_same_sql_bind(
+  $sql, \@bind,
+  'SELECT cd.cdid, cd.artist, cd.title, cd.year, artist.artistid, artist.name FROM cd me, artist artist WHERE ( artist.artistid(+) = me.artist )', [],
+  'WhereJoins search with empty where clause'
+);
 
-is($sa->select([
+($sql, @bind) = $sa->select(
+    [
         { me => "cd" },
         [
             { "-join_type" => "", artist => "artist" },
@@ -50,10 +59,16 @@
     ],
     [ 'cd.cdid', 'cd.artist', 'cd.title', 'cd.year', 'artist.artistid', 'artist.name' ],
     { 'artist.artistid' => 3 },
-    undef),
-   'SELECT cd.cdid, cd.artist, cd.title, cd.year, artist.artistid, artist.name FROM cd me, artist artist WHERE ( ( ( artist.artistid = me.artist ) AND ( artist.artistid = ? ) ) )', 'WhereJoins search with where clause');
+    undef
+);
+is_same_sql_bind(
+  $sql, \@bind,
+  'SELECT cd.cdid, cd.artist, cd.title, cd.year, artist.artistid, artist.name FROM cd me, artist artist WHERE ( ( ( artist.artistid = me.artist ) AND ( artist.artistid = ? ) ) )', [3],
+  'WhereJoins search with where clause'
+);
 
-is($sa->select([
+($sql, @bind) = $sa->select(
+    [
         { me => "cd" },
         [
             { "-join_type" => "LEFT", artist => "artist" },
@@ -62,7 +77,12 @@
     ],
     [ 'cd.cdid', 'cd.artist', 'cd.title', 'cd.year', 'artist.artistid', 'artist.name' ],
     [{ 'artist.artistid' => 3 }, { 'me.cdid' => 5 }],
-    undef),
-   'SELECT cd.cdid, cd.artist, cd.title, cd.year, artist.artistid, artist.name FROM cd me, artist artist WHERE ( ( ( artist.artistid(+) = me.artist ) AND ( ( ( artist.artistid = ? ) OR ( me.cdid = ? ) ) ) ) )', 'WhereJoins search with or in where clause');
+    undef
+);
+is_same_sql_bind(
+  $sql, \@bind,
+  'SELECT cd.cdid, cd.artist, cd.title, cd.year, artist.artistid, artist.name FROM cd me, artist artist WHERE ( ( ( artist.artistid(+) = me.artist ) AND ( ( ( artist.artistid = ? ) OR ( me.cdid = ? ) ) ) ) )', [3, 5],
+  'WhereJoins search with or in where clause'
+);
 
 

Modified: DBIx-Class/0.08/trunk/t/72pg.t
===================================================================
--- DBIx-Class/0.08/trunk/t/72pg.t	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/t/72pg.t	2009-01-18 20:28:20 UTC (rev 5322)
@@ -2,6 +2,7 @@
 use warnings;  
 
 use Test::More;
+use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
 
@@ -13,23 +14,42 @@
   use base 'DBIx::Class';
 
   __PACKAGE__->load_components(qw/Core/);
-  __PACKAGE__->table('casecheck');
+  __PACKAGE__->table('testschema.casecheck');
   __PACKAGE__->add_columns(qw/id name NAME uc_name/);
   __PACKAGE__->column_info_from_storage(1);
   __PACKAGE__->set_primary_key('id');
 
 }
 
+{
+  package DBICTest::Schema::ArrayTest;
+
+  use strict;
+  use warnings;
+  use base 'DBIx::Class';
+
+  __PACKAGE__->load_components(qw/Core/);
+  __PACKAGE__->table('testschema.array_test');
+  __PACKAGE__->add_columns(qw/id arrayfield/);
+  __PACKAGE__->column_info_from_storage(1);
+  __PACKAGE__->set_primary_key('id');
+
+}
+
 my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_PG_${_}" } qw/DSN USER PASS/};
 
 #warn "$dsn $user $pass";
 
-plan skip_all => 'Set $ENV{DBICTEST_PG_DSN}, _USER and _PASS to run this test'
- . ' (note: creates and drops tables named artist and casecheck!)' unless ($dsn && $user);
+plan skip_all => 'Set $ENV{DBICTEST_PG_DSN}, _USER and _PASS to run this test '.
+  '(note: This test drops and creates tables called \'artist\', \'casecheck\', \'array_test\' and \'sequence_test\''.
+  ' as well as following sequences: \'pkid1_seq\', \'pkid2_seq\' and \'nonpkid_seq\''.
+  ' as well as following schemas: \'testschema\'!)'
+    unless ($dsn && $user && $pass);
 
-plan tests => 32;
 
-DBICTest::Schema->load_classes( 'Casecheck' );
+plan tests => 37;
+
+DBICTest::Schema->load_classes( 'Casecheck', 'ArrayTest' );
 my $schema = DBICTest::Schema->connect($dsn, $user, $pass);
 
 # Check that datetime_parser returns correctly before we explicitly connect.
@@ -50,12 +70,13 @@
 {
     local $SIG{__WARN__} = sub {};
     $dbh->do("CREATE SCHEMA testschema;");
-    $dbh->do("CREATE TABLE testschema.artist (artistid serial PRIMARY KEY, name VARCHAR(100), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10));");
+    $dbh->do("CREATE TABLE testschema.artist (artistid serial PRIMARY KEY, name VARCHAR(100), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10), arrayfield INTEGER[]);");
     $dbh->do("CREATE TABLE testschema.sequence_test (pkid1 integer, pkid2 integer, nonpkid integer, name VARCHAR(100), CONSTRAINT pk PRIMARY KEY(pkid1, pkid2));");
     $dbh->do("CREATE SEQUENCE pkid1_seq START 1 MAXVALUE 999999 MINVALUE 0");
     $dbh->do("CREATE SEQUENCE pkid2_seq START 10 MAXVALUE 999999 MINVALUE 0");
     $dbh->do("CREATE SEQUENCE nonpkid_seq START 20 MAXVALUE 999999 MINVALUE 0");
     ok ( $dbh->do('CREATE TABLE testschema.casecheck (id serial PRIMARY KEY, "name" VARCHAR(1), "NAME" VARCHAR(2), "UC_NAME" VARCHAR(3));'), 'Creation of casecheck table');
+    ok ( $dbh->do('CREATE TABLE testschema.array_test (id serial PRIMARY KEY, arrayfield INTEGER[]);'), 'Creation of array_test table');
 }
 
 # This is in Core now, but it's here just to test that it doesn't break
@@ -94,6 +115,12 @@
         'size' => 10,
         'default_value' => undef,
     },
+    'arrayfield' => {
+        'data_type' => 'integer[]',
+        'is_nullable' => 1,
+        'size' => undef,
+        'default_value' => undef,
+    },
 };
 
 
@@ -105,6 +132,36 @@
 is_deeply($type_info, $test_type_info,
           'columns_info_for - column data types');
 
+SKIP: {
+  skip "SQL::Abstract < 1.49 does not pass through arrayrefs", 4
+    if $SQL::Abstract::VERSION < 1.49;
+
+  lives_ok {
+    $schema->resultset('ArrayTest')->create({
+      arrayfield => [1, 2],
+    });
+  } 'inserting arrayref as pg array data';
+
+  lives_ok {
+    $schema->resultset('ArrayTest')->update({
+      arrayfield => [3, 4],
+    });
+  } 'updating arrayref as pg array data';
+
+  $schema->resultset('ArrayTest')->create({
+    arrayfield => [5, 6],
+  });
+
+  my $count;
+  lives_ok {
+    $count = $schema->resultset('ArrayTest')->search({
+      arrayfield => \[ '= ?' => [3, 4] ],   #TODO anything less ugly than this?
+    })->count;
+  } 'comparing arrayref to pg array data does not blow up';
+  is($count, 1, 'comparing arrayref to pg array data gives correct result');
+}
+
+
 my $name_info = $schema->source('Casecheck')->column_info( 'name' );
 is( $name_info->{size}, 1, "Case sensitive matching info for 'name'" );
 
@@ -210,6 +267,7 @@
         $dbh->do("DROP TABLE testschema.artist;");
         $dbh->do("DROP TABLE testschema.casecheck;");
         $dbh->do("DROP TABLE testschema.sequence_test;");
+        $dbh->do("DROP TABLE testschema.array_test;");
         $dbh->do("DROP SEQUENCE pkid1_seq");
         $dbh->do("DROP SEQUENCE pkid2_seq");
         $dbh->do("DROP SEQUENCE nonpkid_seq");

Modified: DBIx-Class/0.08/trunk/t/76joins.t
===================================================================
--- DBIx-Class/0.08/trunk/t/76joins.t	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/t/76joins.t	2009-01-18 20:28:20 UTC (rev 5322)
@@ -5,6 +5,7 @@
 use lib qw(t/lib);
 use DBICTest;
 use Data::Dumper;
+use DBIC::SqlMakerTest;
 
 my $schema = DBICTest->init_schema();
 
@@ -43,7 +44,11 @@
           . 'child.father_id ) JOIN person mother ON ( mother.person_id '
           . '= child.mother_id )'
           ;
-is( $sa->_recurse_from(@j), $match, 'join 1 ok' );
+is_same_sql_bind(
+  $sa->_recurse_from(@j), [],
+  $match, [],
+  'join 1 ok'
+);
 
 my @j2 = (
     { mother => 'person' },
@@ -59,8 +64,13 @@
        . ' father.person_id = child.father_id )) ON ( mother.person_id = '
        . 'child.mother_id )'
        ;
-is( $sa->_recurse_from(@j2), $match, 'join 2 ok' );
+is_same_sql_bind(
+  $sa->_recurse_from(@j2), [],
+  $match, [],
+  'join 2 ok'
+);
 
+
 my @j3 = (
     { child => 'person' },
     [ { father => 'person', -join_type => 'inner' }, { 'father.person_id' => 'child.father_id' }, ],
@@ -71,7 +81,11 @@
           . '= child.mother_id )'
           ;
 
-is( $sa->_recurse_from(@j3), $match, 'join 3 (inner join) ok');
+is_same_sql_bind(
+  $sa->_recurse_from(@j3), [],
+  $match, [],
+  'join 3 (inner join) ok'
+);
 
 my @j4 = (
     { mother => 'person' },
@@ -87,7 +101,11 @@
        . ' father.person_id = child.father_id )) ON ( mother.person_id = '
        . 'child.mother_id )'
        ;
-is( $sa->_recurse_from(@j4), $match, 'join 4 (nested joins + join types) ok');
+is_same_sql_bind(
+  $sa->_recurse_from(@j4), [],
+  $match, [],
+  'join 4 (nested joins + join types) ok'
+);
 
 my @j5 = (
     { child => 'person' },
@@ -98,7 +116,11 @@
           . 'child.father_id ) JOIN person mother ON ( mother.person_id '
           . '= child.mother_id )'
           ;
-is( $sa->_recurse_from(@j5), $match, 'join 5 (SCALAR reference for ON statement) ok' );
+is_same_sql_bind(
+  $sa->_recurse_from(@j5), [],
+  $match, [],
+  'join 5 (SCALAR reference for ON statement) ok'
+);
 
 my @j6 = (
     { child => 'person' },

Modified: DBIx-Class/0.08/trunk/t/91debug.t
===================================================================
--- DBIx-Class/0.08/trunk/t/91debug.t	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/t/91debug.t	2009-01-18 20:28:20 UTC (rev 5322)
@@ -4,10 +4,12 @@
 use Test::More;
 use lib qw(t/lib);
 use DBICTest;
+use DBIC::DebugObj;
+use DBIC::SqlMakerTest;
 
 my $schema = DBICTest->init_schema();
 
-plan tests => 6;
+plan tests => 7;
 
 ok ( $schema->storage->debug(1), 'debug' );
 ok ( defined(
@@ -49,15 +51,24 @@
 
 # test trace output correctness for bind params
 {
-    my $sql = '';
+    my ($sql, @bind) = ('');
     $schema->storage->debugcb( sub { $sql = $_[1] } );
 
     my @cds = $schema->resultset('CD')->search( { artist => 1, cdid => { -between => [ 1, 3 ] }, } );
-    like(
-        $sql,
-        qr/\QSELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE ( artist = ? AND cdid BETWEEN ? AND ? ): '1', '1', '3'\E/,
-        'got correct SQL with all bind parameters'
+    is_same_sql_bind(
+        $sql, [],
+        "SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE ( artist = ? AND cdid BETWEEN ? AND ? ): '1', '1', '3'", [],
+        'got correct SQL with all bind parameters (debugcb)'
     );
+
+    $schema->storage->debugcb(undef);
+    $schema->storage->debugobj(DBIC::DebugObj->new(\$sql, \@bind));
+    @cds = $schema->resultset('CD')->search( { artist => 1, cdid => { -between => [ 1, 3 ] }, } );
+    is_same_sql_bind(
+        $sql, \@bind,
+        "SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE ( artist = ? AND cdid BETWEEN ? AND ? )", ["'1'", "'1'", "'3'"],
+        'got correct SQL with all bind parameters (debugobj)'
+    );
 }
 
 1;

Added: DBIx-Class/0.08/trunk/t/95sql_maker.t
===================================================================
--- DBIx-Class/0.08/trunk/t/95sql_maker.t	                        (rev 0)
+++ DBIx-Class/0.08/trunk/t/95sql_maker.t	2009-01-18 20:28:20 UTC (rev 5322)
@@ -0,0 +1,57 @@
+use strict;
+use warnings;
+
+use Test::More;
+
+use lib qw(t/lib);
+use DBIC::SqlMakerTest;
+
+BEGIN {
+    eval "use DBD::SQLite";
+    plan $@
+        ? ( skip_all => 'needs DBD::SQLite for testing' )
+        : ( tests => 3 );
+}
+
+use_ok('DBICTest');
+
+my $schema = DBICTest->init_schema();
+
+my $sql_maker = $schema->storage->sql_maker;
+
+
+SKIP: {
+  skip "SQL::Abstract < 1.49 does not pass through arrayrefs", 2
+    if $SQL::Abstract::VERSION < 1.49;
+
+  my ($sql, @bind) = $sql_maker->insert(
+            'lottery',
+            {
+              'day' => '2008-11-16',
+              'numbers' => [13, 21, 34, 55, 89]
+            }
+  );
+
+  is_same_sql_bind(
+    $sql, \@bind,
+    q/INSERT INTO lottery (day, numbers) VALUES (?, ?)/,
+      [ ['day' => '2008-11-16'], ['numbers' => [13, 21, 34, 55, 89]] ],
+    'sql_maker passes arrayrefs in insert'
+  );
+
+
+  ($sql, @bind) = $sql_maker->update(
+            'lottery',
+            {
+              'day' => '2008-11-16',
+              'numbers' => [13, 21, 34, 55, 89]
+            }
+  );
+
+  is_same_sql_bind(
+    $sql, \@bind,
+    q/UPDATE lottery SET day = ?, numbers = ?/,
+      [ ['day' => '2008-11-16'], ['numbers' => [13, 21, 34, 55, 89]] ],
+    'sql_maker passes arrayrefs in update'
+  );
+}

Modified: DBIx-Class/0.08/trunk/t/95sql_maker_quote.t
===================================================================
--- DBIx-Class/0.08/trunk/t/95sql_maker_quote.t	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/t/95sql_maker_quote.t	2009-01-18 20:28:20 UTC (rev 5322)
@@ -3,16 +3,16 @@
 
 use Test::More;
 
+use lib qw(t/lib);
+use DBIC::SqlMakerTest;
 
 BEGIN {
     eval "use DBD::SQLite";
     plan $@
         ? ( skip_all => 'needs DBD::SQLite for testing' )
-        : ( tests => 8 );
+        : ( tests => 12 );
 }
 
-use lib qw(t/lib);
-
 use_ok('DBICTest');
 
 my $schema = DBICTest->init_schema();
@@ -22,7 +22,7 @@
 $sql_maker->quote_char('`');
 $sql_maker->name_sep('.');
 
-my ($sql,) = $sql_maker->select(
+my ($sql, @bind) = $sql_maker->select(
           [
             {
               'me' => 'cd'
@@ -51,11 +51,14 @@
           undef
 );
 
-is($sql, 
-   q/SELECT COUNT( * ) FROM `cd` `me`  JOIN `artist` `artist` ON ( `artist`.`artistid` = `me`.`artist` ) WHERE ( `artist`.`name` = ? AND `me`.`year` = ? )/, 
-   'got correct SQL for count query with quoting');
+is_same_sql_bind(
+  $sql, \@bind,
+  q/SELECT COUNT( * ) FROM `cd` `me`  JOIN `artist` `artist` ON ( `artist`.`artistid` = `me`.`artist` ) WHERE ( `artist`.`name` = ? AND `me`.`year` = ? )/, [ ['artist.name' => 'Caterwauler McCrae'], ['me.year' => 2001] ],
+  'got correct SQL and bind parameters for count query with quoting'
+);
 
-($sql,) = $sql_maker->select(
+
+($sql, @bind) = $sql_maker->select(
           [
             {
               'me' => 'cd'
@@ -68,43 +71,130 @@
             'me.year'
           ],
           undef,
+          'year DESC',
+          undef,
+          undef
+);
+
+is_same_sql_bind(
+  $sql, \@bind,
+  q/SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year` FROM `cd` `me` ORDER BY `year DESC`/, [],
+  'scalar ORDER BY okay (single value)'
+);
+
+
+($sql, @bind) = $sql_maker->select(
           [
-            'year DESC'
+            {
+              'me' => 'cd'
+            }
           ],
+          [
+            'me.cdid',
+            'me.artist',
+            'me.title',
+            'me.year'
+          ],
           undef,
+          [
+            'year DESC',
+            'title ASC'
+          ],
+          undef,
           undef
 );
 
-TODO: {
-    local $TODO = "order_by with quoting needs fixing (ash/castaway)";
+is_same_sql_bind(
+  $sql, \@bind,
+  q/SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year` FROM `cd` `me` ORDER BY `year DESC`, `title ASC`/, [],
+  'scalar ORDER BY okay (multiple values)'
+);
 
-    is($sql, 
-       q/SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year` FROM `cd` `me` ORDER BY `year` DESC/, 
-       'quoted ORDER BY with DESC okay');
+SKIP: {
+  skip "SQL::Abstract < 1.49 does not support hashrefs in order_by", 2
+    if $SQL::Abstract::VERSION < 1.49;
+
+  ($sql, @bind) = $sql_maker->select(
+            [
+              {
+                'me' => 'cd'
+              }
+            ],
+            [
+              'me.cdid',
+              'me.artist',
+              'me.title',
+              'me.year'
+            ],
+            undef,
+            { -desc => 'year' },
+            undef,
+            undef
+  );
+
+  is_same_sql_bind(
+    $sql, \@bind,
+    q/SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year` FROM `cd` `me` ORDER BY `year` DESC/, [],
+    'hashref ORDER BY okay (single value)'
+  );
+
+
+  ($sql, @bind) = $sql_maker->select(
+            [
+              {
+                'me' => 'cd'
+              }
+            ],
+            [
+              'me.cdid',
+              'me.artist',
+              'me.title',
+              'me.year'
+            ],
+            undef,
+            [
+              { -desc => 'year' },
+              { -asc => 'title' }
+            ],
+            undef,
+            undef
+  );
+
+  is_same_sql_bind(
+    $sql, \@bind,
+    q/SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year` FROM `cd` `me` ORDER BY `year` DESC, `title` ASC/, [],
+    'hashref ORDER BY okay (multiple values)'
+  );
+
 }
 
-TODO: {
-    local $TODO = "select attr with star needs fixing (mst/nate)";
 
-    ($sql,) = $sql_maker->select(
+($sql, @bind) = $sql_maker->select(
           [
             {
               'me' => 'cd'
             }
           ],
           [
-            'me.*'
+            'me.cdid',
+            'me.artist',
+            'me.title',
+            'me.year'
           ],
           undef,
-          [],
+          \'year DESC',
           undef,
-          undef    
-    );
+          undef
+);
 
-    is($sql, q/SELECT `me`.* FROM `cd` `me`/, 'select attr with me.* is right');
-}
+is_same_sql_bind(
+  $sql, \@bind,
+  q/SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year` FROM `cd` `me` ORDER BY year DESC/, [],
+  'did not quote ORDER BY with scalarref (single value)'
+);
 
-($sql,) = $sql_maker->select(
+
+($sql, @bind) = $sql_maker->select(
           [
             {
               'me' => 'cd'
@@ -118,24 +208,21 @@
           ],
           undef,
           [
-            \'year DESC'
+            \'year DESC',
+            \'title ASC'
           ],
           undef,
           undef
 );
 
-is($sql, 
-   q/SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year` FROM `cd` `me` ORDER BY year DESC/,
-   'did not quote ORDER BY with scalarref');
-
-my %data = ( 
-    name => 'Bill',
-    order => 12
+is_same_sql_bind(
+  $sql, \@bind,
+  q/SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year` FROM `cd` `me` ORDER BY year DESC, title ASC/, [],
+  'did not quote ORDER BY with scalarref (multiple values)'
 );
 
-my @binds;
 
-($sql, at binds) = $sql_maker->update(
+($sql, @bind) = $sql_maker->update(
           'group',
           {
             'order' => '12',
@@ -143,13 +230,42 @@
           }
 );
 
-is($sql,
-   q/UPDATE `group` SET `name` = ?, `order` = ?/,
-   'quoted table names for UPDATE');
+is_same_sql_bind(
+  $sql, \@bind,
+  q/UPDATE `group` SET `name` = ?, `order` = ?/, [ ['name' => 'Bill'], ['order' => '12'] ],
+  'quoted table names for UPDATE'
+);
 
+SKIP: {
+  skip "select attr with star does not work in SQL::Abstract < 1.49", 1
+    if $SQL::Abstract::VERSION < 1.49;
+
+  ($sql, @bind) = $sql_maker->select(
+        [
+          {
+            'me' => 'cd'
+          }
+        ],
+        [
+          'me.*'
+        ],
+        undef,
+        [],
+        undef,
+        undef    
+  );
+
+  is_same_sql_bind(
+    $sql, \@bind,
+    q/SELECT `me`.* FROM `cd` `me`/, [],
+    'select attr with me.* is right'
+  );
+}
+
+
 $sql_maker->quote_char([qw/[ ]/]);
 
-($sql,) = $sql_maker->select(
+($sql, @bind) = $sql_maker->select(
           [
             {
               'me' => 'cd'
@@ -178,12 +294,14 @@
           undef
 );
 
-is($sql,
-   q/SELECT COUNT( * ) FROM [cd] [me]  JOIN [artist] [artist] ON ( [artist].[artistid] = [me].[artist] ) WHERE ( [artist].[name] = ? AND [me].[year] = ? )/,
-   'got correct SQL for count query with bracket quoting');
+is_same_sql_bind(
+  $sql, \@bind,
+  q/SELECT COUNT( * ) FROM [cd] [me]  JOIN [artist] [artist] ON ( [artist].[artistid] = [me].[artist] ) WHERE ( [artist].[name] = ? AND [me].[year] = ? )/, [ ['artist.name' => 'Caterwauler McCrae'], ['me.year' => 2001] ],
+  'got correct SQL and bind parameters for count query with bracket quoting'
+);
 
 
-($sql, at binds) = $sql_maker->update(
+($sql, @bind) = $sql_maker->update(
           'group',
           {
             'order' => '12',
@@ -191,6 +309,8 @@
           }
 );
 
-is($sql,
-   q/UPDATE [group] SET [name] = ?, [order] = ?/,
-   'bracket quoted table names for UPDATE');
+is_same_sql_bind(
+  $sql, \@bind,
+  q/UPDATE [group] SET [name] = ?, [order] = ?/, [ ['name' => 'Bill'], ['order' => '12'] ],
+  'bracket quoted table names for UPDATE'
+);

Modified: DBIx-Class/0.08/trunk/t/99dbic_sqlt_parser.t
===================================================================
--- DBIx-Class/0.08/trunk/t/99dbic_sqlt_parser.t	2009-01-18 20:15:24 UTC (rev 5321)
+++ DBIx-Class/0.08/trunk/t/99dbic_sqlt_parser.t	2009-01-18 20:28:20 UTC (rev 5322)
@@ -9,7 +9,7 @@
 BEGIN {
     eval "use DBD::mysql; use SQL::Translator 0.09;";
     if ($@) {
-        plan skip_all => 'needs SQL::Translator 0.09 for testing';
+        plan skip_all => 'needs DBD::mysql and SQL::Translator 0.09 for testing';
     }
 }
 

Added: DBIx-Class/0.08/trunk/t/lib/DBIC/DebugObj.pm
===================================================================
--- DBIx-Class/0.08/trunk/t/lib/DBIC/DebugObj.pm	                        (rev 0)
+++ DBIx-Class/0.08/trunk/t/lib/DBIC/DebugObj.pm	2009-01-18 20:28:20 UTC (rev 5322)
@@ -0,0 +1,50 @@
+package DBIC::DebugObj;
+
+use strict;
+use warnings;
+
+use Class::C3;
+
+use base qw/DBIx::Class::Storage::Statistics Exporter Class::Accessor::Fast/;
+
+__PACKAGE__->mk_accessors( qw/dbictest_sql_ref dbictest_bind_ref/ );
+
+
+=head2 new(PKG, SQL_REF, BIND_REF, ...)
+
+Creates a new instance that on subsequent queries will store
+the generated SQL to the scalar pointed to by SQL_REF and bind
+values to the array pointed to by BIND_REF.
+
+=cut
+
+sub new {
+  my $pkg = shift;
+  my $sql_ref = shift;
+  my $bind_ref = shift;
+
+  my $self = $pkg->SUPER::new(@_);
+
+  $self->debugfh(undef);
+
+  $self->dbictest_sql_ref($sql_ref);
+  $self->dbictest_bind_ref($bind_ref);
+
+  return $self;
+}
+
+sub query_start {
+  my $self = shift;
+
+  (${$self->dbictest_sql_ref}, @{$self->dbictest_bind_ref}) = @_;
+}
+
+sub query_end { }
+
+sub txn_start { }
+
+sub txn_commit { }
+
+sub txn_rollback { }
+
+1;


Property changes on: DBIx-Class/0.08/trunk/t/lib/DBIC/DebugObj.pm
___________________________________________________________________
Name: svn:eol-style
   + native

Added: DBIx-Class/0.08/trunk/t/lib/DBIC/SqlMakerTest.pm
===================================================================
--- DBIx-Class/0.08/trunk/t/lib/DBIC/SqlMakerTest.pm	                        (rev 0)
+++ DBIx-Class/0.08/trunk/t/lib/DBIC/SqlMakerTest.pm	2009-01-18 20:28:20 UTC (rev 5322)
@@ -0,0 +1,160 @@
+package DBIC::SqlMakerTest;
+
+use strict;
+use warnings;
+
+use base qw/Test::Builder::Module Exporter/;
+
+our @EXPORT = qw/
+  &is_same_sql_bind
+  &eq_sql
+  &eq_bind
+/;
+
+
+{
+  package DBIC::SqlMakerTest::SQLATest;
+
+  # replacement for SQL::Abstract::Test if not available
+
+  use strict;
+  use warnings;
+
+  use base qw/Test::Builder::Module Exporter/;
+
+  use Scalar::Util qw(looks_like_number blessed reftype);
+  use Data::Dumper;
+  use Test::Builder;
+  use Test::Deep qw(eq_deeply);
+
+  our $tb = __PACKAGE__->builder;
+
+  sub is_same_sql_bind
+  {
+    my ($sql1, $bind_ref1, $sql2, $bind_ref2, $msg) = @_;
+
+    my $same_sql = eq_sql($sql1, $sql2);
+    my $same_bind = eq_bind($bind_ref1, $bind_ref2);
+
+    $tb->ok($same_sql && $same_bind, $msg);
+
+    if (!$same_sql) {
+      $tb->diag("SQL expressions differ\n"
+        . "     got: $sql1\n"
+        . "expected: $sql2\n"
+      );
+    }
+    if (!$same_bind) {
+      $tb->diag("BIND values differ\n"
+        . "     got: " . Dumper($bind_ref1)
+        . "expected: " . Dumper($bind_ref2)
+      );
+    }
+  }
+
+  sub eq_sql
+  {
+    my ($left, $right) = @_;
+
+    $left =~ s/\s+//g;
+    $right =~ s/\s+//g;
+
+    return $left eq $right;
+  }
+
+  sub eq_bind
+  {
+    my ($bind_ref1, $bind_ref2) = @_;
+
+    return eq_deeply($bind_ref1, $bind_ref2);
+  }
+}
+
+eval "use SQL::Abstract::Test;";
+if ($@ eq '') {
+  # SQL::Abstract::Test available
+
+  *is_same_sql_bind = \&SQL::Abstract::Test::is_same_sql_bind;
+  *eq_sql = \&SQL::Abstract::Test::eq_sql;
+  *eq_bind = \&SQL::Abstract::Test::eq_bind;
+} else {
+  # old SQL::Abstract
+
+  *is_same_sql_bind = \&DBIC::SqlMakerTest::SQLATest::is_same_sql_bind;
+  *eq_sql = \&DBIC::SqlMakerTest::SQLATest::eq_sql;
+  *eq_bind = \&DBIC::SqlMakerTest::SQLATest::eq_bind;
+}
+
+
+1;
+
+__END__
+
+
+=head1 NAME
+
+DBIC::SqlMakerTest - Helper package for testing sql_maker component of DBIC
+
+=head1 SYNOPSIS
+
+  use Test::More;
+  use DBIC::SqlMakerTest;
+  
+  my ($sql, @bind) = $schema->storage->sql_maker->select(%args);
+  is_same_sql_bind(
+    $sql, \@bind, 
+    $expected_sql, \@expected_bind,
+    'foo bar works'
+  );
+
+=head1 DESCRIPTION
+
+Exports functions that can be used to compare generated SQL and bind values.
+
+If L<SQL::Abstract::Test> (packaged in L<SQL::Abstract> versions 1.50 and
+above) is available, then it is used to perform the comparisons (all functions
+are delegated to id). Otherwise uses simple string comparison for the SQL
+statements and simple L<Data::Dumper>-like recursive stringification for
+comparison of bind values.
+
+
+=head1 FUNCTIONS
+
+=head2 is_same_sql_bind
+
+  is_same_sql_bind(
+    $given_sql, \@given_bind, 
+    $expected_sql, \@expected_bind,
+    $test_msg
+  );
+
+Compares given and expected pairs of C<($sql, \@bind)>, and calls
+L<Test::Builder/ok> on the result, with C<$test_msg> as message.
+
+=head2 eq_sql
+
+  my $is_same = eq_sql($given_sql, $expected_sql);
+
+Compares the two SQL statements. Returns true IFF they are equivalent.
+
+=head2 eq_bind
+
+  my $is_same = eq_sql(\@given_bind, \@expected_bind);
+
+Compares two lists of bind values. Returns true IFF their values are the same.
+
+
+=head1 SEE ALSO
+
+L<SQL::Abstract::Test>, L<Test::More>, L<Test::Builder>.
+
+=head1 AUTHOR
+
+Norbert Buchmuller, <norbi at nix.hu>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2008 by Norbert Buchmuller.
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself. 


Property changes on: DBIx-Class/0.08/trunk/t/lib/DBIC/SqlMakerTest.pm
___________________________________________________________________
Name: svn:eol-style
   + native




More information about the Bast-commits mailing list