Я столкнулся с странным поведением и хочу знать, не ошибаюсь ли я, или API действительно работает именно так.
Я говорю о MYSQLI, мой собственный PHP-фреймворк может анализировать таблицу для создания динамического класса Entity, который работает очень хорошо до сих пор, однако я боюсь с MYSQLI_PRI_KEY_FLAG, который должен сказать мне, является ли индекс столбца частью индекса PRIMARY_KEY ,
Однако приведенная ниже таблица:
ip_ranges
cols:
account_id, min, max, comment
Единственный индекс в этой таблице – уникальный индекс с именем:
account_id_unique
и более трех столбцов:
account_id, min, max
Определенно не определено PRIMARY_KEY.
До сих пор такая хорошая, последняя информация, которая вам нужна, это то, что в массиве $ this-> columns содержатся все данные столбцов, полученные с помощью:
Mysqli_Result::fetch_fields
Теперь я использую следующие 2 функции-члена, чтобы определить, имеет ли столбец флаг PRIMARY_KEY:
public function columnHasFlag($columnName, $flag) { $retVal = false; if(isset($this->columns[strtolower($columnName)]) == true && $this->columns[strtolower($columnName)]["flags"] & $flag) { $retVal = true; } return $retVal; } public function determinePrimaryKeyColumn() { if($this->columnPrimaryKey === null) { foreach($this->columns as $columnName => $data) { if($this->columnHasFlag($columnName, MYSQLI_PRI_KEY_FLAG) == true) { $this->columnPrimaryKey = $columnName; break; } } } }
Странно, что я получаю для приведенной выше таблицы примеров, когда я использую 'vardump' в $ this-> columns [strtolower ($ columnName)] ["flags"], который содержит флаги для столбца «account_id», он возвращает меня значение: "int (49155)"
и columnHasFlag возвращает значение true для оператора: $ this-> columns [strtolower ($ columnName)] ["flags"] & $ flag
($ flag оценивает константу MYSQLI_PRI_KEY_VALUE, которая оценивает значение «2».
Итак, как можно установить флаг? Я думал, что этот флаг установлен только для ключевого индекса PRIMARY, который должен иметь имя primary? Или он установлен для любого другого UNIQUE_KEY?
Однако это кажется довольно странным, потому что существуют отдельные флаги для UNIQUE и ключ PRIMARY в документации mysqli_result :: fetch_field:
NOT_NULL_FLAG = 1 PRI_KEY_FLAG = 2 UNIQUE_KEY_FLAG = 4 ... (http://php.net/manual/en/mysqli-result.fetch-field.php)
Итак, мой вопрос, это ошибка, или я неправильно сравниваю флаги? Или я пропустил что-то в документации?
Я не думаю, что это ошибка, вот цитата из Справочного руководства по MySQL
Индекс UNIQUE может отображаться как PRI, если он не может содержать значения NULL, и в таблице нет PRIMARY KEY. Индекс UNIQUE может отображаться как MUL, если несколько столбцов образуют объединенный индекс UNIQUE; хотя комбинация столбцов уникальна, каждый столбец все еще может содержать несколько вхождений заданного значения.
Это код, который я использовал для проверки этого поведения.
$flags = array( 'NOT_NULL_FLAG' => MYSQLI_NOT_NULL_FLAG, 'PRI_KEY_FLAG' => MYSQLI_PRI_KEY_FLAG, 'UNIQUE_KEY_FLAG' => MYSQLI_UNIQUE_KEY_FLAG, 'MULTIPLE_KEY_FLAG' => MYSQLI_MULTIPLE_KEY_FLAG, 'BLOB_FLAG' => MYSQLI_BLOB_FLAG, 'UNSIGNED_FLAG' => MYSQLI_UNSIGNED_FLAG, 'ZEROFILL_FLAG' => MYSQLI_ZEROFILL_FLAG, 'BINARY_FLAG' => MYSQLI_BINARY_FLAG, 'ENUM_FLAG' => MYSQLI_ENUM_FLAG, 'AUTO_INCREMENT_FLAG' => MYSQLI_AUTO_INCREMENT_FLAG, 'TIMESTAMP_FLAG' => MYSQLI_TIMESTAMP_FLAG, 'SET_FLAG' => MYSQLI_SET_FLAG, 'PART_KEY_FLAG' => MYSQLI_PART_KEY_FLAG, 'NUM_FLAG' => MYSQLI_NUM_FLAG ); function info_array( $result ) { return array_reduce( $result->fetch_fields(), function( $result, $info ) { $result[ $info->name ] = $info; return $result; } ); } function get_flags( $meta, $flags ) { return array_filter( $flags, function( $flag ) use ( $meta ) { return $meta->flags & $flag; } ); } $result = $mysqli->query( 'SELECT * FROM ip_ranges LIMIT 1' ); $column_flags = array(); foreach( info_array( $result ) as $name => $value ) { $column_flags[ $name ] = get_flags( $value, $flags ); } print_r( $column_flags );
Таким образом, я создал таблицу в БД с уникальным индексом по 3 столбцам и получил выход, как вы сказали, все 3 столбца имеют установленный флаг первичного ключа.
Массив ( [account_id] => Массив ( [NOT_NULL_FLAG] => 1 [PRI_KEY_FLAG] => 2 [PART_KEY_FLAG] => 16384 [NUM_FLAG] => 32768) [min] => Массив ( [NOT_NULL_FLAG] => 1 [PRI_KEY_FLAG] => 2 [PART_KEY_FLAG] => 16384 [NUM_FLAG] => 32768) [max] => Массив ( [NOT_NULL_FLAG] => 1 [PRI_KEY_FLAG] => 2 [PART_KEY_FLAG] => 16384 [NUM_FLAG] => 32768) [комментарий] => Массив ( [NOT_NULL_FLAG] => 1) )
Запрос столбцов show ( SHOW COLUMNS FROM ip_ranges
) в mysql admin SHOW COLUMNS FROM ip_ranges
мне тот же результат.
Тип поля Null Key Default Extra account_id int (11) NO PRI NULL min int (11) NO PRI NULL max int (11) NO PRI NULL комментарий varchar () NO NULL
Затем я создал первичный ключ и получил следующий вывод:
Массив ( [id] => Массив ( [NOT_NULL_FLAG] => 1 [PRI_KEY_FLAG] => 2 [AUTO_INCREMENT_FLAG] => 512 [PART_KEY_FLAG] => 16384 [NUM_FLAG] => 32768) [account_id] => Массив ( [NOT_NULL_FLAG] => 1 [MULTIPLE_KEY_FLAG] => 8 [PART_KEY_FLAG] => 16384 [NUM_FLAG] => 32768 ) [min] => Массив ( [NOT_NULL_FLAG] => 1 [PART_KEY_FLAG] => 16384 [NUM_FLAG] => 32768) [max] => Массив ( [NOT_NULL_FLAG] => 1 [PART_KEY_FLAG] => 16384 [NUM_FLAG] => 32768) [комментарий] => Массив ( [NOT_NULL_FLAG] => 1) )
Тип поля Null Key Default Extra id int (11) NO PRI NULL auto_increment account_id int (11) NO MUL NULL min int (11) NO NULL max int (11) NO NULL комментарий varchar () NO NULL
Итак, в конце, php и mysql сообщают то же самое.