Example #1
0
 public function build(Pg $db)
 {
     // iterate over the relations and build the
     foreach ($this->working as $relation) {
         $table = new Table($relation, $this->inherits, $this->inheritedValues);
         $db->query($table);
     }
     $this->catalogRefresh();
     // get our new log table relations
     $logRelations = Relation::r()->findAllBySchema($this->inherits->get('schema'))->findByName($this->working->pluck('name'));
     // build entity history
     foreach ($logRelations as $relation) {
         $original = $this->working->findOneByName($relation->get('name'));
         $fnEntityHistory = new FnEntityHistory($relation, $original);
         $db->query($fnEntityHistory);
         $fnTableAtState = new FnTableAtState($relation, $original);
         $db->query($fnTableAtState);
         $viewTableHistory = new ViewTableHistory($relation, $original);
         $db->query($viewTableHistory);
     }
     return $logRelations;
 }
Example #2
0
    public function parse(QuoteInterface $quoting)
    {
        $schemaOut = $this->inherits->get('schema');
        $logTable = "{$schemaOut}.{$this->relation->get('name')}";
        $logTableQuoted = $quoting->quoteIdent($logTable);
        $originalTable = $quoting->quoteIdent($this->relation->get('fullyQualifiedName'));
        $schemaOut = $quoting->quoteIdent($schemaOut);
        $inherits = $quoting->quoteIdent($this->inherits->get('fullyQualifiedName'));
        $columnsInherits = $this->inherits->getAttributes()->pluck('name');
        foreach ($this->relation->getAttributes() as $column) {
            $name = $column->get('name');
            if (in_array($name, $columnsInherits)) {
                throw new \LogicException("Can't create a log table from {$originalTable}. The column names {$name} is reserved.");
            }
            // casting
            $type = $column->getType();
            if (isset(self::$recast[$type->get('name')])) {
                $cast = self::$recast[$type->get('name')];
            } elseif ($type->isEnum()) {
                $cast = 'text';
            } else {
                $cast = null;
            }
            $insertColumns[] = sprintf("%s%s", $quoting->quoteIdent($name), $cast ? "::{$cast}" : null);
            $createColumns[] = sprintf("%s %s", $quoting->quoteIdent($name), $quoting->quoteIdent($cast ?: $type->get('name')));
        }
        // callback to get a quoted name
        $quotedNameGet = function ($column) use($quoting) {
            return $quoting->quoteIdent($column->get('name'));
        };
        $columns = $this->relation->getAttributes()->map($quotedNameGet);
        $valuesNew = implode(', ', $this->inheritedValues + array_map($this->stringPrepend('NEW.'), $columns));
        $valuesOld = implode(', ', $this->inheritedValues + array_map($this->stringPrepend('OLD.'), $columns));
        $columns = implode(', ', $this->inherits->getAttributes()->map($quotedNameGet) + $columns);
        $insertColumns = implode(', ', $insertColumns);
        $createColumns = implode(",\n    ", $createColumns);
        $name = $this->relation->get('name');
        $output = <<<SQL
CREATE TABLE {$logTableQuoted} (
    {$createColumns},
    CONSTRAINT "pk_logs_{$name}" PRIMARY KEY ("logId")
) INHERITS ( {$inherits} );

CREATE TRIGGER "trg_log_{$name}_restrict"
    BEFORE UPDATE OR DELETE
    ON {$logTableQuoted} FOR EACH STATEMENT EXECUTE PROCEDURE common.restrictTrigger();

CREATE INDEX "idx_logPk_{$name}" on {$logTableQuoted} USING btree ( {$this->relation->getPrimaryKeys()->implode(',', $quotedNameGet)} );

COMMENT ON TABLE {$logTableQuoted} IS E'
@normality.match: logs
@normality.makeable: MAKEABLE_EXCEPTION
@normality.isReadonly: READONLY_EXCEPTION
@normality.logging: {$this->relation->get('fullyQualifiedName')}
';

CREATE OR REPLACE FUNCTION {$schemaOut}."{$name}_insert_update"() RETURNS TRIGGER LANGUAGE plpgsql AS \$\$
DECLARE
BEGIN

/*
    RAISE INFO E'Operation: % Schema: % Table: %',
        TG_OP,
        TG_TABLE_SCHEMA,
        TG_TABLE_NAME;
 */

    INSERT INTO {$logTableQuoted} ( {$columns} )
    VALUES( {$valuesNew} );

    RETURN NEW;

END;\$\$;

CREATE OR REPLACE FUNCTION {$schemaOut}."{$name}_delete"() RETURNS TRIGGER LANGUAGE plpgsql AS \$\$
DECLARE
BEGIN

/*
    RAISE INFO E'Operation: % Schema: % Table: %',
        TG_OP,
        TG_TABLE_SCHEMA,
        TG_TABLE_NAME;
 */

    INSERT INTO {$logTableQuoted} ( {$columns} )
    VALUES( {$valuesOld} );

    RETURN NEW;

END;\$\$;

CREATE TRIGGER "trg_log_{$name}_insert_update"
    AFTER INSERT OR UPDATE
    ON {$originalTable} FOR EACH ROW EXECUTE PROCEDURE {$schemaOut}."{$name}_insert_update"();

CREATE TRIGGER "trg_log_{$name}_delete"
    AFTER DELETE
    ON {$originalTable} FOR EACH ROW EXECUTE PROCEDURE {$schemaOut}."{$name}_delete"();

SQL;
        return $output;
    }