All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.questdb.griffin.SqlExecutionContextImpl Maven / Gradle / Ivy

/*******************************************************************************
 *     ___                  _   ____  ____
 *    / _ \ _   _  ___  ___| |_|  _ \| __ )
 *   | | | | | | |/ _ \/ __| __| | | |  _ \
 *   | |_| | |_| |  __/\__ \ |_| |_| | |_) |
 *    \__\_\\__,_|\___||___/\__|____/|____/
 *
 *  Copyright (c) 2014-2019 Appsicle
 *  Copyright (c) 2019-2020 QuestDB
 *
 *  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.
 *
 ******************************************************************************/

package io.questdb.griffin;

import io.questdb.MessageBus;
import io.questdb.cairo.*;
import io.questdb.cairo.security.AllowAllCairoSecurityContext;
import io.questdb.cairo.sql.BindVariableService;
import io.questdb.cairo.sql.VirtualRecord;
import io.questdb.griffin.engine.analytic.AnalyticContext;
import io.questdb.griffin.engine.analytic.AnalyticContextImpl;
import io.questdb.griffin.engine.functions.rnd.SharedRandom;
import io.questdb.mp.RingQueue;
import io.questdb.mp.Sequence;
import io.questdb.std.IntStack;
import io.questdb.std.Rnd;
import io.questdb.std.Transient;
import io.questdb.std.datetime.microtime.MicrosecondClock;
import io.questdb.tasks.TelemetryTask;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class SqlExecutionContextImpl implements SqlExecutionContext {
    private final IntStack timestampRequiredStack = new IntStack();
    private final int workerCount;
    private final CairoConfiguration cairoConfiguration;
    private final CairoEngine cairoEngine;
    @Nullable
    private final MessageBus messageBus;
    private final MicrosecondClock clock;
    private final AnalyticContextImpl analyticContext = new AnalyticContextImpl();
    private RingQueue telemetryQueue;
    private Sequence telemetryPubSeq;
    private TelemetryMethod telemetryMethod = this::storeTelemetryNoop;
    private BindVariableService bindVariableService;
    private CairoSecurityContext cairoSecurityContext;
    private Rnd random;
    private long requestFd = -1;
    private SqlExecutionInterruptor interruptor = SqlExecutionInterruptor.NOP_INTERRUPTOR;
    private long now;

    public SqlExecutionContextImpl(CairoEngine cairoEngine, int workerCount) {
        this(cairoEngine, workerCount, cairoEngine.getMessageBus());
    }

    public SqlExecutionContextImpl(CairoEngine cairoEngine, int workerCount, @Nullable MessageBus messageBus) {
        this.cairoConfiguration = cairoEngine.getConfiguration();
        this.messageBus = messageBus;
        this.workerCount = workerCount;
        assert workerCount > 0;
        this.cairoEngine = cairoEngine;
        this.clock = cairoConfiguration.getMicrosecondClock();
        this.cairoSecurityContext = AllowAllCairoSecurityContext.INSTANCE;

        if (messageBus != null) {
            this.telemetryQueue = cairoEngine.getTelemetryQueue();
            this.telemetryPubSeq = cairoEngine.getTelemetryPubSequence();
            this.telemetryMethod = this::doStoreTelemetry;
        }
    }

    @Override
    public BindVariableService getBindVariableService() {
        return bindVariableService;
    }

    @Override
    public CairoSecurityContext getCairoSecurityContext() {
        return cairoSecurityContext;
    }

    @Override
    @Nullable
    public MessageBus getMessageBus() {
        return messageBus;
    }

    @Override
    public boolean isTimestampRequired() {
        return timestampRequiredStack.notEmpty() && timestampRequiredStack.peek() == 1;
    }

    @Override
    public void popTimestampRequiredFlag() {
        timestampRequiredStack.pop();
    }

    @Override
    public void pushTimestampRequiredFlag(boolean flag) {
        timestampRequiredStack.push(flag ? 1 : 0);
    }

    @Override
    public int getWorkerCount() {
        return workerCount;
    }

    @Override
    public Rnd getRandom() {
        return random != null ? random : SharedRandom.getRandom(cairoConfiguration);
    }

    @Override
    public void setRandom(Rnd rnd) {
        this.random = rnd;
    }

    @Override
    public CairoEngine getCairoEngine() {
        return cairoEngine;
    }

    @Override
    public long getRequestFd() {
        return requestFd;
    }

    @Override
    public SqlExecutionInterruptor getSqlExecutionInterruptor() {
        return interruptor;
    }

    @Override
    public void storeTelemetry(short event, short origin) {
        telemetryMethod.store(event, origin);
    }

    @Override
    public AnalyticContext getAnalyticContext() {
        return analyticContext;
    }

    @Override
    public void configureAnalyticContext(
            @Nullable VirtualRecord partitionByRecord,
            @Nullable RecordSink partitionBySink,
            @Transient @Nullable ColumnTypes partitionByKeyTypes,
            boolean ordered,
            boolean baseSupportsRandomAccess
    ) {
        analyticContext.of(
                partitionByRecord,
                partitionBySink,
                partitionByKeyTypes,
                ordered,
                baseSupportsRandomAccess
        );
    }

    @Override
    public void initNow() {
        now = cairoConfiguration.getMicrosecondClock().getTicks();
    }

    @Override
    public long getNow() {
        return now;
    }

    public SqlExecutionContextImpl with(
            @NotNull CairoSecurityContext cairoSecurityContext,
            @Nullable BindVariableService bindVariableService,
            @Nullable Rnd rnd
    ) {
        this.cairoSecurityContext = cairoSecurityContext;
        this.bindVariableService = bindVariableService;
        this.random = rnd;
        return this;
    }

    public SqlExecutionContextImpl with(
            long requestFd
    ) {
        this.requestFd = requestFd;
        return this;
    }

    public SqlExecutionContextImpl with(
            @NotNull CairoSecurityContext cairoSecurityContext,
            @Nullable BindVariableService bindVariableService,
            @Nullable Rnd rnd,
            long requestFd,
            @Nullable SqlExecutionInterruptor interruptor
    ) {
        this.cairoSecurityContext = cairoSecurityContext;
        this.bindVariableService = bindVariableService;
        this.random = rnd;
        this.requestFd = requestFd;
        this.interruptor = null == interruptor ? SqlExecutionInterruptor.NOP_INTERRUPTOR : interruptor;
        return this;
    }

    private void doStoreTelemetry(short event, short origin) {
        long cursor = telemetryPubSeq.next();
        while (cursor == -2) {
            cursor = telemetryPubSeq.next();
        }

        if (cursor > -1) {
            TelemetryTask row = telemetryQueue.get(cursor);

            row.created = clock.getTicks();
            row.event = event;
            row.origin = origin;
            telemetryPubSeq.done(cursor);
        }
    }

    private void storeTelemetryNoop(short event, short origin) {
    }

    @FunctionalInterface
    private interface TelemetryMethod {
        void store(short event, short origin);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy