use of io.questdb.griffin.model.QueryModel in project questdb by bluestreak01.
the class SqlCodeGenerator method generateSelectDistinct.
private RecordCursorFactory generateSelectDistinct(QueryModel model, SqlExecutionContext executionContext) throws SqlException {
QueryModel twoDeepNested;
ExpressionNode tableNameEn;
if (model.getColumns().size() == 1 && model.getNestedModel() != null && model.getNestedModel().getSelectModelType() == QueryModel.SELECT_MODEL_CHOOSE && (twoDeepNested = model.getNestedModel().getNestedModel()) != null && twoDeepNested.getWhereClause() == null && twoDeepNested.getLatestBy().size() == 0 && (tableNameEn = twoDeepNested.getTableName()) != null) {
CharSequence tableName = tableNameEn.token;
try (TableReader reader = engine.getReader(executionContext.getCairoSecurityContext(), tableName)) {
CharSequence columnName = model.getBottomUpColumnNames().get(0);
TableReaderMetadata readerMetadata = reader.getMetadata();
int columnIndex = readerMetadata.getColumnIndex(columnName);
int columnType = readerMetadata.getColumnType(columnIndex);
if (readerMetadata.getVersion() >= 416 && ColumnType.isSymbol(columnType)) {
final GenericRecordMetadata distinctSymbolMetadata = new GenericRecordMetadata();
distinctSymbolMetadata.add(BaseRecordMetadata.copyOf(readerMetadata, columnIndex));
return new DistinctSymbolRecordCursorFactory(engine, distinctSymbolMetadata, Chars.toString(tableName), columnIndex, reader.getMetadata().getId(), reader.getVersion());
}
}
}
final RecordCursorFactory factory = generateSubQuery(model, executionContext);
try {
if (factory.recordCursorSupportsRandomAccess() && factory.getMetadata().getTimestampIndex() != -1) {
return new DistinctTimeSeriesRecordCursorFactory(configuration, factory, entityColumnFilter, asm);
}
return new DistinctRecordCursorFactory(configuration, factory, entityColumnFilter, asm);
} catch (Throwable e) {
factory.close();
throw e;
}
}
use of io.questdb.griffin.model.QueryModel in project questdb by bluestreak01.
the class SqlParserTest method testTooManyColumnsEdgeInOrderBy.
@Test
public void testTooManyColumnsEdgeInOrderBy() throws Exception {
try (TableModel model = modelOf("x")) {
for (int i = 0; i < SqlParser.MAX_ORDER_BY_COLUMNS - 1; i++) {
model.col("f" + i, ColumnType.INT);
}
CairoTestUtils.create(model);
}
StringBuilder b = new StringBuilder();
b.append("x order by ");
for (int i = 0; i < SqlParser.MAX_ORDER_BY_COLUMNS - 1; i++) {
if (i > 0) {
b.append(',');
}
b.append('f').append(i);
}
QueryModel st = (QueryModel) compiler.testCompileModel(b, sqlExecutionContext);
Assert.assertEquals(SqlParser.MAX_ORDER_BY_COLUMNS - 1, st.getOrderBy().size());
}
use of io.questdb.griffin.model.QueryModel in project questdb by bluestreak01.
the class AbstractSqlParserTest method validateTopDownColumns.
private void validateTopDownColumns(QueryModel model) {
ObjList<QueryColumn> columns = model.getColumns();
final ObjList<LowerCaseCharSequenceHashSet> nameSets = new ObjList<>();
QueryModel nested = model.getNestedModel();
while (nested != null) {
nameSets.clear();
for (int i = 0, n = nested.getJoinModels().size(); i < n; i++) {
LowerCaseCharSequenceHashSet set = new LowerCaseCharSequenceHashSet();
final QueryModel m = nested.getJoinModels().getQuick(i);
final ObjList<QueryColumn> cols = m.getTopDownColumns();
for (int j = 0, k = cols.size(); j < k; j++) {
QueryColumn qc = cols.getQuick(j);
Assert.assertTrue(set.add(qc.getName()));
}
nameSets.add(set);
}
for (int i = 0, n = columns.size(); i < n; i++) {
AbstractSqlParserTest.checkLiteralIsInSet(columns.getQuick(i).getAst(), nameSets, nested.getAliasIndexes());
}
columns = nested.getTopDownColumns();
nested = nested.getNestedModel();
}
}
use of io.questdb.griffin.model.QueryModel in project questdb by bluestreak01.
the class GroupByUtils method validateGroupByColumns.
public static void validateGroupByColumns(@NotNull QueryModel model, int inferredKeyColumnCount) throws SqlException {
final ObjList<ExpressionNode> groupByColumns = model.getGroupBy();
int explicitKeyColumnCount = groupByColumns.size();
if (explicitKeyColumnCount == 0) {
return;
}
final QueryModel nested = model.getNestedModel();
QueryModel chooseModel = model;
while (chooseModel != null && chooseModel.getSelectModelType() != QueryModel.SELECT_MODEL_CHOOSE && chooseModel.getSelectModelType() != QueryModel.SELECT_MODEL_NONE) {
chooseModel = chooseModel.getNestedModel();
}
for (int i = 0; i < explicitKeyColumnCount; i++) {
final ExpressionNode key = groupByColumns.getQuick(i);
switch(key.type) {
case ExpressionNode.LITERAL:
final int dotIndex = Chars.indexOf(key.token, '.');
if (dotIndex > -1) {
int aliasIndex = model.getAliasIndex(key.token, 0, dotIndex);
if (aliasIndex > -1) {
// we should now check against main model
int refColumn = model.getAliasToColumnMap().keyIndex(key.token);
if (refColumn > -1) {
// a.x not found, look for "x"
refColumn = model.getAliasToColumnMap().keyIndex(key.token, dotIndex + 1, key.token.length());
}
if (refColumn > -1) {
throw SqlException.$(key.position, "group by column does not match any key column is select statement");
}
} else {
if (chooseModel != null && chooseModel.getColumnNameToAliasMap().keyIndex(key.token) < 0) {
continue;
}
throw SqlException.$(key.position, "invalid column reference");
}
} else {
int refColumn = model.getAliasToColumnMap().keyIndex(key.token);
if (refColumn > -1) {
throw SqlException.$(key.position, "group by column does not match any key column is select statement");
}
QueryColumn qc = model.getAliasToColumnMap().valueAt(refColumn);
if (qc.getAst().type != ExpressionNode.LITERAL && qc.getAst().type != ExpressionNode.CONSTANT) {
throw SqlException.$(key.position, "group by column references aggregate expression");
}
}
break;
case ExpressionNode.BIND_VARIABLE:
throw SqlException.$(key.position, "bind variable is not allowed here");
case ExpressionNode.FUNCTION:
case ExpressionNode.OPERATION:
case ExpressionNode.CONSTANT:
final ObjList<QueryColumn> availableColumns = nested.getTopDownColumns();
boolean invalid = true;
for (int j = 0, n = availableColumns.size(); j < n; j++) {
final QueryColumn qc = availableColumns.getQuick(j);
if (qc.getAst().type == key.type) {
if (ExpressionNode.compareNodesGroupBy(key, qc.getAst(), chooseModel)) {
invalid = false;
break;
}
}
}
if (invalid) {
throw SqlException.$(key.position, "group by expression does not match anything select in statement");
}
break;
default:
throw SqlException.$(key.position, "unsupported type of expression");
}
}
if (explicitKeyColumnCount < inferredKeyColumnCount) {
throw SqlException.$(model.getModelPosition(), "not enough columns in group by");
}
}
use of io.questdb.griffin.model.QueryModel in project questdb by bluestreak01.
the class AbstractSqlParserTest method assertModel.
protected void assertModel(String expected, String query, int modelType, TableModel... tableModels) throws SqlException {
createModelsAndRun(() -> {
sink.clear();
ExecutionModel model = compiler.testCompileModel(query, sqlExecutionContext);
Assert.assertEquals(model.getModelType(), modelType);
((Sinkable) model).toSink(sink);
if (model instanceof QueryModel) {
validateTopDownColumns((QueryModel) model);
}
TestUtils.assertEquals(expected, sink);
}, tableModels);
}
Aggregations