Problemas con el indicador MySQLI de PHP MYSQL_PRI_KEY_FLAG

Me encontré con un comportamiento extraño y quiero saber si estoy haciendo un error o si la API funciona de esta manera.

Estoy hablando de MYSQLI, mi propio PHP frameowrk puede analizar la tabla para construir una clase de Entidad dinámica que funciona muy bien hasta ahora, sin embargo, estoy luchando con el MYSQLI_PRI_KEY_FLAG que debería decirme si el índice de la columna es parte de un índice PRIMARY_KEY .

Sin embargo, se da la siguiente tabla:

ip_ranges 

cols son:

 account_id, min, max, comment 

El único índice en esta tabla es un índice único con nombre:

 account_id_unique 

y más de 3 columnas:

 account_id, min, max 

Definitivamente no hay definida PRIMARY_KEY.


Hasta ahora todo bien, la última información que necesita es que las columnas $ this-> array contengan todos los datos de las columnas que se hayan obtenido:

 Mysqli_Result::fetch_fields 

Ahora utilizo las siguientes 2 funciones de miembro para determinar si una columna tiene el indicador 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; } } } } 

Lo extraño es que me sale para la tabla de ejemplo de arriba, cuando uso ‘vardump’ en $ this-> columns [strtolower ($ columnName)] [“flags”] que contiene los flags para la columna “account_id” me devuelve el valor: “int (49155)”

y columnHasFlag me devuelve “verdadero” para la statement: $ this-> columns [strtolower ($ columnName)] [“flags”] & $ flag

($ flag evalúa la constante MYSQLI_PRI_KEY_VALUE que se evalúa como “2”.


Entonces, ¿cómo es posible que la bandera esté configurada? Pensé que esta bandera solo está configurada para el índice de clave PRIMARIO que debe tener el nombre primario. ¿O está configurado para cualquier otro UNIQUE_KEY también?

Sin embargo, esto parece bastante extraño porque hay indicadores separados para UNIQUE y la clave PRIMARY en la documentación de 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) 

Entonces mi pregunta, ¿es esto un error o estoy comparando mal las banderas de alguna manera? ¿O me perdí algo en la documentación?

No creo que sea un error, aquí hay una cita del Manual de Referencia de MySQL

Un índice UNIQUE puede mostrarse como PRI si no puede contener valores NULL y no hay PRIMARY KEY en la tabla. Un índice ÚNICO puede mostrarse como MUL si varias columnas forman un índice UNIQUE compuesto; aunque la combinación de las columnas es única, cada columna puede contener múltiples ocurrencias de un valor dado.

Este es el código que usé para probar ese comportamiento.

 $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 ); 

Así que creé una tabla en DB con índice único sobre 3 columnas y obtuve un resultado como el que me dijiste, las 3 columnas tienen un indicador de clave principal establecido.

 Array (
     [account_id] => Array (
          [NOT_NULL_FLAG] => 1
          [PRI_KEY_FLAG] => 2
          [PART_KEY_FLAG] => 16384
          [NUM_FLAG] => 32768)
     [min] => Matriz (
          [NOT_NULL_FLAG] => 1
          [PRI_KEY_FLAG] => 2
          [PART_KEY_FLAG] => 16384
          [NUM_FLAG] => 32768)
     [max] => Matriz (
          [NOT_NULL_FLAG] => 1
          [PRI_KEY_FLAG] => 2
          [PART_KEY_FLAG] => 16384
          [NUM_FLAG] => 32768)
     [comentario] => Matriz (
          [NOT_NULL_FLAG] => 1)

 )

Una consulta show columns ( SHOW COLUMNS FROM ip_ranges ) en mysql admin me dio el mismo resultado.

 Tipo de campo Clave nula Valor predeterminado extra
 account_id int (11) NO PRI NULL    
 min int (11) NO PRI NULL    
 max int (11) NO PRI NULL    
 comentar varchar () NO NULL    

Luego creé una clave principal y obtuve el siguiente resultado:

 Array (
     [id] => Matriz (
          [NOT_NULL_FLAG] => 1
          [PRI_KEY_FLAG] => 2
          [AUTO_INCREMENT_FLAG] => 512
          [PART_KEY_FLAG] => 16384
          [NUM_FLAG] => 32768)
     [account_id] => Array (
          [NOT_NULL_FLAG] => 1
          [MULTIPLE_KEY_FLAG] => 8
          [PART_KEY_FLAG] => 16384
          [NUM_FLAG] => 32768
         )
     [min] => Matriz (
          [NOT_NULL_FLAG] => 1
          [PART_KEY_FLAG] => 16384
          [NUM_FLAG] => 32768)
     [max] => Matriz (
          [NOT_NULL_FLAG] => 1
          [PART_KEY_FLAG] => 16384
          [NUM_FLAG] => 32768)
     [comentario] => Matriz (
          [NOT_NULL_FLAG] => 1)
 )
 Tipo de campo Clave nula Valor predeterminado 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    
 comentar varchar () NO NULL    

Entonces, al final, el php y el mysql están informando lo mismo.