home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 June / ENTER.ISO / files / xampp-win32-1.4.5-installer.exe / xampp / MDB_usage_testcase.php < prev    next >
Encoding:
PHP Script  |  2004-03-24  |  44.8 KB  |  1,075 lines

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP Version 4                                                        |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1998-2004 Manuel Lemos, Paul Cooper                    |
  6. // | All rights reserved.                                                 |
  7. // +----------------------------------------------------------------------+
  8. // | MDB is a merge of PEAR DB and Metabases that provides a unified DB   |
  9. // | API as well as database abstraction for PHP applications.            |
  10. // | This LICENSE is in the BSD license style.                            |
  11. // |                                                                      |
  12. // | Redistribution and use in source and binary forms, with or without   |
  13. // | modification, are permitted provided that the following conditions   |
  14. // | are met:                                                             |
  15. // |                                                                      |
  16. // | Redistributions of source code must retain the above copyright       |
  17. // | notice, this list of conditions and the following disclaimer.        |
  18. // |                                                                      |
  19. // | Redistributions in binary form must reproduce the above copyright    |
  20. // | notice, this list of conditions and the following disclaimer in the  |
  21. // | documentation and/or other materials provided with the distribution. |
  22. // |                                                                      |
  23. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  24. // | Lukas Smith nor the names of his contributors may be used to endorse |
  25. // | or promote products derived from this software without specific prior|
  26. // | written permission.                                                  |
  27. // |                                                                      |
  28. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  29. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  30. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  31. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  32. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  33. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  34. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  35. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  36. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  37. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  38. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  39. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  40. // +----------------------------------------------------------------------+
  41. // | Author: Paul Cooper <pgc@ucecom.com>                                 |
  42. // +----------------------------------------------------------------------+
  43. //
  44. // $Id: MDB_usage_testcase.php,v 1.28.4.8 2004/01/08 13:43:00 lsmith Exp $
  45.  
  46. class MDB_Usage_TestCase extends PHPUnit_TestCase {
  47.     //contains the dsn of the database we are testing
  48.     var $dsn;
  49.     //contains the options that should be used during testing
  50.     var $options;
  51.     //contains the name of the database we are testing
  52.     var $database;
  53.     //contains the MDB object of the db once we have connected
  54.     var $db;
  55.     // contains field names from the test table
  56.     var $fields;
  57.     // contains the types of the fields from the test table
  58.     var $types;
  59.  
  60.     function MDB_Usage_TestCase($name) {
  61.         $this->PHPUnit_TestCase($name);
  62.     }
  63.  
  64.     function setUp() {
  65.         $this->dsn      = $GLOBALS['dsn'];
  66.         $this->options  = $GLOBALS['options'];
  67.         $this->database = $GLOBALS['database'];
  68.         $this->db =& MDB::connect($this->dsn, $this->options);
  69.         if (MDB::isError($this->db)) {
  70.             $this->assertTrue(false, 'Could not connect to database in setUp');
  71.             exit;
  72.         }
  73.         $this->db->setDatabase($this->database);
  74.         $this->fields = array(
  75.                         'user_name',
  76.                         'user_password',
  77.                         'subscribed',
  78.                         'user_id',
  79.                         'quota',
  80.                         'weight',
  81.                         'access_date',
  82.                         'access_time',
  83.                         'approved'
  84.                     );
  85.         $this->types = array(
  86.                         'text',
  87.                         'text',
  88.                         'boolean',
  89.                         'integer',
  90.                         'decimal',
  91.                         'float',
  92.                         'date',
  93.                         'time',
  94.                         'timestamp'
  95.                     );
  96.         $this->clearTables();
  97.     }
  98.  
  99.     function tearDown() {
  100.         $this->clearTables();
  101.         unset($this->dsn);
  102.         if (!MDB::isError($this->db)) {
  103.             $this->db->disconnect();
  104.         }
  105.         unset($this->db);
  106.     }
  107.  
  108.     function methodExists($name) {
  109.         if (array_key_exists(strtolower($name), array_flip(get_class_methods($this->db)))) {
  110.             return true;
  111.         }
  112.         $this->assertTrue(false, 'method '. $name.' not implemented in '.get_class($this->db));
  113.         return false;
  114.     }
  115.  
  116.     function clearTables() {
  117.         if (MDB::isError($this->db->query('DELETE FROM users'))) {
  118.             $this->assertTrue(false, 'Error deleting from table users');
  119.         }
  120.         if (MDB::isError($this->db->query('DELETE FROM files'))) {
  121.             $this->assertTrue(false, 'Error deleting from table users');
  122.         }
  123.     }
  124.  
  125.     function supported($feature) {
  126.         if (!$this->db->support($feature)) {
  127.             $this->assertTrue(false, 'This database does not support '.$feature);
  128.             return false;
  129.         }
  130.         return true;
  131.     }
  132.  
  133.     function insertTestValues($prepared_query, &$data) {
  134.         for ($i = 0; $i < count($this->fields); $i++) {
  135.             $func = 'setParam'.$this->types[$i];
  136.             $this->db->$func($prepared_query, ($i + 1), $data[$this->fields[$i]]);
  137.         }
  138.     }
  139.  
  140.     function verifyFetchedValues(&$result, $rownum, &$data) {
  141.         $row = $this->db->fetchInto($result, $rownum);
  142.         for ($i = 0; $i < count($this->fields); $i++) {
  143.             $type = $this->types[$i];
  144.             if ($this->types[$i] == 'float') {
  145.                 $delta = 0.0000000001;
  146.             } else {
  147.                 $delta = 0;
  148.             }
  149.             $value = $row[$i];
  150.             $field = $this->fields[$i];
  151.             $this->assertEquals($value, $data[$field], "the value retrieved for field \"$field\" ($value) using type $type doesn't match what was stored ($data[$field]).", $delta);
  152.         }
  153.     }
  154.  
  155.     /**
  156.      * Test typed data storage and retrieval
  157.      *
  158.      * This tests typed data storage and retrieval by executing a single
  159.      * prepared query and then selecting the data back from the database
  160.      * and comparing the results
  161.      */
  162.     function testStorage() {
  163.         $row = 1234;
  164.         $data = array();
  165.         $data['user_name'] = "user_$row";
  166.         $data['user_password'] = 'somepassword';
  167.         $data['subscribed'] = (boolean)($row % 2);
  168.         $data['user_id'] = $row;
  169.         $data['quota'] = strval($row/100);
  170.         $data['weight'] = sqrt($row);
  171.         $data['access_date'] = MDB_Date::mdbToday();
  172.         $data['access_time'] = MDB_Date::mdbTime();
  173.         $data['approved'] = MDB_Date::mdbNow();
  174.  
  175.         $prepared_query = $this->db->prepareQuery('INSERT INTO users (user_name, user_password, subscribed, user_id, quota, weight, access_date, access_time, approved) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', $this->types);
  176.  
  177.         $this->insertTestValues($prepared_query, $data);
  178.  
  179.         $result = $this->db->executeQuery($prepared_query);
  180.  
  181.         $this->db->freePreparedQuery($prepared_query);
  182.  
  183.         if (MDB::isError($result)) {
  184.             $this->assertTrue(false, 'Error executing prepared query'.$result->getMessage());
  185.         }
  186.  
  187.         $result = $this->db->query('SELECT user_name, user_password, subscribed, user_id, quota, weight, access_date, access_time, approved FROM users', $this->types);
  188.  
  189.         if (MDB::isError($result)) {
  190.             $this->assertTrue(false, 'Error selecting from users'.$result->getMessage());
  191.         }
  192.  
  193.         $this->verifyFetchedValues($result, 0, $data);
  194.     }
  195.  
  196.     /**
  197.      * Test bulk fetch
  198.      *
  199.      * This test bulk fetching of result data by using a prepared query to
  200.      * insert an number of rows of data and then retrieving the data columns
  201.      * one by one
  202.      */
  203.     function testBulkFetch() {
  204.         $data = array();
  205.         $total_rows = 5;
  206.  
  207.         $prepared_query = $this->db->prepareQuery('INSERT INTO users (user_name, user_password, subscribed, user_id, quota, weight, access_date, access_time, approved) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', $this->types);
  208.  
  209.         for ($row = 0; $row < $total_rows; $row++) {
  210.             $data[$row]['user_name'] = "user_$row";
  211.             $data[$row]['user_password'] = 'somepassword';
  212.             $data[$row]['subscribed'] = (boolean)($row % 2);
  213.             $data[$row]['user_id'] = $row;
  214.             $data[$row]['quota'] = sprintf("%.2f",strval(1+($row+1)/100));
  215.             $data[$row]['weight'] = sqrt($row);
  216.             $data[$row]['access_date'] = MDB_Date::mdbToday();
  217.             $data[$row]['access_time'] = MDB_Date::mdbTime();
  218.             $data[$row]['approved'] = MDB_Date::mdbNow();
  219.  
  220.             $this->insertTestValues($prepared_query, $data[$row]);
  221.  
  222.             $result = $this->db->executeQuery($prepared_query, $this->types);
  223.  
  224.             if (MDB::isError($result)) {
  225.                 $this->assertTrue(false, 'Error executing prepared query'.$result->getMessage());
  226.             }
  227.         }
  228.  
  229.         $this->db->freePreparedQuery($prepared_query);
  230.  
  231.         $total_fields =  count($this->fields);
  232.         for ($i = 0; $i < $total_fields; $i++) {
  233.             $field = $this->fields[$i];
  234.             for ($row = 0; $row < $total_rows; $row++) {
  235.                 $value = $this->db->queryOne('SELECT '.$field.' FROM users WHERE user_id='.$row, $this->types[$i]);
  236.                 if (MDB::isError($value)) {
  237.                     $this->assertTrue(false, 'Error fetching row '.$row.' for field '.$field.' of type '.$this->types[$i]);
  238.                 } else {
  239.                     $this->assertEquals(strval(trim($value)), strval($data[$row][$field]), 'the query field '.$field.' of type '.$this->types[$i].' for row '.$row.' was returned in "'.$value.'" unlike "'.$data[$row][$field].'" as expected');
  240.                 }
  241.             }
  242.         }
  243.     }
  244.  
  245.     /**
  246.      * Test prepared queries
  247.      *
  248.      * Tests prepared queries, making sure they correctly deal with ?, !, and '
  249.      */
  250.     function testPreparedQueries() {
  251.         $question_value = $this->db->getTextValue('Does this work?');
  252.  
  253.         $prepared_query = $this->db->prepareQuery("INSERT INTO users (user_name, user_password, user_id) VALUES (?, $question_value, 1)", array('text'));
  254.  
  255.         $this->db->setParamText($prepared_query, 1, 'Sure!');
  256.  
  257.         $result = $this->db->executeQuery($prepared_query);
  258.  
  259.         $this->db->freePreparedQuery($prepared_query);
  260.  
  261.         if (MDB::isError($result)) {
  262.             $error = $result->getMessage();
  263.         }
  264.  
  265.         $this->assertTrue(!MDB::isError($result), 'Could not execute prepared query with a text value with a question mark. Error: ');
  266.  
  267.         $question_value = $this->db->getTextValue("Wouldn't it be great if this worked too?");
  268.  
  269.         $prepared_query = $this->db->prepareQuery("INSERT INTO users (user_name, user_password, user_id) VALUES (?, $question_value, 2)", array('text'));
  270.  
  271.         $this->db->setParamText($prepared_query, 1, 'For Sure!');
  272.  
  273.         $result = $this->db->executeQuery($prepared_query);
  274.  
  275.         $this->db->freePreparedQuery($prepared_query);
  276.  
  277.         if (MDB::isError($result)) {
  278.             $error = $result->getMessage();
  279.         }
  280.  
  281.         $this->assertTrue(!MDB::isError($result), 'Could not execute prepared query with a text value with a quote character before a question mark. Error: ');
  282.  
  283.     }
  284.  
  285.     /**
  286.      * Test retrieval of result metadata
  287.      *
  288.      * This tests the result metadata by executing a prepared_query and
  289.      * select the data, and checking the result contains the correct
  290.      * number of columns and that the column names are in the correct order
  291.      */
  292.     function testMetadata() {
  293.         $row = 1234;
  294.         $data = array();
  295.         $data['user_name'] = "user_$row";
  296.         $data['user_password'] = 'somepassword';
  297.         $data['subscribed'] = (boolean)($row % 2);
  298.         $data['user_id'] = $row;
  299.         $data['quota'] = strval($row/100);
  300.         $data['weight'] = sqrt($row);
  301.         $data['access_date'] = MDB_Date::mdbToday();
  302.         $data['access_time'] = MDB_Date::mdbTime();
  303.         $data['approved'] = MDB_Date::mdbNow();
  304.  
  305.         $prepared_query = $this->db->prepareQuery('INSERT INTO users (user_name, user_password, subscribed, user_id, quota, weight, access_date, access_time, approved) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', $this->types);
  306.  
  307.         $this->insertTestValues($prepared_query, $data);
  308.  
  309.         $result = $this->db->executeQuery($prepared_query);
  310.  
  311.         $this->db->freePreparedQuery($prepared_query);
  312.  
  313.         if (MDB::isError($result)) {
  314.             $this->assertTrue(false, 'Error executing prepared query'.$result->getMessage());
  315.         }
  316.  
  317.         $result = $this->db->query('SELECT user_name, user_password, subscribed, user_id, quota, weight, access_date, access_time, approved FROM users', $this->types);
  318.  
  319.         if (MDB::isError($result)) {
  320.             $this->assertTrue(false, 'Error selecting from users'.$result->getMessage());
  321.         }
  322.  
  323.         $numcols = $this->db->numCols($result);
  324.  
  325.         $this->assertEquals($numcols, count($this->fields), "The query result returned a number of $numcols columns unlike ".count($this->fields) .' as expected');
  326.  
  327.         $column_names = $this->db->getColumnNames($result);
  328.         for ($column = 0; $column < $numcols; $column++) {
  329.             $this->assertEquals($column_names[$this->fields[$column]], $column, "The query result column \"".$this->fields[$column]."\" was returned in position ".$column_names[$this->fields[$column]]." unlike $column as expected");
  330.         }
  331.  
  332.     }
  333.  
  334.     /**
  335.      * Test storage and retrieval of nulls
  336.      *
  337.      * This tests null storage and retrieval by successively inserting,
  338.      * selecting, and testing a number of null / not null values
  339.      */
  340.     function testNulls() {
  341.         $test_values = array(
  342.                              array('test', false),
  343.                              array('NULL', false),
  344.                              array('null', false),
  345.                              array('', false),
  346.                              array(null, true)
  347.                              );
  348.  
  349.         for ($test_value = 0; $test_value <= count($test_values); $test_value++) {
  350.             if ($test_value == count($test_values)) {
  351.                 $value = 'NULL';
  352.                 $is_null = true;
  353.             } else {
  354.                 $value = $this->db->getTextValue($test_values[$test_value][0]);
  355.                 $is_null = $test_values[$test_value][1];
  356.             }
  357.  
  358.             $this->clearTables();
  359.  
  360.             $result = $this->db->query("INSERT INTO users (user_name,user_password,user_id) VALUES ($value,$value,0)");
  361.  
  362.             if (MDB::isError($result)) {
  363.                 $this->assertTrue(false, 'Error executing insert query'.$result->getMessage());
  364.             }
  365.  
  366.             $result = $this->db->query('SELECT user_name,user_password FROM users', array('text', 'text'));
  367.  
  368.             if (MDB::isError($result)) {
  369.                 $this->assertTrue(false, 'Error executing select query'.$result->getMessage());
  370.             }
  371.  
  372.             $this->assertTrue(!$this->db->endOfResult($result), 'The query result seems to have reached the end of result earlier than expected');
  373.  
  374.             if ($is_null) {
  375.                 $error_message = 'A query result column is not NULL unlike what was expected';
  376.             } else {
  377.                 $error_message = 'A query result column is NULL even though it was expected to be "' . $test_values[$test_value][0] . '"';
  378.             }
  379.  
  380.             $value = $this->db->resultIsNull($result, 0, 0);
  381.             $this->assertTrue(($value == $is_null), $error_message);
  382.  
  383.             $value = $this->db->resultIsNull($result, 0, 1);
  384.             $this->assertTrue(($value == $is_null), $error_message);
  385.  
  386.             $this->assertTrue($this->db->endOfResult($result), 'the query result did not seem to have reached the end of result as expected after testing only if columns are NULLs');
  387.  
  388.             $this->db->freeResult($result);
  389.         }
  390.     }
  391.  
  392.     /**
  393.      * Tests escaping of text values with special characters
  394.      *
  395.      */
  396.     function testEscapeSequences() {
  397.         $test_strings = array(
  398.                             "'",
  399.                             "\"",
  400.                             "\\",
  401.                             "%",
  402.                             "_",
  403.                             "''",
  404.                             "\"\"",
  405.                             "\\\\",
  406.                             "\\'\\'",
  407.                             "\\\"\\\""
  408.                             );
  409.  
  410.         for($string = 0; $string < count($test_strings); $string++) {
  411.             $this->clearTables();
  412.  
  413.             $value = $this->db->getTextValue($test_strings[$string]);
  414.  
  415.             $result = $this->db->query("INSERT INTO users (user_name,user_password,user_id) VALUES ($value,$value,0)");
  416.  
  417.             if (MDB::isError($result)) {
  418.                 $this->assertTrue(false, 'Error executing insert query'.$result->getMessage());
  419.             }
  420.  
  421.             $result = $this->db->query('SELECT user_name,user_password FROM users', array('text', 'text'));
  422.  
  423.             if (MDB::isError($result)) {
  424.                 $this->assertTrue(false, 'Error executing select query'.$result->getMessage());
  425.             }
  426.  
  427.             $this->assertTrue(!$this->db->endOfResult($result), 'The query result seems to have reached the end of result earlier than expected');
  428.  
  429.             $value = $this->db->fetch($result, 0, 'user_name');
  430.             $this->db->freeResult($result);
  431.  
  432.             $this->assertEquals(rtrim($value), $test_strings[$string], "the value retrieved for field \"user_name\" (\"$value\") doesn't match what was stored (".$test_strings[$string].')');
  433.  
  434.         }
  435.     }
  436.  
  437.     /**
  438.      * Test paged queries
  439.      *
  440.      * Test the use of setSelectedRowRange to return paged queries
  441.      */
  442.     function testRanges() {
  443.         if (!$this->supported('SelectRowRanges')) {
  444.             return;
  445.         }
  446.  
  447.         $data = array();
  448.         $total_rows = 5;
  449.  
  450.         $prepared_query = $this->db->prepareQuery('INSERT INTO users (user_name, user_password, subscribed, user_id, quota, weight, access_date, access_time, approved) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', $this->types);
  451.  
  452.         for ($row = 0; $row < $total_rows; $row++) {
  453.             $data[$row]['user_name'] = "user_$row";
  454.             $data[$row]['user_password'] = 'somepassword';
  455.             $data[$row]['subscribed'] = (boolean)($row % 2);
  456.             $data[$row]['user_id'] = $row;
  457.             $data[$row]['quota'] = sprintf("%.2f",strval(1+($row+1)/100));
  458.             $data[$row]['weight'] = sqrt($row);
  459.             $data[$row]['access_date'] = MDB_Date::mdbToday();
  460.             $data[$row]['access_time'] = MDB_Date::mdbTime();
  461.             $data[$row]['approved'] = MDB_Date::mdbNow();
  462.  
  463.             $this->insertTestValues($prepared_query, $data[$row]);
  464.  
  465.             $result = $this->db->executeQuery($prepared_query);
  466.  
  467.             if (MDB::isError($result)) {
  468.                 $this->assertTrue(false, 'Error executing prepared query'.$result->getMessage());
  469.             }
  470.         }
  471.  
  472.         $this->db->freePreparedQuery($prepared_query);
  473.  
  474.         for ($rows = 2, $start_row = 0; $start_row < $total_rows; $start_row += $rows) {
  475.  
  476.             $this->db->setSelectedRowRange($start_row, $rows);
  477.  
  478.             $result = $this->db->query('SELECT user_name,user_password,subscribed,user_id,quota,weight,access_date,access_time,approved FROM users ORDER BY user_id', $this->types);
  479.  
  480.             if (MDB::isError($result)) {
  481.                 $this->assertTrue(false, 'Error executing select query'.$result->getMessage());
  482.             }
  483.  
  484.             for ($row = 0; $row < $rows && ($row + $start_row < $total_rows); $row++) {
  485.                 $this->verifyFetchedValues($result, $row, $data[$row + $start_row]);
  486.             }
  487.         }
  488.  
  489.         $this->assertTrue($this->db->endOfResult($result), "The query result did not seem to have reached the end of result as expected starting row $start_row after fetching upto row $row");
  490.  
  491.         $this->db->freeResult($result);
  492.  
  493.         for ($rows = 2, $start_row = 0; $start_row < $total_rows; $start_row += $rows) {
  494.  
  495.             $this->db->setSelectedRowRange($start_row, $rows);
  496.  
  497.             $result = $this->db->query('SELECT user_name, user_password, subscribed, user_id, quota, weight, access_date, access_time, approved FROM users ORDER BY user_id', $this->types);
  498.  
  499.             if (MDB::isError($result)) {
  500.                 $this->assertTrue(false, 'Error executing select query'.$result->getMessage());
  501.             }
  502.  
  503.             $result_rows = $this->db->numRows($result);
  504.  
  505.             $this->assertTrue(($result_rows <= $rows), 'expected a result of no more than $rows but the returned number of rows is $result_rows');
  506.  
  507.             for ($row = 0; $row < $result_rows; $row++) {
  508.                 $this->assertTrue(!$this->db->endOfResult($result), 'The query result seem to have reached the end of result at row $row that is before $result_rows as expected');
  509.  
  510.                 $this->verifyFetchedValues($result, $row, $data[$row + $start_row]);
  511.  
  512.             }
  513.         }
  514.  
  515.         $this->assertTrue($this->db->endOfResult($result), 'the query result did not seem to have reached the end of result as expected');
  516.  
  517.         $this->db->freeResult($result);
  518.     }
  519.  
  520.     /**
  521.      * Test the handling of sequences
  522.      */
  523.     function testSequences() {
  524.         if (!$this->supported('Sequences')) {
  525.             return;
  526.         }
  527.  
  528.         for ($start_value = 1; $start_value < 4; $start_value++) {
  529.             $sequence_name = "test_sequence_$start_value";
  530.  
  531.             $result = $this->db->createSequence($sequence_name, $start_value);
  532.             $this->assertTrue(!MDB::isError($result), "Error creating sequence $sequence_name with start value $start_value");
  533.  
  534.             for ($sequence_value = $start_value; $sequence_value < ($start_value + 4); $sequence_value++) {
  535.                 $value = $this->db->nextId($sequence_name, false);
  536.  
  537.                 $this->assertEquals($sequence_value, $value, "The returned sequence value is $value and not $sequence_value as expected with sequence start value with $start_value");
  538.  
  539.             }
  540.  
  541.             $result = $this->db->dropSequence($sequence_name);
  542.  
  543.             if (MDB::isError($result)) {
  544.                 $this->assertTrue(false, "Error dropping sequence $sequence_name : ".$result->getMessage());
  545.             }
  546.  
  547.         }
  548.  
  549.         // Test ondemand creation of sequences
  550.         $sequence_name = 'test_ondemand';
  551.  
  552.         for ($sequence_value = 1; $sequence_value < 4; $sequence_value++) {
  553.             $value = $this->db->nextId($sequence_name);
  554.  
  555.             $this->assertEquals($sequence_value, $value, "Error in ondemand sequences. The returned sequence value is $value and not $sequence_value as expected");
  556.  
  557.         }
  558.  
  559.         $result = $this->db->dropSequence($sequence_name);
  560.  
  561.         if (MDB::isError($result)) {
  562.             $this->assertTrue(false, "Error dropping sequence $sequence_name : ".$result->getMessage());
  563.         }
  564.     }
  565.  
  566.  
  567.     /**
  568.      * Test replace query
  569.      *
  570.      * The replace method emulates the replace query of mysql
  571.      */
  572.     function testReplace() {
  573.         if (!$this->supported('Replace')) {
  574.             return;
  575.         }
  576.  
  577.         $row = 1234;
  578.         $data = array();
  579.         $data['user_name'] = "user_$row";
  580.         $data['user_password'] = 'somepassword';
  581.         $data['subscribed'] = (boolean)($row % 2);
  582.         $data['user_id'] = $row;
  583.         $data['quota'] = strval($row/100);
  584.         $data['weight'] = sqrt($row);
  585.         $data['access_date'] = MDB_Date::mdbToday();
  586.         $data['access_time'] = MDB_Date::mdbTime();
  587.         $data['approved'] = MDB_Date::mdbNow();
  588.  
  589.         $fields = array(
  590.                       'user_name' => array(
  591.                                            'Value' => "user_$row",
  592.                                            'Type' => 'text'
  593.                                          ),
  594.                       'user_password' => array(
  595.                                                'Value' => $data['user_password'],
  596.                                                'Type' => 'text'
  597.                                              ),
  598.                       'subscribed' => array(
  599.                                             'Value' => $data['subscribed'],
  600.                                             'Type' => 'boolean'
  601.                                           ),
  602.                       'user_id' => array(
  603.                                          'Value' => $data['user_id'],
  604.                                          'Type' => 'integer',
  605.                                          'Key' => 1
  606.                                        ),
  607.                       'quota' => array(
  608.                                        'Value' => $data['quota'],
  609.                                        'Type' => 'decimal'
  610.                                      ),
  611.                       'weight' => array(
  612.                                         'Value' => $data['weight'],
  613.                                         'Type' => 'float'
  614.                                       ),
  615.                       'access_date' => array(
  616.                                              'Value' => $data['access_date'],
  617.                                              'Type' => 'date'
  618.                                            ),
  619.                       'access_time' => array(
  620.                                              'Value' => $data['access_time'],
  621.                                              'Type' => 'time'
  622.                                            ),
  623.                       'approved' => array(
  624.                                           'Value' => $data['approved'],
  625.                                           'Type' => 'timestamp'
  626.                                         )
  627.                       );
  628.  
  629.         $support_affected_rows = $this->db->support('AffectedRows');
  630.  
  631.         $result = $this->db->replace('users', $fields);
  632.  
  633.         if (MDB::isError($result)) {
  634.             $this->assertTrue(false, 'Replace failed');
  635.         }
  636.  
  637.         if ($support_affected_rows) {
  638.             $affected_rows = $this->db->affectedRows();
  639.  
  640.             $this->assertEquals(1, $affected_rows, "replacing a row in an empty table returned $affected_rows unlike 1 as expected");
  641.         }
  642.  
  643.         $result = $this->db->query('SELECT user_name, user_password, subscribed, user_id, quota, weight, access_date, access_time, approved FROM users', $this->types);
  644.  
  645.         if (MDB::isError($result)) {
  646.             $this->assertTrue(false, 'Error selecting from users'.$result->getMessage());
  647.         }
  648.  
  649.         $this->verifyFetchedValues($result, 0, $data);
  650.  
  651.         $row = 4321;
  652.         $fields['user_name']['Value']     = $data['user_name']     = "user_$row";
  653.         $fields['user_password']['Value'] = $data['user_password'] = 'somepassword';
  654.         $fields['subscribed']['Value']    = $data['subscribed']    = (boolean)($row % 2);
  655.         $fields['quota']['Value']         = $data['quota']         = strval($row/100);
  656.         $fields['weight']['Value']        = $data['weight']        = sqrt($row);
  657.         $fields['access_date']['Value']   = $data['access_date']   = MDB_Date::mdbToday();
  658.         $fields['access_time']['Value']   = $data['access_time']   = MDB_Date::mdbTime();
  659.         $fields['approved']['Value']      = $data['approved']      = MDB_Date::mdbNow();
  660.  
  661.         $result = $this->db->replace('users', $fields);
  662.  
  663.         if (MDB::isError($result)) {
  664.             $this->assertTrue(false, 'Replace failed');
  665.         }
  666.  
  667.         if ($support_affected_rows) {
  668.             $affected_rows = $this->db->affectedRows();
  669.  
  670.             $this->assertEquals(2, $affected_rows, "replacing a row in a non empty table returned $affected_rows unlike 2 as expected");
  671.         }
  672.  
  673.         $result = $this->db->query('SELECT user_name, user_password, subscribed, user_id, quota, weight, access_date, access_time, approved FROM users', $this->types);
  674.  
  675.         if (MDB::isError($result)) {
  676.             $this->assertTrue(false, 'Error selecting from users'.$result->getMessage());
  677.         }
  678.  
  679.         $this->verifyFetchedValues($result, 0, $data);
  680.  
  681.         $this->assertTrue($this->db->endOfResult($result), 'the query result did not seem to have reached the end of result as expected');
  682.  
  683.         $this->db->freeResult($result);
  684.     }
  685.  
  686.     /**
  687.      * Test affected rows methods
  688.      */
  689.     function testAffectedRows() {
  690.         if (!$this->supported('AffectedRows')) {
  691.             return;
  692.         }
  693.  
  694.         $data = array();
  695.         $total_rows = 7;
  696.  
  697.         $prepared_query = $this->db->prepareQuery('INSERT INTO users (user_name, user_password, subscribed, user_id, quota, weight, access_date, access_time, approved) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', $this->types);
  698.  
  699.         for ($row = 0; $row < $total_rows; $row++) {
  700.             $data[$row]['user_name']     = "user_$row";
  701.             $data[$row]['user_password'] = 'somepassword';
  702.             $data[$row]['subscribed']    = (boolean)($row % 2);
  703.             $data[$row]['user_id']       = $row;
  704.             $data[$row]['quota']         = sprintf("%.2f",strval(1+($row+1)/100));
  705.             $data[$row]['weight']        = sqrt($row);
  706.             $data[$row]['access_date']   = MDB_Date::mdbToday();
  707.             $data[$row]['access_time']   = MDB_Date::mdbTime();
  708.             $data[$row]['approved']      = MDB_Date::mdbNow();
  709.  
  710.             $this->insertTestValues($prepared_query, $data[$row]);
  711.  
  712.             $result = $this->db->executeQuery($prepared_query);
  713.  
  714.             $affected_rows = $this->db->affectedRows();
  715.  
  716.             $this->assertEquals($affected_rows, 1, "Inserting the row $row returned $affected_rows affected row count instead of 1 as expected");
  717.  
  718.             if (MDB::isError($result)) {
  719.                 $this->assertTrue(false, 'Error executing prepared query'.$result->getMessage());
  720.             }
  721.         }
  722.  
  723.         $this->db->freePreparedQuery($prepared_query);
  724.  
  725.         $prepared_query = $this->db->prepareQuery('UPDATE users SET user_password=? WHERE user_id < ?', array('text', 'integer'));
  726.  
  727.         for ($row = 0; $row < $total_rows; $row++) {
  728.             $this->db->setParamText($prepared_query, 1, "another_password_$row");
  729.             $this->db->setParamInteger($prepared_query, 2, $row);
  730.  
  731.             $result = $this->db->executeQuery($prepared_query);
  732.  
  733.             if (MDB::isError($result)) {
  734.                 $this->assertTrue(false, 'Error executing prepared query'.$result->getMessage());
  735.             }
  736.  
  737.             $affected_rows = $this->db->affectedRows();
  738.  
  739.             $this->assertEquals($affected_rows, $row, "Updating the $row rows returned $affected_rows affected row count");
  740.  
  741.         }
  742.  
  743.         $this->db->freePreparedQuery($prepared_query);
  744.  
  745.         $prepared_query = $this->db->prepareQuery('DELETE FROM users WHERE user_id >= ?', array('integer'));
  746.  
  747.         for ($row = $total_rows; $total_rows; $total_rows = $row) {
  748.             $this->db->setParamInteger($prepared_query, 1, $row = intval($total_rows / 2));
  749.  
  750.             $result = $this->db->executeQuery($prepared_query);
  751.  
  752.             if (MDB::isError($result)) {
  753.                 $this->assertTrue(false, 'Error executing prepared query'.$result->getMessage());
  754.             }
  755.  
  756.             $affected_rows = $this->db->affectedRows();
  757.  
  758.             $this->assertEquals($affected_rows, ($total_rows - $row), 'Deleting '.($total_rows - $row)." rows returned $affected_rows affected row count");
  759.  
  760.         }
  761.  
  762.         $this->db->freePreparedQuery($prepared_query);
  763.     }
  764.  
  765.     /**
  766.      * Testing transaction support
  767.      */
  768.     function testTransactions() {
  769.         if (!$this->supported('Transactions')) {
  770.             return;
  771.         }
  772.  
  773.         $this->db->autoCommit(0);
  774.  
  775.         $row = 0;
  776.         $data = array();
  777.         $data['user_name']     = "user_$row";
  778.         $data['user_password'] = 'somepassword';
  779.         $data['subscribed']    = (boolean)($row % 2);
  780.         $data['user_id']       = $row;
  781.         $data['quota']         = strval($row/100);
  782.         $data['weight']        = sqrt($row);
  783.         $data['access_date']   = MDB_Date::mdbToday();
  784.         $data['access_time']   = MDB_Date::mdbTime();
  785.         $data['approved']      = MDB_Date::mdbNow();
  786.  
  787.         $prepared_query = $this->db->prepareQuery('INSERT INTO users (user_name, user_password, subscribed, user_id, quota, weight, access_date, access_time, approved) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', $this->types);
  788.  
  789.         $this->insertTestValues($prepared_query, $data);
  790.         $result = $this->db->executeQuery($prepared_query);
  791.         $this->db->rollback();
  792.  
  793.         $result = $this->db->query('SELECT * FROM users');
  794.         if (MDB::isError($result)) {
  795.             $this->assertTrue(false, 'Error selecting from users'.$result->getMessage());
  796.         }
  797.  
  798.         $this->assertTrue($this->db->endOfResult($result), 'Transaction rollback did not revert the row that was inserted');
  799.         $this->db->freeResult($result);
  800.  
  801.         $this->insertTestValues($prepared_query, $data);
  802.         $result = $this->db->executeQuery($prepared_query);
  803.         $this->db->commit();
  804.  
  805.         $result = $this->db->query('SELECT * FROM users');
  806.         if (MDB::isError($result)) {
  807.             $this->assertTrue(false, 'Error selecting from users'.$result->getMessage());
  808.         }
  809.  
  810.         $this->assertTrue(!$this->db->endOfResult($result), 'Transaction commit did not make permanent the row that was inserted');
  811.         $this->db->freeResult($result);
  812.  
  813.         $result = $this->db->query('DELETE FROM users');
  814.         if (MDB::isError($result)) {
  815.             $this->assertTrue(false, 'Error deleting from users'.$result->getMessage());
  816.             $this->db->rollback();
  817.         }
  818.  
  819.         $autocommit = $this->db->autocommit(1);
  820.         $this->assertTrue(!MDB::isError($autocommit), 'Error autocommiting transactions');
  821.  
  822.         $this->db->freePreparedQuery($prepared_query);
  823.  
  824.         $result = $this->db->query('SELECT * FROM users');
  825.         if (MDB::isError($result)) {
  826.             $this->assertTrue(false, 'Error selecting from users'.$result->getMessage());
  827.         }
  828.  
  829.         $this->assertTrue($this->db->endOfResult($result), 'Transaction end with implicit commit when re-enabling auto-commit did not make permanent the rows that were deleted');
  830.         $this->db->freeResult($result);
  831.     }
  832.  
  833.     /**
  834.      * Testing LOB storage
  835.      */
  836.  
  837.     function testLobStorage() {
  838.         if (!$this->supported('LOBs')) {
  839.             return;
  840.         }
  841.  
  842.         //$prepared_query = $this->db->prepareQuery('INSERT INTO files (document,picture) VALUES (?,?)');
  843.         $prepared_query = $this->db->prepareQuery('INSERT INTO files (ID, document,picture) VALUES (1,?,?)', array('clob', 'blob'));
  844.  
  845.         $character_lob = array(
  846.                               'Database' => $this->db,
  847.                               'Error' => '',
  848.                               'Data' => ''
  849.                               );
  850.         for ($code = 32; $code <= 127; $code++) {
  851.             $character_lob['Data'] .= chr($code);
  852.         }
  853.         $binary_lob = array(
  854.                             'Database' => $this->db,
  855.                             'Error' => '',
  856.                             'Data' => ''
  857.                             );
  858.         for ($code = 0; $code <= 255; $code++) {
  859.             $binary_lob['Data'] .= chr($code);
  860.         }
  861.  
  862.         $clob = $this->db->createLob($character_lob);
  863.         $this->assertTrue(!MDB::isError($clob), 'Error creating character LOB: '.$character_lob['Error']);
  864.  
  865.         $blob = $this->db->createLob($binary_lob);
  866.         $this->assertTrue(!MDB::isError($blob), 'Error creating binary LOB: '.$binary_lob['Error']);
  867.  
  868.         $this->db->setParamClob($prepared_query, 1, $clob, 'document');
  869.         $this->db->setParamBlob($prepared_query, 2, $blob, 'picture');
  870.         $result = $this->db->executeQuery($prepared_query);
  871.  
  872.         if($is_error = MDB::isError($result)) {
  873.             $msg = $result->getUserInfo();
  874.         } else {
  875.             $msg = '';
  876.         }
  877.         $this->assertTrue(!$is_error, 'Error executing prepared query: '.$msg);
  878.  
  879.         $this->db->destroyLob($blob);
  880.         $this->db->destroyLob($clob);
  881.         $this->db->freePreparedQuery($prepared_query);
  882.  
  883.         $result = $this->db->query('SELECT document, picture FROM files', array('clob', 'blob'));
  884.         //$result = $this->db->query('SELECT document, picture FROM files');
  885.         if (MDB::isError($result)) {
  886.             $this->assertTrue(false, 'Error selecting from files'.$result->getMessage());
  887.         }
  888.         $this->assertTrue(!$this->db->endOfResult($result), 'The query result seem to have reached the end of result too soon.');
  889.  
  890.         $clob = $this->db->fetchClob($result, 0, 'document');
  891.         if (!MDB::isError($clob)) {
  892.             for ($value = ''; !$this->db->endOfLob($clob);) {
  893.                 $this->assertTrue(($this->db->readLob($clob, $data, 8192) >= 0), 'Could not read CLOB');
  894.                 $value .= $data;
  895.             }
  896.             $this->db->destroyLob($clob);
  897.  
  898.             $this->assertEquals($value, $character_lob['Data'], 'Retrieved character LOB value ("' . $value . '") is different from what was stored ("' . $character_lob['Data'] . '")');
  899.         } else {
  900.             $this->assertTrue(false, 'Error retrieving CLOB result');
  901.         }
  902.  
  903.         $blob = $this->db->fetchBlob($result, 0, 'picture');
  904.  
  905.         if (!MDB::isError($blob)) {
  906.             for ($value = ''; !$this->db->endOfLob($clob);) {
  907.                 $this->assertTrue(($this->db->readLob($blob, $data, 8192) >= 0), 'Could not read BLOB');
  908.                 $value .= $data;
  909.             }
  910.  
  911.             $this->db->destroyLob($blob);
  912.  
  913.             $this->assertEquals($value, $binary_lob['Data'], 'Retrieved binary LOB value ("'.$value.'") is different from what was stored ("'.$binary_lob['Data'].'")');
  914.         } else {
  915.             $this->assertTrue(false, 'Error retrieving CLOB result');
  916.         }
  917.         $this->db->freeResult($result);
  918.     }
  919.  
  920.     /**
  921.      * Test for lob storage from and to files
  922.      */
  923.  
  924.     function testLobFiles() {
  925.         if (!$this->supported('LOBs')) {
  926.             return;
  927.         }
  928.  
  929.         $prepared_query = $this->db->prepareQuery('INSERT INTO files (ID, document,picture) VALUES (1,?,?)', array('clob', 'blob'));
  930.         //$prepared_query = $this->db->prepareQuery('INSERT INTO files (document,picture) VALUES (?,?)');
  931.  
  932.         $character_data_file = 'character_data';
  933.         if (($file = fopen($character_data_file, 'w'))) {
  934.             for ($character_data = '', $code = 32; $code <= 127; $code++) {
  935.                 $character_data .= chr($code);
  936.             }
  937.             $character_lob = array(
  938.                                    'Type' => 'inputfile',
  939.                                    'Database' => $this->db,
  940.                                    'Error' => '',
  941.                                    'FileName' => $character_data_file
  942.                                    );
  943.             $this->assertTrue((fwrite($file, $character_data, strlen($character_data)) == strlen($character_data)), 'Error creating clob file to read from');
  944.             fclose($file);
  945.         }
  946.  
  947.         $binary_data_file = 'binary_data';
  948.         if (($file = fopen($binary_data_file, 'wb'))) {
  949.             for($binary_data = '', $code = 0; $code <= 255; $code++) {
  950.                     $binary_data .= chr($code);
  951.             }
  952.             $binary_lob = array(
  953.                                 'Type' => 'inputfile',
  954.                                 'Database' => $this->db,
  955.                                 'Error' => '',
  956.                                 'FileName' => $binary_data_file
  957.                                 );
  958.             $this->assertTrue((fwrite($file, $binary_data, strlen($binary_data)) == strlen($binary_data)), 'Error creating blob file to read from');
  959.             fclose($file);
  960.         }
  961.  
  962.         $clob = $this->db->createLob($character_lob);
  963.         $this->assertTrue(!MDB::isError($clob), 'Error creating clob');
  964.  
  965.         $blob = $this->db->createLob($binary_lob);
  966.         $this->assertTrue(!MDB::isError($blob), 'Error creating blob');
  967.  
  968.         $this->db->setParamCLOB($prepared_query, 1, $clob, 'document');
  969.         $this->db->setParamBLOB($prepared_query, 2, $blob, 'picture');
  970.  
  971.         $result = $this->db->executeQuery($prepared_query);
  972.         $this->assertTrue(!MDB::isError($result), 'Error executing prepared query - inserting LOB from files');
  973.  
  974.         $this->db->destroyLOB($blob);
  975.         $this->db->destroyLOB($clob);
  976.  
  977.         $this->db->freePreparedQuery($prepared_query);
  978.  
  979.         $result = $this->db->query('SELECT document, picture FROM files');
  980.         if (MDB::isError($result)) {
  981.             $this->assertTrue(false, 'Error selecting from files'.$result->getMessage());
  982.         }
  983.  
  984.         $this->assertTrue(!$this->db->endOfResult($result), 'The query result seem to have reached the end of result too soon.');
  985.  
  986.         $character_lob = array(
  987.                              'Type' => 'outputfile',
  988.                              'Database' => $this->db,
  989.                              'Result' => $result,
  990.                              'Row' => 0,
  991.                              'Field' => 'document',
  992.                              'Binary' => 0,
  993.                              'Error' => '',
  994.                              'FileName' => $character_data_file
  995.                              );
  996.  
  997.         $clob = $this->db->createLOB($character_lob);
  998.  
  999.         if (!MDB::isError($clob)) {
  1000.             $this->assertTrue(($this->db->readLOB($clob, $data, 0) >= 0), 'Error reading CLOB ');
  1001.             $this->db->destroyLOB($clob);
  1002.  
  1003.             $this->assertTrue(($file = fopen($character_data_file, 'r')), "Error opening character data file: $character_data_file");
  1004.             $this->assertEquals(getType($value = fread($file, filesize($character_data_file))), 'string', "Could not read from character LOB file: $character_data_file");
  1005.             fclose($file);
  1006.  
  1007.             $this->assertEquals($value, $character_data, "retrieved character LOB value (\"".$value."\") is different from what was stored (\"".$character_data."\")");
  1008.         } else {
  1009.             $this->assertTrue(false, 'Error creating character LOB in a file');
  1010.         }
  1011.  
  1012.         $binary_lob = array(
  1013.                             'Type' => 'outputfile',
  1014.                             'Database' => $this->db,
  1015.                             'Result' => $result,
  1016.                             'Row' => 0,
  1017.                             'Field' => 'picture',
  1018.                             'Binary' => 1,
  1019.                             'Error' => '',
  1020.                             'FileName' => $binary_data_file
  1021.                             );
  1022.  
  1023.         $blob = $this->db->createLOB($binary_lob);
  1024.  
  1025.         if (!MDB::isError($blob)) {
  1026.             $this->assertTrue(($this->db->readLOB($blob, $data, 0) >= 0), 'Error reading BLOB ');
  1027.             $this->db->destroyLOB($blob);
  1028.  
  1029.             $this->assertTrue(($file = fopen($binary_data_file, 'rb')), "Error opening binary data file: $binary_data_file");
  1030.             $this->assertEquals(getType($value = fread($file, filesize($binary_data_file))), 'string', "Could not read from binary LOB file: $binary_data_file");
  1031.             fclose($file);
  1032.  
  1033.             $this->assertEquals($value, $binary_data, "retrieved binary LOB value (\"".$value."\") is different from what was stored (\"".$binary_data."\")");
  1034.         } else {
  1035.             $this->assertTrue(false, 'Error creating binary LOB in a file');
  1036.         }
  1037.  
  1038.         $this->db->freeResult($result);
  1039.     }
  1040.  
  1041.     /**
  1042.      * Test handling of lob nulls
  1043.      */
  1044.  
  1045.     function testLobNulls() {
  1046.         if (!$this->supported('LOBs')) {
  1047.             return;
  1048.         }
  1049.  
  1050.         $prepared_query = $this->db->prepareQuery('INSERT INTO files (ID, document,picture) VALUES (1,?,?)', array('clob', 'blob'));
  1051.         //$prepared_query = $this->db->prepareQuery('INSERT INTO files (document,picture) VALUES (?,?)');
  1052.  
  1053.         $this->db->setParamNull($prepared_query, 1, 'clob');
  1054.         $this->db->setParamNull($prepared_query, 2, 'blob');
  1055.  
  1056.         $result = $this->db->executeQuery($prepared_query);
  1057.         $this->assertTrue(!MDB::isError($result), 'Error executing prepared query - inserting NULL lobs');
  1058.  
  1059.         $this->db->freePreparedQuery($prepared_query);
  1060.  
  1061.         $result = $this->db->query('SELECT document, picture FROM files', array('clob', 'blob'));
  1062.         if (MDB::isError($result)) {
  1063.             $this->assertTrue(false, 'Error selecting from files'.$result->getMessage());
  1064.         }
  1065.  
  1066.         $this->assertTrue(!$this->db->endOfResult($result), 'The query result seem to have reached the end of result too soon.');
  1067.  
  1068.         $this->assertTrue($this->db->resultIsNull($result, 0, 'document'), 'A query result large object column is not NULL unlike what was expected (document)');
  1069.         $this->assertTrue($this->db->resultIsNull($result, 0, 'picture'), 'A query result large object column is not NULL unlike what was expected (picture)');
  1070.  
  1071.         $this->db->freeResult($result);
  1072.     }
  1073. }
  1074.  
  1075. ?>