Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

package org.apache.doris.catalog;

import java.util.HashMap;
import java.util.Map;

// MySQL column type
// TYPE codes are defined in the file 'mysql/include/mysql_com.h' enum enum_field_types
// which is also demostrated in
Expand Down Expand Up @@ -55,6 +58,14 @@ public enum MysqlColType {
MYSQL_TYPE_GEOMETRY(255, "GEOMETRY", "GEOMETRY"),
MYSQL_TYPE_MAP(400, "MAP", "MAP");

private static final Map<Integer, MysqlColType> CODE_MAP = new HashMap<>();

static {
for (MysqlColType type : MysqlColType.values()) {
CODE_MAP.put(type.code, type);
}
}

private MysqlColType(int code, String desc, String jdbcColumnTypeName) {
this.code = code;
this.desc = desc;
Expand All @@ -77,6 +88,10 @@ public int getCode() {
return code;
}

public static MysqlColType fromCode(int code) {
return CODE_MAP.get(code);
}

public String getJdbcColumnTypeName() {
return jdbcColumnTypeName;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ PERCENT: 'PERCENT';
PERIOD: 'PERIOD';
PERMISSIVE: 'PERMISSIVE';
PHYSICAL: 'PHYSICAL';
PLACEHOLDER: '?';
PLAN: 'PLAN';
PROCESS: 'PROCESS';
PLUGIN: 'PLUGIN';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,7 @@ constant
| LEFT_BRACE (items+=constant COLON items+=constant)?
(COMMA items+=constant COLON items+=constant)* RIGHT_BRACE #mapLiteral
| LEFT_BRACE items+=constant (COMMA items+=constant)* RIGHT_BRACE #structLiteral
| PLACEHOLDER #placeholder
;

comparisonOperator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@
import org.apache.doris.nereids.trees.expressions.CTEId;
import org.apache.doris.nereids.trees.expressions.ExprId;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.Placeholder;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.expressions.SlotReference;
import org.apache.doris.nereids.trees.expressions.StatementScopeIdGenerator;
import org.apache.doris.nereids.trees.plans.ObjectId;
import org.apache.doris.nereids.trees.plans.PlaceholderId;
import org.apache.doris.nereids.trees.plans.RelationId;
import org.apache.doris.nereids.trees.plans.TableId;
import org.apache.doris.nereids.trees.plans.algebra.Relation;
Expand Down Expand Up @@ -119,6 +121,11 @@ public class StatementContext implements Closeable {
private final Set<String> viewDdlSqlSet = Sets.newHashSet();
private final SqlCacheContext sqlCacheContext;

// generate for next id for prepared statement's placeholders, which is connection level
private final IdGenerator<PlaceholderId> placeHolderIdGenerator = PlaceholderId.createGenerator();
// relation id to placeholders for prepared statement
private final Map<PlaceholderId, Expression> idToPlaceholderRealExpr = new HashMap<>();

// collect all hash join conditions to compute node connectivity in join graph
private final List<Expression> joinFilters = new ArrayList<>();

Expand All @@ -144,6 +151,9 @@ public class StatementContext implements Closeable {
// table locks
private final Stack<CloseableResource> plannerResources = new Stack<>();

// placeholder params for prepared statement
private List<Placeholder> placeholders;

// for create view support in nereids
// key is the start and end position of the sql substring that needs to be replaced,
// and value is the new string used for replacement.
Expand Down Expand Up @@ -370,6 +380,14 @@ public Map<RelationId, Set<Expression>> getConsumerIdToFilters() {
return consumerIdToFilters;
}

public PlaceholderId getNextPlaceholderId() {
return placeHolderIdGenerator.getNextId();
}

public Map<PlaceholderId, Expression> getIdToPlaceholderRealExpr() {
return idToPlaceholderRealExpr;
}

public Map<CTEId, List<Pair<Map<Slot, Slot>, Group>>> getCteIdToConsumerGroup() {
return cteIdToConsumerGroup;
}
Expand Down Expand Up @@ -490,6 +508,14 @@ public void close() {
releasePlannerResources();
}

public List<Placeholder> getPlaceholders() {
return placeholders;
}

public void setPlaceholders(List<Placeholder> placeholders) {
this.placeholders = placeholders;
}

private static class CloseableResource implements Closeable {
public final String resourceName;
public final String threadName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@
import org.apache.doris.nereids.trees.expressions.NullSafeEqual;
import org.apache.doris.nereids.trees.expressions.Or;
import org.apache.doris.nereids.trees.expressions.OrderExpression;
import org.apache.doris.nereids.trees.expressions.Placeholder;
import org.apache.doris.nereids.trees.expressions.Properties;
import org.apache.doris.nereids.trees.expressions.Regexp;
import org.apache.doris.nereids.trees.expressions.ScalarSubquery;
Expand Down Expand Up @@ -494,6 +495,16 @@
public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> {
private final boolean forCreateView;

// Sort the parameters with token position to keep the order with original placeholders
// in prepared statement.Otherwise, the order maybe broken
private final Map<Token, Placeholder> tokenPosToParameters = Maps.newTreeMap((pos1, pos2) -> {
int line = pos1.getLine() - pos2.getLine();
if (line != 0) {
return line;
}
return pos1.getCharPositionInLine() - pos2.getCharPositionInLine();
});

public LogicalPlanBuilder() {
forCreateView = false;
}
Expand Down Expand Up @@ -1010,6 +1021,9 @@ public List<Pair<LogicalPlan, StatementContext>> visitMultiStatements(MultiState
}
logicalPlans.add(Pair.of(
ParserUtils.withOrigin(ctx, () -> (LogicalPlan) visit(statement)), statementContext));
List<Placeholder> params = new ArrayList<>(tokenPosToParameters.values());
statementContext.setPlaceholders(params);
tokenPosToParameters.clear();
}
return logicalPlans;
}
Expand Down Expand Up @@ -2322,6 +2336,13 @@ public Literal visitStringLiteral(StringLiteralContext ctx) {
return new VarcharLiteral(s, strLength);
}

@Override
public Expression visitPlaceholder(DorisParser.PlaceholderContext ctx) {
Placeholder parameter = new Placeholder(ConnectContext.get().getStatementContext().getNextPlaceholderId());
tokenPosToParameters.put(ctx.start, parameter);
return parameter;
}

/**
* cast all items to same types.
* TODO remove this function after we refactor type coercion.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import org.apache.doris.nereids.trees.expressions.Match;
import org.apache.doris.nereids.trees.expressions.NamedExpression;
import org.apache.doris.nereids.trees.expressions.Not;
import org.apache.doris.nereids.trees.expressions.Placeholder;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.expressions.SlotReference;
import org.apache.doris.nereids.trees.expressions.TimestampArithmetic;
Expand Down Expand Up @@ -541,6 +542,13 @@ public Expression visitNot(Not not, ExpressionRewriteContext context) {
return expr;
}

@Override
public Expression visitPlaceholder(Placeholder placeholder, ExpressionRewriteContext context) {
Expression realExpr = context.cascadesContext.getStatementContext()
.getIdToPlaceholderRealExpr().get(placeholder.getPlaceholderId());
return visit(realExpr, context);
}

@Override
public Expression visitComparisonPredicate(ComparisonPredicate cp, ExpressionRewriteContext context) {
Expression left = cp.left().accept(this, context);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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 org.apache.doris.nereids.trees.expressions;

import org.apache.doris.catalog.MysqlColType;
import org.apache.doris.nereids.exceptions.UnboundException;
import org.apache.doris.nereids.trees.expressions.shape.LeafExpression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.trees.plans.PlaceholderId;
import org.apache.doris.nereids.types.DataType;
import org.apache.doris.nereids.types.NullType;

import java.util.Optional;

/**
* Placeholder for prepared statement
*/
public class Placeholder extends Expression implements LeafExpression {
private final PlaceholderId placeholderId;
private final Optional<MysqlColType> mysqlColType;

public Placeholder(PlaceholderId placeholderId) {
this.placeholderId = placeholderId;
this.mysqlColType = Optional.empty();
}

public Placeholder(PlaceholderId placeholderId, MysqlColType mysqlColType) {
this.placeholderId = placeholderId;
this.mysqlColType = Optional.of(mysqlColType);
}

public PlaceholderId getPlaceholderId() {
return placeholderId;
}

@Override
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
return visitor.visitPlaceholder(this, context);
}

@Override
public boolean nullable() {
return true;
}

@Override
public String toSql() {
return "?";
}

@Override
public DataType getDataType() throws UnboundException {
return NullType.INSTANCE;
}

public Placeholder withNewMysqlColType(MysqlColType mysqlColType) {
return new Placeholder(getPlaceholderId(), mysqlColType);
}

public MysqlColType getMysqlColType() {
return mysqlColType.get();
}
}
Loading