{@inheritDoc}

@throws \Cake\Database\Exception when the column type is unknown
178243
public function columnSql(TableSchema $schema, $name)
    {
        $data = $schema->getColumn($name);
        $typeMap = [
            TableSchema::TYPE_BINARY_UUID => ' BINARY(16)',
            TableSchema::TYPE_UUID => ' CHAR(36)',
            TableSchema::TYPE_TINYINTEGER => ' TINYINT',
            TableSchema::TYPE_SMALLINTEGER => ' SMALLINT',
            TableSchema::TYPE_INTEGER => ' INTEGER',
            TableSchema::TYPE_BIGINTEGER => ' BIGINT',
            TableSchema::TYPE_BOOLEAN => ' BOOLEAN',
            TableSchema::TYPE_FLOAT => ' FLOAT',
            TableSchema::TYPE_DECIMAL => ' DECIMAL',
            TableSchema::TYPE_DATE => ' DATE',
            TableSchema::TYPE_TIME => ' TIME',
            TableSchema::TYPE_DATETIME => ' DATETIME',
            TableSchema::TYPE_TIMESTAMP => ' TIMESTAMP',
            TableSchema::TYPE_JSON => ' TEXT'
        ];

        $out = $this->_driver->quoteIdentifier($name);
        $hasUnsigned = [
            TableSchema::TYPE_TINYINTEGER,
            TableSchema::TYPE_SMALLINTEGER,
            TableSchema::TYPE_INTEGER,
            TableSchema::TYPE_BIGINTEGER,
            TableSchema::TYPE_FLOAT,
            TableSchema::TYPE_DECIMAL
        ];

        if (in_array($data['type'], $hasUnsigned, true) &&
            isset($data['unsigned']) && $data['unsigned'] === true
        ) {
            if ($data['type'] !== TableSchema::TYPE_INTEGER || [$name] !== (array)$schema->primaryKey()) {
                $out .= ' UNSIGNED';
            }
        }

        if (isset($typeMap[$data['type']])) {
            $out .= $typeMap[$data['type']];
        }

        if ($data['type'] === TableSchema::TYPE_TEXT && $data['length'] !== TableSchema::LENGTH_TINY) {
            $out .= ' TEXT';
        }

        if ($data['type'] === TableSchema::TYPE_STRING ||
            ($data['type'] === TableSchema::TYPE_TEXT && $data['length'] === TableSchema::LENGTH_TINY)
        ) {
            $out .= ' VARCHAR';

            if (isset($data['length'])) {
                $out .= '(' . (int)$data['length'] . ')';
            }
        }

        if ($data['type'] === TableSchema::TYPE_BINARY) {
            if (isset($data['length'])) {
                $out .= ' BLOB(' . (int)$data['length'] . ')';
            } else {
                $out .= ' BLOB';
            }
        }

        $integerTypes = [
            TableSchema::TYPE_TINYINTEGER,
            TableSchema::TYPE_SMALLINTEGER,
            TableSchema::TYPE_INTEGER,
        ];
        if (in_array($data['type'], $integerTypes, true) &&
            isset($data['length']) && [$name] !== (array)$schema->primaryKey()
        ) {
                $out .= '(' . (int)$data['length'] . ')';
        }

        $hasPrecision = [TableSchema::TYPE_FLOAT, TableSchema::TYPE_DECIMAL];
        if (in_array($data['type'], $hasPrecision, true) &&
            (isset($data['length']) || isset($data['precision']))
        ) {
            $out .= '(' . (int)$data['length'] . ',' . (int)$data['precision'] . ')';
        }

        if (isset($data['null']) && $data['null'] === false) {
            $out .= ' NOT NULL';
        }

        if ($data['type'] === TableSchema::TYPE_INTEGER && [$name] === (array)$schema->primaryKey()) {
            $out .= ' PRIMARY KEY AUTOINCREMENT';
        }

        if (isset($data['null']) && $data['null'] === true && $data['type'] === TableSchema::TYPE_TIMESTAMP) {
            $out .= ' DEFAULT NULL';
        }
        if (isset($data['default'])) {
            $out .= ' DEFAULT ' . $this->_driver->schemaValue($data['default']);
        }

        return $out;
    }
981790
public function setPrimaryKey( $column )
	{
		if( !strlen( trim( $column ) ) )
			throw new \InvalidArgumentException( 'Primary key column cannot be empty' );
		if( !in_array( $column, $this->columns ) )
			throw new \InvalidArgumentException( 'Column "'.$column.'" is not existing and can not be primary key' );
		$this->primaryKey = $column;
	}
1137849
protected function addForeignKeyColumn($column, Table $table, $key = null)
        {
            $add_table = clone $table;
            $key = ($key !== null) ? $key : $add_table->getIdColumn();
            $foreign_column = $add_table->getColumn($key);
            switch ($foreign_column['type']) {
                case 'integer':
                    $this->addInteger($column, $foreign_column['length'], $foreign_column['default_value'], false, false, $foreign_column['unsigned']);
                    break;
                case 'float':
                    $this->addFloat($column, $foreign_column['precision'], $foreign_column['default_value'], false, false, $foreign_column['unsigned']);
                    break;
                case 'varchar':
                    $this->addVarchar($column, $foreign_column['length'], $foreign_column['default_value'], false);
                    break;
                case 'text':
                case 'boolean':
                case 'blob':
                    throw new Exception('Cannot use a text, blob or boolean column as a foreign key');
            }
            $this->foreign_columns[$column] = array('class' => '\\'.get_class($table), 'key' => $key, 'name' => $column);
        }
96565
private function initColumnTypeExtensions()
    {
        $this->columnTypeExtensions = [];

        foreach ($this->loadColumnTypeExtensions() as $extension) {
            if (!$extension instanceof ColumnTypeExtensionInterface) {
                throw new UnexpectedTypeException($extension, ColumnTypeExtensionInterface::class);
            }

            $type = $extension->getExtendedType();

            $this->columnTypeExtensions[$type][] = $extension;
        }
    }
1136109
protected function prepareDefaultValue(Column $column)
    {
        $typeMapper = $this->getDataType();

        $default = $column->getDefault();

        if (!$column->getAllowNull() && $default === null && !$column->isPrimary()) {
            $default = $typeMapper::getDefaultValue($column->getType());

            $column->defaultValue($default);
        }

        return $column;
    }
742948
public function columnTypeNullable(array $info, $type) {
		if (!$type || empty($info['null'])) {
			return $type;
		}

		if (static::$nullableMap === null) {
			static::$nullableMap = (array)Configure::read('IdeHelper.nullableMap');
		}

		if (isset(static::$nullableMap[$type]) && static::$nullableMap[$type] === false) {
			return $type;
		}

		$type .= '|null';

		return $type;
	}
1179166
public function checkMandatoryColumns(array $data)
    {
        $diff = array_diff($this->mandatoryColumns, array_keys($data));

        if (\count($diff) > 0) {
            throw new \UnexpectedValueException(
                Translator::getInstance()->trans(
                    'The following columns are missing: %columns',
                    [
                        '%columns' => implode(', ', $diff)
                    ]
                )
            );
        }
    }
420286
public static function processDomainsAndTypes($columns, $types = null, $model = null) {
		// cache domains and types
		if (empty(self::$domains)) {
			$object = new \Object\Data\Domains();
			// use unprocessed data - a must
			self::$domains = $object->data;
		}
		if (empty(self::$types)) {
			if (!empty($types)) {
				self::$types = $types;
			} else {
				$object = new \Object\Data\Types();
				// use unprocessed data - a must
				self::$types = $object->data;
			}
		}
		$domain_attributes = array_merge(['type'], self::$attributes['schema'], self::$attributes['php'], self::$attributes['misc']);
		$type_attributes = array_merge(self::$attributes['schema'], self::$attributes['php'], self::$attributes['misc']);
		foreach ($columns as $k => $v) {
			if (isset($v['domain'])) {
				// check if domain exists
				if (!isset(self::$domains[$v['domain']])) {
					Throw new \Exception('Domain: ' . $v['domain'] . '?');
				}
				// populate domain attributes
				foreach ($domain_attributes as $v2) {
					if (array_key_exists($v2, self::$domains[$v['domain']]) && !array_key_exists($v2, $columns[$k])) {
						$columns[$k][$v2] = self::$domains[$v['domain']][$v2];
					}
				}
			}
			// populate type attributes
			if (isset($columns[$k]['type']) && isset(self::$types[$columns[$k]['type']])) {
				foreach ($type_attributes as $v2) {
					if (array_key_exists($v2, self::$types[$columns[$k]['type']]) && !array_key_exists($v2, $columns[$k])) {
						$columns[$k][$v2] = self::$types[$columns[$k]['type']][$v2];
					}
				}
			}
			// we default to string
			if (empty($columns[$k]['php_type'])) {
				$columns[$k]['php_type'] = 'string';
			}
			// sequence type and name
			if (!empty($columns[$k]['sequence']) && !empty($model)) {
				$columns[$k]['sequence_type'] = 'global_simple';
				if ($model->tenant) {
					$columns[$k]['sequence_type'] = 'tenant_simple';
				}
				if ($model->module) {
					$columns[$k]['sequence_type'] = 'module_simple';
				}
			}
		}
		return $columns;
	}
643735
final public function setSqlType(string $sqlType = null) : ColumnInterface
    {
        if ($sqlType) {
            $available = [
                self::SQL_TYPE_BOOLEAN,
                self::SQL_TYPE_DOUBLE,
                self::SQL_TYPE_FLOAT,
                self::SQL_TYPE_INT,
                self::SQL_TYPE_INTEGER,
                self::SQL_TYPE_STRING,
            ];

            if (!in_array($sqlType, $available)) {
                if (!class_exists($sqlType)) {
                    throw new \InvalidArgumentException('Invalid SQL type: '.$sqlType);
                } else {
                    $reflection = new \ReflectionClass($sqlType);
                    if (!$reflection->isSubclassOf(Behavior::class)) {
                        throw new \InvalidArgumentException('SQL type '.$sqlType.' must be instance of '.Behavior::class);
                    }
                }
            }
        }

        $this->sqlType = $sqlType;

        return $this;
    }
1023228
protected function getColumnIndexByKey(int $index, string $error_message)
    {
        if ($index < 0) {
            throw new Exception($error_message);
        }

        if ([] === $this->header) {
            return $index;
        }

        $value = array_search($index, array_flip($this->header), true);
        if (false !== $value) {
            return $value;
        }

        throw new Exception(sprintf($error_message, $index));
    }
607127
public function getColumnByIndex($index)
    {
        if(!isset($this->columns[$index])){
            throw new Exception(sprintf("Column index %s is not valid",$index));
        }
        return $this->columns[$index];
    }
751195
public function update()
    {
        //translate model data to sql data
        if (is_null($this->schema)) {
            throw Exception::forNoSchema();
        }

        $data = $this->schema->toSql();

        //queries to run
        $queries = [];
        //this is used to determine whether to add/alter/remove columns
        $exists = [];

        //if there's no system
        if (!$this->exists($data['name'])) {
            //go to create mode
            return $this->create($data, true);
        }

        $primary = $this->resource->getPrimaryKey($data['name']);
        $columns = $this->resource->getColumns($data['name']);
        $query = $this->resource->getAlterQuery($data['name']);

        //remove or change fields
        foreach ($columns as $current) {
            //don't do primary
            if ($primary === $current['Field']) {
                continue;
            }

            $exists[] = $name = $current['Field'];

            //if there is no field in the data
            if (!isset($data['columns'][$name])) {
                $query->removeField($name);
                continue;
            }

            $column = $data['columns'][$name];

            $attributes = ['type' => $column['type']];

            if (isset($column['length'])) {
                $attributes['type'] .= '(' . $column['length'] . ')';
            }

            if (isset($column['default']) && strlen($column['default'])) {
                $attributes['default'] = $column['default'];
            } else if (!isset($column['required']) || !$column['required']) {
                $attributes['null'] = true;
            }

            if (isset($column['required']) && $column['required']) {
                $attributes['null'] = false;
            }

            if (isset($column['attribute']) && $column['attribute']) {
                $attributes['attribute'] = $column['attribute'];
            }

            $default = null;
            if (isset($attributes['default'])) {
                $default = $attributes['default'];
            }

            //if all matches
            if ($attributes['type'] === $current['Type']
                && $attributes['null'] == ($current['Null'] === 'YES')
                && $default === $current['Default']
            ) {
                continue;
            }

            //do the alter
            $query->changeField($name, $attributes);
        }

        //add fields
        foreach ($data['columns'] as $name => $column) {
            if (in_array($name, $exists)) {
                continue;
            }

            $attributes = ['type' => $column['type']];

            if (isset($column['length'])) {
                $attributes['type'] .= '(' . $column['length'] . ')';
            }

            if (isset($column['default']) && strlen($column['default'])) {
                $attributes['default'] = $column['default'];
            } else if (!isset($column['required']) || !$column['required']) {
                $attributes['null'] = true;
            }

            if (isset($column['required']) && $column['required']) {
                $attributes['null'] = false;
            }

            if (isset($column['attribute']) && $column['attribute']) {
                $attributes['attribute'] = $column['attribute'];
            }

            $query->addField($name, $attributes);

            if (isset($column['index']) && $column['index']) {
                $query->addKey($name, [$name]);
            }

            if (isset($column['unique']) && $column['unique']) {
                $query->addUniqueKey($name, [$name]);
            }

            if (isset($column['primary']) && $column['primary']) {
                $query->addPrimaryKey($name);
            }
        }

        $query = (string) $query;
        if ($query !== 'ALTER TABLE `' . $data['name'] . '` ;') {
            $queries[] = $query;
        }

        $installed = $this->resource->getTables($data['name'] . '_%');
        $relations = array_keys($data['relations']);

        //determine the relation tables that need to be removed
        foreach ($installed as $relation) {
            //uninstall if it's not in the schema
            if (!in_array($relation, $relations)) {
                $queries[] = 'DROP TABLE IF EXISTS `' . $relation . '`;';
            }
        }

        //determine the relation tables that need to be added
        foreach ($data['relations'] as $table => $relation) {
            //install if it's installed
            if (in_array($table, $installed)) {
                continue;
            }

            $query = $this->resource->getCreateQuery($table);

            $query->addPrimaryKey($relation['primary1']);
            $query->addField($relation['primary1'], [
                'type' => 'int(10)',
                'null' => false,
                'attribute' => 'UNSIGNED'
            ]);

            $query->addPrimaryKey($relation['primary2']);
            $query->addField($relation['primary2'], [
                'type' => 'int(10)',
                'null' => false,
                'attribute' => 'UNSIGNED'
            ]);

            $queries[] = 'DROP TABLE IF EXISTS `'. $table . '`;';
            $queries[] = (string) $query;
        }

        //execute queries
        $results = [];
        foreach ($queries as $query) {
            $results[] = [
                'query' => $query,
                'results' => $this->resource->query($query)
            ];
        }

        return $results;
    }
1194585
protected function buildCols()
    {
        if (!$this->cols) {
            throw new Exception('No columns in the SELECT.');
        }

        $cols = array();
        foreach ($this->cols as $key => $val) {
            if (is_int($key)) {
                $cols[] = $this->quoteNamesIn($val);
            } else {
                $cols[] = $this->quoteNamesIn("$val AS $key");
            }
        }

        return $this->indentCsv($cols);
    }
43122
protected function _changedColumnsStatement()
    {
        $columns = $this->_sql->getChangedColumns();
        if (empty($columns)) {
            return null;
        }

        return $this->_parseChangedColumns();
    }
669957
final public function getFieldType(string $table, string $column): string
    {
        /* @noinspection PhpUnhandledExceptionInspection */
        return $this->getColumnsMetadata($table)['fieldTypes'][$column];
    }
915808
public function dropColumn(string $column): AbstractTable
    {
        if (empty($schema = $this->current->findColumn($column))) {
            throw new SchemaException("Undefined column '{$column}' in '{$this->getName()}'");
        }

        //Dropping column from current schema
        $this->current->forgetColumn($schema);

        return $this;
    }
870310
protected function _DefineColumn($Column) {
      if (!is_array($Column->Type) && !in_array($Column->Type, array('tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'char', 'varchar', 'varbinary', 'date', 'datetime', 'mediumtext', 'longtext', 'text', 'decimal', 'numeric', 'float', 'double', 'enum', 'timestamp', 'tinyblob', 'blob', 'mediumblob', 'longblob')))
         throw new Exception(sprintf(T('The specified data type (%1$s) is not accepted for the MySQL database.'), $Column->Type));
      
      $Return = '`'.$Column->Name.'` '.$Column->Type;
      
      $LengthTypes = $this->Types('length');
      if ($Column->Length != '' && in_array(strtolower($Column->Type), $LengthTypes)) {
         if($Column->Precision != '')
            $Return .= '('.$Column->Length.', '.$Column->Precision.')';
         else
            $Return .= '('.$Column->Length.')';
      }
      if (property_exists($Column, 'Unsigned') && $Column->Unsigned) {
         $Return .= ' unsigned';
      }

      if (is_array($Column->Enum))
         $Return .= "('".implode("','", $Column->Enum)."')";

      if (!$Column->AllowNull)
         $Return .= ' not null';

      if (!(is_null($Column->Default) || $Column->Default === '') && strcasecmp($Column->Type, 'timestamp') != 0)
         $Return .= " default ".self::_QuoteValue($Column->Default);

      if ($Column->AutoIncrement)
         $Return .= ' auto_increment';

      return $Return;
   }