use of herddb.index.PrimaryIndexPrefixScan in project herddb by diennea.
the class SQLPlanner method discoverIndexOperations.
private void discoverIndexOperations(Expression expressionWhere, Table table, String mainTableAlias, SQLRecordPredicate where, TableSpaceManager tableSpaceManager) throws StatementExecutionException {
SQLRecordKeyFunction keyFunction = findIndexAccess(expressionWhere, table.primaryKey, table, mainTableAlias, EqualsTo.class);
IndexOperation result = null;
if (keyFunction != null) {
if (keyFunction.isFullPrimaryKey()) {
result = new PrimaryIndexSeek(keyFunction);
} else {
result = new PrimaryIndexPrefixScan(keyFunction);
}
} else {
SQLRecordKeyFunction rangeMin = findIndexAccess(expressionWhere, table.primaryKey, table, mainTableAlias, GreaterThanEquals.class);
if (rangeMin != null && !rangeMin.isFullPrimaryKey()) {
rangeMin = null;
}
if (rangeMin == null) {
rangeMin = findIndexAccess(expressionWhere, table.primaryKey, table, mainTableAlias, GreaterThan.class);
if (rangeMin != null && !rangeMin.isFullPrimaryKey()) {
rangeMin = null;
}
}
SQLRecordKeyFunction rangeMax = findIndexAccess(expressionWhere, table.primaryKey, table, mainTableAlias, MinorThanEquals.class);
if (rangeMax != null && !rangeMax.isFullPrimaryKey()) {
rangeMax = null;
}
if (rangeMax == null) {
rangeMax = findIndexAccess(expressionWhere, table.primaryKey, table, mainTableAlias, MinorThan.class);
if (rangeMax != null && !rangeMax.isFullPrimaryKey()) {
rangeMax = null;
}
}
if (rangeMin != null || rangeMax != null) {
result = new PrimaryIndexRangeScan(table.primaryKey, rangeMin, rangeMax);
}
}
if (result == null) {
Map<String, AbstractIndexManager> indexes = tableSpaceManager.getIndexesOnTable(table.name);
if (indexes != null) {
// TODO: use some kind of statistics, maybe using an index is more expensive than a full table scan
for (AbstractIndexManager index : indexes.values()) {
if (!index.isAvailable()) {
continue;
}
IndexOperation secondaryIndexOperation = findSecondaryIndexOperation(index, expressionWhere, table);
if (secondaryIndexOperation != null) {
result = secondaryIndexOperation;
break;
}
}
}
}
where.setIndexOperation(result);
Expression filterPk = findFiltersOnPrimaryKey(table, table.name, expressionWhere);
where.setPrimaryKeyFilter(filterPk);
}
use of herddb.index.PrimaryIndexPrefixScan in project herddb by diennea.
the class CalcitePlanner method scanForIndexAccess.
private IndexOperation scanForIndexAccess(CompiledSQLExpression expressionWhere, Table table, TableSpaceManager tableSpaceManager) {
SQLRecordKeyFunction keyFunction = findIndexAccess(expressionWhere, table.primaryKey, table, "=", table);
IndexOperation result = null;
if (keyFunction != null) {
if (keyFunction.isFullPrimaryKey()) {
result = new PrimaryIndexSeek(keyFunction);
} else {
result = new PrimaryIndexPrefixScan(keyFunction);
}
} else {
SQLRecordKeyFunction rangeMin = findIndexAccess(expressionWhere, table.primaryKey, table, ">=", table);
if (rangeMin != null && !rangeMin.isFullPrimaryKey()) {
rangeMin = null;
}
if (rangeMin == null) {
rangeMin = findIndexAccess(expressionWhere, table.primaryKey, table, ">", table);
if (rangeMin != null && !rangeMin.isFullPrimaryKey()) {
rangeMin = null;
}
}
SQLRecordKeyFunction rangeMax = findIndexAccess(expressionWhere, table.primaryKey, table, "<=", table);
if (rangeMax != null && !rangeMax.isFullPrimaryKey()) {
rangeMax = null;
}
if (rangeMax == null) {
rangeMax = findIndexAccess(expressionWhere, table.primaryKey, table, "<", table);
if (rangeMax != null && !rangeMax.isFullPrimaryKey()) {
rangeMax = null;
}
}
if (rangeMin != null || rangeMax != null) {
result = new PrimaryIndexRangeScan(table.primaryKey, rangeMin, rangeMax);
}
}
if (result == null) {
Map<String, AbstractIndexManager> indexes = tableSpaceManager.getIndexesOnTable(table.name);
if (indexes != null) {
// TODO: use some kind of statistics, maybe using an index is more expensive than a full table scan
for (AbstractIndexManager index : indexes.values()) {
if (!index.isAvailable()) {
continue;
}
IndexOperation secondaryIndexOperation = findSecondaryIndexOperation(index, expressionWhere, table);
if (secondaryIndexOperation != null) {
result = secondaryIndexOperation;
break;
}
}
}
}
return result;
}
use of herddb.index.PrimaryIndexPrefixScan in project herddb by diennea.
the class SimpleIndexAccessTest method multipleColumnPrimaryKeyPrefixScanWithAliasTest.
@Test
public void multipleColumnPrimaryKeyPrefixScanWithAliasTest() throws Exception {
String nodeId = "localhost";
try (DBManager manager = new DBManager("localhost", new MemoryMetadataStorageManager(), new MemoryDataStorageManager(), new MemoryCommitLogManager(), null, null)) {
manager.start();
CreateTableSpaceStatement st1 = new CreateTableSpaceStatement("tblspace1", Collections.singleton(nodeId), nodeId, 1, 0, 0);
manager.executeStatement(st1, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
manager.waitForTablespace("tblspace1", 10000);
execute(manager, "CREATE TABLE tblspace1.q1_HISTORY (\n" + " MSG_ID BIGINT NOT NULL,\n" + " SID TINYINT NOT NULL, \n" + " STATUS INT NOT NULL,\n" + " TIMESTAMP TIMESTAMP NOT NULL,\n" + " STATUSLINE VARCHAR(2000) NULL,\n" + " IDBOUNCECATEGORY SMALLINT NULL,\n" + " PRIMARY KEY (MSG_ID, SID)\n" + ") ;", Collections.emptyList());
assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.q1_HISTORY(MSG_ID,SID,STATUS) values(1,1,1)", Collections.emptyList()).getUpdateCount());
assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.q1_HISTORY(MSG_ID,SID,STATUS) values(1,2,1)", Collections.emptyList()).getUpdateCount());
assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.q1_HISTORY(MSG_ID,SID,STATUS) values(1,3,1)", Collections.emptyList()).getUpdateCount());
assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.q1_HISTORY(MSG_ID,SID,STATUS) values(2,1,1)", Collections.emptyList()).getUpdateCount());
assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.q1_HISTORY(MSG_ID,SID,STATUS) values(2,2,1)", Collections.emptyList()).getUpdateCount());
{
TranslatedQuery translate = manager.getPlanner().translate(TableSpace.DEFAULT, "" + "SELECT H.SID, H.STATUS, H.`TIMESTAMP`, H.STATUSLINE, H.IDBOUNCECATEGORY " + "FROM tblspace1.q1_HISTORY AS H " + "WHERE H.MSG_ID=?", Arrays.asList(1), true, true, false, -1);
ScanStatement scan = translate.plan.mainStatement.unwrap(ScanStatement.class);
assertTrue(scan.getPredicate().getIndexOperation() instanceof PrimaryIndexPrefixScan);
try (DataScanner scan1 = manager.scan(scan, translate.context, TransactionContext.NO_TRANSACTION)) {
assertEquals(3, scan1.consume().size());
}
}
}
}
use of herddb.index.PrimaryIndexPrefixScan in project herddb by diennea.
the class BLinkKeyToPageIndex method scanner.
@Override
public Stream<Entry<Bytes, Long>> scanner(IndexOperation operation, StatementEvaluationContext context, TableContext tableContext, AbstractIndexManager index) throws DataStorageManagerException, StatementExecutionException {
if (operation instanceof PrimaryIndexSeek) {
PrimaryIndexSeek seek = (PrimaryIndexSeek) operation;
byte[] seekValue = seek.value.computeNewValue(null, context, tableContext);
if (seekValue == null) {
return Stream.empty();
}
Bytes key = Bytes.from_array(seekValue);
Long pageId = getTree().search(key);
if (pageId == null) {
return Stream.empty();
}
return Stream.of(new AbstractMap.SimpleImmutableEntry<>(key, pageId));
}
if (operation instanceof PrimaryIndexPrefixScan) {
PrimaryIndexPrefixScan scan = (PrimaryIndexPrefixScan) operation;
// SQLRecordKeyFunction value = sis.value;
byte[] refvalue = scan.value.computeNewValue(null, context, tableContext);
Bytes firstKey = Bytes.from_array(refvalue);
Bytes lastKey = firstKey.next();
return getTree().scan(firstKey, lastKey);
}
// every predicate (WHEREs...) will always be evaluated anyway on every record, in order to guarantee correctness
if (index != null) {
return index.recordSetScanner(operation, context, tableContext, this);
}
if (operation == null) {
Stream<Map.Entry<Bytes, Long>> baseStream = getTree().scan(null, null);
return baseStream;
} else if (operation instanceof PrimaryIndexRangeScan) {
Bytes refminvalue;
PrimaryIndexRangeScan sis = (PrimaryIndexRangeScan) operation;
SQLRecordKeyFunction minKey = sis.minValue;
if (minKey != null) {
refminvalue = Bytes.from_array(minKey.computeNewValue(null, context, tableContext));
} else {
refminvalue = null;
}
Bytes refmaxvalue;
SQLRecordKeyFunction maxKey = sis.maxValue;
if (maxKey != null) {
refmaxvalue = Bytes.from_array(maxKey.computeNewValue(null, context, tableContext));
} else {
refmaxvalue = null;
}
return getTree().scan(refminvalue, refmaxvalue, refmaxvalue != null);
}
throw new DataStorageManagerException("operation " + operation + " not implemented on " + this.getClass());
}
use of herddb.index.PrimaryIndexPrefixScan in project herddb by diennea.
the class SimpleIndexAccessTest method multipleColumnPrimaryKeyPrefixScanTest.
@Test
public void multipleColumnPrimaryKeyPrefixScanTest() throws Exception {
String nodeId = "localhost";
try (DBManager manager = new DBManager("localhost", new MemoryMetadataStorageManager(), new MemoryDataStorageManager(), new MemoryCommitLogManager(), null, null)) {
manager.start();
CreateTableSpaceStatement st1 = new CreateTableSpaceStatement("tblspace1", Collections.singleton(nodeId), nodeId, 1, 0, 0);
manager.executeStatement(st1, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
manager.waitForTablespace("tblspace1", 10000);
execute(manager, "CREATE TABLE tblspace1.tsql (k1 string," + "n1 int," + "s1 string, " + "primary key (k1,n1)" + ")", Collections.emptyList());
assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.tsql(k1,n1) values(?,?)", Arrays.asList("mykey", Integer.valueOf(1234))).getUpdateCount());
assertEquals(1, executeUpdate(manager, "INSERT INTO tblspace1.tsql(k1,n1) values(?,?)", Arrays.asList("mykey", Integer.valueOf(1235))).getUpdateCount());
{
TranslatedQuery translate = manager.getPlanner().translate(TableSpace.DEFAULT, "SELECT k1 as theKey,'one' as theStringConstant,3 LongConstant FROM tblspace1.tsql where k1 = ?", Arrays.asList("mykey"), true, true, false, -1);
ScanStatement scan = translate.plan.mainStatement.unwrap(ScanStatement.class);
assertTrue(scan.getPredicate().getIndexOperation() instanceof PrimaryIndexPrefixScan);
try (DataScanner scan1 = manager.scan(scan, translate.context, TransactionContext.NO_TRANSACTION)) {
assertEquals(2, scan1.consume().size());
}
}
{
TranslatedQuery translate = manager.getPlanner().translate(TableSpace.DEFAULT, "SELECT k1 as theKey,'one' as theStringConstant,3 LongConstant FROM tblspace1.tsql where k1 = ? and n1 <> 1235", Arrays.asList("mykey"), true, true, false, -1);
ScanStatement scan = translate.plan.mainStatement.unwrap(ScanStatement.class);
assertTrue(scan.getPredicate().getIndexOperation() instanceof PrimaryIndexPrefixScan);
try (DataScanner scan1 = manager.scan(scan, translate.context, TransactionContext.NO_TRANSACTION)) {
assertEquals(1, scan1.consume().size());
}
}
{
TranslatedQuery translate = manager.getPlanner().translate(TableSpace.DEFAULT, "SELECT k1 as theKey,'one' as theStringConstant,3 LongConstant FROM tblspace1.tsql where k1 = ? and n1 = 1235", Arrays.asList("mykey"), true, true, false, -1);
ScanStatement scan = translate.plan.mainStatement.unwrap(ScanStatement.class);
assertTrue(scan.getPredicate().getIndexOperation() instanceof PrimaryIndexSeek);
try (DataScanner scan1 = manager.scan(scan, translate.context, TransactionContext.NO_TRANSACTION)) {
assertEquals(1, scan1.consume().size());
}
}
}
}
Aggregations