mirror of https://gitee.com/bigwinds/arangodb
193 lines
6.9 KiB
JavaScript
193 lines
6.9 KiB
JavaScript
/*jshint globalstrict:false, strict:false */
|
|
/*global assertEqual, assertNotEqual, assertTrue, assertFalse, fail */
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief test the index
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// @author Jan Steemann
|
|
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
var jsunity = require("jsunity");
|
|
var internal = require("internal");
|
|
var errors = internal.errors;
|
|
var db = require("@arangodb").db;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief test suite: check unique indexes
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function uniqueIndexSuite() {
|
|
'use strict';
|
|
var cn = "UnitTestsCollectionIdx";
|
|
|
|
var runTest = function(indexType) {
|
|
var tests = [
|
|
{ shardKeys: ["a"], indexKeys: ["a"], result: true },
|
|
{ shardKeys: ["b"], indexKeys: ["b"], result: true },
|
|
{ shardKeys: ["a"], indexKeys: ["b"], result: false },
|
|
{ shardKeys: ["b"], indexKeys: ["a"], result: false },
|
|
{ shardKeys: ["a"], indexKeys: ["a", "b"], result: true },
|
|
{ shardKeys: ["a"], indexKeys: ["b", "a"], result: true },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["c"], result: false },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["b"], result: false },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["a"], result: false },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["a", "c"], result: false },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["c", "a"], result: false },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["a", "b"], result: true },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["b", "a"], result: true },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["a", "b", "c"], result: true },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["b", "a", "c"], result: true },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["c", "b", "a"], result: true },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["b", "c", "a"], result: true },
|
|
{ shardKeys: ["a", "b"], indexKeys: ["a", "b", "c", "d"], result: true },
|
|
{ shardKeys: ["a", "b", "c"], indexKeys: ["a"], result: false },
|
|
{ shardKeys: ["a", "b", "c"], indexKeys: ["b"], result: false },
|
|
{ shardKeys: ["a", "b", "c"], indexKeys: ["c"], result: false },
|
|
{ shardKeys: ["a", "b", "c"], indexKeys: ["a", "b"], result: false },
|
|
{ shardKeys: ["a", "b", "c"], indexKeys: ["a", "c"], result: false },
|
|
{ shardKeys: ["a", "b", "c"], indexKeys: ["b", "c"], result: false },
|
|
{ shardKeys: ["a", "b", "c"], indexKeys: ["a", "b", "c"], result: true },
|
|
{ shardKeys: ["a", "b", "c"], indexKeys: ["a", "b", "c", "d"], result: true },
|
|
{ shardKeys: ["a", "b", "c"], indexKeys: ["a", "b", "d"], result: false },
|
|
{ shardKeys: ["a", "b", "c"], indexKeys: ["a", "b", "d", "c"], result: true }
|
|
];
|
|
|
|
tests.forEach(function(test) {
|
|
// drop collection first in case it already exists
|
|
internal.db._drop(cn);
|
|
|
|
var collection = internal.db._create(cn, { shardKeys: test.shardKeys, numberOfShards: 4 });
|
|
if (test.result) {
|
|
// index creation should work
|
|
var idx = collection.ensureIndex({ type: indexType, fields: test.indexKeys, unique: true });
|
|
assertTrue(idx.isNewlyCreated);
|
|
assertTrue(idx.unique);
|
|
assertEqual(test.indexKeys, idx.fields);
|
|
|
|
// now actually insert unique values
|
|
var n = 1000;
|
|
var threshold = 2;
|
|
while (n > Math.pow(threshold, test.indexKeys.length)) {
|
|
threshold += 2;
|
|
}
|
|
|
|
var initState = function(indexKeys) {
|
|
var state = { };
|
|
for (var key in indexKeys) {
|
|
state[indexKeys[key]] = 0;
|
|
}
|
|
return state;
|
|
};
|
|
|
|
var permute = function(state, indexKeys) {
|
|
for (var key in indexKeys) {
|
|
if (++state[indexKeys[key]] >= threshold) {
|
|
state[indexKeys[key]] = 0;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
return state;
|
|
};
|
|
|
|
var state = initState(test.indexKeys), i;
|
|
for (i = 0; i < n; ++i) {
|
|
collection.insert(state);
|
|
permute(state, test.indexKeys);
|
|
}
|
|
|
|
var filter = function(state) {
|
|
var parts = [];
|
|
for (var key in state) {
|
|
parts.push("doc." + key + " == " + state[key]);
|
|
}
|
|
return parts.join(" && ");
|
|
};
|
|
|
|
state = initState(test.indexKeys);
|
|
for (i = 0; i < n;) {
|
|
var query = "FOR doc IN " + collection.name() + " FILTER " + filter(state) + " RETURN 1";
|
|
if (i === 0) {
|
|
// on first invocation check that the index is actually used
|
|
assertNotEqual(-1, db._createStatement(query).explain().plan.nodes.map(function(node) { return node.type; }).indexOf("IndexNode"));
|
|
}
|
|
|
|
// expect exactly one result
|
|
assertEqual(1, db._query(query).toArray().length);
|
|
|
|
// query some random elements only to save time
|
|
var skip = Math.floor(Math.random() * 15) + 1;
|
|
while (skip > 0) {
|
|
permute(state, test.indexKeys);
|
|
--skip;
|
|
++i;
|
|
}
|
|
if (i >= n) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
// index creation should fail
|
|
try {
|
|
collection.ensureIndex({ type: indexType, fields: test.indexKeys, unique: true });
|
|
fail();
|
|
} catch (err) {
|
|
assertEqual(errors.ERROR_CLUSTER_UNSUPPORTED.code, err.errorNum);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
return {
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief set up
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
setUp : function () {
|
|
},
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief tear down
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
tearDown : function () {
|
|
internal.db._drop(cn);
|
|
},
|
|
|
|
testUniqueHashIndexes : function () {
|
|
runTest("hash");
|
|
},
|
|
|
|
testUniqueSkiplistIndexes : function () {
|
|
runTest("skiplist");
|
|
}
|
|
|
|
};
|
|
}
|
|
|
|
jsunity.run(uniqueIndexSuite);
|
|
|
|
return jsunity.done();
|