Merge upstream branch
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index b41a420..15195b2 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -651,7 +651,7 @@
 	 */
 	public function is_write_type($sql)
 	{
-		return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD DATA|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|OPTIMIZE)\s+/i', $sql);
+		return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD DATA|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|OPTIMIZE|REINDEX)\s+/i', $sql);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index 7108a6d..84f7791 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -147,7 +147,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	public function db_set_charset($charset, $collation)
+	protected function _db_set_charset($charset, $collation)
 	{
 		return function_exists('mysql_set_charset')
 			? @mysql_set_charset($charset, $this->conn_id)
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index d668108..df0f50d 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -147,6 +147,19 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Set client character set
+	 *
+	 * @param       string
+	 * @return      bool
+	 */
+	protected function _db_set_charset($charset)
+	{
+		return (pg_set_client_encoding($this->conn_id, $charset) === 0);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Database version number
 	 *
 	 * @return	string
@@ -209,18 +222,12 @@
 	/**
 	 * Begin Transaction
 	 *
-	 * @access	public
 	 * @return	bool
 	 */
-	function trans_begin($test_mode = FALSE)
+	public function trans_begin($test_mode = FALSE)
 	{
-		if ( ! $this->trans_enabled)
-		{
-			return TRUE;
-		}
-
 		// When transactions are nested we only begin/commit/rollback the outermost ones
-		if ($this->_trans_depth > 0)
+		if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
 		{
 			return TRUE;
 		}
@@ -228,9 +235,9 @@
 		// Reset the transaction failure flag.
 		// If the $test_mode flag is set to TRUE transactions will be rolled back
 		// even if the queries produce a successful result.
-		$this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
+		$this->_trans_failure = ($test_mode === TRUE);
 
-		return @pg_exec($this->conn_id, "begin");
+		return @pg_query($this->conn_id, 'BEGIN');
 	}
 
 	// --------------------------------------------------------------------
@@ -238,23 +245,17 @@
 	/**
 	 * Commit Transaction
 	 *
-	 * @access	public
 	 * @return	bool
 	 */
-	function trans_commit()
+	public function trans_commit()
 	{
-		if ( ! $this->trans_enabled)
-		{
-			return TRUE;
-		}
-
 		// When transactions are nested we only begin/commit/rollback the outermost ones
-		if ($this->_trans_depth > 0)
+		if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
 		{
 			return TRUE;
 		}
 
-		return @pg_exec($this->conn_id, "commit");
+		return @pg_query($this->conn_id, 'COMMIT');
 	}
 
 	// --------------------------------------------------------------------
@@ -262,23 +263,17 @@
 	/**
 	 * Rollback Transaction
 	 *
-	 * @access	public
 	 * @return	bool
 	 */
-	function trans_rollback()
+	public function trans_rollback()
 	{
-		if ( ! $this->trans_enabled)
-		{
-			return TRUE;
-		}
-
 		// When transactions are nested we only begin/commit/rollback the outermost ones
-		if ($this->_trans_depth > 0)
+		if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
 		{
 			return TRUE;
 		}
 
-		return @pg_exec($this->conn_id, "rollback");
+		return @pg_query($this->conn_id, 'ROLLBACK');
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/postgre/postgre_utility.php b/system/database/drivers/postgre/postgre_utility.php
index dffd8c5..c426b36 100644
--- a/system/database/drivers/postgre/postgre_utility.php
+++ b/system/database/drivers/postgre/postgre_utility.php
@@ -1,13 +1,13 @@
-<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
 /**
  * CodeIgniter
  *
  * An open source application development framework for PHP 5.1.6 or newer
  *
  * NOTICE OF LICENSE
- * 
+ *
  * Licensed under the Open Software License version 3.0
- * 
+ *
  * This source file is subject to the Open Software License (OSL 3.0) that is
  * bundled with this package in the files license.txt / license.rst.  It is
  * also available through the world wide web at this URL:
@@ -25,8 +25,6 @@
  * @filesource
  */
 
-// ------------------------------------------------------------------------
-
 /**
  * Postgre Utility Class
  *
@@ -39,12 +37,11 @@
 	/**
 	 * List databases
 	 *
-	 * @access	private
-	 * @return	bool
+	 * @return	string
 	 */
-	function _list_databases()
+	public function _list_databases()
 	{
-		return "SELECT datname FROM pg_database";
+		return 'SELECT datname FROM pg_database';
 	}
 
 	// --------------------------------------------------------------------
@@ -52,15 +49,12 @@
 	/**
 	 * Optimize table query
 	 *
-	 * Is table optimization supported in Postgre?
-	 *
-	 * @access	private
 	 * @param	string	the table name
-	 * @return	object
+	 * @return	string
 	 */
-	function _optimize_table($table)
+	public function _optimize_table($table)
 	{
-		return FALSE;
+		return 'REINDEX TABLE '.$this->db->protect_identifiers($table);
 	}
 
 	// --------------------------------------------------------------------
@@ -68,13 +62,10 @@
 	/**
 	 * Repair table query
 	 *
-	 * Are table repairs supported in Postgre?
-	 *
-	 * @access	private
 	 * @param	string	the table name
-	 * @return	object
+	 * @return	bool
 	 */
-	function _repair_table($table)
+	public function _repair_table($table)
 	{
 		return FALSE;
 	}
@@ -84,7 +75,6 @@
 	/**
 	 * Postgre Export
 	 *
-	 * @access	private
 	 * @param	array	Preferences
 	 * @return	mixed
 	 */
@@ -95,6 +85,5 @@
 	}
 }
 
-
 /* End of file postgre_utility.php */
-/* Location: ./system/database/drivers/postgre/postgre_utility.php */
\ No newline at end of file
+/* Location: ./system/database/drivers/postgre/postgre_utility.php */
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 35a41a9..f3db78e 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -58,7 +58,10 @@
    -  Added an optional database name parameter to db_select().
    -  Replaced the _error_message() and _error_number() methods with error(), that returns an array containing the last database error code and message.
    -  Improved version() implementation so that drivers that have a native function to get the version number don't have to be defined in the core DB_driver class.
-   -  PostgreSQL driver now uses pg_version() to get the database version number, when possible.
+   -  Improved support of the PostgreSQL driver, including:
+	 -  pg_version() is now used to get the database version number, when possible.
+	 -  Added db_set_charset() support.
+	 -  Added _optimize_table() support for the :doc:`Database Utility Class <database/utilities>` (rebuilds table indexes).
    -  Added support for SQLite3 database driver.
 
 -  Libraries