conn = null; $this->errMsg = null; $this->escapeData = true; $this->result = array(); $this->includeStandardObjects = false; } function name() { return 'pgsql'; } function hasServer() { return true; } function hasObject($type) { switch($type) { case 'table': case 'view': //case 'procedure': case 'function': case 'trigger': case 'sequence': case 'template': case 'schema': return true; break; case 'event': //if ( ((float)Session::get('db', 'version_full')) >= 5.1 ) // return true; break; } return false; } function getObjectTypes() { $types = array( 'schemas', 'tables', 'views', 'functions', 'triggers' ); if ($this->hasObject('event')) $types[] = 'events'; return $types; } function getObjectList( $details = false ) { $data = array( 'schemas' => $this->getSchemas(), 'tables' => $this->getTables( $details ), 'views' => $this->getViews(), 'functions' => $this->getFunctions(), 'triggers' => $this->getTriggers(), ); if ($this->hasObject('event')) $data['events'] = $this->getEvents(); return $data; } function getBackQuotes() { return '"'; } function getQuotes() { return "'"; } function getStandardDbList() { return array( 'postgres', 'test' ); } function setAuthOptions($options) { } function connect($ip, $user, $password, $db="") { if (!function_exists('pg_connect')) { return $this->error(str_replace('{{NAME}}', 'PGSQL', __('{{NAME}} client library is not installed'))); } $this->conn_str = $this->build_conn_string($ip, $user, $password, $db); $this->conn = @pg_connect($this->conn_str); if (!$this->conn) return $this->error(__('Database connection failed to the server')); $this->ip = $ip; $this->user = $user; $this->password = $password; $this->db = $db; $this->selectVersion(); $this->query("SET CLIENT_ENCODING to 'utf8'"); $this->query("SET NAMES 'utf8'"); return true; } function disconnect() { @pg_close($this->conn); $this->conn = false; return true; } function getCurrentUser() { if ($this->query('select user')) { $row = $this->fetchRow(); return $row[0]; } return ''; } function selectDb($db) { $this->db = $db; //$this->conn_str = $this->build_conn_string($this->ip, $user, $password, $db); @pg_connect("dbname=" . pg_escape_string($db) ); } function createDatabase( $name ) { $sql = "create database \"".$this->escape($name)."\""; return $this->query($sql); } function query($sql, $stack=0) { // call with query($sql, 1) to store multiple results if (!$this->conn) { log_message("DB: Connection has been closed"); return false; } if (v($this->result[$stack])) @pg_free_result($this->result[$stack]); $this->result[$stack] = ""; $this->stack_last = $stack; $this->lastQuery = $sql; $this->queryTime = $this->getMicroTime(); $this->result[$stack] = @pg_query($this->conn, $sql); $this->queryTime = $this->getMicroTime() - $this->queryTime; if ($this->result[$stack] === FALSE) { $this->errMsg = pg_errormessage($this->conn); log_message("DB: $sql ::: ".@pg_errormessage($this->conn)); return false; } return true; } function getWarnings() { $ret = array(); /*$res = pg_query($this->conn, "SHOW WARNINGS"); if ($res !== FALSE) { while($row = pg_fetch_array($res)) $ret[$row['Code']] = $row['Message']; }*/ $ret[] = pg_errormessage($this->conn); return $ret; } function getQueryTime($time=false) { // returns formatted given value or internal query time return sprintf("%.2f", ($time ? $time : $this->queryTime) * 1000) . " ms"; } function hasAffectedRows() { return ($this->getAffectedRows() > 0); } function insert($table, $values) { if (!is_array($values)) return false; $sql = "insert into $table ("; foreach($values as $field=>$value) $sql .= " $field,"; $sql = substr($sql, 0, strlen($sql) - 1); $sql .= ") values ("; foreach($values as $field=>$value) { if ($this->escapeData) $sql .= "'" . $this->escape($value) . "',"; else $sql .= "'$value',"; } $sql = substr($sql, 0, strlen($sql) - 1); $sql .= ")"; $this->query($sql); } function update($table, $values, $condition="") { if (!is_array($values)) return false; $sql = "update $table set "; foreach($values as $field=>$value) { if ($this->escapeData) $sql .= "$field = '" . $this->escape($field) . "',"; else $sql .= "$field = '$value',"; } $sql = substr($sql, 0, strlen($sql) - 1); if ($condition != "") $sql .= "$condition"; $this->query($sql); } function getInsertID() { return pg_getlastoid($this->result[$this->stack_last]); } function getResult($stack=0) { return $this->result[$stack]; } function hasResult($stack=0) { return (@pg_result_status($this->result[$stack]) == PGSQL_TUPLES_OK); //( is_resource($this->result[$stack]) && get_resource_type($this->result[$stack]) === 'pgsql result' ) } function fetchRow($stack=0, $type="") { if($type == "") $type = PGSQL_BOTH; else if ($type == "num") $type = PGSQL_NUM; else if ($type == "assoc") $type = PGSQL_ASSOC; if (!$this->result[$stack]) { log_message("DB: called fetchRow[$stack] but result is false"); return NULL; } return @pg_fetch_array($this->result[$stack], NULL, $type); } function fetchSpecificRow($num, $type="", $stack=0) { if($type == "") $type = PGSQL_BOTH; else if ($type == "num") $type = PGSQL_NUM; else if ($type == "assoc") $type = PGSQL_ASSOC; if (!$this->result[$stack]) { log_message("DB: called fetchSpecificRow[$stack] but result is false"); return NULL; } return @pg_fetch_array($this->result[$stack], $num, $type); } function numRows($stack=0) { return pg_numrows($this->result[$stack]); } function error($str) { log_message("DB: " . $str); $this->errMsg = $str; return false; } function getError() { return $this->errMsg; } function escape($str) { return pg_escape_string($this->conn, $str); } function quote($str) { if(strpos($str, '.') === false) return '"' . $str . '"'; return '"' . str_replace('.', '"."', $str) . '"'; } function setEscape($escape=true) { $this->escapeData = $escape; } function getAffectedRows() { return pg_affected_rows( $this->result[$this->stack_last] ); } /**************************************/ function getDatabases() { $res = pg_query($this->conn, "SELECT datname FROM pg_database WHERE NOT datistemplate ORDER BY datname"); $ret = array(); while($row = pg_fetch_array($res)) $ret[] = $row[0]; return $ret; } function getSchemas() { if (!$this->db) return array(); $extra = $this->includeStandardObjects ? "" : "WHERE nspname NOT LIKE 'pg@_%' ESCAPE '@' AND nspname != 'information_schema'"; $res = pg_query($this->conn, "SELECT pn.nspname, pu.rolname AS nspowner, pg_catalog.obj_description(pn.oid, 'pg_namespace') AS nspcomment FROM pg_catalog.pg_namespace pn LEFT JOIN pg_catalog.pg_roles pu ON (pn.nspowner = pu.oid) $extra ORDER BY nspname"); $ret = array(); while($row = pg_fetch_array($res)) $ret[] = $row[0]; return $ret; } function getTables( $details = false ) { if (!$this->db) return array(); $extra = $this->includeStandardObjects ? "" : "AND table_schema NOT LIKE 'pg@_%' ESCAPE '@' AND table_schema != 'information_schema'"; $res = pg_query($this->conn, "SELECT table_schema, table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' $extra ORDER BY table_name"); $ret = array(); while($row = pg_fetch_array($res)) { $schema = $row[0]; if (!isset($ret[$schema])) $ret[$schema] = array(); // @@TODO: add details for table for pgsql databases $ret[$schema][] = $row[1]; } return $ret; } function getViews() { if (!$this->db) return array(); $extra = $this->includeStandardObjects ? "" : "AND table_schema NOT LIKE 'pg@_%' ESCAPE '@' AND table_schema != 'information_schema'"; $res = pg_query($this->conn, "SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema = current_schema() and table_type = 'VIEW' $extra ORDER BY table_name"); if (!$res) return array(); $ret = array(); while($row = pg_fetch_array($res)) { $schema = $row[0]; if (!isset($ret[$schema])) $ret[$schema] = array(); $ret[$schema][] = $row[1]; } return $ret; } function getFunctions() { if (!$this->db) return array(); $extra = $this->includeStandardObjects ? "" : "WHERE n.nspname NOT LIKE 'pg@_%' ESCAPE '@' AND n.nspname != 'information_schema'"; $res = pg_query($this->conn, "SELECT n.nspname, p.proname AS name FROM pg_proc p INNER JOIN pg_namespace n ON p.pronamespace = n.oid LEFT OUTER JOIN pg_roles u ON u.oid = p.proowner $extra ORDER BY p.proname, n.nspname"); if (!$res) return array(); $ret = array(); while($row = pg_fetch_array($res)) { $schema = $row[0]; if (!isset($ret[$schema])) $ret[$schema] = array(); $ret[$schema][] = $row[1]; } return $ret; } function getTriggers() { if (!$this->db) return array(); $extra = $this->includeStandardObjects ? "" : "AND n.nspname NOT LIKE 'pg@_%' ESCAPE '@' AND n.nspname != 'information_schema'"; $res = pg_query($this->conn, "SELECT n.nspname, tgname FROM pg_trigger t INNER JOIN pg_class c ON t.tgrelid = c.oid INNER JOIN pg_namespace n ON c.relnamespace = n.oid WHERE t.tgisinternal = 'f' $extra ORDER BY t.tgname"); if (!$res) return array(); $ret = array(); while($row = pg_fetch_array($res)) { $schema = $row[0]; if (!isset($ret[$schema])) $ret[$schema] = array(); $ret[$schema][] = $row[1]; } return $ret; } function getSequences() { if (!$this->db) return array(); $extra = $this->includeStandardObjects ? "" : "AND n.nspname NOT LIKE 'pg@_%' ESCAPE '@' AND n.nspname != 'information_schema'"; $res = pg_query($this->conn, "SELECT n.nspname, c.relname AS name, ds.description, n.nspname, d.refobjid as owntab, u.rolname AS usename FROM pg_class c LEFT OUTER JOIN pg_roles u ON u.oid = c.relowner INNER JOIN pg_namespace n ON c.relnamespace = n.oid LEFT OUTER JOIN pg_depend d on c.relkind = 'S' and d.classid = c.tableoid and d.objid = c.oid and d.objsubid = 0 and d.refclassid = c.tableoid and d.deptype = 'i' LEFT OUTER JOIN pg_description ds ON c.oid = ds.objoid WHERE c.relkind = 'S' $extra ORDER BY c.relname"); if (!$res) return array(); $ret = array(); while($row = pg_fetch_array($res)) { $schema = $row[0]; if (!isset($ret[$schema])) $ret[$schema] = array(); $ret[$schema][] = $row[1]; } return $ret; } /**************************************/ function getFieldInfo($stack=0) { $fields = array(); $tables = array(); $num_fields = pg_num_fields($this->result[$stack]); for($i=0; $i<$num_fields; $i++) { $f = new StdClass; $f->name = pg_field_name($this->result[$stack], $i); $f->table = pg_field_table($this->result[$stack], $i); $f->type = pg_field_type($this->result[$stack], $i); $f->blob = 0; $f->pkey = 0; $f->ukey = 0; $f->mkey = 0; $f->numeric = substr($f->type, 0, 3) == 'int' ? 1 : 0; if (!isset($tables[$f->table])) $tables[$f->table] = array(); $tables[$f->table][] = "'".$f->name."'"; $fields[] = $f; } $this->getFieldMetaInfo($fields, $tables); $this->getFieldConstraints($fields, $tables); return $fields; } function getMicroTime() { list($usec, $sec) = explode(" ",microtime()); return ((float)$usec + (float)$sec); } function selectVersion() { $res = pg_query($this->conn, "select version()"); $row = pg_fetch_array($res); preg_match('/([PostgreSQL]+)[\s]+([0-9.]+)[,\s]+(.*)/i', $row[0], $matches); Session::set('db', 'version', intval($matches[2])); Session::set('db', 'version_full', $matches[2]); Session::set('db', 'version_comment', $matches[3]); } function getCreateCommand($type, $name) { $func = 'getCreateCommandFor' . $type; if (method_exists($this, $func)) return $this->$func( $name ); return ''; //return 'Create command is not available for the given object type'; } function getDropCommand( $table ) { return "drop table if exists " . $this->quote( $table ); } function getTruncateCommand( $table ) { return 'truncate table ' . $this->quote( $table ); } function getFieldValues($table, $name) { $sql = 'show full fields from "'.$table.'" where "Field" = \''.$this->escape($name).'\''; $res = pg_query($this->conn, $sql); if (pg_numrows($res) == 0) return ( (object) array('list' => array()) ); $row = pg_fetch_array($res); $type = $row['Type']; preg_match('/enum\((.*)\)$/', $type, $matches); if (!isset($matches[1])) preg_match('/set\((.*)\)$/', $type, $matches); if (isset($matches[1])) { if (phpCheck(5.3)) { $regex = "/\('(.*)'\)/"; preg_match_all($regex, $row['Type'], $list); return array_map('replace_single_quotes', explode("','", $list[1][0])); } else { $list = explode(',', $matches[1]); foreach($list as $k => $v) $list[$k] = str_replace("\\'", "'", trim($v, " '")); return $list; } } return ( (object) array('list' => array()) ); } function getEngines() { $sql = 'show engines'; $res = pg_query($this->conn, $sql); if (pg_numrows($res) == 0) return ( array() ); $arr = array(); while($row = pg_fetch_array($res)) if ($row['Support'] != 'NO') $arr[] = $row['Engine']; return $arr; } function getCharsets() { $sql = 'show character set'; $res = pg_query($this->conn, $sql); if (pg_numrows($res) == 0) return ( array() ); $arr = array(); while($row = pg_fetch_array($res)) $arr[] = $row['Charset']; asort($arr); return $arr; } function getCollations() { $sql = 'show collation'; $res = pg_query($this->conn, $sql); if (pg_numrows($res) == 0) return ( array() ); $arr = array(); while($row = pg_fetch_array($res)) $arr[] = $row['Collation']; asort($arr); return $arr; } function getTableFields($table) { $fields = array(); $tables = array(); $tables[$table] = array(); $this->getFieldMetaInfo($fields, $tables); return $fields; } function getTableProperties($table) { $sql = "show table status where \"Name\" like '".$this->escape($table)."'"; if (!$this->query($sql, "_tmp_query")) return FALSE; return $this->fetchRow("_tmp_query"); } function queryTableStatus() { $sql = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_type = 'BASE TABLE' ORDER BY table_name"; return $this->query($sql); } function getTableDescription( $table ) { list($schema, $tbl) = strpos($table, '.') === FALSE ? array('', $table) : explode('.', $table); $sql = "select * from INFORMATION_SCHEMA.COLUMNS where table_schema = '" . $this->escape( $schema ) . "' and table_name = '". $this->escape( $tbl ) . "' order by ordinal_position"; return $this->query($sql); } function flush($option = '', $skiplog=false) { $options = array('HOSTS', 'PRIVILEGES', 'TABLES', 'STATUS', 'DES_KEY_FILE', 'QUERY CACHE', 'USER_RESOURCES', 'TABLES WITH READ LOCK'); if ($option == '') { foreach($options as $option) { $sql = "flush " . ( $skiplog ? "NO_WRITE_TO_BINLOG " : "") . $this->escape($option); $this->query($sql, '_temp_flush'); } $this->query('UNLOCK TABLES', '_temp_flush'); } else { $sql = "flush " . ( $skiplog ? "NO_WRITE_TO_BINLOG " : "") . $this->escape($option); $this->query($sql, '_temp_flush'); if ($option == 'TABLES WITH READ LOCK') $this->query('UNLOCK TABLES', '_temp_flush'); } return true; } function getLastQuery() { return $this->lastQuery; } function getInsertStatement($tbl) { $fields = array(); $tables = array(); $tables[$tbl] = array(); $this->getFieldMetaInfo($fields, $tables); $str = "INSERT INTO ".$this->quote($tbl)." ("; $str2 = " VALUES ("; $num = count($fields); for($i=0; $i<$num; $i++) { $str .= ($i==0 ? "\"" : ",\"") . $fields[$i]->name . "\""; if ($fields[$i]->autoinc) { $str2 .= $i==0 ? 'NULL' : ',NULL'; } else if ( $fields[$i]->numeric ) { $str2 .= $i==0 ? "0" : ", 0"; } else { $str2 .= $i==0 ? "''" : ",''"; } } $str .= ")"; $str2 .= ")"; return $str.$str2; } function getUpdateStatement($tbl) { $fields = array(); $tables = array(); $tables[$tbl] = array(); $this->getFieldMetaInfo($fields, $tables); $this->getFieldConstraints($fields, $tables); $pKey = ''; // if a primary key is available, this helps avoid multikey attributes in where clause $str2 = ""; $str = "UPDATE ".$this->quote($tbl)." SET "; $num = count($fields); for($i=0; $i<$num; $i++) { $str .= ($i==0 ? "\"" : ", \"") . $fields[$i]->name . "\"=''"; if ($fields[$i]->pkey) $pKey = $fields[$i]->name; if ($str2 != "") $str2 .= " AND "; $str2 .= "\"".$fields[$i]->name."\"=''"; } // if we found a primary key, then use it only for where clause and discard other keys if ($pKey != '') $str2 = "\"$pKey\"=''"; if ($str2 != "") $str2 = " WHERE " . $str2; return $str . $str2; } function truncateTable($tbl) { return $this->query('truncate table '.$this->quote($tbl)); } function renameObject($name, $type, $new_name) { $result = false; list($schema, $new_name) = $this->splitObjectName( $new_name ); if($type == 'table') { $query = 'alter '.$this->escape($type).' ' . $this->quote($name) . ' rename to '.$this->quote($new_name); $result = $this->query($query); } else { $func = 'rename' . $type; if (method_exists($this, $func)) return $this->$func( $name ); } return $result; } function dropObject($name, $type) { $result = false; $query = 'drop '.$this->escape($type).' '.$this->quote($name); $result = $this->query($query); return $result; } function copyObject($name, $type, $new_name) { $result = false; if($type == 'table') { $query = 'create '.$this->escape($type). ' ' . $this->quote($new_name) . ' (like ' . $this->quote($name) . ")"; $result = $this->query($query); if ($result) { $query = 'insert into ' . $this->quote($new_name) . ' select * from ' . $this->quote($name); $result = $this->query($query); } } else { $command = $this->getCreateCommand($type, $name); $search = '/(create.*'.$type. ' )('.$name.'|\"'.$name.'\")/i'; $replace = '${1} "'.$new_name.'"'; $query = preg_replace($search, $replace, $command, 1); $result = $this->query($query); } return $result; } function getAutoIncField($table) { $sql = "show full fields from \"".$this->escape($table)."\""; if (!$this->query($sql, "_temp")) return false; $i = 0; while($row = $this->fetchRow("_temp")) { if (strpos($row["Extra"], "auto_increment") !== false) { return $i; } $i++; } return -1; } function queryVariables() { return $this->query("SHOW ALL"); } function getLimit($count, $offset = 0) { return " limit $count offset $offset"; } function addExportHeader( $name, $obj = 'db', $type='insert' ) { $str = ''; switch($type) { case 'insert': if ( $obj == 'db' ) { $str = "-- Database export results for db ".$name."\n"; $str .= "\nSET statement_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSET check_function_bodies = false;\nSET client_min_messages = warning;\nSET search_path = public, pg_catalog;\nSET default_tablespace = '';\nSET default_with_oids = false;\n"; $str .= "\n-- Export data\n\n"; } else if ( $obj == 'table' ) { $str = "-- Table data export for table ".$name."\n"; $str .= "\nSET statement_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSET check_function_bodies = false;\nSET client_min_messages = warning;\nSET search_path = public, pg_catalog;\nSET default_tablespace = '';\nSET default_with_oids = false;\n"; $str .= "\n-- Export data\n\n"; } else if ( $obj == 'query' ) { $str = "-- Export results for query data\n"; $str .= "-- Query: \n-- ".str_replace("\n", "\n--", $name)."\n"; $str .= "\n-- Export data\n"; } break; } return $str; } function addExportFooter( $type='insert' ) { return "\n"; } function set_constraint( $constraint, $value ) { switch ($constraint) { case 'fkey': //$this->query('SET FOREIGN_KEY_CHECKS=' . ($value ? '1' : '0') ); break; } } /***** private functions ******/ protected function splitObjectName( $obj ) { return strpos($obj, '.') === FALSE ? array('', $obj) : explode('.', $obj); } // builds connection string for pgsql connect method from parameters protected function build_conn_string($ip, $user, $password, $db) { $host = $ip; $port = ''; if (strpos($ip, ':') !== false) { list($host, $port) = explode(':', $ip); } $str = "host=" . pg_escape_string($host) . " user=" . pg_escape_string($user); $str .= " password=" . pg_escape_string($password); if( !empty($port) ) $str .= " port=" . pg_escape_string($port); if( empty($db) ) $db = 'template1'; $str .= " dbname=" . pg_escape_string($db); return $str; } protected function getFieldMetaInfo(&$fields, $tables) { $sql = "select table_name, column_name, is_nullable, column_default, data_type from information_schema.columns where "; foreach($tables as $table => $keys) { list($schema, $tbl) = strpos($table, '.') === FALSE ? array('', $table) : explode('.', $table); $sql .= "(\"table_schema\"='".trim($schema, '"\' ')."' and \"table_name\"='".trim($tbl, '"\' ')."'"; if (count($keys) > 0) $sql .= " and \"column_name\" in (".implode(',', $keys).")) OR "; else $sql .= ") OR "; } $sql = substr($sql, 0, -3) . ' order by ordinal_position'; $res = pg_query($this->conn, $sql); if (!$res) return; while($row = pg_fetch_array($res)) { $found = false; for($i=0; $itable == $row[0] && $fields[$i]->name == $row[1]) { $fields[$i]->not_null = $row[2] == "YES" ? 0 : 1; $fields[$i]->datatype = $row[4]; $fields[$i]->default = $row[3]; $found = true; break; } } if (!$found) { // create new field info $f= new StdClass; $f->name = $row[1]; $f->table = $row[0]; $f->type = $row[4]; $f->blob = 0; $f->pkey = 0; $f->ukey = 0; $f->mkey = 0; $f->not_null = $row[2] == "YES" ? 0 : 1; $f->datatype = $row[4]; $f->default = $row[3]; //$f->zerofill = ($meta->flags & ZEROFILL_FLAG) ? 1 : 0; //$f->unsigned = ($meta->flags & UNSIGNED_FLAG) ? 1 : 0; $f->autoinc = 0; $f->numeric = substr($f->type, 0, 3) == 'int' ? 1 : 0; /*if ($meta->flags & ENUM_FLAG) $f->type = 'enum'; else if ($meta->flags & SET_FLAG) $f->type = 'set'; else if ($meta->flags & BINARY_FLAG) $f->type = 'binary'; else if ($meta->type < 10) $f->type = 'numeric'; else $f->type = 'char'; if ($f->type == 'enum' || $f->type == 'set') $f->list = $this->getFieldValues($f->table, $f->name); */ $fields[] = $f; } } } protected function getFieldConstraints(&$fields, $tables) { $sql = "select c.contype as type, ns1.nspname as schema, r1.relname as table, f1.attname as field FROM pg_catalog.pg_constraint AS c JOIN pg_catalog.pg_class AS r1 ON (c.conrelid=r1.oid) JOIN pg_catalog.pg_attribute AS f1 ON (f1.attrelid=r1.oid AND (f1.attnum=c.conkey[1])) JOIN pg_catalog.pg_namespace AS ns1 ON r1.relnamespace=ns1.oid LEFT JOIN ( pg_catalog.pg_class AS r2 JOIN pg_catalog.pg_namespace AS ns2 ON (r2.relnamespace=ns2.oid) ) ON (c.confrelid=r2.oid) LEFT JOIN pg_catalog.pg_attribute AS f2 ON (f2.attrelid=r2.oid AND ((c.confkey[1]=f2.attnum AND c.conkey[1]=f1.attnum))) WHERE "; foreach($tables as $table => $keys) { list($schema, $tbl) = $this->splitObjectName( $table ); $schema = trim($schema, '"\' '); if ($schema) $sql .= "(ns1.nspname='".$schema."' and r1.relname='".trim($tbl, '"\' ')."') OR "; else $sql .= "(r1.relname='".trim($tbl, '"\' ')."') OR "; } $sql = substr($sql, 0, -3); $res = pg_query($this->conn, $sql); if (!$res) return; while($row = pg_fetch_array($res)) { for($i=0; $itable == $row[2] && $fields[$i]->name == $row[3]) { $fields[$i]->pkey = $row[0] == "p" ? 1 : 0; $fields[$i]->ukey = $row[0] == "u" ? 1 : 0; break; } } } } protected function getCreateCommandForView( $name ) { list($schema, $name) = $this->splitObjectName( $name ); $sql = "SELECT c.relname, n.nspname, pg_catalog.pg_get_userbyid(c.relowner) AS relowner, pg_catalog.pg_get_viewdef(c.oid, true) AS createcmd, pg_catalog.obj_description(c.oid, 'pg_class') AS comments FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON (n.oid = c.relnamespace) WHERE (c.relname = '" . $this->escape($name) . "') AND n.nspname='" . $this->escape( $schema ) . "'"; if (!$this->query($sql, '_temp') || $this->numRows('_temp') == 0) return ''; $row = $this->fetchRow('_temp'); $cmd = 'CREATE VIEW ' . $this->quote( $row['nspname'] . '.' . $row['relname'] ) . " AS \n" . $row['createcmd']; if ($row['comments'] != '') { $cmd = "BEGIN; \n" . $cmd . "\nCOMMENT ON VIEW " . $this->quote( $row['nspname'] . '.' . $row['relname'] ) . " IS '" . $this->escape($row['comments']) . "';\nEND;"; } return $cmd; } } ?>