Autoupdate multicolumn indexes
This commit is contained in:
parent
62d0e459c0
commit
12eadb80ae
|
@ -320,7 +320,9 @@ MySQL.prototype.isActual = function (cb) {
|
||||||
Object.keys(this._models).forEach(function (model) {
|
Object.keys(this._models).forEach(function (model) {
|
||||||
wait += 1;
|
wait += 1;
|
||||||
self.query('SHOW FIELDS FROM ' + model, function (err, fields) {
|
self.query('SHOW FIELDS FROM ' + model, function (err, fields) {
|
||||||
self.alterTable(model, fields, null, done, true);
|
self.query('SHOW INDEXES FROM ' + model, function (err, indexes) {
|
||||||
|
self.alterTable(model, fields, indexes, done, true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -341,7 +343,25 @@ MySQL.prototype.alterTable = function (model, actualFields, actualIndexes, done,
|
||||||
var propNames = Object.keys(m.properties).filter(function (name) {
|
var propNames = Object.keys(m.properties).filter(function (name) {
|
||||||
return !!m.properties[name];
|
return !!m.properties[name];
|
||||||
});
|
});
|
||||||
|
var indexNames = m.settings.indexes ? Object.keys(m.settings.indexes).filter(function (name) {
|
||||||
|
return !!m.settings.indexes[name];
|
||||||
|
}) : [];
|
||||||
var sql = [];
|
var sql = [];
|
||||||
|
var ai = {};
|
||||||
|
|
||||||
|
if (actualIndexes) {
|
||||||
|
actualIndexes.forEach(function (i) {
|
||||||
|
var name = i.Key_name;
|
||||||
|
if (!ai[name]) {
|
||||||
|
ai[name] = {
|
||||||
|
info: i,
|
||||||
|
columns: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
ai[name].columns[i.Seq_in_index - 1] = i.Column_name;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var aiNames = Object.keys(ai);
|
||||||
|
|
||||||
// change/add new fields
|
// change/add new fields
|
||||||
propNames.forEach(function (propName) {
|
propNames.forEach(function (propName) {
|
||||||
|
@ -368,34 +388,74 @@ MySQL.prototype.alterTable = function (model, actualFields, actualIndexes, done,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// add single-column indexes
|
// remove indexes
|
||||||
propNames.forEach(function (propName) {
|
aiNames.forEach(function (indexName) {
|
||||||
if (!m.properties[propName].index) {
|
if (indexName === 'id' || indexName === 'PRIMARY') return;
|
||||||
return;
|
if (indexNames.indexOf(indexName) === -1 || m.properties[indexName] && !m.properties[indexName].index) {
|
||||||
}
|
sql.push('DROP INDEX `' + indexName + '`');
|
||||||
var found;
|
} else {
|
||||||
if (actualIndexes) {
|
// first: check single (only type and kind)
|
||||||
actualIndexes.forEach(function (f) {
|
if (m.properties[indexName] && !m.properties[indexName].index) {
|
||||||
if (f.Column_name === propName) {
|
// TODO
|
||||||
found = f;
|
|
||||||
}
|
}
|
||||||
|
// second: check multiple indexes
|
||||||
|
var orderMatched = true;
|
||||||
|
if (indexNames.indexOf(indexName) !== -1) {
|
||||||
|
m.settings.indexes[indexName].columns.split(/,\s*/).forEach(function (columnName, i) {
|
||||||
|
if (ai[indexName].columns[i] !== columnName) orderMatched = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!orderMatched) {
|
||||||
sql.push('ADD INDEX `' + propName + '` (`' + propName + '`)');
|
sql.push('DROP INDEX `' + indexName + '`');
|
||||||
|
delete ai[indexName];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove single-column indexes
|
// add single-column indexes
|
||||||
if (actualIndexes) {
|
propNames.forEach(function (propName) {
|
||||||
actualIndexes.forEach(function (f) {
|
var i = m.properties[propName].index;
|
||||||
var propName = f.Key_name;
|
if (!i) {
|
||||||
if (propName === 'id') return;
|
return;
|
||||||
if (m.properties[propName] && !m.properties[propName].index) {
|
}
|
||||||
sql.push('DROP INDEX `' + propName + '`');
|
var found = ai[propName] && ai[propName].info;
|
||||||
|
if (!found) {
|
||||||
|
var type = '';
|
||||||
|
var kind = '';
|
||||||
|
if (i.type) {
|
||||||
|
type = 'USING ' + i.type;
|
||||||
|
}
|
||||||
|
if (i.kind) {
|
||||||
|
// kind = i.kind;
|
||||||
|
}
|
||||||
|
if (kind && type) {
|
||||||
|
sql.push('ADD ' + kind + ' INDEX `' + propName + '` (`' + propName + '`) ' + type);
|
||||||
|
} else {
|
||||||
|
sql.push('ADD ' + kind + ' INDEX `' + propName + '` ' + type + ' (`' + propName + '`) ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// add multi-column indexes
|
||||||
|
indexNames.forEach(function (indexName) {
|
||||||
|
var i = m.settings.indexes[indexName];
|
||||||
|
var found = ai[indexName] && ai[indexName].info;
|
||||||
|
if (!found) {
|
||||||
|
var type = '';
|
||||||
|
var kind = '';
|
||||||
|
if (i.type) {
|
||||||
|
type = 'USING ' + i.kind;
|
||||||
}
|
}
|
||||||
|
if (i.kind) {
|
||||||
|
kind = i.kind;
|
||||||
|
}
|
||||||
|
if (kind && type) {
|
||||||
|
sql.push('ADD ' + kind + ' INDEX `' + indexName + '` (' + i.columns + ') ' + type);
|
||||||
|
} else {
|
||||||
|
sql.push('ADD ' + kind + ' INDEX ' + type + ' `' + indexName + '` (' + i.columns + ')');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (sql.length) {
|
if (sql.length) {
|
||||||
if (checkOnly) {
|
if (checkOnly) {
|
||||||
|
|
|
@ -23,6 +23,9 @@ User = schema.define 'User',
|
||||||
birthDate: Date
|
birthDate: Date
|
||||||
pendingPeriod: Number
|
pendingPeriod: Number
|
||||||
createdByAdmin: Boolean
|
createdByAdmin: Boolean
|
||||||
|
, indexes:
|
||||||
|
index1:
|
||||||
|
columns: 'email, createdByAdmin'
|
||||||
|
|
||||||
withBlankDatabase = (cb) ->
|
withBlankDatabase = (cb) ->
|
||||||
db = schema.settings.database = DBNAME
|
db = schema.settings.database = DBNAME
|
||||||
|
@ -45,7 +48,7 @@ getIndexes = (model, cb) ->
|
||||||
cb err
|
cb err
|
||||||
else
|
else
|
||||||
indexes = {}
|
indexes = {}
|
||||||
res.forEach (index) -> indexes[index.Key_name] = index
|
res.forEach (index) -> indexes[index.Key_name] = index if index.Seq_in_index == 1
|
||||||
cb err, indexes
|
cb err, indexes
|
||||||
|
|
||||||
it 'should run migration', (test) ->
|
it 'should run migration', (test) ->
|
||||||
|
@ -146,18 +149,32 @@ it 'should autoupgrade', (test) ->
|
||||||
it 'should check actuality of schema', (test) ->
|
it 'should check actuality of schema', (test) ->
|
||||||
# drop column
|
# drop column
|
||||||
User.schema.isActual (err, ok) ->
|
User.schema.isActual (err, ok) ->
|
||||||
test.ok ok
|
test.ok ok, 'schema is actual'
|
||||||
User.defineProperty 'email', false
|
User.defineProperty 'email', false
|
||||||
User.schema.isActual (err, ok) ->
|
User.schema.isActual (err, ok) ->
|
||||||
test.ok not ok
|
test.ok not ok, 'schema is not actual'
|
||||||
test.done()
|
test.done()
|
||||||
|
|
||||||
it 'should add single-column index', (test) ->
|
it 'should add single-column index', (test) ->
|
||||||
User.defineProperty 'email', type: String, index: true
|
User.defineProperty 'email', type: String, index: { kind: 'FULLTEXT', type: 'HASH'}
|
||||||
User.schema.autoupdate (err) ->
|
User.schema.autoupdate (err) ->
|
||||||
return console.log(err) if err
|
return console.log(err) if err
|
||||||
getIndexes 'User', (err, ixs) ->
|
getIndexes 'User', (err, ixs) ->
|
||||||
test.ok ixs.email && ixs.email.Column_name == 'email'
|
test.ok ixs.email && ixs.email.Column_name == 'email'
|
||||||
|
console.log(ixs)
|
||||||
|
test.equal ixs.email.Index_type, 'BTREE' # default
|
||||||
|
test.done()
|
||||||
|
|
||||||
|
it 'should change type of single-column index', (test) ->
|
||||||
|
User.defineProperty 'email', type: String, index: { type: 'BTREE' }
|
||||||
|
User.schema.isActual (err, ok) ->
|
||||||
|
test.ok not ok, 'schema is not actual'
|
||||||
|
User.schema.autoupdate (err) ->
|
||||||
|
return console.log(err) if err
|
||||||
|
getIndexes 'User', (err, ixs) ->
|
||||||
|
console.log ixs.email
|
||||||
|
test.ok ixs.email && ixs.email.Column_name == 'email'
|
||||||
|
test.equal ixs.email.Index_type, 'BTREE'
|
||||||
test.done()
|
test.done()
|
||||||
|
|
||||||
it 'should remove single-column index', (test) ->
|
it 'should remove single-column index', (test) ->
|
||||||
|
@ -168,6 +185,16 @@ it 'should remove single-column index', (test) ->
|
||||||
test.ok !ixs.email
|
test.ok !ixs.email
|
||||||
test.done()
|
test.done()
|
||||||
|
|
||||||
|
it 'should update multi-column index when order of columns changed', (test) ->
|
||||||
|
User.schema.adapter._models.User.settings.indexes.index1.columns = 'createdByAdmin, email'
|
||||||
|
User.schema.isActual (err, ok) ->
|
||||||
|
test.ok not ok, 'schema is not actual'
|
||||||
|
User.schema.autoupdate (err) ->
|
||||||
|
return console.log(err) if err
|
||||||
|
getIndexes 'User', (err, ixs) ->
|
||||||
|
test.equals ixs.index1.Column_name, 'createdByAdmin'
|
||||||
|
test.done()
|
||||||
|
|
||||||
it 'should disconnect when done', (test) ->
|
it 'should disconnect when done', (test) ->
|
||||||
schema.disconnect()
|
schema.disconnect()
|
||||||
test.done()
|
test.done()
|
||||||
|
|
Loading…
Reference in New Issue