/** * {@inheritDoc} */ public function constraintSql(Table $table, $name) { $data = $table->constraint($name); if ($this->_driver->autoQuoting()) { $out = 'CONSTRAINT ' . $this->_driver->quoteIdentifier($name); } else { $out = 'CONSTRAINT ' . $name; } if ($data['type'] === Table::CONSTRAINT_PRIMARY) { $out = 'PRIMARY KEY'; } if ($data['type'] === Table::CONSTRAINT_UNIQUE) { $out .= ' UNIQUE'; } return $this->_keySql($out, $data); }
/** * Generates a string representation of a schema. * * @param \Cake\Database\Schema\Table $table Table schema * @return string fields definitions */ protected function _generateSchema(Table $table) { $cols = $indexes = $constraints = []; foreach ($table->columns() as $field) { $fieldData = $table->column($field); $properties = implode(', ', $this->_values($fieldData)); $cols[] = " '{$field}' => [{$properties}],"; } foreach ($table->indexes() as $index) { $fieldData = $table->index($index); $properties = implode(', ', $this->_values($fieldData)); $indexes[] = " '{$index}' => [{$properties}],"; } foreach ($table->constraints() as $index) { $fieldData = $table->constraint($index); $properties = implode(', ', $this->_values($fieldData)); $constraints[] = " '{$index}' => [{$properties}],"; } $options = $this->_values($table->options()); $content = implode("\n", $cols) . "\n"; if (!empty($indexes)) { $content .= " '_indexes' => [\n" . implode("\n", $indexes) . "\n ],\n"; } if (!empty($constraints)) { $content .= " '_constraints' => [\n" . implode("\n", $constraints) . "\n ],\n"; } if (!empty($options)) { foreach ($options as &$option) { $option = ' ' . $option; } $content .= " '_options' => [\n" . implode(",\n", $options) . "\n ],\n"; } return "[\n{$content} ]"; }
/** * Does individual field validation handling. * * @param \Cake\Database\Schema\Table $schema The table schema for the current field. * @param string $fieldName Name of field to be validated. * @param array $metaData metadata for field * @param string $primaryKey The primary key field * @return array Array of validation for the field. */ public function fieldValidation($schema, $fieldName, array $metaData, $primaryKey) { $ignoreFields = ['created', 'modified', 'updated']; if (in_array($fieldName, $ignoreFields)) { return false; } $rule = false; if ($fieldName === 'email') { $rule = 'email'; } elseif ($metaData['type'] === 'uuid') { $rule = 'uuid'; } elseif ($metaData['type'] === 'integer') { $rule = 'numeric'; } elseif ($metaData['type'] === 'float') { $rule = 'numeric'; } elseif ($metaData['type'] === 'decimal') { $rule = 'decimal'; } elseif ($metaData['type'] === 'boolean') { $rule = 'boolean'; } elseif ($metaData['type'] === 'date') { $rule = 'date'; } elseif ($metaData['type'] === 'time') { $rule = 'time'; } elseif ($metaData['type'] === 'datetime') { $rule = 'datetime'; } elseif ($metaData['type'] === 'inet') { $rule = 'ip'; } $allowEmpty = false; if (in_array($fieldName, $primaryKey)) { $allowEmpty = 'create'; } elseif ($metaData['null'] === true) { $allowEmpty = true; } $validation = ['valid' => ['rule' => $rule, 'allowEmpty' => $allowEmpty]]; foreach ($schema->constraints() as $constraint) { $constraint = $schema->constraint($constraint); if (!in_array($fieldName, $constraint['columns']) || count($constraint['columns']) > 1) { continue; } if ($constraint['type'] === SchemaTable::CONSTRAINT_UNIQUE) { $validation['unique'] = ['rule' => 'validateUnique', 'provider' => 'table']; } } return $validation; }
/** * {@inheritDoc} */ public function constraintSql(Table $table, $name) { $data = $table->constraint($name); if ($data['type'] === Table::CONSTRAINT_PRIMARY) { $columns = array_map([$this->_driver, 'quoteIdentifier'], $data['columns']); return sprintf('PRIMARY KEY (%s)', implode(', ', $columns)); } if ($data['type'] === Table::CONSTRAINT_UNIQUE) { $out = 'UNIQUE KEY '; } if ($data['type'] === Table::CONSTRAINT_FOREIGN) { $out = 'CONSTRAINT '; } $out .= $this->_driver->quoteIdentifier($name); return $this->_keySql($out, $data); }
/** * {@inheritDoc} * * Note integer primary keys will return ''. This is intentional as Sqlite requires * that integer primary keys be defined in the column definition. * */ public function constraintSql(Table $table, $name) { $data = $table->constraint($name); if ($data['type'] === Table::CONSTRAINT_PRIMARY && count($data['columns']) === 1 && $table->column($data['columns'][0])['type'] === 'integer') { return ''; } $clause = ''; if ($data['type'] === Table::CONSTRAINT_PRIMARY) { $type = 'PRIMARY KEY'; } if ($data['type'] === Table::CONSTRAINT_UNIQUE) { $type = 'UNIQUE'; } if ($data['type'] === Table::CONSTRAINT_FOREIGN) { $type = 'FOREIGN KEY'; $clause = sprintf(' REFERENCES %s (%s) ON UPDATE %s ON DELETE %s', $this->_driver->quoteIdentifier($data['references'][0]), $this->_driver->quoteIdentifier($data['references'][1]), $this->_foreignOnClause($data['update']), $this->_foreignOnClause($data['delete'])); } $columns = array_map([$this->_driver, 'quoteIdentifier'], $data['columns']); return sprintf('CONSTRAINT %s %s (%s)%s', $this->_driver->quoteIdentifier($name), $type, implode(', ', $columns), $clause); }
/** * {@inheritDoc} */ public function dropConstraintSql(Table $table) { $sqlPattern = 'ALTER TABLE %s DROP FOREIGN KEY %s;'; $sql = []; foreach ($table->constraints() as $name) { $constraint = $table->constraint($name); if ($constraint['type'] === Table::CONSTRAINT_FOREIGN) { $tableName = $this->_driver->quoteIdentifier($table->name()); $constraintName = $this->_driver->quoteIdentifier($name); $sql[] = sprintf($sqlPattern, $tableName, $constraintName); } } return $sql; }
/** * Add/update a constraint into the schema object. * * @param \Cake\Database\Schema\Table $table The table to update. * @param string $name The index name. * @param string $type The index type. * @param array $row The metadata record to update with. * @return void */ protected function _convertConstraint($table, $name, $type, $row) { $constraint = $table->constraint($name); if (!$constraint) { $constraint = ['type' => $type, 'columns' => []]; } $constraint['columns'][] = $row['attname']; $table->addConstraint($name, $constraint); }
/** * Returns table primary key. * * @param Table $table Table schema object. * @return array|null */ protected function _getPrimaryKey(Table $table) { $constraints = $table->constraints(); foreach ($constraints as $name) { $constraint = $table->constraint($name); if ($this->_isSingleKey($table, [$constraint])) { return $constraint; } } return null; }
/** * find the table, if any, actually referenced by the passed key field. * Search tables in db for keyField; if found search key constraints * for the table to which it refers. * * @param \Cake\Database\Schema\Table $schema The table schema to find a constraint for. * @param string $keyField The field to check for a constraint. * @return string|null Either the referenced table or null if the field has no constraints. */ public function findTableReferencedBy($schema, $keyField) { if (!$schema->column($keyField)) { return null; } foreach ($schema->constraints() as $constraint) { $constraintInfo = $schema->constraint($constraint); if (in_array($keyField, $constraintInfo['columns'])) { if (!isset($constraintInfo['references'])) { continue; } return $constraintInfo['references'][0]; } } return null; }
public function convertIndexDescription(Table $table, $row) { $type = null; $columns = $length = []; $name = $row['CONSTRAINT_NAME']; switch ($row['CONSTRAINT_TYPE']) { case 'P': $name = $type = Table::CONSTRAINT_PRIMARY; break; case 'U': $type = Table::CONSTRAINT_UNIQUE; break; default: return; //Not doing anything here with Oracle "Check" constraints or "Reference" constraints } $columns[] = strtolower($row['COLUMN_NAME']); $isIndex = $type === Table::INDEX_INDEX || $type === Table::INDEX_FULLTEXT; if ($isIndex) { $existing = $table->index($name); } else { $existing = $table->constraint($name); } // MySQL multi column indexes come back as multiple rows. if (!empty($existing)) { $columns = array_merge($existing['columns'], $columns); $length = array_merge($existing['length'], $length); } if ($isIndex) { $table->addIndex($name, ['type' => $type, 'columns' => $columns, 'length' => $length]); } else { $table->addConstraint($name, ['type' => $type, 'columns' => $columns, 'length' => $length]); } }
/** * Generates SQL statements dropping foreign keys for the table. * * @param \Cake\Database\Connection $db Connection to run the SQL queries on. * @param \Cake\Database\Schema\Table $table Drop foreign keys for this table. * @return array List of SQL statements dropping foreign keys. */ protected function _generateDropForeignKeys($db, Schema $table) { $type = 'other'; if ($db->driver() instanceof Mysql) { $type = 'mysql'; } $queries = []; foreach ($table->constraints() as $constraintName) { $constraint = $table->constraint($constraintName); if ($constraint['type'] === Schema::CONSTRAINT_FOREIGN) { // TODO: Move this into the driver if ($type === 'mysql') { $template = 'ALTER TABLE %s DROP FOREIGN KEY %s'; } else { $template = 'ALTER TABLE %s DROP CONSTRAINT %s'; } $queries[] = sprintf($template, $table->name(), $constraintName); } } return $queries; }
/** * {@inheritDoc} */ public function constraintSql(Table $table, $name) { $data = $table->constraint($name); if ($data['type'] === Table::CONSTRAINT_PRIMARY) { return sprintf('CONSTRAINT pk_%s_0 PRIMARY KEY ("%s")', $table->name(), implode(', ', $data['columns'])); } return false; }