/**
  *
  * This allows the cached values for a table's field list to be erased.
  * If $tablename is empty, then the whole cache is erased.
  *
  * @param string $tableName
  *
  * @return boolean
  */
 function clearCachedFieldlist($tableName = false)
 {
     if ($tableName != false) {
         unset(self::$cached_fieldlists[$tableName]);
     } else {
         self::$cached_fieldlists = array();
     }
     return true;
 }
 /**
  * 
  * @param string $tableName
  * @param array $partitions
  * @param array $indexes
  * @param array $extensions
  */
 public function createOrReplacePartition($tableName, $partitions, $indexes, $extensions)
 {
     //We need the plpgsql language to be installed for this to work:
     $this->createLanguage('plpgsql');
     $trigger = 'CREATE OR REPLACE FUNCTION ' . $tableName . '_insert_trigger() RETURNS TRIGGER AS $$ BEGIN ';
     $first = true;
     //Do we need to create a tablespace for this item?
     if ($extensions && isset($extensions['tablespace'])) {
         $this->createOrReplaceTablespace($extensions['tablespace']['name'], $extensions['tablespace']['location']);
         $tableSpace = ' TABLESPACE ' . $extensions['tablespace']['name'];
     } else {
         $tableSpace = '';
     }
     foreach ($partitions as $partition_name => $partition_value) {
         //Check that this child table does not already exist:
         if (!$this->hasTable($partition_name)) {
             $this->query("CREATE TABLE \"{$partition_name}\" (CHECK (" . str_replace('NEW.', '', $partition_value) . ")) INHERITS (\"{$tableName}\"){$tableSpace};");
         } else {
             //Drop the constraint, we will recreate in in the next line
             $existing_constraint = $this->preparedQuery("SELECT conname FROM pg_constraint WHERE conname = ?;", array("{$partition_name}_pkey"));
             if ($existing_constraint) {
                 $this->query("ALTER TABLE \"{$partition_name}\" DROP CONSTRAINT \"{$partition_name}_pkey\";");
             }
             $this->dropTrigger(strtolower('trigger_' . $tableName . '_insert'), $tableName);
         }
         $this->query("ALTER TABLE \"{$partition_name}\" ADD CONSTRAINT \"{$partition_name}_pkey\" PRIMARY KEY (\"ID\");");
         if ($first) {
             $trigger .= 'IF';
             $first = false;
         } else {
             $trigger .= 'ELSIF';
         }
         $trigger .= " ({$partition_value}) THEN INSERT INTO \"{$partition_name}\" VALUES (NEW.*);";
         if ($indexes) {
             // We need to propogate the indexes through to the child pages.
             // Some of this code is duplicated, and could be tidied up
             foreach ($indexes as $name => $this_index) {
                 if ($this_index['type'] == 'fulltext') {
                     $fillfactor = $where = '';
                     if (isset($this_index['fillfactor'])) {
                         $fillfactor = 'WITH (FILLFACTOR = ' . $this_index['fillfactor'] . ')';
                     }
                     if (isset($this_index['where'])) {
                         $where = 'WHERE ' . $this_index['where'];
                     }
                     $clusterMethod = PostgreSQLDatabase::default_fts_cluster_method();
                     $this->query("CREATE INDEX \"" . $this->buildPostgresIndexName($partition_name, $this_index['name']) . "\" ON \"" . $partition_name . "\" USING {$clusterMethod}(\"ts_" . $name . "\") {$fillfactor} {$where}");
                     $ts_details = $this->fulltext($this_index, $partition_name, $name);
                     $this->query($ts_details['triggers']);
                 } else {
                     if (is_array($this_index)) {
                         $index_name = $this_index['name'];
                     } else {
                         $index_name = trim($this_index, '()');
                     }
                     $createIndex = $this->getIndexSqlDefinition($partition_name, $index_name, $this_index);
                     if ($createIndex !== false) {
                         $this->query($createIndex);
                     }
                 }
             }
         }
         //Lastly, clustering goes here:
         if ($extensions && isset($extensions['cluster'])) {
             $this->query("CLUSTER \"{$partition_name}\" USING \"{$extensions['cluster']}\";");
         }
     }
     $trigger .= 'ELSE RAISE EXCEPTION \'Value id out of range.  Fix the ' . $tableName . '_insert_trigger() function!\'; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql;';
     $trigger .= 'CREATE TRIGGER trigger_' . $tableName . '_insert BEFORE INSERT ON "' . $tableName . '" FOR EACH ROW EXECUTE PROCEDURE ' . $tableName . '_insert_trigger();';
     $this->query($trigger);
 }