/**
  * @see TableInfo::initColumns()
  */
 protected function initColumns()
 {
     include_once 'creole/metadata/ColumnInfo.php';
     include_once 'creole/drivers/odbc/ODBCTypes.php';
     ODBCTypes::loadTypeMap($this->conn);
     $result = @odbc_columns($this->dblink, $this->dbname, '', $this->name);
     if (!$result) {
         throw new SQLException('Could not get column names', $this->conn->nativeError());
     }
     while (odbc_fetch_row($result)) {
         $name = odbc_result($result, 'COLUMN_NAME');
         $type = odbc_result($result, 'TYPE_NAME');
         $length = odbc_result($result, 'LENGTH');
         $is_nullable = odbc_result($result, 'NULLABLE');
         $default = '';
         $precision = odbc_result($result, 'PRECISION');
         $this->columns[$name] = new ColumnInfo($this, $name, ODBCTypes::getType($type), $type, $length, $precision, $is_nullable, $default);
     }
     @odbc_free_result($result);
     $this->colsLoaded = true;
 }
 /**
  * This method will return a native type that corresponds to the specified
  * Creole (JDBC-like) type.
  * If there is more than one matching native type, then the LAST defined
  * native type will be returned.
  * @param int $creoleType
  * @return string Native type string.
  */
 public static function getNativeType($creoleType)
 {
     if (!self::$typeMap) {
         self::loadTypeMap();
     }
     if (self::$reverseMap === null) {
         self::$reverseMap = array_flip(self::$typeMap);
     }
     return @self::$reverseMap[$creoleType];
 }
 /**
  * Caches specified records up to and including the specified 1-based
  * record position. If -1 is specified, all records will be cached.
  * @param integer Maximum record position to cache.
  * @return void
  * @throws SQLException
  */
 public function loadCache($recPos = -1)
 {
     $rid = $this->result->getHandle();
     $curRecs = count($this->recs);
     $totRecs = $curRecs ? $this->offset + $curRecs : 0;
     while (1) {
         // Is record already cached?
         if ($this->lastPos != -1 || $recPos > -1 && $recPos <= $curRecs) {
             return;
         }
         // Fetch row (no buffers copied yet).
         $rowNum = ++$totRecs;
         $result = @odbc_fetch_row($rid, $rowNum);
         // All records cached?
         if ($result === false || $this->limit > 0 && $curRecs + 1 > $this->limit) {
             $this->lastPos = $curRecs;
             continue;
         }
         // Ignore offset records.
         if ($totRecs <= $this->offset) {
             continue;
         }
         // Load row array.
         $row = array();
         for ($i = 0, $n = @odbc_num_fields($rid); $i < $n; $i++) {
             $fldNum = $i + 1;
             $row[$i] = odbc_result($rid, $fldNum);
             // Cache lobs if necessary
             if ($this->cacheLobs) {
                 ODBCTypes::loadTypeMap($this->conn);
                 $nativeType = @odbc_field_type($rid, $fldNum);
                 $creoleType = ODBCTypes::getType($nativeType);
                 $isBlob = $creoleType == CreoleTypes::BLOB || $creoleType == CreoleTypes::LONGVARBINARY;
                 $isClob = $creoleType == CreoleTypes::CLOB || $creoleType == CreoleTypes::LONGVARCHAR;
                 if (($isBlob || $isClob) && $row[$i] !== null) {
                     $binmode = $isBlob ? ODBC_BINMODE_RETURN : ODBC_BINMODE_CONVERT;
                     $curdata = $row[$i];
                     $row[$i] = $this->readLobData($fldNum, $binmode, $curdata);
                 }
             }
         }
         // Add record to cache.
         $this->recs[++$curRecs] = $row;
     }
 }