CPgsqlSchema


system.db.schema.pgsql
继承 class CPgsqlSchema » CDbSchema » CComponent
源自 1.0
版本 $Id: CPgsqlSchema.php 3515 2011-12-28 12:29:24Z mdomba $
源码
CPgsqlSchema是从PostgreSQL数据库检索元数据信息的类。

公共属性

属性 类型 描述 定义在
columnTypes array 映射到实体列类型的抽象列类型。 CPgsqlSchema
commandBuilder CDbCommandBuilder the SQL command builder for this connection. CDbSchema
dbConnection CDbConnection database connection. CDbSchema
tableNames array Returns all table names in the database. CDbSchema
tables array Returns the metadata for all tables in the database. CDbSchema

公共方法

方法 描述 定义在
__call() 如果类中没有调的方法名,则调用这个方法。 CComponent
__construct() Constructor. CDbSchema
__get() 返回一个属性值、一个事件处理程序列表或一个行为名称。 CComponent
__isset() 检查一个属性是否为null。 CComponent
__set() 设置一个组件的属性值。 CComponent
__unset() 设置一个组件的属性为null。 CComponent
addColumn() 构造添加新列的SQL语句。 CPgsqlSchema
addForeignKey() Builds a SQL statement for adding a foreign key constraint to an existing table. CDbSchema
alterColumn() 构造改变列定义的SQL语句。 CPgsqlSchema
asa() 返回这个名字的行为对象。 CComponent
attachBehavior() 附加一个行为到组件。 CComponent
attachBehaviors() 附加一个行为列表到组件。 CComponent
attachEventHandler() 为事件附加一个事件处理程序。 CComponent
canGetProperty() 确定属性是否可读。 CComponent
canSetProperty() 确定属性是否可写。 CComponent
checkIntegrity() 启用或禁用完整性检查。 CPgsqlSchema
compareTableNames() Compares two table names. CDbSchema
createIndex() Builds a SQL statement for creating a new index. CDbSchema
createTable() Builds a SQL statement for creating a new DB table. CDbSchema
detachBehavior() 从组件中分离一个行为。 CComponent
detachBehaviors() 从组件中分离所有行为。 CComponent
detachEventHandler() 分离一个存在的事件处理程序。 CComponent
disableBehavior() 禁用一个附加行为。 CComponent
disableBehaviors() 禁用组件附加的所有行为。 CComponent
dropColumn() Builds a SQL statement for dropping a DB column. CDbSchema
dropForeignKey() Builds a SQL statement for dropping a foreign key constraint. CDbSchema
dropIndex() 构造删除索引的SQL语句。 CPgsqlSchema
dropTable() Builds a SQL statement for dropping a DB table. CDbSchema
enableBehavior() 启用一个附加行为。 CComponent
enableBehaviors() 启用组件附加的所有行为。 CComponent
evaluateExpression() 计算一个PHP表达式,或根据组件上下文执行回调。 CComponent
getColumnType() Converts an abstract column type into a physical column type. CDbSchema
getCommandBuilder() 返回the SQL command builder for this connection. CDbSchema
getDbConnection() 返回database connection. The connection is active. CDbSchema
getEventHandlers() 返回一个事件的附加处理程序列表。 CComponent
getTable() Obtains the metadata for the named table. CDbSchema
getTableNames() Returns all table names in the database. CDbSchema
getTables() Returns the metadata for all tables in the database. CDbSchema
hasEvent() 确定一个事件是否定义。 CComponent
hasEventHandler() 检查事件是否有附加的处理程序。 CComponent
hasProperty() 确定属性是否被定义。 CComponent
quoteColumnName() Quotes a column name for use in a query. CDbSchema
quoteSimpleColumnName() Quotes a simple column name for use in a query. CDbSchema
quoteSimpleTableName() 用引号引用表名以便查询时使用。 CPgsqlSchema
quoteTableName() Quotes a table name for use in a query. CDbSchema
raiseEvent() 发起一个事件。 CComponent
refresh() Refreshes the schema. CDbSchema
renameColumn() Builds a SQL statement for renaming a column. CDbSchema
renameTable() 构造重命名数据表的SQL语句。 CPgsqlSchema
resetSequence() 重置表的主键的序列值。 CPgsqlSchema
truncateTable() Builds a SQL statement for truncating a DB table. CDbSchema

受保护方法

方法 描述 定义在
createColumn() 创建一个列。 CPgsqlSchema
createCommandBuilder() Creates a command builder for the database. CDbSchema
findColumns() 收集列的元数据。 CPgsqlSchema
findConstraints() 收集给定表主键列和外键列的详细信息。 CPgsqlSchema
findForeignKey() 收集外键信息。 CPgsqlSchema
findPrimaryKey() 收集主键信息。 CPgsqlSchema
findTableNames() 返回所有数据库里的表名。 CPgsqlSchema
loadTable() 为指定表载入元数据。 CPgsqlSchema
resolveTableNames() 生成各种表名。 CPgsqlSchema

属性详细

columnTypes 属性 (可用自 v1.1.6)
public array $columnTypes;

映射到实体列类型的抽象列类型。

方法详细

addColumn() 方法 (可用自 v1.1.6)
public string addColumn(string $table, string $column, string $type)
$table string 要添加新列的表。该表名会被指定方法正确引用。
$column string 新列名。该列名会被指定方法正确引用。
$type string 列类型。getColumnType方法会被调用来将虚拟列类型(若存在) 转换为对应的实体列类型。任何未被识别为虚拟类型的类型会被保留在生成的SQL中。 例如,‘string’会被转为‘varchar(255)’,而‘string not null’会被转为‘varchar(255) not null’。
{return} string 改变列定义的SQL语句。
public function addColumn($table$column$type)
{
    
$type=$this->getColumnType($type);
    
$sql='ALTER TABLE ' $this->quoteTableName($table)
        . 
' ADD COLUMN ' $this->quoteColumnName($column) . ' '
        
$this->getColumnType($type);
    return 
$sql;
}

构造添加新列的SQL语句。

alterColumn() 方法 (可用自 v1.1.6)
public string alterColumn(string $table, string $column, string $type)
$table string 要改变的列所在表。该表名会被指定方法正确引用。
$column string 要改变的列名。该列名会被指定方法正确引用。
$type string 新的列类型。getColumnType方法会被调用来将虚拟列类型(若存在) 转换为对应的实体列类型。任何未被识别为虚拟类型的类型会被保留在生成的SQL中。 例如,‘string’会被转为‘varchar(255)’,而‘string not null’会被转为‘varchar(255) not null’。
{return} string 改变列定义的SQL语句。
public function alterColumn($table$column$type)
{
    
$type=$this->getColumnType($type);
    
$sql='ALTER TABLE ' $this->quoteTableName($table) . ' ALTER COLUMN '
        
$this->quoteColumnName($column) . ' TYPE ' $this->getColumnType($type);
    return 
$sql;
}

构造改变列定义的SQL语句。

checkIntegrity() 方法 (可用自 v1.1)
public void checkIntegrity(boolean $check=true, string $schema='')
$check boolean 是否开启完整性检查。
$schema string 各表schema。默认为空字符串,意味着当前或默认schema。
public function checkIntegrity($check=true,$schema='')
{
    
$enable=$check 'ENABLE' 'DISABLE';
    
$tableNames=$this->getTableNames($schema);
    
$db=$this->getDbConnection();
    foreach(
$tableNames as $tableName)
    {
        
$tableName='"'.$tableName.'"';
        if(
strpos($tableName,'.')!==false)
            
$tableName=str_replace('.','"."',$tableName);
        
$db->createCommand("ALTER TABLE $tableName $enable TRIGGER ALL")->execute();
    }
}

启用或禁用完整性检查。

createColumn() 方法
protected CDbColumnSchema createColumn(array $column)
$column array 列元数据
{return} CDbColumnSchema 规范的列元数据
protected function createColumn($column)
{
    
$c=new CPgsqlColumnSchema;
    
$c->name=$column['attname'];
    
$c->rawName=$this->quoteColumnName($c->name);
    
$c->allowNull=!$column['attnotnull'];
    
$c->isPrimaryKey=false;
    
$c->isForeignKey=false;

    
$c->init($column['type'],$column['atthasdef'] ? $column['adsrc'] : null);

    return 
$c;
}

创建一个列。

dropIndex() 方法 (可用自 v1.1.6)
public string dropIndex(string $name, string $table)
$name string 要删除的索引名。该索引名会被指定方法正确引用。
$table string 要删除的索引所在表。该表名会被指定方法正确引用。
{return} string 删除索引的SQL语句。
public function dropIndex($name$table)
{
    return 
'DROP INDEX '.$this->quoteTableName($name);
}

构造删除索引的SQL语句。

findColumns() 方法
protected boolean findColumns(CPgsqlTableSchema $table)
$table CPgsqlTableSchema 表元数据
{return} boolean 表是否存在于数据库里
protected function findColumns($table)
{
    
$sql=<<<EOD
SELECT a.attname, LOWER(format_type(a.atttypid, a.atttypmod)) AS type, d.adsrc, a.attnotnull, a.atthasdef
FROM pg_attribute a LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attnum > 0 AND NOT a.attisdropped
AND a.attrelid = (SELECT oid FROM pg_catalog.pg_class WHERE relname=:table
    AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = :schema))
ORDER BY a.attnum
EOD;
    
$command=$this->getDbConnection()->createCommand($sql);
    
$command->bindValue(':table',$table->name);
    
$command->bindValue(':schema',$table->schemaName);

    if((
$columns=$command->queryAll())===array())
        return 
false;

    foreach(
$columns as $column)
    {
        
$c=$this->createColumn($column);
        
$table->columns[$c->name]=$c;

        if(
stripos($column['adsrc'],'nextval')===&& preg_match('/nextval\([^\']*\'([^\']+)\'[^\)]*\)/i',$column['adsrc'],$matches))
        {
            if(
strpos($matches[1],'.')!==false || $table->schemaName===self::DEFAULT_SCHEMA)
                
$this->_sequences[$table->rawName.'.'.$c->name]=$matches[1];
            else
                
$this->_sequences[$table->rawName.'.'.$c->name]=$table->schemaName.'.'.$matches[1];
            
$c->autoIncrement=true;
        }
    }
    return 
true;
}

收集列的元数据。

findConstraints() 方法
protected void findConstraints(CPgsqlTableSchema $table)
$table CPgsqlTableSchema 表元数据
protected function findConstraints($table)
{
    
$sql=<<<EOD
SELECT conname, consrc, contype, indkey FROM (
SELECT
    conname,
    CASE WHEN contype='f' THEN
        pg_catalog.pg_get_constraintdef(oid)
    ELSE
        'CHECK (' || consrc || ')'
    END AS consrc,
    contype,
    conrelid AS relid,
    NULL AS indkey
FROM
    pg_catalog.pg_constraint
WHERE
    contype IN ('f', 'c')
UNION ALL
SELECT
    pc.relname,
    NULL,
    CASE WHEN indisprimary THEN
            'p'
    ELSE
            'u'
    END,
    pi.indrelid,
    indkey
FROM
    pg_catalog.pg_class pc,
    pg_catalog.pg_index pi
WHERE
    pc.oid=pi.indexrelid
    AND EXISTS (
        SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c
        ON (d.refclassid = c.tableoid AND d.refobjid = c.oid)
        WHERE d.classid = pc.tableoid AND d.objid = pc.oid AND d.deptype = 'i' AND c.contype IN ('u', 'p')
)
) AS sub
WHERE relid = (SELECT oid FROM pg_catalog.pg_class WHERE relname=:table
AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace
WHERE nspname=:schema))
EOD;
    
$command=$this->getDbConnection()->createCommand($sql);
    
$command->bindValue(':table',$table->name);
    
$command->bindValue(':schema',$table->schemaName);
    foreach(
$command->queryAll() as $row)
    {
        if(
$row['contype']==='p'// primary key
            
$this->findPrimaryKey($table,$row['indkey']);
        else if(
$row['contype']==='f'// foreign key
            
$this->findForeignKey($table,$row['consrc']);
    }
}

收集给定表主键列和外键列的详细信息。

findForeignKey() 方法
protected void findForeignKey(CPgsqlTableSchema $table, string $src)
$table CPgsqlTableSchema 表元数据
$src string pgsql外键定义
protected function findForeignKey($table,$src)
{
    
$matches=array();
    
$brackets='\(([^\)]+)\)';
    
$pattern="/FOREIGN\s+KEY\s+{$brackets}\s+REFERENCES\s+([^\(]+){$brackets}/i";
    if(
preg_match($pattern,str_replace('"','',$src),$matches))
    {
        
$keys=preg_split('/,\s+/'$matches[1]);
        
$tableName=$matches[2];
        
$fkeys=preg_split('/,\s+/'$matches[3]);
        foreach(
$keys as $i=>$key)
        {
            
$table->foreignKeys[$key]=array($tableName,$fkeys[$i]);
            if(isset(
$table->columns[$key]))
                
$table->columns[$key]->isForeignKey=true;
        }
    }
}

收集外键信息。

findPrimaryKey() 方法
protected void findPrimaryKey(CPgsqlTableSchema $table, string $indices)
$table CPgsqlTableSchema 表元数据
$indices string pgsql主键索引列表
protected function findPrimaryKey($table,$indices)
{
    
$indices=implode(', ',preg_split('/\s+/',$indices));
    
$sql=<<<EOD
SELECT attnum, attname FROM pg_catalog.pg_attribute WHERE
attrelid=(
    SELECT oid FROM pg_catalog.pg_class WHERE relname=:table AND relnamespace=(
        SELECT oid FROM pg_catalog.pg_namespace WHERE nspname=:schema
    )
)
AND attnum IN (
{$indices})
EOD;
    
$command=$this->getDbConnection()->createCommand($sql);
    
$command->bindValue(':table',$table->name);
    
$command->bindValue(':schema',$table->schemaName);
    foreach(
$command->queryAll() as $row)
    {
        
$name=$row['attname'];
        if(isset(
$table->columns[$name]))
        {
            
$table->columns[$name]->isPrimaryKey=true;
            if(
$table->primaryKey===null)
                
$table->primaryKey=$name;
            else if(
is_string($table->primaryKey))
                
$table->primaryKey=array($table->primaryKey,$name);
            else
                
$table->primaryKey[]=$name;
        }
    }
}

收集主键信息。

findTableNames() 方法
protected array findTableNames(string $schema='')
$schema string 表schema。默认是空字符串,意味着当前或默认schema。 若为空,则返回的表名会被加上schema名前缀。
{return} array 数据库里的所有表名。
protected function findTableNames($schema='')
{
    if(
$schema==='')
        
$schema=self::DEFAULT_SCHEMA;
    
$sql=<<<EOD
SELECT table_name, table_schema FROM information_schema.tables
WHERE table_schema=:schema AND table_type='BASE TABLE'
EOD;
    
$command=$this->getDbConnection()->createCommand($sql);
    
$command->bindParam(':schema',$schema);
    
$rows=$command->queryAll();
    
$names=array();
    foreach(
$rows as $row)
    {
        if(
$schema===self::DEFAULT_SCHEMA)
            
$names[]=$row['table_name'];
        else
            
$names[]=$row['table_schema'].'.'.$row['table_name'];
    }
    return 
$names;
}

返回所有数据库里的表名。

loadTable() 方法
protected CDbTableSchema loadTable(string $name)
$name string 表名
{return} CDbTableSchema 取决于表元数据的驱动。
protected function loadTable($name)
{
    
$table=new CPgsqlTableSchema;
    
$this->resolveTableNames($table,$name);
    if(!
$this->findColumns($table))
        return 
null;
    
$this->findConstraints($table);

    if(
is_string($table->primaryKey) && isset($this->_sequences[$table->rawName.'.'.$table->primaryKey]))
        
$table->sequenceName=$this->_sequences[$table->rawName.'.'.$table->primaryKey];
    else if(
is_array($table->primaryKey))
    {
        foreach(
$table->primaryKey as $pk)
        {
            if(isset(
$this->_sequences[$table->rawName.'.'.$pk]))
            {
                
$table->sequenceName=$this->_sequences[$table->rawName.'.'.$pk];
                break;
            }
        }
    }

    return 
$table;
}

为指定表载入元数据。

quoteSimpleTableName() 方法 (可用自 v1.1.6)
public string quoteSimpleTableName(string $name)
$name string 表名
{return} string 正确引用的表名
public function quoteSimpleTableName($name)
{
    return 
'"'.$name.'"';
}

用引号引用表名以便查询时使用。 一个不包括前缀的简单表名。

renameTable() 方法 (可用自 v1.1.6)
public string renameTable(string $table, string $newName)
$table string 要重命名的表。该表名会被指定方法正确引用。
$newName string 新表名。 该表名会被指定方法正确引用。
{return} string 重命名数据表的SQL语句。
public function renameTable($table$newName)
{
    return 
'ALTER TABLE ' $this->quoteTableName($table) . ' RENAME TO ' $this->quoteTableName($newName);
}

构造重命名数据表的SQL语句。

resetSequence() 方法 (可用自 v1.1)
public void resetSequence(CDbTableSchema $table, mixed $value=NULL)
$table CDbTableSchema 要重置主键序列的表schema
$value mixed 新插入行的主键值。如果未设置, 则新行主键值为1。
public function resetSequence($table,$value=null)
{
    if(
$table->sequenceName!==null)
    {
        
$seq='"'.$table->sequenceName.'"';
        if(
strpos($seq,'.')!==false)
            
$seq=str_replace('.','"."',$seq);
        if(
$value===null)
            
$value="(SELECT COALESCE(MAX(\"{$table->primaryKey}\"),0) FROM {$table->rawName}) + 1";
        else
            
$value=(int)$value;
        
$this->getDbConnection()->createCommand("SELECT SETVAL('$seq', $value, false)")->execute();
    }
}

重置表的主键的序列值。 序列会被充值,这样一来,新插入行的主键值 将会是指定值或者1。

resolveTableNames() 方法
protected void resolveTableNames(CPgsqlTableSchema $table, string $name)
$table CPgsqlTableSchema 表元数据
$name string 未引用的表名
protected function resolveTableNames($table,$name)
{
    
$parts=explode('.',str_replace('"','',$name));
    if(isset(
$parts[1]))
    {
        
$schemaName=$parts[0];
        
$tableName=$parts[1];
    }
    else
    {
        
$schemaName=self::DEFAULT_SCHEMA;
        
$tableName=$parts[0];
    }

    
$table->name=$tableName;
    
$table->schemaName=$schemaName;
    if(
$schemaName===self::DEFAULT_SCHEMA)
        
$table->rawName=$this->quoteTableName($tableName);
    else
        
$table->rawName=$this->quoteTableName($schemaName).'.'.$this->quoteTableName($tableName);
}

生成各种表名。