diff --git a/db/sql.php b/db/sql.php index 4e464d7e..f816a973 100644 --- a/db/sql.php +++ b/db/sql.php @@ -321,19 +321,37 @@ function schema($table,$fields=NULL,$ttl=0) { if (strpos($table,'.')) list($schema,$table)=explode('.',$table); // Supported engines + // format: engine_name => array of: + // 0: query + // 1: field name of column name + // 2: field name of column type + // 3: field name of default value + // 4: field name of nullable value + // 5: expected field value to be nullable + // 6: field name of primary key flag + // 7: expected field value to be a primary key + // 8: field name of auto increment check (optional) + // 9: expected field value to be an auto-incremented identifier $cmd=[ 'sqlite2?'=>[ - 'PRAGMA table_info(`'.$table.'`)', - 'name','type','dflt_value','notnull',0,'pk',TRUE], + 'SELECT * FROM pragma_table_info('.$this->quote($table).') JOIN ('. + 'SELECT sql FROM sqlite_master WHERE type=\'table\' AND '. + 'name='.$this->quote($table).')', + 'name','type','dflt_value','notnull',0,'pk',TRUE,'sql', + '/\W(%s)\W+[^,]+?AUTOINCREMENT\W/i'], 'mysql'=>[ 'SHOW columns FROM `'.$this->dbname.'`.`'.$table.'`', - 'Field','Type','Default','Null','YES','Key','PRI'], + 'Field','Type','Default','Null','YES','Key','PRI','Extra','auto_increment'], 'mssql|sqlsrv|sybase|dblib|pgsql|odbc'=>[ 'SELECT '. 'C.COLUMN_NAME AS field,'. 'C.DATA_TYPE AS type,'. 'C.COLUMN_DEFAULT AS defval,'. 'C.IS_NULLABLE AS nullable,'. + ($this->engine=='pgsql' + ?'COALESCE(POSITION(\'nextval\' IN C.COLUMN_DEFAULT),0) AS autoinc,' + :'columnproperty(object_id(C.TABLE_NAME),C.COLUMN_NAME,\'IsIdentity\')' + .' AS autoinc,'). 'T.CONSTRAINT_TYPE AS pkey '. 'FROM INFORMATION_SCHEMA.COLUMNS AS C '. 'LEFT OUTER JOIN '. @@ -356,7 +374,7 @@ function schema($table,$fields=NULL,$ttl=0) { ($this->dbname? (' AND C.TABLE_CATALOG='. $this->quote($this->dbname)):''), - 'field','type','defval','nullable','YES','pkey','PRIMARY KEY'], + 'field','type','defval','nullable','YES','pkey','PRIMARY KEY','autoinc',1], 'oci'=>[ 'SELECT c.column_name AS field, '. 'c.data_type AS type, '. @@ -397,7 +415,13 @@ function schema($table,$fields=NULL,$ttl=0) { preg_replace('/^\s*([\'"])(.*)\1\s*/','\2', $row[$val[3]]):$row[$val[3]], 'nullable'=>$row[$val[4]]==$val[5], - 'pkey'=>$row[$val[6]]==$val[7] + 'pkey'=>$row[$val[6]]==$val[7], + 'auto_inc'=>isset($val[8]) && isset($row[$val[8]]) + ? ($this->engine=='sqlite'? + (bool) preg_match(sprintf($val[9],$row[$val[1]]), + $row[$val[8]]): + ($row[$val[8]]==$val[9]) + ) : NULL, ]; } if ($fw->CACHE && $ttl) diff --git a/db/sql/mapper.php b/db/sql/mapper.php index 1eb45c6d..c65bfe98 100644 --- a/db/sql/mapper.php +++ b/db/sql/mapper.php @@ -438,17 +438,20 @@ function insert() { // duplicate record foreach ($this->fields as $key=>&$field) { $field['changed']=true; - if ($field['pkey'] && !$inc && $field['pdo_type']==\PDO::PARAM_INT - && !$field['nullable']) + if ($field['pkey'] && !$inc && ($field['auto_inc'] === TRUE || + ($field['auto_inc'] === NULL && !$field['nullable'] + && $field['pdo_type']==\PDO::PARAM_INT) + )) $inc=$key; unset($field); } foreach ($this->fields as $key=>&$field) { if ($field['pkey']) { $field['previous']=$field['value']; - if (!$inc && $field['pdo_type']==\PDO::PARAM_INT && - empty($field['value']) && !$field['nullable'] && - is_null($field['default'])) + if (!$inc && empty($field['value']) && + ($field['auto_inc'] === TRUE || ($field['auto_inc'] === NULL + && $field['pdo_type']==\PDO::PARAM_INT && !$field['nullable'])) + ) $inc=$key; $filter.=($filter?' AND ':'').$this->db->quotekey($key).'=?'; $nkeys[$nctr+1]=[$field['value'],$field['pdo_type']];