Search in sources :

Example 11 with RecordColumnMetadata

use of com.questdb.common.RecordColumnMetadata in project questdb by bluestreak01.

the class QueryHandler method resume.

@SuppressWarnings("ConstantConditions")
@Override
public void resume(IOContext context) throws IOException {
    QueryHandlerContext ctx = localContext.get(context);
    if (ctx == null || ctx.cursor == null) {
        return;
    }
    final ChunkedResponse r = context.chunkedResponse();
    final int columnCount = ctx.metadata.getColumnCount();
    OUT: while (true) {
        try {
            SWITCH: switch(ctx.queryState) {
                case QUERY_PREFIX:
                    if (ctx.noMeta) {
                        r.put('{').putQuoted("dataset").put(":[");
                        ctx.queryState = QUERY_RECORD_START;
                        break;
                    }
                    r.bookmark();
                    r.put('{').putQuoted("query").put(':').encodeUtf8AndQuote(ctx.query);
                    r.put(',').putQuoted("columns").put(':').put('[');
                    ctx.queryState = QUERY_METADATA;
                    ctx.columnIndex = 0;
                // fall through
                case QUERY_METADATA:
                    for (; ctx.columnIndex < columnCount; ctx.columnIndex++) {
                        RecordColumnMetadata column = ctx.metadata.getColumnQuick(ctx.columnIndex);
                        r.bookmark();
                        if (ctx.columnIndex > 0) {
                            r.put(',');
                        }
                        r.put('{').putQuoted("name").put(':').putQuoted(column.getName()).put(',').putQuoted("type").put(':').putQuoted(ColumnType.nameOf(column.getType()));
                        r.put('}');
                    }
                    ctx.queryState = QUERY_META_SUFFIX;
                // fall through
                case QUERY_META_SUFFIX:
                    r.bookmark();
                    r.put("],\"dataset\":[");
                    ctx.queryState = QUERY_RECORD_START;
                // fall through
                case QUERY_RECORD_START:
                    if (ctx.record == null) {
                        // check if cursor has any records
                        while (true) {
                            if (ctx.cursor.hasNext()) {
                                ctx.record = ctx.cursor.next();
                                ctx.count++;
                                if (ctx.fetchAll && ctx.count > ctx.stop) {
                                    ctx.cancellationHandler.check();
                                    continue;
                                }
                                if (ctx.count > ctx.skip) {
                                    break;
                                }
                            } else {
                                ctx.queryState = QUERY_DATA_SUFFIX;
                                break SWITCH;
                            }
                        }
                    }
                    if (ctx.count > ctx.stop) {
                        ctx.queryState = QUERY_DATA_SUFFIX;
                        break;
                    }
                    r.bookmark();
                    if (ctx.count > ctx.skip + 1) {
                        r.put(',');
                    }
                    r.put('[');
                    ctx.queryState = QUERY_RECORD_COLUMNS;
                    ctx.columnIndex = 0;
                // fall through
                case QUERY_RECORD_COLUMNS:
                    for (; ctx.columnIndex < columnCount; ctx.columnIndex++) {
                        RecordColumnMetadata m = ctx.metadata.getColumnQuick(ctx.columnIndex);
                        r.bookmark();
                        if (ctx.columnIndex > 0) {
                            r.put(',');
                        }
                        putValue(r, m.getType(), ctx.record, ctx.columnIndex);
                    }
                    ctx.queryState = QUERY_RECORD_SUFFIX;
                case QUERY_RECORD_SUFFIX:
                    r.bookmark();
                    r.put(']');
                    ctx.record = null;
                    ctx.queryState = QUERY_RECORD_START;
                    break;
                case QUERY_DATA_SUFFIX:
                    sendDone(r, ctx);
                    break OUT;
                default:
                    break OUT;
            }
        } catch (ResponseContentBufferTooSmallException ignored) {
            if (r.resetToBookmark()) {
                r.sendChunk();
            } else {
                // what we have here is out unit of data, column value or query
                // is larger that response content buffer
                // all we can do in this scenario is to log appropriately
                // and disconnect socket
                ctx.info().$("Response buffer is too small, state=").$(ctx.queryState).$();
                throw DisconnectedChannelException.INSTANCE;
            }
        }
    }
}
Also used : ResponseContentBufferTooSmallException(com.questdb.ex.ResponseContentBufferTooSmallException) RecordColumnMetadata(com.questdb.common.RecordColumnMetadata) ChunkedResponse(com.questdb.net.http.ChunkedResponse)

Example 12 with RecordColumnMetadata

use of com.questdb.common.RecordColumnMetadata in project questdb by bluestreak01.

the class QueryFilterAnalyser method analyzeEquals0.

private boolean analyzeEquals0(AliasTranslator translator, IntrinsicModel model, ExprNode node, ExprNode a, ExprNode b, RecordMetadata m) throws ParserException {
    if (Chars.equals(a.token, b.token)) {
        node.intrinsicValue = IntrinsicValue.TRUE;
        return true;
    }
    if (a.type == ExprNode.LITERAL && b.type == ExprNode.CONSTANT) {
        if (isTimestamp(a)) {
            CharSequence seq = quoteEraser.ofQuoted(b.token);
            model.intersectIntervals(seq, 0, seq.length(), b.position);
            node.intrinsicValue = IntrinsicValue.TRUE;
            return true;
        } else {
            CharSequence column = translator.translateAlias(a.token);
            int index = m.getColumnIndexQuiet(column);
            if (index == -1) {
                throw QueryError.invalidColumn(a.position, a.token);
            }
            RecordColumnMetadata meta = m.getColumnQuick(index);
            switch(meta.getType()) {
                case ColumnType.SYMBOL:
                case ColumnType.STRING:
                case ColumnType.LONG:
                case ColumnType.INT:
                    if (meta.isIndexed()) {
                        // check if we are limited by preferred column
                        if (preferredKeyColumn != null && !Chars.equals(preferredKeyColumn, column)) {
                            return false;
                        }
                        boolean newColumn = true;
                        // check if we already have indexed column and it is of worse selectivity
                        if (model.keyColumn != null && (newColumn = !Chars.equals(model.keyColumn, column)) && meta.getBucketCount() <= m.getColumn(model.keyColumn).getBucketCount()) {
                            return false;
                        }
                        String value = Chars.equals("null", b.token) ? null : Chars.stripQuotes(b.token);
                        if (newColumn) {
                            model.keyColumn = column.toString();
                            model.keyValues.clear();
                            model.keyValuePositions.clear();
                            model.keyValues.add(value);
                            model.keyValuePositions.add(b.position);
                            for (int n = 0, k = keyNodes.size(); n < k; n++) {
                                keyNodes.getQuick(n).intrinsicValue = IntrinsicValue.UNDEFINED;
                            }
                            keyNodes.clear();
                        } else {
                            // otherwise invalidate entire model
                            if (model.keyValues.contains(value)) {
                                model.keyValues.clear();
                                model.keyValuePositions.clear();
                                model.keyValues.add(value);
                                model.keyValuePositions.add(b.position);
                            } else {
                                model.intrinsicValue = IntrinsicValue.FALSE;
                                return false;
                            }
                        }
                        keyNodes.add(node);
                        node.intrinsicValue = IntrinsicValue.TRUE;
                        return true;
                    }
                // fall through
                default:
                    return false;
            }
        }
    }
    return false;
}
Also used : RecordColumnMetadata(com.questdb.common.RecordColumnMetadata) FlyweightCharSequence(com.questdb.std.str.FlyweightCharSequence)

Example 13 with RecordColumnMetadata

use of com.questdb.common.RecordColumnMetadata in project questdb by bluestreak01.

the class QueryFilterAnalyser method analyzeNotEquals0.

private boolean analyzeNotEquals0(AliasTranslator translator, IntrinsicModel model, ExprNode node, ExprNode a, ExprNode b, RecordMetadata m) throws ParserException {
    if (Chars.equals(a.token, b.token)) {
        model.intrinsicValue = IntrinsicValue.FALSE;
        return true;
    }
    if (a.type == ExprNode.LITERAL && b.type == ExprNode.CONSTANT) {
        if (isTimestamp(a)) {
            CharSequence seq = quoteEraser.ofQuoted(b.token);
            model.subtractIntervals(seq, 0, seq.length(), b.position);
            node.intrinsicValue = IntrinsicValue.TRUE;
            return true;
        } else {
            String column = translator.translateAlias(a.token).toString();
            int index = m.getColumnIndexQuiet(column);
            if (index == -1) {
                throw QueryError.invalidColumn(a.position, a.token);
            }
            RecordColumnMetadata meta = m.getColumnQuick(index);
            switch(meta.getType()) {
                case ColumnType.SYMBOL:
                case ColumnType.STRING:
                case ColumnType.LONG:
                case ColumnType.INT:
                    if (meta.isIndexed()) {
                        // check if we are limited by preferred column
                        if (preferredKeyColumn != null && !preferredKeyColumn.equals(column)) {
                            return false;
                        }
                        keyExclNodes.add(node);
                        return false;
                    }
                    break;
                default:
                    break;
            }
        }
    }
    return false;
}
Also used : RecordColumnMetadata(com.questdb.common.RecordColumnMetadata) FlyweightCharSequence(com.questdb.std.str.FlyweightCharSequence)

Example 14 with RecordColumnMetadata

use of com.questdb.common.RecordColumnMetadata in project questdb by bluestreak01.

the class QueryFilterAnalyser method analyzeInLambda.

private boolean analyzeInLambda(IntrinsicModel model, CharSequence col, RecordMetadata meta, ExprNode node) throws ParserException {
    RecordColumnMetadata colMeta = meta.getColumn(col);
    if (colMeta.isIndexed()) {
        if (preferredKeyColumn != null && !col.equals(preferredKeyColumn)) {
            return false;
        }
        if (node.rhs == null || node.rhs.type != ExprNode.LAMBDA) {
            return false;
        }
        // check if we already have indexed column and it is of worse selectivity
        if (model.keyColumn != null && (!Chars.equals(model.keyColumn, col)) && colMeta.getBucketCount() <= meta.getColumn(model.keyColumn).getBucketCount()) {
            return false;
        }
        if ((col.equals(model.keyColumn) && model.keyValuesIsLambda) || node.paramCount > 2) {
            throw ParserException.$(node.position, "Multiple lambda expressions not supported");
        }
        model.keyValues.clear();
        model.keyValuePositions.clear();
        model.keyValues.add(unquote(node.rhs.token));
        model.keyValuePositions.add(node.position);
        model.keyValuesIsLambda = true;
        // revert previously processed nodes
        for (int n = 0, k = keyNodes.size(); n < k; n++) {
            keyNodes.getQuick(n).intrinsicValue = IntrinsicValue.UNDEFINED;
        }
        keyNodes.clear();
        model.keyColumn = col;
        keyNodes.add(node);
        node.intrinsicValue = IntrinsicValue.TRUE;
        return true;
    }
    return false;
}
Also used : RecordColumnMetadata(com.questdb.common.RecordColumnMetadata)

Example 15 with RecordColumnMetadata

use of com.questdb.common.RecordColumnMetadata in project questdb by bluestreak01.

the class QueryFilterAnalyser method analyzeListOfValues.

private boolean analyzeListOfValues(IntrinsicModel model, CharSequence col, RecordMetadata meta, ExprNode node) {
    RecordColumnMetadata colMeta = meta.getColumn(col);
    if (colMeta.isIndexed()) {
        boolean newColumn = true;
        if (preferredKeyColumn != null && !col.equals(preferredKeyColumn)) {
            return false;
        }
        // check if we already have indexed column and it is of worse selectivity
        if (model.keyColumn != null && (newColumn = !Chars.equals(model.keyColumn, col)) && colMeta.getBucketCount() <= meta.getColumn(model.keyColumn).getBucketCount()) {
            return false;
        }
        int i = node.paramCount - 1;
        tempKeys.clear();
        tempPos.clear();
        // if any of values is not an indexed constant - bail out
        if (i == 1) {
            if (node.rhs == null || node.rhs.type != ExprNode.CONSTANT) {
                return false;
            }
            if (tempKeys.add(unquote(node.rhs.token))) {
                tempPos.add(node.position);
            }
        } else {
            for (i--; i > -1; i--) {
                ExprNode c = node.args.getQuick(i);
                if (c.type != ExprNode.CONSTANT) {
                    return false;
                }
                if (tempKeys.add(unquote(c.token))) {
                    tempPos.add(c.position);
                }
            }
        }
        // and reset intrinsic values on nodes associated with old column
        if (newColumn) {
            model.keyValues.clear();
            model.keyValuePositions.clear();
            model.keyValues.addAll(tempKeys);
            model.keyValuePositions.addAll(tempPos);
            for (int n = 0, k = keyNodes.size(); n < k; n++) {
                keyNodes.getQuick(n).intrinsicValue = IntrinsicValue.UNDEFINED;
            }
            keyNodes.clear();
            model.keyColumn = col;
            keyNodes.add(node);
            node.intrinsicValue = IntrinsicValue.TRUE;
            return true;
        } else if (!model.keyValuesIsLambda) {
            // calculate overlap of values
            replaceAllWithOverlap(model);
            keyNodes.add(node);
            node.intrinsicValue = IntrinsicValue.TRUE;
            return true;
        }
    }
    return false;
}
Also used : ExprNode(com.questdb.griffin.common.ExprNode) RecordColumnMetadata(com.questdb.common.RecordColumnMetadata)

Aggregations

RecordColumnMetadata (com.questdb.common.RecordColumnMetadata)17 FlyweightCharSequence (com.questdb.std.str.FlyweightCharSequence)4 Path (com.questdb.std.str.Path)3 StringSink (com.questdb.std.str.StringSink)3 ColumnMetadata (com.questdb.store.factory.configuration.ColumnMetadata)3 ResponseContentBufferTooSmallException (com.questdb.ex.ResponseContentBufferTooSmallException)2 ChunkedResponse (com.questdb.net.http.ChunkedResponse)2 ExprNode (com.questdb.griffin.common.ExprNode)1 ImportedColumnMetadata (com.questdb.parser.ImportedColumnMetadata)1 ExprNode (com.questdb.parser.sql.model.ExprNode)1 JournalMetadata (com.questdb.store.factory.configuration.JournalMetadata)1