/** * * 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); }