MDB2
[ class tree: MDB2 ] [ index: MDB2 ] [ all elements ]

Source for file odbc.php

Documentation is available at odbc.php

  1. <?php
  2.  
  3.  
  4. require_once 'MDB2/Driver/Reverse/Common.php';
  5.  
  6. /**
  7.  * MDB2 MSSQL driver for the schema reverse engineering module
  8.  *
  9.  * @package MDB2
  10.  * @category Database
  11.  * @author  Lukas Smith <smith@dybnet.de>
  12.  * @author  Lorenzo Alberton <l.alberton@quipo.it>
  13.  */
  14. class MDB2_Driver_Reverse_odbc extends MDB2_Driver_Reverse_Common
  15. {
  16.     // {{{ getTableFieldDefinition()
  17.  
  18.     /**
  19.      * Get the structure of a field into an array
  20.      *
  21.      * @param string $table_name name of table that should be used in method
  22.      * @param string $field_name name of field that should be used in method
  23.      * @return mixed data array on success, a MDB2 error on failure
  24.      * @access public
  25.      */
  26.     function getTableFieldDefinition($table_name, $field_name)
  27.     {
  28.         $db =& $this->getDBInstance();
  29.         if (MDB2::isError($db)) {
  30.             return $db;
  31.         }
  32.  
  33.         $result = $db->loadModule('Datatype', null, true);
  34.         if (MDB2::isError($result)) {
  35.             return $result;
  36.         }
  37.  
  38.         list($schema, $table) = $this->splitTableSchema($table_name);
  39.  
  40.         $table = $db->quoteIdentifier($table, true);
  41.         $fldname = $db->quoteIdentifier($field_name, true);
  42.  
  43.         $res = odbc_columns($db->connection,"%","%",$table);
  44.         $column = array();
  45.         while($data = odbc_fetch_array($res)) {
  46.         
  47.             if(strcasecmp($field_name,$data['COLUMN_NAME'])) {
  48.                 $column['table_name'] = $data['TABLE_NAME'];
  49.                 $column['name'] = $data['COLUMN_NAME'];
  50.                 $column['type'] = $data['TYPE_NAME'];
  51.                 if($data['IS_NULLABLE'] == "YES") {
  52.                        $column['is_nullable'] = 1;
  53.                 } else {
  54.                     $column['is_nullable'] = 0;
  55.                 }
  56.                 $column['column_default'] = $data['COLUMN_DEF'];
  57.                 $column['length'] = $data['COLUMNZ_SIZE'];
  58.                 $column['numeric_precision'] = $data['NUM_PREC_RADIX'];
  59.                 $column['numeric_scale'] = $data['DECIMAL_DIGITS'];
  60.                 $column['collation_name'] = NULL;    
  61.             }
  62.         }
  63.  
  64.         /*
  65.         $query = "SELECT t.table_name,
  66.                          c.column_name 'name',
  67.                          c.data_type 'type',
  68.                          CASE c.is_nullable WHEN 'YES' THEN 1 ELSE 0 END AS 'is_nullable',
  69.                          c.column_default,
  70.                          c.character_maximum_length 'length',
  71.                          c.numeric_precision,
  72.                          c.numeric_scale,
  73.                          c.character_set_name,
  74.                          c.collation_name
  75.                     FROM INFORMATION_SCHEMA.TABLES t,
  76.                          INFORMATION_SCHEMA.COLUMNS c
  77.                    WHERE t.table_name = c.table_name
  78.                      AND t.table_name = '$table'
  79.                      AND c.column_name = '$fldname'";
  80.         if (!empty($schema)) {
  81.             $query .= " AND t.table_schema = '" .$db->quoteIdentifier($schema, true) ."'";
  82.         }
  83.         $query .= ' ORDER BY t.table_name';
  84.         $column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
  85.         if (MDB2::isError($column)) {
  86.             return $column;
  87.         }
  88.         */
  89.         if (empty($column)) {
  90.             return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
  91.                 'it was not specified an existing table column', __FUNCTION__);
  92.         }
  93.  
  94.         if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
  95.             if ($db->options['field_case'] == CASE_LOWER) {
  96.                 $column['name'] = strtolower($column['name']);
  97.             } else {
  98.                 $column['name'] = strtoupper($column['name']);
  99.             }
  100.         } else {
  101.             $column = array_change_key_case($column, $db->options['field_case']);
  102.         }
  103.         $mapped_datatype = $db->datatype->mapNativeDatatype($column);
  104.         if (MDB2::isError($mapped_datatype)) {
  105.             return $mapped_datatype;
  106.         }
  107.         list($types, $length, $unsigned, $fixed) = $mapped_datatype;
  108.         $notnull = true;
  109.         if ($column['is_nullable']) {
  110.             $notnull = false;
  111.         }
  112.         $default = false;
  113.         if (array_key_exists('column_default', $column)) {
  114.             $default = $column['column_default'];
  115.             if (is_null($default) && $notnull) {
  116.                 $default = '';
  117.             } elseif (strlen($default) > 4
  118.                    && substr($default, 0, 1) == '('
  119.                    &&  substr($default, -1, 1) == ')'
  120.             ) {
  121.                 //mssql wraps the default value in parentheses: "((1234))", "(NULL)"
  122.                 $default = trim($default, '()');
  123.                 if ($default == 'NULL') {
  124.                     $default = null;
  125.                 }
  126.             }
  127.         }
  128.         $definition[0] = array(
  129.             'notnull' => $notnull,
  130.             'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
  131.         );
  132.         if (!is_null($length)) {
  133.             $definition[0]['length'] = $length;
  134.         }
  135.         if (!is_null($unsigned)) {
  136.             $definition[0]['unsigned'] = $unsigned;
  137.         }
  138.         if (!is_null($fixed)) {
  139.             $definition[0]['fixed'] = $fixed;
  140.         }
  141.         if ($default !== false) {
  142.             $definition[0]['default'] = $default;
  143.         }
  144.         foreach ($types as $key => $type) {
  145.             $definition[$key] = $definition[0];
  146.             if ($type == 'clob' || $type == 'blob') {
  147.                 unset($definition[$key]['default']);
  148.             }
  149.             $definition[$key]['type'] = $type;
  150.             $definition[$key]['mdb2type'] = $type;
  151.         }
  152.         return $definition;
  153.     }
  154.  
  155.     // }}}
  156.     // {{{ getTableIndexDefinition()
  157.  
  158.     /**
  159.      * Get the structure of an index into an array
  160.      *
  161.      * @param string $table_name name of table that should be used in method
  162.      * @param string $index_name name of index that should be used in method
  163.      * @return mixed data array on success, a MDB2 error on failure
  164.      * @access public
  165.      */
  166.     function getTableIndexDefinition($table_name, $index_name)
  167.     {
  168.         $db =& $this->getDBInstance();
  169.         if (MDB2::isError($db)) {
  170.             return $db;
  171.         }
  172.  
  173.         list($schema, $table) = $this->splitTableSchema($table_name);
  174.  
  175.         $table = $db->quoteIdentifier($table, true);
  176.         //$idxname = $db->quoteIdentifier($index_name, true);
  177.  
  178.         $query = "SELECT OBJECT_NAME(i.id) tablename,
  179.                          i.name indexname,
  180.                          c.name field_name,
  181.                          CASE INDEXKEY_PROPERTY(i.id, i.indid, ik.keyno, 'IsDescending')
  182.                            WHEN 1 THEN 'DESC' ELSE 'ASC'
  183.                          END 'collation',
  184.                          ik.keyno 'position'
  185.                     FROM sysindexes i
  186.                     JOIN sysindexkeys ik ON ik.id = i.id AND ik.indid = i.indid
  187.                     JOIN syscolumns c ON c.id = ik.id AND c.colid = ik.colid
  188.                    WHERE OBJECT_NAME(i.id) = '$table'
  189.                      AND i.name = '%s'
  190.                      AND NOT EXISTS (
  191.                             SELECT *
  192.                               FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k
  193.                              WHERE k.table_name = OBJECT_NAME(i.id)
  194.                                AND k.constraint_name = i.name";
  195.         if (!empty($schema)) {
  196.             $query .= " AND k.table_schema = '" .$db->quoteIdentifier($schema, true) ."'";
  197.         }
  198.         $query .= ')
  199.                 ORDER BY tablename, indexname, ik.keyno';
  200.  
  201.         $index_name_mdb2 = $db->getIndexName($index_name);
  202.         $result = $db->queryRow(sprintf($query, $index_name_mdb2));
  203.         if (!MDB2::isError($result) && !is_null($result)) {
  204.             // apply 'idxname_format' only if the query succeeded, otherwise
  205.             // fallback to the given $index_name, without transformation
  206.             $index_name = $index_name_mdb2;
  207.         }
  208.         $result = $db->query(sprintf($query, $index_name));
  209.         if (MDB2::isError($result)) {
  210.             return $result;
  211.         }
  212.  
  213.         $definition = array();
  214.         while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
  215.             $column_name = $row['field_name'];
  216.             if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
  217.                 if ($db->options['field_case'] == CASE_LOWER) {
  218.                     $column_name = strtolower($column_name);
  219.                 } else {
  220.                     $column_name = strtoupper($column_name);
  221.                 }
  222.             }
  223.             $definition['fields'][$column_name] = array(
  224.                 'position' => (int)$row['position'],
  225.             );
  226.             if (!empty($row['collation'])) {
  227.                 $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'ASC'
  228.                     ? 'ascending' : 'descending');
  229.             }
  230.         }
  231.         $result->free();
  232.         if (empty($definition['fields'])) {
  233.             return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
  234.                 'it was not specified an existing table index', __FUNCTION__);
  235.         }
  236.         return $definition;
  237.     }
  238.  
  239.     // }}}
  240.     // {{{ getTableConstraintDefinition()
  241.  
  242.     /**
  243.      * Get the structure of a constraint into an array
  244.      *
  245.      * @param string $table_name      name of table that should be used in method
  246.      * @param string $constraint_name name of constraint that should be used in method
  247.      * @return mixed data array on success, a MDB2 error on failure
  248.      * @access public
  249.      */
  250.     function getTableConstraintDefinition($table_name, $constraint_name)
  251.     {
  252.         $db =& $this->getDBInstance();
  253.         if (MDB2::isError($db)) {
  254.             return $db;
  255.         }
  256.  
  257.         list($schema, $table) = $this->splitTableSchema($table_name);
  258.  
  259.         $table = $db->quoteIdentifier($table, true);
  260.         $query = "SELECT k.table_name,
  261.                          k.column_name field_name,
  262.                          CASE c.constraint_type WHEN 'PRIMARY KEY' THEN 1 ELSE 0 END 'primary',
  263.                          CASE c.constraint_type WHEN 'UNIQUE' THEN 1 ELSE 0 END 'unique',
  264.                          CASE c.constraint_type WHEN 'FOREIGN KEY' THEN 1 ELSE 0 END 'foreign',
  265.                          CASE c.constraint_type WHEN 'CHECK' THEN 1 ELSE 0 END 'check',
  266.                          CASE c.is_deferrable WHEN 'NO' THEN 0 ELSE 1 END 'deferrable',
  267.                          CASE c.initially_deferred WHEN 'NO' THEN 0 ELSE 1 END 'initiallydeferred',
  268.                          rc.match_option 'match',
  269.                          rc.update_rule 'onupdate',
  270.                          rc.delete_rule 'ondelete',
  271.                          kcu.table_name 'references_table',
  272.                          kcu.column_name 'references_field',
  273.                          k.ordinal_position 'field_position'
  274.                     FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k
  275.                     LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS c
  276.                       ON k.table_name = c.table_name
  277.                      AND k.table_schema = c.table_schema
  278.                      AND k.table_catalog = c.table_catalog
  279.                      AND k.constraint_catalog = c.constraint_catalog
  280.                      AND k.constraint_name = c.constraint_name
  281.                LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
  282.                       ON rc.constraint_schema = c.constraint_schema
  283.                      AND rc.constraint_catalog = c.constraint_catalog
  284.                      AND rc.constraint_name = c.constraint_name
  285.                LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
  286.                       ON rc.unique_constraint_schema = kcu.constraint_schema
  287.                      AND rc.unique_constraint_catalog = kcu.constraint_catalog
  288.                      AND rc.unique_constraint_name = kcu.constraint_name
  289.                      AND k.ordinal_position = kcu.ordinal_position
  290.                    WHERE k.constraint_catalog = DB_NAME()
  291.                      AND k.table_name = '$table'
  292.                      AND k.constraint_name = '%s'";
  293.         if (!empty($schema)) {
  294.             $query .= " AND k.table_schema = '" .$db->quoteIdentifier($schema, true) ."'";
  295.         }
  296.         $query .= ' ORDER BY k.constraint_name,
  297.                              k.ordinal_position';
  298.  
  299.         $constraint_name_mdb2 = $db->getIndexName($constraint_name);
  300.         $result = $db->queryRow(sprintf($query, $constraint_name_mdb2));
  301.         if (!MDB2::isError($result) && !is_null($result)) {
  302.             // apply 'idxname_format' only if the query succeeded, otherwise
  303.             // fallback to the given $index_name, without transformation
  304.             $constraint_name = $constraint_name_mdb2;
  305.         }
  306.         $result = $db->query(sprintf($query, $constraint_name));
  307.         if (MDB2::isError($result)) {
  308.             return $result;
  309.         }
  310.  
  311.         $definition = array(
  312.             'fields' => array()
  313.         );
  314.         while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
  315.             $row = array_change_key_case($row, CASE_LOWER);
  316.             $column_name = $row['field_name'];
  317.             if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
  318.                 if ($db->options['field_case'] == CASE_LOWER) {
  319.                     $column_name = strtolower($column_name);
  320.                 } else {
  321.                     $column_name = strtoupper($column_name);
  322.                 }
  323.             }
  324.             $definition['fields'][$column_name] = array(
  325.                 'position' => (int)$row['field_position']
  326.             );
  327.             if ($row['foreign']) {
  328.                 $ref_column_name = $row['references_field'];
  329.                 if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
  330.                     if ($db->options['field_case'] == CASE_LOWER) {
  331.                         $ref_column_name = strtolower($ref_column_name);
  332.                     } else {
  333.                         $ref_column_name = strtoupper($ref_column_name);
  334.                     }
  335.                 }
  336.                 $definition['references']['table'] = $row['references_table'];
  337.                 $definition['references']['fields'][$ref_column_name] = array(
  338.                     'position' => (int)$row['field_position']
  339.                 );
  340.             }
  341.             //collation?!?
  342.             /*
  343.             if (!empty($row['collation'])) {
  344.                 $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'ASC'
  345.                     ? 'ascending' : 'descending');
  346.             }
  347.             */
  348.             $lastrow = $row;
  349.             // otherwise $row is no longer usable on exit from loop
  350.         }
  351.         $result->free();
  352.         if (empty($definition['fields'])) {
  353.             return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
  354.                 $constraint_name . ' is not an existing table constraint', __FUNCTION__);
  355.         }
  356.  
  357.         $definition['primary'] = (boolean)$lastrow['primary'];
  358.         $definition['unique']  = (boolean)$lastrow['unique'];
  359.         $definition['foreign'] = (boolean)$lastrow['foreign'];
  360.         $definition['check']   = (boolean)$lastrow['check'];
  361.         $definition['deferrable'] = (boolean)$lastrow['deferrable'];
  362.         $definition['initiallydeferred'] = (boolean)$lastrow['initiallydeferred'];
  363.         $definition['onupdate'] = $lastrow['onupdate'];
  364.         $definition['ondelete'] = $lastrow['ondelete'];
  365.         $definition['match']    = $lastrow['match'];
  366.  
  367.         return $definition;
  368.     }
  369.  
  370.     // }}}
  371.     // {{{ getTriggerDefinition()
  372.  
  373.     /**
  374.      * Get the structure of a trigger into an array
  375.      *
  376.      * EXPERIMENTAL
  377.      *
  378.      * WARNING: this function is experimental and may change the returned value
  379.      * at any time until labelled as non-experimental
  380.      *
  381.      * @param string    $trigger    name of trigger that should be used in method
  382.      * @return mixed data array on success, a MDB2 error on failure
  383.      * @access public
  384.      */
  385.     function getTriggerDefinition($trigger)
  386.     {
  387.         $db =& $this->getDBInstance();
  388.         if (MDB2::isError($db)) {
  389.             return $db;
  390.         }
  391.  
  392.         $query = "SELECT sys1.name trigger_name,
  393.                          sys2.name table_name,
  394.                          c.text trigger_body,
  395.                          c.encrypted is_encripted,
  396.                          CASE
  397.                            WHEN OBJECTPROPERTY(sys1.id, 'ExecIsTriggerDisabled') = 1
  398.                            THEN 0 ELSE 1
  399.                          END trigger_enabled,
  400.                          CASE
  401.                            WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsertTrigger') = 1
  402.                            THEN 'INSERT'
  403.                            WHEN OBJECTPROPERTY(sys1.id, 'ExecIsUpdateTrigger') = 1
  404.                            THEN 'UPDATE'
  405.                            WHEN OBJECTPROPERTY(sys1.id, 'ExecIsDeleteTrigger') = 1
  406.                            THEN 'DELETE'
  407.                          END trigger_event,
  408.                          CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsteadOfTrigger') = 1
  409.                            THEN 'INSTEAD OF' ELSE 'AFTER'
  410.                          END trigger_type,
  411.                          '' trigger_comment
  412.                     FROM sysobjects sys1
  413.                     JOIN sysobjects sys2 ON sys1.parent_obj = sys2.id
  414.                     JOIN syscomments c ON sys1.id = c.id
  415.                    WHERE sys1.xtype = 'TR'
  416.                      AND sys1.name = ". $db->quote($trigger, 'text');
  417.  
  418.         $types = array(
  419.             'trigger_name'    => 'text',
  420.             'table_name'      => 'text',
  421.             'trigger_body'    => 'text',
  422.             'trigger_type'    => 'text',
  423.             'trigger_event'   => 'text',
  424.             'trigger_comment' => 'text',
  425.             'trigger_enabled' => 'boolean',
  426.             'is_encripted'    => 'boolean',
  427.         );
  428.  
  429.         $def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
  430.         if (MDB2::isError($def)) {
  431.             return $def;
  432.         }
  433.         $trg_body = $db->queryCol('EXEC sp_helptext '. $db->quote($trigger, 'text'), 'text');
  434.         if (!MDB2::isError($trg_body)) {
  435.             $def['trigger_body'] = implode(' ', $trg_body);
  436.         }
  437.         return $def;
  438.     }
  439.  
  440.     // }}}
  441.     // {{{ tableInfo()
  442.  
  443.     /**
  444.      * Returns information about a table or a result set
  445.      *
  446.      * NOTE: only supports 'table' and 'flags' if <var>$result</var>
  447.      * is a table name.
  448.      *
  449.      * @param object|string $result  MDB2_result object from a query or a
  450.      *                                  string containing the name of a table.
  451.      *                                  While this also accepts a query result
  452.      *                                  resource identifier, this behavior is
  453.      *                                  deprecated.
  454.      * @param int            $mode    a valid tableInfo mode
  455.      *
  456.      * @return array  an associative array with the information requested.
  457.      *                  A MDB2_Error object on failure.
  458.      *
  459.      * @see MDB2_Driver_Common::tableInfo()
  460.      */
  461.     function tableInfo($result, $mode = null)
  462.     {
  463.         if (is_string($result)) {
  464.            return parent::tableInfo($result, $mode);
  465.         }
  466.  
  467.         $db =& $this->getDBInstance();
  468.         if (MDB2::isError($db)) {
  469.             return $db;
  470.         }
  471.  
  472.         $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
  473.         if (!is_resource($resource)) {
  474.             return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
  475.                 'Could not generate result resource', __FUNCTION__);
  476.         }
  477.  
  478.         if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
  479.             if ($db->options['field_case'] == CASE_LOWER) {
  480.                 $case_func = 'strtolower';
  481.             } else {
  482.                 $case_func = 'strtoupper';
  483.             }
  484.         } else {
  485.             $case_func = 'strval';
  486.         }
  487.  
  488.         $count = @mssql_num_fields($resource);
  489.         $res   = array();
  490.  
  491.         if ($mode) {
  492.             $res['num_fields'] = $count;
  493.         }
  494.  
  495.         $db->loadModule('Datatype', null, true);
  496.         for ($i = 0; $i < $count; $i++) {
  497.             $res[$i] = array(
  498.                 'table' => '',
  499.                 'name'  => $case_func(@mssql_field_name($resource, $i)),
  500.                 'type'  => @mssql_field_type($resource, $i),
  501.                 'length'   => @mssql_field_length($resource, $i),
  502.                 'flags' => '',
  503.             );
  504.             $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
  505.             if (MDB2::isError($mdb2type_info)) {
  506.                return $mdb2type_info;
  507.             }
  508.             $res[$i]['mdb2type'] = $mdb2type_info[0][0];
  509.             if ($mode & MDB2_TABLEINFO_ORDER) {
  510.                 $res['order'][$res[$i]['name']] = $i;
  511.             }
  512.             if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
  513.                 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
  514.             }
  515.         }
  516.  
  517.         return $res;
  518.     }
  519.  
  520.     // }}}
  521.     // {{{ _mssql_field_flags()
  522.  
  523.     /**
  524.      * Get a column's flags
  525.      *
  526.      * Supports "not_null", "primary_key",
  527.      * "auto_increment" (mssql identity), "timestamp" (mssql timestamp),
  528.      * "unique_key" (mssql unique index, unique check or primary_key) and
  529.      * "multiple_key" (multikey index)
  530.      *
  531.      * mssql timestamp is NOT similar to the mysql timestamp so this is maybe
  532.      * not useful at all - is the behaviour of mysql_field_flags that primary
  533.      * keys are alway unique? is the interpretation of multiple_key correct?
  534.      *
  535.      * @param string $table   the table name
  536.      * @param string $column  the field name
  537.      *
  538.      * @return string  the flags
  539.      *
  540.      * @access protected
  541.      * @author Joern Barthel <j_barthel@web.de>
  542.      */
  543.     function _mssql_field_flags($table, $column)
  544.     {
  545.         $db =& $this->getDBInstance();
  546.         if (MDB2::isError($db)) {
  547.             return $db;
  548.         }
  549.  
  550.         static $tableName = null;
  551.         static $flags = array();
  552.  
  553.         if ($table != $tableName) {
  554.  
  555.             $flags = array();
  556.             $tableName = $table;
  557.  
  558.             // get unique and primary keys
  559.             $res = $db->queryAll("EXEC SP_HELPINDEX[$table]", null, MDB2_FETCHMODE_ASSOC);
  560.  
  561.             foreach ($res as $val) {
  562.                 $val = array_change_key_case($val, CASE_LOWER);
  563.                 $keys = explode(', ', $val['index_keys']);
  564.  
  565.                 if (sizeof($keys) > 1) {
  566.                     foreach ($keys as $key) {
  567.                         $this->_add_flag($flags[$key], 'multiple_key');
  568.                     }
  569.                 }
  570.  
  571.                 if (strpos($val['index_description'], 'primary key')) {
  572.                     foreach ($keys as $key) {
  573.                         $this->_add_flag($flags[$key], 'primary_key');
  574.                     }
  575.                 } elseif (strpos($val['index_description'], 'unique')) {
  576.                     foreach ($keys as $key) {
  577.                         $this->_add_flag($flags[$key], 'unique_key');
  578.                     }
  579.                 }
  580.             }
  581.  
  582.             // get auto_increment, not_null and timestamp
  583.             $res = $db->queryAll("EXEC SP_COLUMNS[$table]", null, MDB2_FETCHMODE_ASSOC);
  584.  
  585.             foreach ($res as $val) {
  586.                 $val = array_change_key_case($val, CASE_LOWER);
  587.                 if ($val['nullable'] == '0') {
  588.                     $this->_add_flag($flags[$val['column_name']], 'not_null');
  589.                 }
  590.                 if (strpos($val['type_name'], 'identity')) {
  591.                     $this->_add_flag($flags[$val['column_name']], 'auto_increment');
  592.                 }
  593.                 if (strpos($val['type_name'], 'timestamp')) {
  594.                     $this->_add_flag($flags[$val['column_name']], 'timestamp');
  595.                 }
  596.             }
  597.         }
  598.  
  599.         if (!empty($flags[$column])) {
  600.             return(implode(' ', $flags[$column]));
  601.         }
  602.         return '';
  603.     }
  604.  
  605.     // }}}
  606.     // {{{ _add_flag()
  607.  
  608.     /**
  609.      * Adds a string to the flags array if the flag is not yet in there
  610.      * - if there is no flag present the array is created
  611.      *
  612.      * @param array  &$array  the reference to the flag-array
  613.      * @param string $value   the flag value
  614.      *
  615.      * @return void 
  616.      *
  617.      * @access protected
  618.      * @author Joern Barthel <j_barthel@web.de>
  619.      */
  620.     function _add_flag(&$array, $value)
  621.     {
  622.         if (!is_array($array)) {
  623.             $array = array($value);
  624.         } elseif (!in_array($value, $array)) {
  625.             array_push($array, $value);
  626.         }
  627.     }
  628.  
  629.     // }}}
  630. }
  631. ?>

Documentation generated on Mon, 11 Mar 2019 15:51:22 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.