[limb-svn] r6837 - in 3.x/trunk/limb/dbal: src/drivers src/drivers/linter src/dump tests/bench tests/cases tests/cases/driver tests/cases/driver/linter tests/cases/non-driver/.fixture

svn at limb-project.com svn at limb-project.com
Fri Mar 14 18:48:44 MSK 2008


Author: svk
Date: 2008-03-14 18:48:44 +0300 (Fri, 14 Mar 2008)
New Revision: 6837
URL: http://fisheye.limb-project.com/changelog/limb/?cs=6837

Added:
   3.x/trunk/limb/dbal/src/drivers/linter/
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterColumnInfo.class.php
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterConnection.class.php
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterDbInfo.class.php
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterDropStatement.class.php
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterInsertStatement.class.php
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterManipulationStatement.class.php
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterQueryStatement.class.php
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterRecord.class.php
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterRecordSet.class.php
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterStatement.class.php
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterTableInfo.class.php
   3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterTypeInfo.class.php
   3.x/trunk/limb/dbal/src/dump/lmbLinterDumpLoader.class.php
   3.x/trunk/limb/dbal/tests/bench/fetching_linter.php
   3.x/trunk/limb/dbal/tests/bench/fetching_mysql.php
   3.x/trunk/limb/dbal/tests/bench/fetching_pgsql.php
   3.x/trunk/limb/dbal/tests/cases/.setup.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/
   3.x/trunk/limb/dbal/tests/cases/driver/linter/.skipif.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/fixture.inc.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterColumnInfoTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterConnectionTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDbInfoTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDeleteTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDriverTransactionTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterInsertTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterQueryTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterRecordSetTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterRecordTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterStatementTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterTableInfoTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterTypeInfoTest.class.php
   3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterUpdateTest.class.php
   3.x/trunk/limb/dbal/tests/cases/non-driver/.fixture/init_tests.linter
Log:
-- dbal :: linter driver added

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterColumnInfo.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterColumnInfo.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterColumnInfo.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,74 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+lmb_require('limb/dbal/src/drivers/lmbDbColumnInfo.class.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterTypeInfo.class.php');
+
+/**
+ * class lmbLinterColumnInfo.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterColumnInfo extends lmbDbColumnInfo
+{
+  protected $nativeType;
+  protected $isAutoIncrement;
+  protected $isExisting = false;
+
+  function __construct(
+                $table,
+                $name,
+                $nativeType = null,
+                $size = null,
+                $scale = null,
+                $isNullable = null,
+                $default = null,
+                $isAutoIncrement = null,
+                $isExisting = false)
+  {
+
+    $this->nativeType = $this->canonicalizeNativeType($nativeType);
+    $this->isAutoIncrement = $this->canonicalizeIsAutoincrement($isAutoIncrement);
+
+    $typeinfo = new lmbLinterTypeInfo();
+    $typemap = $typeinfo->getNativeToColumnTypeMapping();
+    $type = $typemap[$nativeType];
+
+    $this->isExisting = $isExisting;
+
+    parent::__construct($table, $name, $type, $size, $scale, $isNullable, $default);
+  }
+
+  function getNativeType()
+  {
+    return $this->nativeType;
+  }
+
+  function canonicalizeNativeType($nativeType)
+  {
+    return $nativeType;
+  }
+
+  function isAutoIncrement()
+  {
+    return $this->isAutoIncrement === true;
+  }
+
+  function canonicalizeIsAutoIncrement($isAutoIncrement)
+  {
+    return is_null($isAutoIncrement) ?  null : (bool) $isAutoIncrement;
+  }
+
+  function escapeIdentifier($name)
+  {
+    return "\"$name\"";
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterConnection.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterConnection.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterConnection.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,428 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/dbal/src/drivers/lmbDbConnection.interface.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterQueryStatement.class.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterDropStatement.class.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterInsertStatement.class.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterManipulationStatement.class.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterStatement.class.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterDbInfo.class.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterTypeInfo.class.php');
+
+/**
+ * class lmbLinterConnection.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterConnection implements lmbDbConnection
+{
+  const CURSOR_POOL_LIMIT = 64;
+  const LINTER_EMPTY_DATASET = -18;
+  
+  protected $connectionId;
+  protected $config;
+  protected $transactionCount = 0;
+  protected $cursorPool = array();
+  protected $mode = null;
+  protected $useConnection = false;
+  
+
+  function __construct($config)
+  {
+    $this->config = $config;
+  }
+
+  function getType()
+  {
+    return 'linter';
+  }
+
+  function getConnectionId()
+  {
+    if(!isset($this->connectionId))
+      $this->connect();
+      
+    return $this->connectionId;
+  }
+
+  function getHash()
+  {
+    return crc32(serialize($this->config));
+  }
+
+  function getConfigValue($param = null)
+  {
+    if (is_null($param))
+      return $this->config;
+    elseif (array_key_exists($param, $this->config))
+      return $this->config[$param];
+    else
+      return false;
+  }
+  
+  function connect()
+  {
+    $persistent = null;
+
+    if(isset($this->config['charset']) && ($charset = $this->config['charset']))
+      $r = linter_set_codepage($this->map_charset($this->config['charset']));
+    
+    $port = $this->config['port'];
+    $database = addslashes($this->config['database']);
+    $user = addslashes($this->config['user']);
+    $password = addslashes($this->config['password']);
+    
+    if (is_null($this->mode))
+      $this->mode = isset($this->config['extra']['mode']) ? $this->config['extra']['mode'] : TM_AUTOCOMMIT;
+      
+    $conn = @linter_open_connect($user, $password, $database, $this->mode);
+    $this->connectionId = $conn;
+    
+    if ($conn < 0)
+    {
+      $this->_raiseError($conn);
+      $this->connectionId = null;
+    }
+	
+
+
+  }
+  
+  
+
+  function __wakeup()
+  {
+    $this->connectionId = null;
+  }
+
+  function disconnect()
+  {
+    if($this->connectionId > 0)
+    {
+      linter_close_connect($this->connectionId);
+      $this->connectionId = null;
+    }
+  }
+
+  function closeCursor($cursorId)
+  {
+    linter_close_cursor($cursorId);
+    unset($this->cursorPool[$cursorId]);
+  }
+  
+  function _raiseError($code, $conn_id = null, $args=array())
+  {
+    if (is_null($conn_id))
+      $conn_id = $this->connectionId;
+      
+    if ($code >= 0 && $this->connectionId >= 0)
+      return false;
+      
+    if ($this->connectionId < 0)
+    {
+      $lin_err = linter_last_error($this->connectionId, LINTER_ERROR);
+      $sys_err = linter_last_error($this->connectionId, SYSTEM_ERROR);
+      $err_message = sprintf("Linter connect error %s, system error %s\n", $lin_err, $sys_err);
+      $err_code = $sys_err;
+    }
+    elseif($code == LPE_INVALID_CONNECT)
+    {
+      $err_code = -1;
+      $err_message = "Invalid connect";
+    }
+    elseif($code == LPE_LINTER_ERROR)
+    {
+      $lin_err = linter_last_error($conn_id, LINTER_ERROR);
+      $sys_err = linter_last_error($conn_id, SYSTEM_ERROR);
+      $err_message = linter_error_msg($conn_id);
+      $err_code = $lin_err;
+      if ($err_code <= 2 && $err_code > 0) return self::LINTER_EMPTY_DATASET;
+      if ($err_code >= 2000 && $err_code < 3000)
+      {
+        $err_row = $sys_err & 0xFFFF;
+        $err_pos = $sys_err >> 16;
+        $err_message .= sprintf(" at row %d, position %d", $err_row, $err_pos);
+      }
+      else
+        $err_message .= sprintf(", system error %d", $sys_err);
+    }
+    else
+    {
+      $err_message = sprintf("Linter extension error %d", $code);
+      $err_code = $code;
+    }
+    $err_message .= ". " . count($this->cursorPool)." cursors opened";
+    throw new lmbException("Database error: No:" . $err_code.". Description: ".$err_message);
+    return true;
+  }
+
+  protected function prepare_sql($sql)
+  {
+    $sql = trim($sql);
+    $sql = $this->escapeTableName($sql);
+    $sql = $this->escapeInsertFields($sql);
+    return $sql;    
+  }
+  
+  protected function handle_cursor_pool()
+  {
+    if (!$this->useConnection)
+    {
+      if (count($this->cursorPool) > self::CURSOR_POOL_LIMIT)
+      {
+        $cursors = array_keys($this->cursorPool);
+        $this->closeCursor($cursors[0]);
+      }
+      $result = linter_open_cursor($this->getConnectionId());
+      
+      if ($result < 0)
+        $this->_raiseError($result);
+        
+      linter_set_cursor_opt($result, CO_DT_FORMAT, "YYYY-MM-DD HH:MI:SS");
+      linter_set_cursor_opt($result, CO_FETCH_BLOBS_AS_USUAL_DATA, 1);
+
+      $this->cursorPool[$result] = "opened";
+    }
+    else
+      $result = true;
+      
+    return $result;
+  }
+  
+  protected function handle_call_result($res, $cur, $sql)
+  {
+    if ($res < 0)
+    {
+      $res = $this->_raiseError($res, $this->useConnection ? $this->connectionId : $cur, array('sql' => $sql));
+//      if ($res != self::LINTER_EMPTY_DATASET)
+//      {
+//        var_dump($sql);
+//        var_dump($res);
+//      }
+      if (!$this->useConnection)
+      {
+        linter_close_cursor($cur);
+        unset($this->cursorPool[$cur]);
+      }
+      return $res;
+    }
+    else
+      return $cur;
+  }
+  
+  function prepare($sql)
+  {
+    $result = null;
+    $sql = $this->prepare_sql($sql);
+    
+    $result = $this->handle_cursor_pool();
+    
+    $res = linter_prepare($this->useConnection ? $this->connectionId : $result, $sql);
+    return $this->handle_call_result($res, $result, $sql);
+  }
+  
+  function execute($sql)
+  {
+    $result = null;
+    $sql = $this->prepare_sql($sql);
+    
+    $result = $this->handle_cursor_pool();
+    $res = linter_exec_direct($this->useConnection ? $this->connectionId : $result, $sql);
+    
+    return $this->handle_call_result($res, $result, $sql);
+  }
+  
+  function pexecute($curId, $args)
+  {
+    $result = linter_execute($curId, $args);
+    return $this->handle_call_result($result, $curId, "");
+  }
+  
+  function cexecute($sql)
+  {
+    $this->useConnection = true;
+    $res = $this->execute($sql);
+    $this->useConnection = false;
+    return $res;
+  }
+
+  function beginTransaction()
+  {
+    $this->check_mode();
+    $this->transactionCount += 1;
+    return $this->cexecute('set savepoint sp' . $this->transactionCount . ';');
+  }
+
+  function commitTransaction()
+  {
+    $this->check_mode();
+    $result = $this->cexecute('commit to savepoint sp' . $this->transactionCount . ';');
+    if ($this->transactionCount) $this->transactionCount -= 1;
+    return $result;
+  }
+
+  function rollbackTransaction()
+  {
+    if ($this->transactionCount === 0) return false;
+    $this->check_mode();
+    $result = $this->cexecute('rollback to savepoint sp' . $this->transactionCount . ';');
+    if ($this->transactionCount) $this->transactionCount -= 1;
+    return $result;
+  }
+
+  function check_mode()
+  {
+    if (!($this->mode & TM_EXCLUSIVE))
+    {
+      $this->disconnect();
+      $this->mode |= TM_EXCLUSIVE;
+      $this->connect();
+    }
+  }
+  
+  function newStatement($sql)
+  {
+    if(preg_match('/^\s*\(*\s*(\w+).*$/m', $sql, $match))
+      $statement = $match[1];
+    else
+      $statement = $sql;
+      
+    switch(strtoupper($statement))
+    {
+      case 'SELECT':
+      case 'SHOW':
+      case 'DESCRIBE':
+      case 'EXPLAIN':
+      return new lmbLinterQueryStatement($this, $sql);
+      case 'DROP':
+      return new lmbLinterDropStatement($this, $sql);
+      case 'INSERT':
+      return new lmbLinterInsertStatement($this, $sql);
+      case 'UPDATE':
+      case 'DELETE':
+      return new lmbLinterManipulationStatement($this, $sql);
+      default:
+      return new lmbLinterStatement($this, $sql);
+    }
+  }
+
+  function getTypeInfo()
+  {
+    return new lmbLinterTypeInfo();
+  }
+
+  function getDatabaseInfo()
+  {
+    return new lmbLinterDbInfo($this, $this->config['database'], true);
+  }
+
+  function quoteIdentifier($id)
+  {
+    if(!$id)
+      return '';
+      
+    $pieces = explode('.', $id);
+    $quoted = '"' . $pieces[0] . '"';
+    if(isset($pieces[1]))
+       $quoted .= '."' . $pieces[1] . '"';
+       
+    return $quoted;
+  }
+
+  function escape($string)
+  {
+    $string = str_replace("'", "''", $string);
+    return $string;
+  }
+  
+  function escapeTableName($sql)
+  {
+    if (preg_match("#(insert into|create table|from|alter table|update)(\s+)([a-zA-Z_]+)(\s|$)#siU", $sql, $matches, PREG_OFFSET_CAPTURE))
+    {
+      if ($sql[$matches[3][1]] != '"' && $sql[$matches[3][1]+strlen($matches[1][0])] != '#')
+        $sql = preg_replace("#(insert into|create table|from|alter table|update)(\s+){$matches[3][0]}#siU", '$1$2"'.$matches[3][0].'"', $sql);
+    }
+    return $sql;
+  }
+
+  function escapeInsertFields($sql)
+  {
+    if (preg_match("#insert into .+\((.+)\) values#siU", $sql, $matches))
+    {
+      $fields_str = $matches[1];
+      $fields_arr = explode(",", $fields_str);
+      foreach ($fields_arr as $key => $field)
+      {
+        $field = trim($field);
+        if ($field{0} != '"' && $field{strlen($field)-1} != '"')
+          $fields_arr[$key] = '"' . $field . '"';
+      }
+      $sql = preg_replace("#(insert into .+\()(.+)(\) values)#siU", "\\1" . implode(", ", $fields_arr) . "\\3", $sql);
+    }
+    return $sql;
+  }
+  
+  function getSequenceValue($table, $colname)
+  {
+    return (int)($this->newStatement("SELECT last_autoinc")->getOneValue());
+  }
+  
+  
+  protected function map_charset($charset)
+  {
+    switch ($charset)
+    {
+      case "utf-8":
+      case "utf8":
+      case "UTF-8":
+      case "UTF8":
+      case "unicode":
+      case "UNICODE":
+        return "UTF-8";
+        break;
+      case "windows-1251";
+      case "Windows-1251":
+      case "cp1251":
+      case "CP1251":
+      default:
+        return "CP1251";
+        break;
+    }
+  }
+  
+  function getMbCharset()
+  {
+    if (!isset($this->config['charset']))
+    {
+      return 'Windows-1251';
+    }
+    switch ($this->config['charset'])
+    {
+      case "utf-8":
+      case "utf8":
+      case "UTF-8":
+      case "UTF8":
+      case "unicode":
+      case "UNICODE":
+        return "UTF-8";
+        break;
+      case "windows-1251";
+      case "Windows-1251":
+      case "cp1251":
+      case "CP1251":
+      default:
+        return "Windows-1251";
+        break;
+    }
+    
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterDbInfo.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterDbInfo.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterDbInfo.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,63 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+lmb_require('limb/dbal/src/drivers/lmbDbInfo.class.php');
+lmb_require('limb/dbal/src/drivers/linter/lmbLinterTableInfo.class.php');
+
+/**
+ * class lmbLinterDbInfo.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterDbInfo extends lmbDbInfo
+{
+  protected $connection;
+  protected $isExisting = false;
+  protected $isTablesLoaded = false;
+
+  function __construct($connection, $name, $isExisting = false)
+  {
+    $this->connection = $connection;
+    $this->isExisting = $isExisting;
+    parent::__construct($name);
+  }
+
+  function getConnection()
+  {
+    return $this->connection;
+  }
+
+  function loadTables()
+  {
+    if($this->isExisting && !$this->isTablesLoaded)
+    {
+
+      $result = $this->connection->execute("select TABLE_NAME from TABLES WHERE TABLE_TYPE='TABLE' ORDER BY TABLE_NAME");
+
+      while(is_array($row = linter_fetch_array($result)))
+        $this->tables[$row['TABLE_NAME']] = $row['TABLE_NAME'];
+
+      $this->connection->closeCursor($result);
+      $this->isTablesLoaded = true;
+    }
+  }
+
+  function getTable($name)
+  {
+    if(!$this->hasTable($name))
+      throw new lmbDbException('Table does not exist ' . $name);
+      
+    if(!is_object($this->tables[$name]))
+      $this->tables[$name] = new lmbLinterTableInfo($this, $name, true, $this->tables[$name]);
+      
+    return $this->tables[$name];
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterDropStatement.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterDropStatement.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterDropStatement.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,33 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+
+lmb_require(dirname(__FILE__) . '/lmbLinterStatement.class.php');
+
+/**
+ * class lmbLinterDropStatement.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterDropStatement extends lmbLinterStatement
+{
+  function execute()
+  {
+    try
+    {
+      $this->queryId = @$this->connection->execute($this->getSQL());
+      return $this->queryId;
+    }
+    catch(lmbException $e)
+    {
+    }
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterInsertStatement.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterInsertStatement.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterInsertStatement.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,39 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+lmb_require('limb/dbal/src/drivers/lmbDbInsertStatement.interface.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterManipulationStatement.class.php');
+
+/**
+ * class lmbLinterInsertStatement.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterInsertStatement extends lmbLinterManipulationStatement implements lmbDbInsertStatement
+{
+  function insertId($field_name = 'id')
+  {
+    $this->execute();
+
+    if(isset($this->parameters[$field_name]) && !empty($this->parameters[$field_name]))
+      return $this->parameters[$field_name];
+    else
+      return $this->connection->getSequenceValue(0, 0);
+  }
+
+  function _retriveTableName($sql)
+  {
+    preg_match('/INSERT\s+INTO\s+(\S+)/i', $sql, $m);
+    //removing possible quotes
+    $m[1] = str_replace('"','',$m[1]);
+    return $m[1];
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterManipulationStatement.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterManipulationStatement.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterManipulationStatement.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,136 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+lmb_require('limb/dbal/src/drivers/lmbDbManipulationStatement.interface.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterStatement.class.php');
+
+/**
+ * class lmbLinterManipulationStatement.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterManipulationStatement extends lmbLinterStatement implements lmbDbManipulationStatement
+{
+  protected $queryId;
+  protected $hasBlobs = false;
+  protected $blobs = array();
+  protected $tbl = null;
+  protected $isUpdateQuery = false;
+  protected $tableName;
+  protected $whereCondition;
+  protected $queryChecked = false;
+
+  function getAffectedRowCount()
+  {
+    if($this->queryId > 0)
+      return linter_get_cursor_opt($this->queryId, CO_ROW_COUNT);
+  }
+
+  
+  function execute()
+  {
+    $this->checkQuery();
+    if ($this->isUpdateQuery && $this->hasBlobs)
+    {
+      $pk = $this->tbl->getPrimaryKey();
+      $sql = 'select * from "' . $this->tableName . '" ' . $this->whereCondition.';';
+      $stmt = $this->connection->newStatement($sql);
+      if (preg_match_all("#:(.+):#Us", $this->whereCondition, $matches, PREG_SET_ORDER))
+      {
+        foreach ($matches as $match)
+        {
+          if (isset($this->parameters[$match[1]]))
+            $stmt->set($match[1], $this->parameters[$match[1]]);
+        }
+      }
+      $rs = $stmt->getRecordset();
+      if ($rs->count() > 1 && count($pk))
+      {
+        foreach ($rs as $k => $record)
+        {
+          $sql = 'UPDATE "' . $this->tableName . '" SET';
+          
+          foreach ($this->blobs as $name=>$value)
+            $sql .= '"' . $name . '" = :' . $name . ':, ';
+            
+          $sql = substr($sql, 0, strlen($sql)-2);
+          $sql .= ' WHERE ';
+          
+          foreach ($pk as $key)
+            $sql .= '"' . $key . '" = :' . $key . ': AND ';
+            
+          $sql = substr($sql, 0, strlen($sql)-4);
+          $s = $this->connection->newStatement($sql);
+          
+          foreach ($this->blobs as $name => $value)
+            $s->set($name, $value);
+            
+          foreach ($pk as $key)
+            $s->set($key, $record->get($key));
+            
+          $s->execute();
+        }
+      }
+    }
+    $this->queryId = parent :: execute();
+    return $this->queryId;
+  }
+  
+  protected function checkQuery()
+  {
+    if (!$this->queryChecked)
+    {
+      if (preg_match("#^\s*update\s+(\S+)\s+set.+(WHERE.+)?$#siU", $this->sql, $m))
+      {
+        $this->isUpdateQuery = true;
+        $this->tableName = str_replace('"', '', $m[1]);
+        
+        if (isset($m[2]))
+          $this->whereCondition = $m[2];
+          
+        $this->getTable();
+      }
+      $this->queryChecked = true;
+    }
+  }
+  
+  function set($name, $value)
+  {
+    $this->checkQuery();
+    if ($this->isUpdateQuery && $this->tbl->hasColumn($name) && $this->tbl->getColumn($name)->getType() == LIMB_DB_TYPE_BLOB)
+      $this->setBlob($name, $value);
+    else
+      parent::set($name, $value);
+  }
+  
+  protected function getTable()
+  {
+    if (is_null($this->tbl))
+      $this->tbl = new lmbLinterTableInfo($this->connection->getDatabaseInfo(), $this->tableName);
+  }
+  
+  function setBlob($name, $value)
+  {
+    $this->checkQuery();
+    $this->hasBlobs = true;
+    $this->blobs[$name] = $value;
+    parent::setBlob($name, $value);
+  }
+  
+  function setClob($name, $value)
+  {
+    $this->checkQuery();
+    $this->hasBlobs = true;
+    $this->blobs[$name] = $value;
+    parent::setClob($name, $value);
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterQueryStatement.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterQueryStatement.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterQueryStatement.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,59 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+lmb_require('limb/dbal/src/drivers/lmbDbQueryStatement.interface.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterStatement.class.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterRecord.class.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterRecordSet.class.php');
+lmb_require(dirname(__FILE__) . '/lmbLinterArraySet.class.php');
+
+/**
+ * class lmbLinterQueryStatement.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterQueryStatement extends lmbLinterStatement implements lmbDbQueryStatement
+{
+  function getOneRecord()
+  {
+    $record = new lmbLinterRecord();
+    $queryId = $this->execute();
+    $values = linter_get_data_array($queryId);
+    $record->import($values);
+    $this->free();
+    return $record;
+  }
+
+  function getOneValue()
+  {
+    $queryId = $this->execute();
+    $row = linter_get_data_row($queryId);
+    $this->free();
+    if(is_array($row) && count($row))
+      return $row[0];
+  }
+
+  function getOneColumnAsArray()
+  {
+    $column = array();
+    $queryId = $this->execute();
+    while(is_array($row = linter_fetch_row($queryId)))
+      $column[] = $row[0];
+    $this->free();
+    return $column;
+  }
+
+  function getRecordSet()
+  {
+    return new lmbLinterRecordSet($this->connection, $this);
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterRecord.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterRecord.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterRecord.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,162 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+lmb_require('limb/dbal/src/drivers/lmbDbBaseRecord.class.php');
+
+/**
+ * class lmbLinterRecord.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterRecord extends lmbDbBaseRecord
+{
+  protected $properties = array();
+
+  function __construct($data = array())
+  {
+    $this->properties = $data;
+  }
+
+  function get($name, $default = LIMB_UNDEFINED)
+  {
+    if(isset($this->properties[$name]))
+      return $this->properties[$name];
+    if(LIMB_UNDEFINED != $default)
+      return $default;
+  }
+
+  function set($name, $value)
+  {
+    $this->properties[$name] = $value;
+  }
+
+  function export()
+  {
+    return $this->properties;
+  }
+
+  function import($values)
+  {
+    $this->properties = $values;
+  }
+
+  function remove($name)
+  {
+    if(isset($this->properties[$name]))
+      unset($this->properties[$name]);
+  }
+
+  function has($name)
+  {
+    return isset($this->properties[$name]);
+  }
+
+  function reset()
+  {
+    $this->properties = array();
+  }
+
+  function getInteger($name)
+  {
+    $value = $this->get($name);
+    return is_null($value) ?  null : (int) $value;
+  }
+
+  function getFloat($name)
+  {
+    $value = $this->get($name);
+    return is_null($value) ?  null : (float) $value;
+  }
+
+  function getString($name)
+  {
+    $value = $this->get($name);
+    return is_null($value) ?  null : (string) $value;
+  }
+
+  function getBoolean($name)
+  {
+    $value = $this->get($name);
+    if(is_null($value))
+      return null;
+
+    return $value == 'TRUE' ?  true : false;
+  }
+  
+  
+  
+
+  function getIntegerTimeStamp($name)
+  {
+    $value = $this->get($name);
+    if(is_integer($value))
+      return $value;
+    elseif ($value == '0000-00-00 00:00:00' || $value == '' || $value == 'NULL' || preg_match("#^[0:\. ]+$#", $value))
+      return null;
+    else if(is_string($value))
+    {
+      $ts = strtotime($value);
+      if($ts === -1)
+      {
+        if(preg_match('/([\d]{4})([\d]{2})([\d]{2})([\d]{2})([\d]{2})([\d]{2})/', $value, $matches))
+          return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
+      }
+      else
+        return $ts;
+    }
+  }
+
+  function _getDate($name, $format)
+  {
+    $value = $this->get($name);
+    if(is_integer($value))
+      return date($format, $value);
+    elseif ($value == '0000-00-00 00:00:00' || $value == '' || $value == 'NULL' || preg_match("#^[0:\. ]+$#", $value))
+      return null;
+    else
+    {
+      $value = strtotime($value);
+      return date($format, $value);
+    }
+  }
+
+  function getStringDate($name)
+  {
+    return $this->_getDate($name, 'Y-m-d');
+  }
+
+  function getStringTime($name)
+  {
+    return $this->_getDate($name, 'H:i:s');
+  }
+
+  function getStringTimeStamp($name)
+  {
+    return $this->_getDate($name, 'Y-m-d H:i:s');
+  }
+
+  function getStringFixed($name)
+  {
+    $value = $this->get($name);
+    return is_null($value) ?  null : (string) $value;
+  }
+
+  function getBlob($name)
+  {
+    $value = $this->get($name);
+    return is_null($value) ?  null : ($value);
+  }
+
+  function getClob($name)
+  {
+    return $this->get($name);
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterRecordSet.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterRecordSet.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterRecordSet.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,129 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+lmb_require('limb/dbal/src/drivers/lmbDbBaseRecordSet.class.php');
+lmb_require('limb/dbal/src/drivers/linter/lmbLinterRecord.class.php');
+
+/**
+ * class lmbLinterRecordSet.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterRecordSet extends lmbDbBaseRecordSet
+{
+  protected $queryId;
+  protected $stmt;
+  protected $connection;
+
+  protected $current;
+  protected $valid;
+  protected $key;
+
+  function __construct($connection, $stmt)
+  {
+    $this->connection = $connection;
+    $this->stmt = $stmt;
+  }
+
+  function freeQuery()
+  {
+    if(isset($this->queryId) && $this->queryId > 0)
+    {
+      $this->connection->closeCursor($this->queryId);
+      $this->queryId = null;
+    }
+  }
+
+  function rewind()
+  {
+    if(isset($this->queryId) && $this->queryId > 0 && linter_get_cursor_opt($this->queryId, CO_ROW_COUNT))
+    {
+      $ret = linter_fetch($this->queryId, 1, FETCH_ABSNUM);
+      
+      if( $ret < 0)
+        $this->connection->_raiseError($ret, $this->queryId);
+    }
+    elseif(!$this->queryId)
+    {
+
+      if(is_array($this->sort_params))
+        $this->stmt->addOrder($this->sort_params);
+
+      if($this->limit)
+        $this->stmt->addLimit($this->offset, $this->limit);
+        
+      $this->queryId = $this->stmt->execute();
+    }
+    $this->key = 1;
+    $this->next();
+  }
+
+  function next()
+  {
+    $this->current = new lmbLinterRecord();
+    $values = linter_fetch_array($this->queryId);
+    $this->current->import($values);
+    $this->valid = is_array($values);
+    $this->key++;
+  }
+
+  function valid()
+  {
+    return $this->valid;
+  }
+
+  function current()
+  {
+    return $this->current;
+  }
+
+  function key()
+  {
+    return $this->key;
+  }
+
+  
+  function at($pos)
+  {
+    $stmt = clone $this->stmt;
+    if($this->sort_params)
+      $stmt->addOrder($this->sort_params);
+    $stmt->addLimit($pos, 1);
+
+    $queryId = $stmt->execute();
+    $arr = linter_fetch_array($queryId);
+    if ($this->queryId > 0)
+      $this->connection->closeCursor($queryId);
+    
+    if (is_array($arr))
+    {
+      $record = new lmbLinterRecord();
+      $record->import($arr);
+      return $record;
+    }
+    
+  }
+  
+
+  function countPaginated()
+  {
+    if(is_null($this->queryId))
+      $this->rewind();
+    return linter_get_cursor_opt($this->queryId, CO_ROW_COUNT);
+  }
+
+  function count()
+  {
+    return $this->stmt->count();
+  }
+  
+}
+
+

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterStatement.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterStatement.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterStatement.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,305 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+lmb_require('limb/dbal/src/drivers/lmbDbStatement.interface.php');
+
+/**
+ * class lmbLinterStatement.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterStatement implements lmbDbStatement
+{
+  protected $sql;
+  protected $prepared_sql;
+  protected $statement;
+  protected $connection;
+  protected $parameters = array();
+  protected $queryId;
+  protected $prepRequired = false;
+  protected $prepParams = array();
+
+  function __construct($connection, $sql)
+  {
+    $this->sql = $sql;
+    $this->connection = $connection;
+  }
+
+  function setNull($name)
+  {
+    $this->parameters[$name] = 'null';
+  }
+
+  function setSmallInt($name, $value)
+  {
+    $this->parameters[$name] = is_null($value) ?  'null' : intval($value);
+  }
+
+  function setInteger($name, $value)
+  {
+    $this->parameters[$name] = is_null($value) ?  'null' : intval($value);
+  }
+
+  function setFloat($name, $value)
+  {
+    $this->parameters[$name] = is_null($value) ?
+    'null' :
+    floatval($value);
+  }
+
+  function setDouble($name, $value)
+  {
+    if(is_float($value) || is_integer($value))
+      $this->parameters[$name] = $value;
+    else if(is_string($value) && preg_match('/^(|-)\d+(|.\d+)$/', $value))
+      $this->parameters[$name] = $value;
+    else
+      $this->parameters[$name] = 'null';
+  }
+
+  function setDecimal($name, $value)
+  {
+    if(is_float($value) || is_integer($value))
+      $this->parameters[$name] = $value;
+    else if(is_string($value) && preg_match('/^(|-)\d+(|.\d+)$/', $value))
+      $this->parameters[$name] = $value;
+    else
+      $this->parameters[$name] = 'null';
+  }
+
+  function setBoolean($name, $value)
+  {
+    $this->parameters[$name] = is_null($value) ?
+    'null' :(($value) ?  "TRUE" : "FALSE");
+  }
+
+  function setChar($name, $value)
+  {
+    $this->parameters[$name] = is_null($value) ?
+    'null' : $value;
+  }
+
+  function setVarChar($name, $value)
+  {
+    $this->parameters[$name] = is_null($value) ?
+    'null' : $value;
+  }
+
+  function setClob($name, $value)
+  {
+    $this->parameters[$name] = is_null($value) ?
+    'null' : $value;
+  }
+
+  protected function _setDate($name, $value, $format)
+  {
+    if(is_int($value))
+      $this->parameters[$name] = date($format, $value);
+    else if(is_string($value))
+      $this->parameters[$name] = date($format, strtotime($value));
+    else
+      $this->parameters[$name] = 'null';
+  }
+
+  function setDate($name, $value)
+  {
+    $this->_setDate($name, $value, 'Y-m-d');
+  }
+
+  function setTime($name, $value)
+  {
+    $this->_setDate($name, $value, 'Y-m-d H:i:s');
+  }
+
+  function setTimeStamp($name, $value)
+  {
+    $this->_setDate($name, $value, 'Y-m-d H:i:s');
+  }
+
+  function setBlob($name, $value)
+  {
+    $this->parameters[$name] = is_null($value) ?
+    'null' : $value;
+  }
+
+  function nullDateValue()
+  {
+    return '00.00.0000 00:00:00';
+  }
+  
+  function set($name, $value)
+  {
+    if(is_string($value))
+      $this->setChar($name, $value);
+    else if(is_int($value))
+      $this->setInteger($name, $value);
+    else if(is_bool($value))
+      $this->setBoolean($name, $value);
+    else if(is_float($value))
+      $this->setFloat($name, $value);
+    else
+      $this->setNull($name);
+  }
+
+  function import($paramList)
+  {
+    foreach($paramList as $name=>$value)
+    {
+      $this->set($name, $value);
+    }
+  }
+
+  function getSQL()
+  {
+    if (is_null($this->prepared_sql))
+      return $this->sql;
+    else
+      return $this->prepared_sql;
+  }
+
+  function execute()
+  {
+    $this->_prepareStatement();
+    if ($this->prepRequired)
+      return $this->connection->pexecute($this->queryId, $this->prepParams);
+    else
+    {
+      $this->queryId = $this->connection->execute($this->getSQL());
+      $this->prepared_sql = null;
+      return $this->queryId;
+    }
+  }
+  
+  function setConnection($connection)
+  {
+    $this->connection = $connection;
+  }
+  
+  function free()
+  {
+    $this->connection->closeCursor($this->queryId);    
+  }
+  
+  
+  protected function _prepareStatement()
+  {
+    $sql = $this->checkForParams($this->sql);
+    if (!is_null($sql))
+    {
+      $this->queryId = $this->connection->prepare($sql);
+  
+      if($this->queryId < 0)
+      {
+        $this->connection->_raiseError();
+        return;
+      }
+    }
+  }
+  
+  protected function check_type($param)
+  {
+    if (is_string($param)) 
+      return "'".$this->connection->escape($param)."'";
+    else
+      return $param;
+  }
+  
+  protected function checkForParams($sql)
+  {
+    $newsql = '';
+    $iter = 0;
+    $nulls = false;
+
+    if (preg_match("#^select :(\w+):;?$#i", $sql, $m))
+    {
+      $this->prepRequired = false;
+      if (isset($this->parameters[$m[1]]))
+      {
+        $sql = str_replace(":".$m[1].":", $this->check_type($this->parameters[$m[1]]), $sql);
+        $this->prepared_sql = $sql;
+        return null;
+      }
+      else
+      {
+        $this->prepared_sql = "select null;";
+        return null;
+      }
+    }
+    while(preg_match('/^(\'[^\']*?\')|(--[^(\n)]*?\n)|(:(?-U)\w+:(?U))|.+/Us', $sql, $matches))
+    {
+      if(isset($matches[3]))
+      {
+        $param = str_replace(':', '', $matches[0]);
+
+        if(!array_key_exists($param, $this->parameters))
+          $this->parameters[$param] = null;
+          
+        if (is_null($this->parameters[$param]) || $this->parameters[$param] == "null")
+        {
+          $newsql .= 'null';
+          $nulls = true;
+        }
+        else
+        {
+          $this->prepParams[] = $this->parameters[$param];
+          $newsql .= ":p_$param";
+          $iter++;
+        }
+      }
+      else
+        $newsql .= $matches[0];
+
+      $sql = substr($sql, strlen($matches[0]));
+    }
+    
+    if ($iter > 0)
+      $this->prepRequired = true;
+    else
+      $this->prepRequired = false;
+      
+    if ($nulls)
+      $this->prepared_sql = $newsql;
+      
+    return $newsql;
+  }
+
+  function addOrder($sort_params)
+  {
+    if(preg_match('~(?<=FROM).+\s+ORDER\s+BY\s+~i', $this->sql))
+      $this->sql .= ',';
+    else
+      $this->sql .= ' ORDER BY ';
+
+    foreach($sort_params as $field => $order)
+      $this->sql .= $this->connection->quoteIdentifier($field) . " $order,";
+
+    $this->sql = rtrim($this->sql, ',');
+  }
+  
+  function addLimit($offset, $limit)
+  {
+        $this->sql .= ' LIMIT ' . $offset . ', ' . $limit;
+  }
+  
+  function count()
+  {
+    if (!$this->queryId)
+      $this->execute();
+      
+    if ($this->queryId == lmbLinterConnection::LINTER_EMPTY_DATASET)
+      return 0;
+      
+    return linter_get_cursor_opt($this->queryId, CO_ROW_COUNT);
+  }
+    
+  
+  
+}
+
+

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterTableInfo.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterTableInfo.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterTableInfo.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,74 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+lmb_require('limb/dbal/src/drivers/lmbDbTableInfo.class.php');
+lmb_require('limb/dbal/src/drivers/linter/lmbLinterColumnInfo.class.php');
+
+/**
+ * class lmbLinterTableInfo.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterTableInfo extends lmbDbTableInfo
+{
+  protected $database;
+
+  protected $isColumnsLoaded = false;
+
+
+  function __construct($database, $name)
+  {
+    parent::__construct($name);
+    $this->database = $database;
+  }
+
+  //Based on code from Creole
+  function loadColumns()
+  {
+      $connection = $this->database->getConnection();
+
+      $result = $connection->execute(sprintf("select * from COLUMNS where TABLE_NAME='%s'", $this->name));
+
+      while(is_array($row = linter_fetch_array($result)))
+      {
+        $column = new lmbLinterColumnInfo($this, $row['COLUMN_NAME'], str_replace(" AUTOINC", "", $row['TYPE_NAME']), $row['COLUMN_SIZE'], 
+                      $row['DECIMAL_DIGITS'], $row['NULLABLE'], null, (strpos($row['TYPE_NAME'], 'AUTOINC') !== false)
+        );
+        $name = $row['COLUMN_NAME'];
+
+        $this->columns[$name] = $column;
+      }
+
+      $this->isColumnsLoaded = true;
+  }
+  
+  function getPrimaryKey()
+  {
+	  $sql = 'SELECT * FROM PRIMARY_KEYS WHERE TABLE_NAME = \'%s\'';
+		$sql = sprintf($sql, $this->name);
+		$stmt = $this->database->getConnection()->newStatement($sql);
+		$rs = $stmt->getRecordset();
+		$keys = array();
+		
+		foreach ($rs as $k => $record)
+		  $keys[] = $record->get('COLUMN_NAME');
+		  
+		$rs->freeQuery();
+		return $keys;		
+    
+  }
+  
+  function getDatabase()
+  {
+    return $this->database;
+  }
+
+}
+
+

Added: 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterTypeInfo.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterTypeInfo.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/drivers/linter/lmbLinterTypeInfo.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,44 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+lmb_require('limb/dbal/src/drivers/lmbDbTypeInfo.class.php');
+
+/**
+ * class lmbLinterTypeInfo.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterTypeInfo extends lmbDbTypeInfo
+{
+  function getNativeToColumnTypeMapping()
+  {
+    return array(
+      'SMALLINT' => LIMB_DB_TYPE_SMALLINT,
+      'INTEGER' => LIMB_DB_TYPE_INTEGER,
+      'INT' => LIMB_DB_TYPE_INTEGER,
+      'BIGINT' => LIMB_DB_TYPE_DECIMAL,
+      'BYTE' => LIMB_DB_TYPE_CHAR,
+      'NCHAR_VARYING' => LIMB_DB_TYPE_VARCHAR,
+      'REAL' => LIMB_DB_TYPE_FLOAT,
+      'FLOAT' => LIMB_DB_TYPE_FLOAT,
+      'cash' => LIMB_DB_TYPE_FLOAT,
+      'money' => LIMB_DB_TYPE_FLOAT,
+      'DECIMAL' => LIMB_DB_TYPE_DECIMAL,
+      'NUMERIC' => LIMB_DB_TYPE_DECIMAL,
+      'DOUBLE' => LIMB_DB_TYPE_DOUBLE,
+      'CHAR' => LIMB_DB_TYPE_CHAR,
+      'CHARACTER' => LIMB_DB_TYPE_CHAR,
+      'VARCHAR' => LIMB_DB_TYPE_VARCHAR,
+      'DATE' => LIMB_DB_TYPE_DATE,
+      'BLOB' => LIMB_DB_TYPE_BLOB,
+      'BOOLEAN' => LIMB_DB_TYPE_BOOLEAN
+   );
+  }
+}
+

Added: 3.x/trunk/limb/dbal/src/dump/lmbLinterDumpLoader.class.php
===================================================================
--- 3.x/trunk/limb/dbal/src/dump/lmbLinterDumpLoader.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/src/dump/lmbLinterDumpLoader.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,112 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html
+ */
+lmb_require('limb/dbal/src/lmbSimpleDb.class.php');
+lmb_require('limb/fs/src/exception/lmbFileNotFoundException.class.php');
+
+/**
+ * class lmbLinterDumpLoader.
+ *
+ * @package dbal
+ * @version $Id: $
+ */
+class lmbLinterDumpLoader
+{
+  protected $affected_tables = array();
+  protected $statements = array();
+
+  function __construct($file_path = null)
+  {
+    if($file_path)
+      $this->loadFile($file_path);
+  }
+
+  function getStatements()
+  {
+    return $this->statements;
+  }
+
+  function cleanTables($connection)
+  {
+    $db = new lmbSimpleDb($connection);
+
+    foreach($this->affected_tables as $table)
+      $db->delete($table);
+  }
+
+  function getAffectedTables()
+  {
+    return $this->affected_tables;
+  }
+
+  function execute($connection, $regex = '')
+  {
+    foreach($this->statements as $sql)
+    {
+      if($regex && !preg_match($regex, $sql, $m))
+        continue;
+
+      $stmt = $connection->newStatement($sql);
+      $stmt->execute();
+    }
+  }
+
+  function loadFile($file_path)
+  {
+    if(!file_exists($file_path))
+      throw new lmbFileNotFoundException($file_path);
+
+    $this->loadStatements(file_get_contents($file_path));
+  }
+
+  function loadStatements($sql)
+  {
+    $this->statements = $this->_retrieveStatements($sql);
+    $this->affected_tables = $this->_getAffectedTables($this->statements);
+  }
+
+  protected function _getAffectedTables($stmts)
+  {
+    $affected_tables = array();
+    foreach($stmts as $sql)
+    {
+      if(preg_match("|insert\s+?into\s+?([^\s]+)|i", $sql, $matches))
+      {
+        if(!in_array($matches[1], $affected_tables))
+        {
+          $affected_tables[] = $this->_processTableName($matches[1]);
+        }
+      }
+    }
+    return $affected_tables;
+  }
+
+  protected function _processTableName($name)
+  {
+    return $name;
+  }
+
+  protected function _retrieveStatements($raw_sql)
+  {
+    //naive implementation
+    $stmts = preg_split('/;\s*\n/', $raw_sql);
+    $processed = array();
+    foreach($stmts as $stmt)
+    {
+      if($stmt = $this->_processStatement($stmt))
+        $processed[] = $stmt;
+    }
+    return $processed;
+  }
+
+  protected function _processStatement($sql)
+  {
+    return $sql;
+  }
+}
+

Added: 3.x/trunk/limb/dbal/tests/bench/fetching_linter.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/bench/fetching_linter.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/bench/fetching_linter.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,68 @@
+<?php
+
+set_include_path(dirname(__FILE__) . '/../../../../');
+
+$mark = microtime(true);
+
+require_once('limb/core/common.inc.php');
+require_once('limb/dbal/common.inc.php');
+
+echo "dbal common includes: " . (microtime(true) - $mark) . "\n";
+
+$linter_db = linter_open_connect('SYSTEM', 'MANAGER', 'Demo', TM_AUTOCOMMIT);
+$cur = linter_open_cursor($linter_db);
+
+linter_exec_direct($cur, 'CREATE OR REPLACE TABLE "foo" ("bar" varchar(10));');
+linter_exec_direct($cur, 'INSERT INTO "foo" VALUES (\'some value\');');
+
+$mark = microtime(true);
+
+
+for($i=0;$i<1000;$i++)
+{
+  linter_exec_direct($cur, 'SELECT "bar" FROM "foo";');
+  while(is_array($entry = linter_fetch_array($cur)))
+   $bar = $entry['bar'];
+}
+
+echo "native linter fetching: " . (microtime(true) - $mark) . "\n";
+
+$conn = lmbDBAL :: newConnection('linter://SYSTEM:MANAGER@localhost/Demo');
+
+$mark = microtime(true);
+
+for($i=0;$i<1000;$i++)
+{
+  $rs = lmbDBAL :: fetch('SELECT "bar" FROM "foo";', $conn);
+  foreach($rs as $record)
+   $bar = $record['bar'];
+  $rs->freeQuery();
+}
+
+echo "lmbDBAL :: fetch(), array access: " . (microtime(true) - $mark) . "\n";
+
+$mark = microtime(true);
+
+for($i=0;$i<1000;$i++)
+{
+  $rs = lmbDBAL :: fetch('SELECT "bar" FROM "foo";', $conn);
+  foreach($rs as $record)
+   $bar = $record->get('bar');
+  $rs->freeQuery();
+}
+
+echo "lmbDBAL :: fetch(), getter: " . (microtime(true) - $mark) . "\n";
+
+$mark = microtime(true);
+
+for($i=0;$i<1000;$i++)
+{
+  $stmt = $conn->newStatement('SELECT "bar" FROM "foo";');
+  $rs = $stmt->getRecordSet();
+  foreach($rs as $record)
+   $bar = $record->get('bar');
+}
+
+echo "lmbLinterConnection :: newStatement(), getter: " . (microtime(true) - $mark) . "\n";
+
+linter_close_connect($linter_db);
\ No newline at end of file

Added: 3.x/trunk/limb/dbal/tests/bench/fetching_mysql.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/bench/fetching_mysql.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/bench/fetching_mysql.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,71 @@
+<?php
+
+set_include_path(dirname(__FILE__) . '/../../../../');
+
+$mark = microtime(true);
+
+require_once('limb/core/common.inc.php');
+require_once('limb/dbal/common.inc.php');
+
+echo "dbal common includes: " . (microtime(true) - $mark) . "\n";
+
+$mysql_db = mysql_connect('localhost', 'gfu', '1561611');
+mysql_select_db('gfu');
+
+mysql_query('CREATE TABLE foo (bar varchar(10))');
+mysql_query('INSERT INTO foo VALUES (\'some value\')');
+
+
+$mark = microtime(true);
+
+
+for($i=0;$i<1000;$i++)
+{
+  $q = mysql_query('SELECT bar FROM foo');
+  while($entry = mysql_fetch_assoc($q))
+   $bar = $entry['bar'];
+}
+
+echo "native mysql fetching: " . (microtime(true) - $mark) . "\n";
+
+$conn = lmbDBAL :: newConnection('mysql://gfu:1561611@localhost/gfu');
+
+$mark = microtime(true);
+
+for($i=0;$i<1000;$i++)
+{
+  $rs = lmbDBAL :: fetch('SELECT bar FROM foo', $conn);
+  foreach($rs as $record)
+   $bar = $record['bar'];
+  //$rs->freeQuery();
+}
+
+echo "lmbDBAL :: fetch(), array access: " . (microtime(true) - $mark) . "\n";
+
+$mark = microtime(true);
+
+for($i=0;$i<1000;$i++)
+{
+  $rs = lmbDBAL :: fetch('SELECT bar FROM foo', $conn);
+  foreach($rs as $record)
+   $bar = $record->get('bar');
+}
+
+echo "lmbDBAL :: fetch(), getter: " . (microtime(true) - $mark) . "\n";
+
+$mark = microtime(true);
+
+for($i=0;$i<1000;$i++)
+{
+  $stmt = $conn->newStatement('SELECT bar FROM foo');
+  $rs = $stmt->getRecordSet();
+  foreach($rs as $record)
+   $bar = $record->get('bar');
+}
+
+echo "lmbMysqlConnection :: newStatement(), getter: " . (microtime(true) - $mark) . "\n";
+
+
+mysql_query("drop table foo");
+
+mysql_close();
\ No newline at end of file

Added: 3.x/trunk/limb/dbal/tests/bench/fetching_pgsql.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/bench/fetching_pgsql.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/bench/fetching_pgsql.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,72 @@
+<?php
+
+set_include_path(dirname(__FILE__) . '/../../../../');
+
+$mark = microtime(true);
+
+require_once('limb/core/common.inc.php');
+require_once('limb/dbal/common.inc.php');
+
+echo "dbal common includes: " . (microtime(true) - $mark) . "\n";
+$conn_string = "host=sheep port=5432 dbname=test user=lamb password=bar";
+
+$pgsql_db = pg_connect('host=localhost user=php password=1561611 dbname=medkrug');
+
+pg_query($pgsql_db, 'CREATE TABLE foo (bar varchar(10))');
+pg_query($pgsql_db, 'INSERT INTO foo VALUES (\'some value\')');
+
+
+$mark = microtime(true);
+
+
+for($i=0;$i<1000;$i++)
+{
+  $q = pg_query($pgsql_db, 'SELECT bar FROM foo');
+  while($entry = pg_fetch_assoc($q))
+   $bar = $entry['bar'];
+}
+
+echo "native pgsql fetching: " . (microtime(true) - $mark) . "\n";
+
+$conn = lmbDBAL :: newConnection('pgsql://php:1561611@localhost/medkrug');
+
+$mark = microtime(true);
+
+for($i=0;$i<1000;$i++)
+{
+  $rs = lmbDBAL :: fetch('SELECT bar FROM foo', $conn);
+  foreach($rs as $record)
+   $bar = $record['bar'];
+  $rs->freeQuery();
+}
+
+echo "lmbDBAL :: fetch(), array access: " . (microtime(true) - $mark) . "\n";
+
+$mark = microtime(true);
+
+for($i=0;$i<1000;$i++)
+{
+  $rs = lmbDBAL :: fetch('SELECT bar FROM foo', $conn);
+  foreach($rs as $record)
+   $bar = $record->get('bar');
+  $rs->freeQuery();
+}
+
+echo "lmbDBAL :: fetch(), getter: " . (microtime(true) - $mark) . "\n";
+
+$mark = microtime(true);
+
+for($i=0;$i<1000;$i++)
+{
+  $stmt = $conn->newStatement('SELECT bar FROM foo');
+  $rs = $stmt->getRecordSet();
+  foreach($rs as $record)
+   $bar = $record->get('bar');
+}
+
+echo "lmbPgsqlConnection :: newStatement(), getter: " . (microtime(true) - $mark) . "\n";
+
+
+pg_query($pgsql_db, "drop table foo");
+
+pg_close($pgsql_db);
\ No newline at end of file

Added: 3.x/trunk/limb/dbal/tests/cases/.setup.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/.setup.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/.setup.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,5 @@
+<?php
+require_once(dirname(__FILE__) . '/../../../../setup.php');
+require_once(dirname(__FILE__) . '/../../common.inc.php');
+
+?>
\ No newline at end of file

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/.skipif.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/.skipif.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/.skipif.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,11 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+require_once('limb/dbal/common.inc.php');
+return lmbToolkit :: instance()->getDefaultDbConnection()->getType() != 'linter';
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/fixture.inc.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/fixture.inc.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/fixture.inc.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,104 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+function DriverLinterSetup($conn)
+{
+  $sql = 'DROP TABLE "founding_fathers" CASCADE;';
+  DriverLinterExec($conn, $sql);
+
+  $sql = '
+      CREATE OR REPLACE TABLE "founding_fathers" (
+        "id" INT NOT NULL AUTOINC,
+        "first" varchar(50) NOT NULL default \'\',
+        "last" varchar(50) NOT NULL default \'\',
+        PRIMARY KEY  ("id"));';
+  DriverLinterExec($conn, $sql);
+
+  $sql = 'DROP TABLE "standard_types" CASCADE;';
+  DriverLinterExec($conn, $sql);
+
+  $sql = '
+      CREATE OR REPLACE TABLE "standard_types" (
+          "id" INT NOT NULL AUTOINC,
+          "type_smallint" smallint,
+          "type_integer" integer,
+          "type_boolean" boolean,
+          "type_char" char(30),
+          "type_varchar" varchar(30),
+          "type_clob" blob,
+          "type_float" float,
+          "type_double" double precision,
+          "type_decimal" decimal (20, 2),
+          "type_timestamp" date,
+          "type_date" date,
+          "type_time" date,
+          "type_blob" blob,
+          PRIMARY KEY ("id"));';
+  DriverLinterExec($conn, $sql);
+
+  DriverLinterExec($conn, 'TRUNCATE TABLE "founding_fathers";');
+  DriverLinterExec($conn, 'TRUNCATE TABLE "standard_types";');
+
+  $inserts = array(
+      'INSERT INTO "founding_fathers" ("first", "last") VALUES (\'George\', \'Washington\');',
+      'INSERT INTO "founding_fathers" ("first", "last") VALUES (\'Alexander\', \'Hamilton\');',
+      'INSERT INTO "founding_fathers" ("first", "last") VALUES (\'Benjamin\', \'Franklin\');'
+  );
+
+  foreach($inserts as $sql)
+    DriverLinterExec($conn, $sql);
+}
+
+function DriverLinterExec($conn, $sql)
+{
+  $result = @linter_exec_direct($conn, $sql);
+  if($result < 0 && stripos($sql, 'DROP') === false)
+  { //ignoring drop errors
+    _raiseError($result, $conn, array('sql' => $sql));
+    throw new lmbDbException('Linter execute error happened: ' . $sql . linter_last_error($conn));
+  }
+}
+
+
+  function _raiseError($code, $conn_id = null, $args=array())
+  {
+    if($code == LPE_INVALID_CONNECT)
+    {
+      $err_code = -1;
+      $err_message = "Invalid connect";
+    }
+    elseif($code == LPE_LINTER_ERROR)
+    {
+      $lin_err = linter_last_error($conn_id, LINTER_ERROR);
+      $sys_err = linter_last_error($conn_id, SYSTEM_ERROR);
+      $err_message = linter_error_msg($conn_id);
+      $err_code = $lin_err;
+      var_dump($err_code);
+      var_dump($args['sql']);
+      if ($err_code <= 2 && $err_code > 0) return false;
+      if ($err_code >= 2000 && $err_code < 3000)
+      {
+        $err_row = $sys_err & 0xFFFF;
+        $err_pos = $sys_err >> 16;
+        $err_message .= sprintf(" at row %d, position %d", $err_row, $err_pos);
+      }
+      else
+        $err_message .= sprintf(", system error %d", $sys_err);
+    }
+    else
+    {
+      $err_message = sprintf("Linter extension error %d", $code);
+      $err_code = $code;
+    }
+    throw new lmbException("Database error: No:" . $err_code.". Description: ".$err_message);
+    return true;
+  }
+
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterColumnInfoTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterColumnInfoTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterColumnInfoTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,22 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+require_once(dirname(__FILE__) . '/../DriverColumnInfoTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterColumnInfoTest extends DriverColumnInfoTestBase
+{
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    parent::setUp();
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterConnectionTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterConnectionTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterConnectionTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,29 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+require_once(dirname(__FILE__) . '/../DriverConnectionTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterConnectionTest extends DriverConnectionTestBase
+{
+
+  function lmbLinterConnectionTest()
+  {
+    parent :: DriverConnectionTestBase('lmbLinterQueryStatement', 'lmbLinterInsertStatement', 'lmbLinterManipulationStatement', 'lmbLinterStatement');
+  }
+
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    parent::setUp();
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDbInfoTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDbInfoTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDbInfoTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,23 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+require_once(dirname(__FILE__) . '/../DriverDatabaseInfoTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterDbInfoTest extends DriverDatabaseInfoTestBase
+{
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    parent::setUp();
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDeleteTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDeleteTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDeleteTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,23 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+require_once(dirname(__FILE__) . '/../DriverDeleteTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterDeleteTest extends DriverDeleteTestBase
+{
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    parent::setUp();
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDriverTransactionTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDriverTransactionTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterDriverTransactionTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,48 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+require_once(dirname(__FILE__) . '/../DriverTransactionTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterDriverTransactionTest extends DriverTransactionTestBase
+{
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    parent::setUp();
+  }
+  
+  function testCommitTransaction()
+  {
+    $this->assertEqual($this->_countRecords(), 0);
+
+    $this->connection->beginTransaction();
+    $stmt = $this->connection->newStatement('INSERT INTO founding_fathers ("first", "last") VALUES (\'George\', \'Washington\');');
+    $stmt->execute();
+    $this->connection->commitTransaction();
+
+    $this->assertEqual($this->_countRecords(), 1);
+  }
+
+  function testRollbackTransaction()
+  {
+    $this->assertEqual($this->_countRecords(), 0);
+
+    $this->connection->beginTransaction();
+    $stmt = $this->connection->newStatement('INSERT INTO founding_fathers ("first", "last") VALUES (\'George\', \'Washington\')');
+    $stmt->execute();
+    $this->connection->rollbackTransaction();
+
+    $this->assertEqual($this->_countRecords(), 0);
+  }
+  
+}
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterInsertTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterInsertTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterInsertTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,103 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+require_once(dirname(__FILE__) . '/../DriverInsertTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterInsertTest extends DriverInsertTestBase
+{
+
+  function lmbLinterInsertTest()
+  {
+    parent :: DriverInsertTestBase('lmbLinterInsertStatement');
+  }
+
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    parent::setUp();
+  }
+
+  function testInsertIdShouldUseSequence()
+  {
+    $sql = '
+        INSERT INTO founding_fathers (
+            "first", "last"
+        ) VALUES (
+            :first:, :last:
+        )';
+    $stmt = $this->connection->newStatement($sql);
+    $stmt->setVarChar('first', 'Richard');
+    $stmt->setVarChar('last', 'Nixon');
+
+    $id = $stmt->insertId('id');
+    $this->assertTrue($id > 0);
+
+    $this->connection->newStatement("DELETE FROM founding_fathers")->execute();
+
+    $new_id = $stmt->insertId('id');
+    $this->assertEqual($new_id - $id, 1);
+  }
+  
+  function testInsert()
+  {
+    $sql = '
+          INSERT INTO founding_fathers (
+              "first", "last"
+          ) VALUES (
+              :first:, :last:
+          )';
+    $stmt = $this->connection->newStatement($sql);
+    $stmt->setVarChar('first', 'Richard');
+    $stmt->setVarChar('last', 'Nixon');
+    $stmt->execute();
+    $this->assertEqual($stmt->getAffectedRowCount(), 1);
+    $this->checkRecord(4);
+  }
+
+  function testInsertId()
+  {
+    $sql = '
+        INSERT INTO founding_fathers (
+            "first", "last"
+        ) VALUES (
+            :first:, :last:
+        )';
+    $stmt = $this->connection->newStatement($sql);
+    $this->assertIsA($stmt, $this->insert_stmt_class);
+
+    $stmt->setVarChar('first', 'Richard');
+    $stmt->setVarChar('last', 'Nixon');
+
+    $id = $stmt->insertId('id');
+    $this->assertEqual($stmt->getAffectedRowCount(), 1);
+    $this->assertIdentical($id, 4);
+    $this->checkRecord(4);
+  }
+  
+  function checkRecord($id)
+  {
+    $sql = 'SELECT * FROM founding_fathers WHERE "id" = :id:';
+    $stmt = $this->connection->newStatement($sql);
+    $stmt->setInteger('id', $id);
+    $record = $stmt->getOneRecord();
+    $this->assertNotNull($record);
+    if($record)
+    {
+      $this->assertEqual($record->get('id'), $id);
+      $this->assertEqual($record->get('first'), 'Richard');
+      $this->assertEqual($record->get('last'), 'Nixon');
+    }
+  }
+  
+  
+}
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterQueryTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterQueryTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterQueryTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,54 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+require_once(dirname(__FILE__) . '/../DriverQueryTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterQueryTest extends DriverQueryTestBase
+{
+
+  function lmbLinterQueryTest()
+  {
+    parent :: DriverQueryTestBase('lmbLinterRecord');
+  }
+
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    parent::setUp();
+  }
+
+
+  function testGetOneRecord()
+  {
+    $sql = 'SELECT * FROM founding_fathers WHERE "id" = 1';
+    $stmt = $this->connection->newStatement($sql);
+    $record = $stmt->getOneRecord();
+    $this->assertIsA($record, $this->record_class);
+    $this->assertEqual($record->get('id'), 1);
+    $this->assertEqual($record->get('first'), 'George');
+    $this->assertEqual($record->get('last'), 'Washington');
+  }
+
+  function testGetOneValue()
+  {
+    $sql = 'SELECT "first" FROM founding_fathers';
+    $stmt = $this->connection->newStatement($sql);
+    $this->assertEqual($stmt->getOneValue(), 'George');
+  }
+
+  function testGetOneColumnArray()
+  {
+    $sql = 'SELECT "first" FROM founding_fathers';
+    $stmt = $this->connection->newStatement($sql);
+    $testarray = array('George', 'Alexander', 'Benjamin');
+    $this->assertEqual($stmt->getOneColumnAsArray($sql), $testarray);
+  }
+}

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterRecordSetTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterRecordSetTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterRecordSetTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,93 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+require_once(dirname(__FILE__) . '/../DriverRecordSetTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterRecordSetTest extends DriverRecordSetTestBase
+{
+
+  function lmbLinterRecordSetTest()
+  {
+    parent :: DriverRecordSetTestBase('lmbLinterRecord');
+  }
+
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    $sql = 'SELECT "id", "first" FROM founding_fathers ORDER BY "id"';
+    $this->stmt = $this->connection->newStatement($sql);
+    $this->cursor = $this->stmt->getRecordSet();
+  }
+  
+  function testSort()
+  {
+    $sql = 'SELECT "id", "first" FROM founding_fathers';
+    $rs = $this->connection->newStatement($sql)->getRecordSet();
+    $rs->sort(array('id' => 'DESC'));
+
+    $rs->rewind();
+    $this->assertEqual($rs->current()->get('first'), 'Benjamin');
+    $rs->next();
+    $this->assertEqual($rs->current()->get('first'), 'Alexander');
+    $rs->next();
+    $this->assertEqual($rs->current()->get('first'), 'George');
+  }
+
+  function testSortPaginated()
+  {
+    $sql = 'SELECT "id", "first" FROM founding_fathers';
+    $rs = $this->connection->newStatement($sql)->getRecordSet();
+    $rs->sort(array('id' => 'DESC'));
+    $rs->paginate(0, 1);
+
+    $rs->rewind();
+    $this->assertEqual($rs->current()->get('first'), 'Benjamin');
+    $rs->next();
+    $this->assertFalse($rs->valid());
+  }
+
+  function testSortPreservesExistingOrderBy()
+  {
+    $sql = 'SELECT "id", "first" FROM founding_fathers ORdeR By "first"';
+    $rs = $this->connection->newStatement($sql)->getRecordSet();
+    $rs->sort(array('id' => 'DESC'));
+
+    $rs->rewind();
+    $this->assertEqual($rs->current()->get('first'), 'Alexander');
+    $rs->next();
+    $this->assertEqual($rs->current()->get('first'), 'Benjamin');
+    $rs->next();
+    $this->assertEqual($rs->current()->get('first'), 'George');
+  }
+
+
+  function testsAtAfterPagination()
+  {
+    $sql = 'SELECT "id", "first" FROM founding_fathers';
+    $rs = $this->connection->newStatement($sql)->getRecordSet();
+    $rs->paginate(1, 1);
+
+    $this->assertEqual($rs->at(0)->get('first'), 'George');
+  }
+
+  function testsAtAfterSort()
+  {
+    $sql = 'SELECT "id", "first" FROM founding_fathers';
+    $rs = $this->connection->newStatement($sql)->getRecordSet();
+    $rs->sort(array('id' => 'DESC'));
+
+    $this->assertEqual($rs->at(0)->get('first'), 'Benjamin');
+    $this->assertEqual($rs->at(1)->get('first'), 'Alexander');
+    $this->assertEqual($rs->at(2)->get('first'), 'George');
+  }
+  
+}
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterRecordTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterRecordTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterRecordTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,28 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+require_once(dirname(__FILE__) . '/../DriverRecordTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterRecordTest extends DriverRecordTestBase
+{
+  function __construct()
+  {
+    parent :: __construct('lmbLinterRecord');
+  }
+
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    parent::setUp();
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterStatementTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterStatementTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterStatementTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,447 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+require_once(dirname(__FILE__) . '/../DriverStatementTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterStatementTest extends DriverStatementTestBase
+{
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    parent::setUp();
+  }
+
+  
+  function setTypedValue($type, $column, $value)
+  {
+    $setterList = lmbDbTypeInfo::getColumnTypeAccessors();
+    $setter = $setterList[$type];
+    $this->assertNotNull($setter);
+
+    $sql = '
+          INSERT INTO standard_types (
+              "'.$column.'"
+          ) VALUES (
+              :'.$column.':
+          )';
+    $stmt = $this->connection->newStatement($sql);
+
+    $stmt->$setter($column, $value);
+
+    $id = $stmt->insertId('id');
+
+    $sql = 'SELECT * FROM standard_types WHERE "id" = :id:';
+    $stmt = $this->connection->newStatement($sql);
+    $stmt->setInteger('id', $id);
+    $record = $stmt->getOneRecord();
+
+    return $record;
+  }
+  
+  
+  function checkSmallIntValue($value)
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+    $stmt->setSmallInt('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), is_null($value) ? 'null' : $value);
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_SMALLINT, 'type_smallint', $value);
+    $this->assertIdentical($record->getInteger('type_smallint'), is_null($value) ? 0 : $value);
+    $this->assertEqual($record->get('type_smallint'), $value);
+  }
+  
+  function checkIntegerValue($value)
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+    $stmt->setInteger('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), is_null($value) ? 'null' : $value);
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_INTEGER, 'type_integer', $value);
+    $this->assertIdentical($record->getInteger('type_integer'), is_null($value) ? 0 : $value);
+    $this->assertEqual($record->get('type_integer'), $value);
+  }
+  
+  function checkBooleanValue($value)
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+    $stmt->setBoolean('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), is_null($value) ? 'null' : ($value ? 'TRUE' : 'FALSE'));
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_BOOLEAN, 'type_boolean', $value);
+    
+    if(is_null($value))
+      $this->assertIdentical($record->getBoolean('type_boolean'), false);
+    else
+      $this->assertIdentical($record->getBoolean('type_boolean'), (boolean) $value);
+  }
+  
+  function checkFloatValue($value)
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+    $stmt->setFloat('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), (float) $value);
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_FLOAT, 'type_float', $value);
+    
+    if(is_null($value))
+      $this->assertIdentical($record->getFloat('type_float'), 0.0);
+    else
+      $this->assertEqual(round($record->getFloat('type_float'), 2), round((float) $value, 2));
+      
+    $this->assertEqual(round($record->get('type_float'), 2), round($value, 2));
+  }
+  
+  function checkDoubleValue($value)
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+    $stmt->setDouble('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), is_null($value) ? 'null' : $value);
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_DOUBLE, 'type_double', $value);
+    
+    if(is_string($value))
+      $this->assertEqual($record->getStringFixed('type_double'), $value);
+    else
+      $this->assertEqual(round($record->getFloat('type_double'), 2), round($value, 2));
+      
+    $this->assertEqual(round($record->get('type_double'), 2), round($value, 2));
+  }
+
+  function checkDecimalValue($value)
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+    $stmt->setDecimal('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), is_null($value) ? 'null' : $value);
+    
+    $record = $this->setTypedValue(LIMB_DB_TYPE_DECIMAL, 'type_decimal', $value);
+    $this->assertEqual($record->getStringFixed('type_decimal'), is_null($value) ? 0 : $value);
+    $this->assertEqual($record->get('type_decimal'), is_null($value) ? 0 : $value);
+  }
+  
+  function testSetDecimal()
+  {
+    $this->checkDecimalValue(0);
+    $this->checkDecimalValue((float) 0);
+    $this->checkDecimalValue(null);
+    $this->checkDecimalValue(3.14);
+    $this->checkDecimalValue('3.14');
+    $this->checkDecimalValue('123456789012345678.01'); // To big for float
+  }
+  
+  
+  function testSetChar()
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+
+    $string_list = array("Hello 'World!'",
+          '"', '\'', '\\', '\\"', '\\\'', '\\0', '\\1',
+          "%", "_", '&', '<', '>', '$', '`');
+    foreach($string_list as $value)
+    {
+      $stmt->setChar('literal', $value);
+      $this->assertIdentical($stmt->getOneValue(), $value);
+    }
+
+    foreach($string_list as $value)
+    {
+      $record = $this->setTypedValue(LIMB_DB_TYPE_CHAR, 'type_char', $value);
+      //some databases fill char fields with spaces and we have to trim values
+      $this->assertIdentical(trim($record->getString('type_char')), $value);
+      $this->assertEqual(trim($record->get('type_char')), $value);
+    }
+
+    $value = null;
+    $stmt->setChar('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), is_null($value) ? 'null' : $value);
+
+    $value = null;
+    $record = $this->setTypedValue(LIMB_DB_TYPE_CHAR, 'type_char', $value);
+    $this->assertIdentical($record->getString('type_char'), is_null($value) ? '' : $value);
+    $this->assertEqual($record->get('type_char'), $value);
+
+    $value = ' trim ';
+    $value = null;
+    $stmt->setChar('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), is_null($value) ? 'null' : $value);
+  }
+  
+  
+  function testSetVarChar()
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+
+    $string_list = array("Hello 'World!'",
+          '"', '\'', '\\', '\\"', '\\\'', '\\0', '\\1',
+          "%", "_", '&', '<', '>', '$', '`');
+    foreach($string_list as $value)
+    {
+      $stmt->setVarChar('literal', $value);
+      $this->assertIdentical($stmt->getOneValue(), $value);
+    }
+
+    foreach($string_list as $value)
+    {
+      $record = $this->setTypedValue(LIMB_DB_TYPE_VARCHAR, 'type_varchar', $value);
+      $this->assertIdentical($record->getString('type_varchar'), $value);
+      $this->assertEqual($record->get('type_varchar'), $value);
+    }
+
+    $value = null;
+    $stmt->setVarChar('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), is_null($value) ? 'null' : $value);
+
+    $value = null;
+    $record = $this->setTypedValue(LIMB_DB_TYPE_VARCHAR, 'type_varchar', $value);
+    $this->assertIdentical($record->getString('type_varchar'), is_null($value) ? '' : $value);
+    $this->assertEqual($record->get('type_varchar'), $value);
+
+    $value = ' trim ';
+    $stmt->setVarChar('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), $value);
+
+  }
+
+  
+  function testBlob()
+  {
+    //$stmt = $this->connection->newStatement('SELECT :literal:');
+
+    $string_list = array("Hello 'World!'",
+          '"', '\'', '\\', '\\"', '\\\'', '\\0', '\\1',
+          "%", "_", '&', '<', '>', '$', '`');
+
+    foreach($string_list as $value)
+    {
+      $record = $this->setTypedValue(LIMB_DB_TYPE_BLOB, 'type_blob', $value);
+      $this->assertIdentical($record->getString('type_blob'), $value);
+      $this->assertEqual($record->get('type_blob'), $value);
+    }
+
+    $value = null;
+    $record = $this->setTypedValue(LIMB_DB_TYPE_BLOB, 'type_blob', $value);
+    $this->assertIdentical($record->getString('type_blob'), is_null($value) ? '' : $value);
+    $this->assertEqual($record->get('type_blob'), $value);
+
+  }
+  
+  function testCharset()
+  {
+    $string_list = array("Текст", "ЁЁЁЁЁЁЁ");
+
+    foreach($string_list as $value)
+    {
+      $value = mb_convert_encoding($value, $this->connection->getMbCharset(), 'UTF-8');
+      
+      $record = $this->setTypedValue(LIMB_DB_TYPE_VARCHAR, 'type_varchar', $value);
+      $this->assertIdentical($record->getString('type_varchar'), $value);
+      $this->assertEqual($record->get('type_varchar'), $value);
+      
+      $record = $this->setTypedValue(LIMB_DB_TYPE_BLOB, 'type_blob', $value);
+      $this->assertIdentical($record->getString('type_blob'), $value);
+      $this->assertEqual($record->get('type_blob'), $value);
+      
+    }
+
+  }
+  
+  
+  function testSetDate()
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+
+    $value = null;
+    $stmt->setDate('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), "null");
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_DATE, 'type_date', $value);
+    $this->assertIdentical($record->getStringDate('type_date'), null);
+    $this->assertEqual($record->get('type_date'), $stmt->nullDateValue());
+
+    $value = '2009-12-28';
+
+    $stmt->setDate('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), $value);
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_DATE, 'type_date', $value);
+    $this->assertIdentical($record->getStringDate('type_date'), $value);
+    $this->assertEqual($record->get('type_date'), $value . " 00:00:00");
+
+    $value = '1941-12-07';
+
+    $stmt->setDate('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), $value);
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_DATE, 'type_date', $value);
+    $this->assertIdentical($record->getStringDate('type_date'), $value);
+    $this->assertEqual($record->get('type_date'), $value . " 00:00:00");
+
+    $value = 'Bad Date Value';
+  }
+
+  function testSetTime()
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+
+    $value = null;
+    $stmt->setTime('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), 'null');
+
+    $value = null;
+    $record = $this->setTypedValue(LIMB_DB_TYPE_TIME, 'type_time', $value);
+    $this->assertIdentical($record->getString('type_time'), $stmt->nullDateValue());
+    $this->assertEqual($record->get('type_time'), $stmt->nullDateValue());
+
+    $value = '06:01:01';
+
+    $stmt->setTime('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), date('Y-m-d') . " " . $value);
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_TIME, 'type_time', $value);
+    $this->assertIdentical($record->getStringTime('type_time'), $value);
+    $this->assertEqual($record->get('type_time'), date('Y-m-d') . " " . $value);
+
+    $value = '18:01:01';
+
+    $stmt->setTime('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), date('Y-m-d') . " " . $value);
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_TIME, 'type_time', $value);
+    $this->assertIdentical($record->getStringTime('type_time'), $value);
+    $this->assertEqual($record->get('type_time'), date('Y-m-d') . " " . $value);
+
+    $value = 'Bad Time Value';
+  }
+
+  function testSetTimeStamp()
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+
+    $value = null;
+    $stmt->setTime('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), 'null');
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_TIMESTAMP, 'type_timestamp', $value);
+    $this->assertIdentical($record->getStringTimeStamp('type_timestamp'), $value);
+    $this->assertIdentical($record->getIntegerTimeStamp('type_timestamp'), $value);
+    $this->assertEqual($record->get('type_timestamp'), $stmt->nullDateValue());
+
+    $value = '2009-12-28 18:01:01';
+    $stmt->setTime('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), $value);
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_TIMESTAMP, 'type_timestamp', $value);
+    $this->assertIdentical($record->getStringTimeStamp('type_timestamp'), $value);
+    $this->assertEqual($record->get('type_timestamp'), $value);
+
+    $value = '2009-12-28 06:01:01';
+    $stmt->setTime('literal', $value);
+    $this->assertEqual($stmt->getOneValue(), $value);
+
+    $record = $this->setTypedValue(LIMB_DB_TYPE_TIMESTAMP, 'type_timestamp', $value);
+    $this->assertIdentical($record->getStringTimeStamp('type_timestamp'), $value);
+    $this->assertIdentical($record->getIntegerTimeStamp('type_timestamp'),
+          mktime(6, 1, 1, 12, 28, 2009));
+    $this->assertEqual($record->get('type_timestamp'), $value);
+
+    $value = 'Bad TimeStamp Value';
+  }
+  
+  
+  function testSetNull()
+  {
+    $stmt = $this->connection->newStatement('SELECT :literal:');
+    $stmt->setNull('literal');
+    $this->assertIdentical($stmt->getOneValue(), 'null');
+
+    $sql = '
+          INSERT INTO standard_types (
+              "type_smallint",
+              "type_integer",
+              "type_boolean",
+              "type_char",
+              "type_varchar",
+              "type_clob",
+              "type_float",
+              "type_double",
+              "type_decimal",
+              "type_timestamp",
+              "type_date",
+              "type_time",
+              "type_blob"
+          ) VALUES (
+              :type_smallint:,
+              :type_integer:,
+              :type_boolean:,
+              :type_char:,
+              :type_varchar:,
+              :type_clob:,
+              :type_float:,
+              :type_double:,
+              :type_decimal:,
+              :type_timestamp:,
+              :type_date:,
+              :type_time:,
+              :type_blob:
+          )';
+    $stmt = $this->connection->newStatement($sql);
+
+    $stmt->setNull('type_smallint');
+    $stmt->setNull('type_integer');
+    $stmt->setNull('type_boolean');
+    $stmt->setNull('type_char');
+    $stmt->setNull('type_varchar');
+    $stmt->setNull('type_clob');
+    $stmt->setNull('type_float');
+    $stmt->setNull('type_double');
+    $stmt->setNull('type_decimal');
+    $stmt->setNull('type_timestamp');
+    $stmt->setNull('type_date');
+    $stmt->setNull('type_time');
+    $stmt->setNull('type_blob');
+
+    $id = $stmt->insertId('id');
+
+    $sql = 'SELECT * FROM standard_types WHERE "id" = :id:';
+    $stmt = $this->connection->newStatement($sql);
+    $stmt->setInteger('id', $id);
+    $record = $stmt->getOneRecord();
+
+    /* generic gets */
+    $this->assertEqual($record->get('type_smallint'), 0);
+    $this->assertEqual($record->get('type_integer'), 0);
+    $this->assertEqual($record->get('type_boolean'), 0);
+    $this->assertEqual($record->get('type_char'), 0);
+    $this->assertEqual($record->get('type_varchar'), 0);
+    $this->assertEqual($record->get('type_clob'), 0);
+    $this->assertEqual($record->get('type_float'), 0);
+    $this->assertEqual($record->get('type_double'), 0);
+    $this->assertEqual($record->get('type_decimal'), 0);
+    $this->assertEqual($record->get('type_timestamp'), 0);
+    $this->assertEqual($record->get('type_date'), 0);
+    $this->assertEqual($record->get('type_time'), 0);
+    $this->assertEqual($record->get('type_blob'), 0);
+
+    /* typed gets */
+    $this->assertEqual($record->getInteger('type_smallint'), 0);
+    $this->assertEqual($record->getInteger('type_integer'), 0);
+    $this->assertEqual($record->getBoolean('type_boolean'), 0);
+    $this->assertEqual($record->getString('type_char'), 0);
+    $this->assertEqual($record->getString('type_varchar'), 0);
+    $this->assertEqual($record->getString('type_clob'), 0);
+    $this->assertEqual($record->getFloat('type_float'), 0);
+    $this->assertEqual($record->getStringFixed('type_double'), 0);
+    $this->assertEqual($record->getStringFixed('type_decimal'), 0);
+    $this->assertEqual($record->getStringTimeStamp('type_timestamp'), 0);
+    $this->assertEqual($record->getStringDate('type_date'), 0);
+    $this->assertEqual($record->getStringTime('type_time'), 0);
+    $this->assertEqual($record->getString('type_blob'), 0);
+  }
+}
\ No newline at end of file

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterTableInfoTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterTableInfoTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterTableInfoTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,23 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+require_once(dirname(__FILE__) . '/../DriverTableInfoTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterTableInfoTest extends DriverTableInfoTestBase
+{
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    parent::setUp();
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterTypeInfoTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterTypeInfoTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterTypeInfoTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,28 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+require_once(dirname(__FILE__) . '/../DriverTypeInfoTestBase.class.php');
+
+class lmbLinterTypeInfoTest extends DriverTypeInfoTestBase
+{
+
+  function lmbLinterTypeInfoTest()
+  {
+    parent :: DriverTypeInfoTestBase('lmbLinterStatement', 'lmbLinterRecord');
+  }
+
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    $this->typeInfo = $this->connection->getTypeInfo();
+    parent::setUp();
+  }
+}
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterUpdateTest.class.php
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterUpdateTest.class.php	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/driver/linter/lmbLinterUpdateTest.class.php	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,84 @@
+<?php
+/*
+ * Limb PHP Framework
+ *
+ * @link http://limb-project.com 
+ * @copyright  Copyright &copy; 2004-2007 BIT(http://bit-creative.com)
+ * @license    LGPL http://www.gnu.org/copyleft/lesser.html 
+ */
+
+require_once(dirname(__FILE__) . '/../DriverUpdateTestBase.class.php');
+require_once(dirname(__FILE__) . '/fixture.inc.php');
+
+class lmbLinterUpdateTest extends DriverUpdateTestBase
+{
+
+  function lmbLinterUpdateTest()
+  {
+    parent :: DriverUpdateTestBase('lmbLinterManipulationStatement');
+  }
+
+  function setUp()
+  {
+    $this->connection = lmbToolkit :: instance()->getDefaultDbConnection();
+    DriverLinterSetup($this->connection->getConnectionId());
+    parent::setUp();
+  }
+  
+  function testUpdate()
+  {
+    $sql = '
+          UPDATE founding_fathers SET
+              "first" = :first:,
+              "last" = :last:
+          WHERE
+              "id" = :id:';
+    $stmt = $this->connection->newStatement($sql);
+    $this->assertIsA($stmt, $this->manip_stmt_class);
+
+    $stmt->setVarChar('first', 'Richard');
+    $stmt->setVarChar('last', 'Nixon');
+    $stmt->setInteger('id', 3);
+
+    $stmt->execute();
+    $this->assertEqual($stmt->getAffectedRowCount(), 1);
+
+    $this->checkRecord(3);
+  }
+
+  function testAffectedRowCount()
+  {
+    $sql = '
+          UPDATE founding_fathers SET
+              "first" = :first:,
+              "last" = :last:';
+    $stmt = $this->connection->newStatement($sql);
+    $this->assertIsA($stmt, $this->manip_stmt_class);
+
+    $stmt->setVarChar('first', 'Richard');
+    $stmt->setVarChar('last', 'Nixon');
+
+    $stmt->execute();
+    $this->assertEqual($stmt->getAffectedRowCount(), 3);
+  }
+  
+  function checkRecord($id)
+  {
+    $sql = 'SELECT * FROM founding_fathers WHERE "id" = :id:';
+    $stmt = $this->connection->newStatement($sql);
+    $stmt->setInteger('id', $id);
+    $record = $stmt->getOneRecord();
+    $this->assertNotNull($record);
+    if($record)
+    {
+      $this->assertEqual($record->get('id'), $id);
+      $this->assertEqual($record->get('first'), 'Richard');
+      $this->assertEqual($record->get('last'), 'Nixon');
+    }
+  }
+  
+  
+  
+}
+
+

Added: 3.x/trunk/limb/dbal/tests/cases/non-driver/.fixture/init_tests.linter
===================================================================
--- 3.x/trunk/limb/dbal/tests/cases/non-driver/.fixture/init_tests.linter	                        (rev 0)
+++ 3.x/trunk/limb/dbal/tests/cases/non-driver/.fixture/init_tests.linter	2008-03-14 15:48:44 UTC (rev 6837)
@@ -0,0 +1,45 @@
+DROP TABLE "test_one_table_object" CASCADE;
+
+CREATE TABLE "test_one_table_object" (
+  "id" INT NOT NULL AUTOINC,
+  "annotation" blob,
+  "content" blob,
+  "news_date" date default NULL,
+  PRIMARY KEY  ("id")
+)  ;
+
+DROP TABLE "test_db_table" CASCADE;
+CREATE TABLE "test_db_table" (
+  "id" INT NOT NULL AUTOINC,
+  "description" blob,
+  "title" varchar(255) NOT NULL default '',
+  "ordr" int NULL,
+  PRIMARY KEY  ("id")
+)  ;
+
+DROP TABLE "test_one_table_object" CASCADE;
+CREATE TABLE "test_one_table_object" (
+  "id" INT NOT NULL AUTOINC,
+  "annotation" varchar(4000),
+  "content" varchar(4000),
+  "news_date" date default NULL,
+  PRIMARY KEY  ("id")
+)  ;
+
+DROP TABLE "all_types_test" CASCADE;
+CREATE TABLE "all_types_test" (
+ "field_int" int default NULL,
+ "field_varchar" varchar(255) default NULL,
+ "field_char" varchar(11) default NULL,
+ "field_date" date default NULL,
+ "field_datetime" int default NULL,
+ "field_time" date default NULL,
+ "field_text" blob,
+ "field_smallint" int default NULL,
+ "field_bigint" int default NULL,
+ "field_blob" blob,
+ "field_float" float default NULL,
+ "field_decimal" decimal(10,0) default NULL,
+ "field_tinyint" int default NULL
+)   ;
+



More information about the limb-svn mailing list