#At file:///home/cpowers/work/dev/dev-02/mysql/
2736 Christopher Powers 2008-07-08
WL#4048 Falcon: On-line add attribute, Falcon handler part
Online add/drop index implementation
modified:
mysql-test/suite/falcon/r/falcon_bug_22161.result
storage/falcon/Statement.cpp
storage/falcon/StorageDatabase.cpp
storage/falcon/StorageDatabase.h
storage/falcon/StorageTableShare.cpp
storage/falcon/StorageTableShare.h
storage/falcon/ha_falcon.cpp
storage/falcon/ha_falcon.h
per-file comments:
mysql-test/suite/falcon/r/falcon_bug_22161.result
Removed one of three warnings from result file. Online add index takes a different
path than offline.
storage/falcon/Statement.cpp
Added Statement::dropIndex()
storage/falcon/StorageDatabase.cpp
Added StorageDatabase::dropIndex
storage/falcon/StorageDatabase.h
Added StorageDatabase::dropIndex()
storage/falcon/StorageTableShare.cpp
Added StorageTableShare::dropIndex()
Modified ::getIndex() to rebuild the table share index array when and index is added
or dropped.
Modified ::haveIndexes() to also check if the number of indexes has changed.
storage/falcon/ha_falcon.cpp
Added StorageInterface::dropIndex() - first form
Added support for add/drop index to check_if_supported_alter() and
alter_table_phase1()
Disabled online add column until issues with new and old formats are resolved (bug
tbd)
Added StorageInterface::addIndex()
Added StorageInterface::dropIndex() - second form, called from alter_phase_1()
Modified call to StorageTableShare::haveIndexes() in StorageInterface::setIndexes()
storage/falcon/ha_falcon.h
Added StorageInterface::dropIndex() - first form
Added StorageInterface::addIndex()
Added StorageInterface::dropIndex() - second form
=== modified file 'mysql-test/suite/falcon/r/falcon_bug_22161.result'
--- a/mysql-test/suite/falcon/r/falcon_bug_22161.result 2008-02-06 15:21:13 +0000
+++ b/mysql-test/suite/falcon/r/falcon_bug_22161.result 2008-07-09 04:38:02 +0000
@@ -12,7 +12,6 @@
Warnings:
Warning 1071 Specified key was too long; max key length is 1100 bytes
Warning 1071 Specified key was too long; max key length is 1100 bytes
-Warning 1071 Specified key was too long; max key length is 1100 bytes
SELECT count(*) FROM t1;
count(*)
1
=== modified file 'storage/falcon/Statement.cpp'
--- a/storage/falcon/Statement.cpp 2008-04-05 22:09:17 +0000
+++ b/storage/falcon/Statement.cpp 2008-07-09 04:38:02 +0000
@@ -2306,9 +2306,11 @@
if (index)
{
+ Transaction *sysTransaction = database->getSystemTransaction();
table->dropIndex(index);
- index->deleteIndex(transaction);
+ index->deleteIndex(sysTransaction); /* transaction */
delete index;
+ database->commitSystemTransaction();
}
Index::deleteIndex (database, schema, name);
=== modified file 'storage/falcon/StorageDatabase.cpp'
--- a/storage/falcon/StorageDatabase.cpp 2008-05-02 22:09:28 +0000
+++ b/storage/falcon/StorageDatabase.cpp 2008-07-09 04:38:02 +0000
@@ -711,6 +711,31 @@
return 0;
}
+int StorageDatabase::dropIndex(StorageConnection *storageConnection, Table* table, const
char* indexName, const char* sql)
+{
+ Connection *connection = storageConnection->connection;
+ Statement *statement = connection->createStatement();
+
+ try
+ {
+ statement->execute(sql);
+ }
+ catch (SQLException& exception)
+ {
+ storageConnection->setErrorText(&exception);
+ statement->release();
+
+ if (exception.getSqlcode() == INDEX_OVERFLOW)
+ return StorageErrorIndexOverflow;
+
+ return StorageErrorNoIndex;
+ }
+
+ statement->release();
+
+ return 0;
+}
+
int StorageDatabase::renameTable(StorageConnection* storageConnection, Table* table,
const char* tableName, const char *schemaName)
{
Connection *connection = storageConnection->connection;
=== modified file 'storage/falcon/StorageDatabase.h'
--- a/storage/falcon/StorageDatabase.h 2008-05-02 22:09:28 +0000
+++ b/storage/falcon/StorageDatabase.h 2008-07-09 04:38:02 +0000
@@ -75,6 +75,7 @@
void close(void);
void validateCache(void);
int createIndex(StorageConnection* storageConnection, Table* table, const char*
indexName, const char* sql);
+ int dropIndex(StorageConnection* storageConnection, Table* table, const char*
indexName, const char* sql);
int insert(Connection* connection, Table* table, Stream* stream);
int nextRow(StorageTable* storageTable, int recordNumber, bool lockForUpdate);
=== modified file 'storage/falcon/StorageTableShare.cpp'
--- a/storage/falcon/StorageTableShare.cpp 2008-04-24 14:07:55 +0000
+++ b/storage/falcon/StorageTableShare.cpp 2008-07-09 04:38:02 +0000
@@ -250,6 +250,14 @@
return storageDatabase->createIndex(storageConnection, table, name, sql);
}
+int StorageTableShare::dropIndex(StorageConnection *storageConnection, const char* name,
const char* sql)
+{
+ if (!table)
+ open();
+
+ return storageDatabase->dropIndex(storageConnection, table, name, sql);
+}
+
int StorageTableShare::renameTable(StorageConnection *storageConnection, const char*
newName)
{
char tableName[256];
@@ -271,6 +279,17 @@
StorageIndexDesc* StorageTableShare::getIndex(int indexCount, int indexId,
StorageIndexDesc* indexDesc)
{
+ // Rebuild array if indexes have been added or dropped. Assume
StorageTableShare::lock(exclusive).
+
+ if (numberIndexes != indexCount)
+ {
+ for (int n = 0; n < numberIndexes; ++n)
+ delete indexes[n];
+
+ delete [] indexes;
+ indexes = NULL;
+ }
+
if (!indexes)
{
indexes = new StorageIndexDesc*[indexCount];
@@ -352,10 +371,13 @@
return -1;
}
-int StorageTableShare::haveIndexes(void)
+int StorageTableShare::haveIndexes(int indexCount)
{
if (indexes == NULL)
return false;
+
+ if (indexCount > numberIndexes)
+ return false;
for (int n = 0; n < numberIndexes; ++n)
if (indexes[n]== NULL)
=== modified file 'storage/falcon/StorageTableShare.h'
--- a/storage/falcon/StorageTableShare.h 2008-04-23 14:39:53 +0000
+++ b/storage/falcon/StorageTableShare.h 2008-07-09 04:38:02 +0000
@@ -98,10 +98,11 @@
virtual void lock(bool exclusiveLock);
virtual void unlock(void);
virtual int createIndex(StorageConnection *storageConnection, const char* name, const
char* sql);
+ virtual int dropIndex(StorageConnection *storageConnection, const char* name, const
char* sql);
virtual int renameTable(StorageConnection *storageConnection, const char* newName);
virtual INT64 getSequenceValue(int delta);
virtual int setSequenceValue(INT64 value);
- virtual int haveIndexes(void);
+ virtual int haveIndexes(int indexCount);
virtual void cleanupFieldName(const char* name, char* buffer, int bufferLength);
virtual void setTablePath(const char* path, bool tempTable);
virtual void registerCollation(const char* collationName, void* arg);
=== modified file 'storage/falcon/ha_falcon.cpp'
--- a/storage/falcon/ha_falcon.cpp 2008-06-26 13:30:24 +0000
+++ b/storage/falcon/ha_falcon.cpp 2008-07-09 04:38:02 +0000
@@ -739,7 +739,6 @@
DBUG_RETURN(tableFlags);
}
-
ulong StorageInterface::index_flags(uint idx, uint part, bool all_parts) const
{
DBUG_ENTER("StorageInterface::index_flags");
@@ -749,7 +748,6 @@
//DBUG_RETURN(HA_READ_RANGE | HA_KEY_SCAN_NOT_ROR | (indexOrder ? HA_READ_ORDER : 0));
}
-
int StorageInterface::create(const char *mySqlName, TABLE *form, HA_CREATE_INFO *info)
{
DBUG_ENTER("StorageInterface::create");
@@ -867,6 +865,16 @@
return storageTable->share->createIndex(storageConnection, key->name, sql);
}
+int StorageInterface::dropIndex(const char *schemaName, const char *tableName,
+ KEY *key, int indexNumber)
+{
+ CmdGen gen;
+ gen.gen("drop index %s.\"%s$%d\"", schemaName, tableName, indexNumber);
+ const char *sql = gen.getString();
+
+ return storageTable->share->dropIndex(storageConnection, key->name, sql);
+}
+
#if 0
uint StorageInterface::alter_table_flags(uint flags)
{
@@ -2084,42 +2092,102 @@
int StorageInterface::check_if_supported_alter(TABLE *altered_table, HA_CREATE_INFO
*create_info, HA_ALTER_FLAGS *alter_flags, uint table_changes)
{
DBUG_ENTER("StorageInterface::check_if_supported_alter");
- // ulonglong bits = alter_flags->to_ulonglong();
tempTable = (create_info->options & HA_LEX_CREATE_TMP_TABLE) ? true : false;
-
- if (!tempTable && alter_flags->is_set(HA_ADD_COLUMN))
+ HA_ALTER_FLAGS supported;
+ supported = supported | HA_ADD_INDEX | HA_DROP_INDEX;
+ /**
+ | HA_ADD_COLUMN | HA_ADD_UNIQUE_INDEX | HA_DROP_UNIQUE_INDEX
+ | HA_COLUMN_STORAGE | HA_COLUMN_FORMAT;
+ **/
+ HA_ALTER_FLAGS notSupported = ~(supported);
+
+ if (tempTable || (*alter_flags & notSupported).is_set())
+ DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
+
+ // TODO:
+ // 1. Check for supported ALTER combinations
+ // 2. Check for explicit default (altered_table->s->default_values)
+
+ if (alter_flags->is_set(HA_ADD_COLUMN))
{
Field *field = NULL;
- for (uint n = 0; n < table->s->fields; ++n, field = NULL)
+ for (uint i = 0; i < altered_table->s->fields; i++)
{
- field = altered_table->s->field[n];
+ field = altered_table->s->field[i];
+ bool found = false;
- if (strcmp(table->s->field[n]->field_name, field->field_name) != 0)
- break;
- }
-
- if (!field)
- field = altered_table->field[altered_table->s->fields - 1];
-
- if (!field->real_maybe_null())
- DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
-
- DBUG_RETURN(HA_ALTER_SUPPORTED_NO_LOCK);
- }
-
- DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
+ for (uint n = 0; n < table->s->fields; n++)
+ if (found = (strcmp(table->s->field[n]->field_name, field->field_name) ==
0))
+ break;
+
+ if (field && !found)
+ if (!field->real_maybe_null())
+ {
+ DBUG_PRINT("info",("Online add column must be nullable"));
+ DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
+ }
+ }
+ }
+
+ // TODO for Add Index:
+ // 1. Check for supported ALTER combinations
+ // 2. Can error message be improved for non-null columns?
+
+ if (alter_flags->is_set(HA_ADD_INDEX))
+ {
+ for (unsigned int n = 0; n < altered_table->s->keys; n++)
+ {
+ if (n != altered_table->s->primary_key)
+ {
+ KEY *key = altered_table->key_info + n;
+ KEY *tableEnd = table->key_info + table->s->keys;
+ KEY *tableKey;
+
+ // Determine if this is a new index
+
+ for (tableKey = table->key_info; tableKey < tableEnd; tableKey++)
+ if (!strcmp(tableKey->name, key->name))
+ break;
+
+ // Verify that each part is nullable
+
+ if (tableKey >= tableEnd)
+ for (uint p = 0; p < key->key_parts; p++)
+ {
+ KEY_PART_INFO *keyPart = key->key_part + p;
+ if (keyPart && !keyPart->field->real_maybe_null())
+ {
+ DBUG_PRINT("info",("Online add index columns must be nullable"));
+ DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
+ }
+ }
+ }
+ }
+ }
+
+ if (alter_flags->is_set(HA_DROP_INDEX))
+ {
+ }
+
+ DBUG_RETURN(HA_ALTER_SUPPORTED_NO_LOCK);
}
int StorageInterface::alter_table_phase1(THD* thd, TABLE* altered_table, HA_CREATE_INFO*
create_info, HA_ALTER_INFO* alter_info, HA_ALTER_FLAGS* alter_flags)
{
DBUG_ENTER("StorageInterface::alter_table_phase1");
- // ulonglong bits = alter_flags->to_ulonglong();
+ int ret = 0;
if (alter_flags->is_set(HA_ADD_COLUMN))
- DBUG_RETURN(addColumn(thd, altered_table, create_info, alter_info, alter_flags));
-
- DBUG_RETURN(HA_ERR_UNSUPPORTED);
+ ret = addColumn(thd, altered_table, create_info, alter_info, alter_flags);
+
+ if (alter_flags->is_set(HA_ADD_INDEX) && !ret)
+ ret = addIndex(thd, altered_table, create_info, alter_info, alter_flags);
+
+ if (alter_flags->is_set(HA_DROP_INDEX) && !ret)
+ ret = dropIndex(thd, altered_table, create_info, alter_info, alter_flags);
+
+ DBUG_RETURN(ret);
}
int StorageInterface::alter_table_phase2(THD* thd, TABLE* altered_table, HA_CREATE_INFO*
create_info, HA_ALTER_INFO* alter_info, HA_ALTER_FLAGS* alter_flags)
@@ -2136,11 +2204,12 @@
DBUG_RETURN(0);
}
-
int StorageInterface::addColumn(THD* thd, TABLE* alteredTable, HA_CREATE_INFO*
createInfo, HA_ALTER_INFO* alterInfo, HA_ALTER_FLAGS* alterFlags)
{
int ret;
int64 incrementValue = 0;
+ const char *tableName = storageTable->getName();
+ const char *schemaName = storageTable->getSchemaName();
CmdGen gen;
genTable(alteredTable, &gen);
@@ -2168,19 +2237,66 @@
if ((ret = storageTable->upgrade(gen.getString(), incrementValue)))
return (error(ret));
- /***
- for (n = 0; n < form->s->keys; ++n)
- if (n != form->s->primary_key)
- if ((ret = createIndex(schemaName, tableName, form->key_info + n, n)))
+ return 0;
+}
+
+int StorageInterface::addIndex(THD* thd, TABLE* alteredTable, HA_CREATE_INFO* createInfo,
HA_ALTER_INFO* alterInfo, HA_ALTER_FLAGS* alterFlags)
+{
+ int ret;
+ const char *tableName = storageTable->getName();
+ const char *schemaName = storageTable->getSchemaName();
+
+ // Find indexes to be added by comparing table and alteredTable
+
+ for (unsigned int n = 0; n < alteredTable->s->keys; n++)
+ {
+ if (n != alteredTable->s->primary_key)
+ {
+ KEY *key = alteredTable->key_info + n;
+ KEY *tableEnd = table->key_info + table->s->keys;
+ KEY *tableKey;
+
+ for (tableKey = table->key_info; tableKey < tableEnd; tableKey++)
+ if (!strcmp(tableKey->name, key->name))
+ break;
+
+ if (tableKey >= tableEnd)
+ if ((ret = createIndex(schemaName, tableName, key, n)))
+ return (error(ret));
+ }
+ }
+ return 0;
+}
+
+int StorageInterface::dropIndex(THD* thd, TABLE* alteredTable, HA_CREATE_INFO*
createInfo, HA_ALTER_INFO* alterInfo, HA_ALTER_FLAGS* alterFlags)
+{
+ int ret;
+ const char *tableName = storageTable->getName();
+ const char *schemaName = storageTable->getSchemaName();
+
+ // Find indexes to be dropped by comparing table and alteredTable
+
+ for (unsigned int n = 0; n < table->s->keys; n++)
+ {
+ if (n != table->s->primary_key)
{
- storageTable->deleteTable();
+ KEY *key = table->key_info + n;
+ KEY *alterEnd = alteredTable->key_info + alteredTable->s->keys;
+ KEY *alterKey;
+
+ for (alterKey = alteredTable->key_info; alterKey < alterEnd; alterKey++)
+ if (!strcmp(alterKey->name, key->name))
+ break;
+ if (alterKey >= alterEnd)
+ if ((ret = dropIndex(schemaName, tableName, key, n)))
return (error(ret));
}
- ***/
+ }
return 0;
}
+
uint StorageInterface::max_supported_key_length(void) const
{
// Assume 4K page unless proven otherwise.
@@ -2216,15 +2332,14 @@
}
}
-
int StorageInterface::setIndexes(void)
{
- if (!table || storageShare->haveIndexes())
+ if (!table || storageShare->haveIndexes(table->s->keys))
return 0;
storageShare->lock(true);
- if (!storageShare->haveIndexes())
+ if (!storageShare->haveIndexes(table->s->keys))
{
StorageIndexDesc indexDesc;
@@ -2245,7 +2360,6 @@
return 0;
}
-
int StorageInterface::genTable(TABLE* table, CmdGen* gen)
{
const char *tableName = storageTable->getName();
@@ -2617,7 +2731,7 @@
dataStream->decode();
Field *field = fieldMap[fieldFormat->fieldId];
- // If we don't a field for the physical field, just skip over it and don't worrry.
+ // If we don't have a field for the physical field, just skip over it and don't worry
if (field == NULL)
continue;
=== modified file 'storage/falcon/ha_falcon.h'
--- a/storage/falcon/ha_falcon.h 2008-06-02 11:19:39 +0000
+++ b/storage/falcon/ha_falcon.h 2008-07-09 04:38:02 +0000
@@ -109,10 +109,12 @@
#endif
int addColumn(THD* thd, TABLE* altered_table, HA_CREATE_INFO* create_info,
HA_ALTER_INFO* alter_info, HA_ALTER_FLAGS* alter_flags);
+ int addIndex(THD* thd, TABLE* alteredTable, HA_CREATE_INFO* createInfo,
HA_ALTER_INFO* alterInfo, HA_ALTER_FLAGS* alterFlags);
+ int dropIndex(THD* thd, TABLE* alteredTable, HA_CREATE_INFO* createInfo,
HA_ALTER_INFO* alterInfo, HA_ALTER_FLAGS* alterFlags);
void getDemographics(void);
- int createIndex(const char *schemaName, const char *tableName,
- KEY *key, int indexNumber);
+ int createIndex(const char *schemaName, const char *tableName, KEY *key, int
indexNumber);
+ int dropIndex(const char *schemaName, const char *tableName, KEY *key, int
indexNumber);
void getKeyDesc(KEY *keyInfo, StorageIndexDesc *indexInfo);
void startTransaction(void);
bool threadSwitch(THD *newThread);