Commit 34a85bc1 authored by Johan Cwiklinski's avatar Johan Cwiklinski Committed by Johan Cwiklinski

Move & Improve isIndex to support pirmaryand compound keys

parent 6514254b
......@@ -447,6 +447,8 @@ function getUserName($ID, $link = 0) {
* @param $field string name of the index
*
* @return boolean : index exists ?
*
* @deprecated 10.0.0
**/
function isIndex($table, $field) {
$dbu = new DbUtils();
......
......@@ -451,10 +451,13 @@ final class DbUtils {
* @param string $field name of the index
*
* @return boolean
*
* @deprecated 10.0.0
*/
public function isIndex($table, $field) {
global $DB;
Toolbox::Deprecated('Use AbstractDatabase::indexExists');
if (!$DB->tableExists($table)) {
trigger_error("Table $table does not exists", E_USER_WARNING);
return false;
......
......@@ -505,8 +505,9 @@ class Migration {
* @return void
**/
function addKey($table, $fields, $indexname = '', $type = 'INDEX', $len = 0) {
global $DB;
// si pas de nom d'index, on prend celui du ou des champs
//when no index name provided, compute from field(s) name(s)
if (!$indexname) {
if (is_array($fields)) {
$indexname = implode($fields, "_");
......@@ -515,7 +516,7 @@ class Migration {
}
}
if (!isIndex($table, $indexname)) {
if (!$DB->indexExists($table, $fields, $indexname)) {
if (is_array($fields)) {
if ($len) {
$fields = "`".implode($fields, "`($len), `")."`($len)";
......@@ -548,8 +549,9 @@ class Migration {
* @return void
**/
function dropKey($table, $indexname) {
global $DB;
if (isIndex($table, $indexname)) {
if ($DB->indexExists($table, [], $indexname)) {
$this->change[$table][] = "DROP INDEX `$indexname`";
}
}
......
......@@ -2039,9 +2039,8 @@ Regards,',
'registration_uuid' => Telemetry::generateRegistrationUuid()
]);
if (isIndex('glpi_authldaps', 'use_tls')) {
$query = "ALTER TABLE `glpi_authldaps` DROP INDEX `use_tls`";
$DB->queryOrDie($query, "9.2 drop index use_tls for glpi_authldaps");
if ($DB->indexExists('glpi_authldaps', 'use_tls')) {
$migration->dropKey('glpi_authldaps', 'use_tls');
}
//Fix some field order from old migrations
......
......@@ -53,7 +53,7 @@ function update92to921() {
$migration->changeField("glpi_tickets", "slas_id", "slts_ttr_id", "integer");
$migration->migrationOneTable('glpi_tickets');
}
if (isIndex('glpi_tickets', 'slas_id')) {
if ($DB->indexExists('glpi_tickets', 'slas_id')) {
$migration->dropKey('glpi_tickets', 'slas_id');
}
if ($DB->fieldExists('glpi_tickets', 'slts_ttr_id')) {
......
......@@ -751,7 +751,7 @@ function update92to93() {
/** /Add Item_Device* display preferences */
// upgrade for users multi-domains
if (!isIndex('glpi_users', 'unicityloginauth')) {
if (!$DB->indexExists('glpi_users', [], 'unicityloginauth')) {
$migration->dropKey("glpi_users", "unicity");
$migration->addKey(
'glpi_users',
......
......@@ -493,6 +493,43 @@ abstract class AbstractDatabase
return [];
}
/**
* List indexes of a table
*
* @param string $table Table name condition
* @param boolean $usecache If use field list cache (default true)
*
* @return mixed list of indexed columns
*
* @since 10.0.0
*/
public function listIndexes(string $table, bool $usecache = true)
{
static $icache = [];
if (!$this->cache_disabled && $usecache && isset($icache[$table])) {
return $icache[$table];
}
$iterator = $this->request([
'SELECT' => ['index_name AS INDEX_NAME', 'column_name AS COLUMN_NAME'],
'FROM' => 'information_schema.statistics',
'WHERE' => [
'table_schema' => $this->dbdefault,
'table_name' => $table
]
]);
if (count($iterator)) {
$icache[$table] = [];
while ($data = $iterator->next()) {
$icache[$table][$data["INDEX_NAME"]][] = $data['COLUMN_NAME'];
}
return $icache[$table];
}
return [];
}
/**
* Free result memory
*
......@@ -717,7 +754,7 @@ abstract class AbstractDatabase
*
* @param string $table Table name for the field we're looking for
* @param string $field Field name
* @param Boolean $usecache Use cache; @see Database::listFields(), defaults to true
* @param boolean $usecache Use cache; @see Database::listFields(), defaults to true
*
* @return boolean
*/
......@@ -732,6 +769,49 @@ abstract class AbstractDatabase
return false;
}
/**
* Check if an index exists
*
* @since 10.0
*
* @param string $table Table name for the field we're looking for
* @param string|array $field Field(s) name(s)
* @param string $name Index name
* @param boolean $usecache Use cache; @see Database::listIndexes(), defaults to true
*
* @return boolean
*
* @since 10.0.0
*/
public function indexExists(string $table, $field, $name = null, bool $usecache = true): bool
{
if (!$this->tableExists($table)) {
trigger_error("Table $table does not exists", E_USER_WARNING);
return false;
}
if (!is_array($field)) {
$field = [$field];
}
if ($indexes = $this->listIndexes($table, $usecache)) {
foreach ($indexes as $key => $current) {
if (null !== $name && $key == $name) {
//an index with the name already exists
return true;
}
sort($current);
sort($field);
if (array_values($current) == $field) {
return true;
}
}
return false;
}
return false;
}
/**
* Disable table cache globally; usefull for migrations
*
......
......@@ -427,39 +427,6 @@ class DbUtils extends DbTestCase {
}
}
public function testIsIndex() {
$this
->if($this->newTestedInstance)
->then
->boolean($this->testedInstance->isIndex('glpi_configs', 'fakeField'))->isFalse()
->boolean($this->testedInstance->isIndex('glpi_configs', 'name'))->isFalse()
->boolean($this->testedInstance->isIndex('glpi_configs', 'value'))->isFalse()
->boolean($this->testedInstance->isIndex('glpi_users', 'locations_id'))->isTrue()
->boolean($this->testedInstance->isIndex('glpi_users', 'unicityloginauth'))->isTrue()
->when(
function () {
$this->boolean($this->testedInstance->isIndex('fakeTable', 'id'))->isFalse();
}
)->error
->withType(E_USER_WARNING)
->exists();
//keep testing old method from db.function
$this->boolean(isIndex('glpi_configs', 'fakeField'))->isFalse();
$this->boolean(isIndex('glpi_configs', 'name'))->isFalse();
$this->boolean(isIndex('glpi_users', 'locations_id'))->isTrue();
$this->boolean(isIndex('glpi_users', 'unicityloginauth'))->isTrue();
$this->when(
function () {
$this->boolean(isIndex('fakeTable', 'id'))->isFalse();
}
)->error
->withType(E_USER_WARNING)
->exists();
}
public function testGetEntityRestrict() {
$this->login();
$this->newTestedInstance();
......
......@@ -311,4 +311,112 @@ class MySql extends \GLPITestCase {
->string($this->db->quote("First\rSecond"))->isIdenticalTo("'First\\rSecond'")
->string($this->db->quote('Hi, "you"'))->isIdenticalTo("'Hi, \\\"you\\\"'");
}
public function testIndexExists() {
$this
->boolean($this->db->indexExists('glpi_configs', 'fakeField'))->isFalse()
->boolean($this->db->indexExists('glpi_configs', 'id'))->isTrue()
->boolean($this->db->indexExists('glpi_configs', 'context'))->isFalse()
->boolean($this->db->indexExists('glpi_configs', 'name'))->isFalse()
->boolean($this->db->indexExists('glpi_configs', ['name', 'context']))->isTrue()
->boolean($this->db->indexExists('glpi_groups_tickets', ['tickets_id', 'type'], 'unicity'))->isTrue()
->boolean($this->db->indexExists('glpi_groups_tickets', ['tickets_id', 'type', 'groups_id']))->isTrue()
->boolean($this->db->indexExists('glpi_configs', 'value'))->isFalse()
->boolean($this->db->indexExists('glpi_users', 'locations_id'))->isTrue()
->boolean($this->db->indexExists('glpi_users', [], 'unicityloginauth'))->isTrue()
->when(
function () {
$this->boolean($this->db->indexExists('fakeTable', 'id'))->isFalse();
}
)->error
->withType(E_USER_WARNING)
->exists();
}
public function testListIndexes() {
$this
->array($this->db->listIndexes('glpi_groups_tickets'))
->isIdenticalTo([
'PRIMARY' => [
0 => 'id',
],
'unicity' => [
0 => 'tickets_id',
1 => 'type',
2 => 'groups_id',
],
'group' => [
0 => 'groups_id',
1 => 'type',
]
]);
$this
->array($this->db->listIndexes('glpi_users'))
->isIdenticalTo([
'PRIMARY' => [
0 => 'id'
],
'unicityloginauth' => [
0 => 'name',
1 => 'authtype',
2 => 'auths_id'
],
'firstname' => [
0 => 'firstname'
],
'realname' => [
0 => 'realname'
],
'entities_id' => [
0 => 'entities_id'
],
'profiles_id' => [
0 => 'profiles_id'
],
'locations_id' => [
0 => 'locations_id'
],
'usertitles_id' => [
0 => 'usertitles_id'
],
'usercategories_id' => [
0 => 'usercategories_id'
],
'is_deleted' => [
0 => 'is_deleted'
],
'is_active' => [
0 => 'is_active'
],
'date_mod' => [
0 => 'date_mod'
],
'authitem' => [
0 => 'authtype',
1 => 'auths_id'
],
'is_deleted_ldap' => [
0 => 'is_deleted_ldap'
],
'date_creation' => [
0 => 'date_creation'
],
'begin_date' => [
0 => 'begin_date'
],
'end_date' => [
0 => 'end_date'
],
'sync_field' => [
0 => 'sync_field'
],
'groups_id' => [
0 => 'groups_id'
],
'users_id_supervisor' => [
0 => 'users_id_supervisor'
]
]);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment