use of io.mycat.calcite.logical.MycatView in project Mycat2 by MyCATApache.
the class MycatViewPlan method execute.
@Override
public Observable<VectorSchemaRoot> execute(RootContext rootContext) {
RootAllocator rootAllocator = new RootAllocator();
NewMycatDataContext context = (NewMycatDataContext) rootContext.getContext();
DrdsSqlWithParams drdsSql = context.getDrdsSql();
MycatView view = (MycatView) mycatView;
CopyMycatRowMetaData rowMetaData = new CopyMycatRowMetaData(new CalciteRowMetaData(view.getRowType().getFieldList()));
MycatRelDatasourceSourceInfo mycatRelDatasourceSourceInfo = new MycatRelDatasourceSourceInfo(rowMetaData, view.getSQLTemplate(DrdsSql.isForUpdate(drdsSql.getParameterizedStatement())), view);
SqlNode sqlTemplate = mycatRelDatasourceSourceInfo.getSqlTemplate();
List<PartitionGroup> partitionGroups = AsyncMycatDataContextImpl.getSqlMap(Collections.emptyMap(), view, drdsSql, drdsSql.getHintDataNodeFilter());
ImmutableMultimap<String, SqlString> stringSqlStringImmutableMultimap = view.apply(-1, sqlTemplate, partitionGroups, drdsSql.getParams());
List<Observable<VectorSchemaRoot>> observableList = new ArrayList<>();
for (Map.Entry<String, SqlString> entry : stringSqlStringImmutableMultimap.entries()) {
String key = entry.getKey();
SqlString sqlString = entry.getValue();
observableList.add(Observable.create(emitter -> {
Future<NewMycatConnection> connectionFuture = context.getConnection(context.getContext().resolveDatasourceTargetName(key));
Future<Observable<VectorSchemaRoot>> observableFuture = connectionFuture.map(connection -> {
Observable<VectorSchemaRoot> observable = connection.prepareQuery(sqlString.getSql(), MycatPreparedStatementUtil.extractParams(drdsSql.getParams(), sqlString.getDynamicParameters()), MycatRelDataType.getMycatRelType(MycatViewPlan.this.schema()), rootAllocator);
return observable.doOnComplete(() -> context.recycleConnection(context.getContext().resolveDatasourceTargetName(key), Future.succeededFuture(connection)));
});
observableFuture.onFailure(event -> emitter.tryOnError(event));
observableFuture.onSuccess(event -> {
event = event.doOnComplete(() -> emitter.onComplete());
event = event.doOnError(throwable -> emitter.tryOnError(throwable));
event.forEach(vectorSchemaRoot -> emitter.onNext(vectorSchemaRoot));
});
}));
}
return Observable.fromIterable(observableList).flatMap(i -> i);
}
use of io.mycat.calcite.logical.MycatView in project Mycat2 by MyCATApache.
the class VertxUpdateExecuter method explainUpdate.
@SneakyThrows
public static Collection<VertxExecuter.EachSQL> explainUpdate(DrdsSqlWithParams drdsSqlWithParams, MycatDataContext context) {
SQLStatement statement = drdsSqlWithParams.getParameterizedStatement();
List<Object> maybeList = drdsSqlWithParams.getParams();
boolean multi = !maybeList.isEmpty() && maybeList.get(0) instanceof List;
List<List<Object>> paramList = multi ? (List) maybeList : Collections.singletonList(maybeList);
List<VertxExecuter.EachSQL> res = new ArrayList<>();
for (List<Object> params : paramList) {
SQLExprTableSource tableSource = (SQLExprTableSource) getTableSource(statement);
String alias = SQLUtils.normalize(tableSource.computeAlias());
String tableName = SQLUtils.normalize(tableSource.getTableName());
String schemaName = SQLUtils.normalize(tableSource.getSchema());
MetadataManager metadataManager = MetaClusterCurrent.wrapper(MetadataManager.class);
TableHandler table = metadataManager.getTable(schemaName, tableName);
switch(table.getType()) {
case SHARDING:
{
ShardingTable shardingTable = (ShardingTable) table;
SimpleColumnInfo primaryKey = shardingTable.getPrimaryKey();
SQLExpr where = getWhere(statement);
if (where == null) {
handleEmptyWhereSharding(statement, res, params, shardingTable);
continue;
}
SQLSelectStatement sqlSelectStatement = new SQLSelectStatement();
SQLSelect sqlSelect = new SQLSelect();
sqlSelect.setQuery(new SQLSelectQueryBlock());
sqlSelectStatement.setSelect(sqlSelect);
SQLSelectQueryBlock queryBlock = sqlSelectStatement.getSelect().getQueryBlock();
queryBlock.addWhere(where);
queryBlock.setFrom(tableSource.clone());
Set<String> selectKeys = getSelectKeys(shardingTable, primaryKey);
for (String selectKey : selectKeys) {
queryBlock.addSelectItem(new SQLPropertyExpr(alias, selectKey), selectKey);
}
List<Object> innerParams = new ArrayList<>();
List<SqlTypeName> innerTypes = new ArrayList<>();
List<SqlTypeName> typeNames = drdsSqlWithParams.getTypeNames();
where.accept(new MySqlASTVisitorAdapter() {
@Override
public boolean visit(SQLVariantRefExpr x) {
innerParams.add(params.get(x.getIndex()));
if (!typeNames.isEmpty()) {
innerTypes.add(typeNames.get(x.getIndex()));
}
return false;
}
});
DrdsSqlWithParams queryDrdsSqlWithParams = new DrdsSqlWithParams(sqlSelectStatement.toString(), innerParams, false, innerTypes, Collections.emptyList(), Collections.emptyList());
QueryPlanner planCache = MetaClusterCurrent.wrapper(QueryPlanner.class);
List<CodeExecuterContext> acceptedMycatRelList = planCache.getAcceptedMycatRelList(queryDrdsSqlWithParams);
CodeExecuterContext codeExecuterContext = acceptedMycatRelList.get(0);
MycatView mycatRel = (MycatView) codeExecuterContext.getMycatRel();
List<PartitionGroup> sqlMap = AsyncMycatDataContextImpl.getSqlMap(Collections.emptyMap(), mycatRel, queryDrdsSqlWithParams, drdsSqlWithParams.getHintDataNodeFilter());
List<Partition> partitions = sqlMap.stream().map(partitionGroup -> partitionGroup.get(shardingTable.getUniqueName())).collect(Collectors.toList());
handleTargets(statement, res, params, partitions);
if (shardingTable.getIndexTables().isEmpty()) {
continue;
}
// //////////////////////////////////////index-scan////////////////////////////////////////////////////////////
Objects.requireNonNull(shardingTable.getPrimaryKey(), " need primary key");
RowBaseIterator bindable = MetaClusterCurrent.wrapper(ExecutorProvider.class).runAsObjectArray(context, sqlSelectStatement.toString());
try {
List<Object[]> list = new ArrayList<>();
while (bindable.next()) {
list.add(bindable.getObjects());
}
if (list.size() > 1000) {
throw new IllegalArgumentException("The number of update rows exceeds the limit.");
}
for (ShardingTable indexTable : shardingTable.getIndexTables()) {
SQLStatement eachStatement = SQLUtils.parseSingleMysqlStatement(drdsSqlWithParams.getParameterizedSQL());
SQLExprTableSource sqlTableSource = new SQLExprTableSource();
sqlTableSource.setExpr(indexTable.getTableName());
sqlTableSource.setSchema(indexTable.getSchemaName());
setFrom(eachStatement, sqlTableSource);
RelDataType rowType = codeExecuterContext.getMycatRel().getRowType();
List<SQLExpr> backConditions = getBackCondition(selectKeys, indexTable, rowType);
setWhere(eachStatement, backConditions.stream().reduce((sqlExpr, sqlExpr2) -> SQLBinaryOpExpr.and(sqlExpr, sqlExpr2)).orElse(null));
for (Object[] eachParams : list) {
List<Object> newEachParams = getNewEachParams(backConditions, eachParams);
Collection<VertxExecuter.EachSQL> eachSQLS = VertxUpdateExecuter.explainUpdate(new DrdsSqlWithParams(eachStatement.toString(), newEachParams, false, getTypes(newEachParams), Collections.emptyList(), Collections.emptyList()), context);
res.addAll(eachSQLS);
}
}
continue;
} finally {
context.getTransactionSession().closeStatementState().toCompletionStage().toCompletableFuture().get(1, TimeUnit.SECONDS);
}
}
case GLOBAL:
{
GlobalTable globalTable = (GlobalTable) table;
handleTargets(statement, res, params, globalTable.getGlobalDataNode());
continue;
}
case NORMAL:
{
handleNormal(statement, res, params, (NormalTable) table);
continue;
}
case CUSTOM:
throw new UnsupportedOperationException();
default:
throw new IllegalStateException("Unexpected value: " + table.getType());
}
}
return res;
}
use of io.mycat.calcite.logical.MycatView in project Mycat2 by MyCATApache.
the class DrdsExecutorCompiler method getCodeExecuterContext.
@NotNull
@SneakyThrows
public static CodeExecuterContext getCodeExecuterContext(Map<RexNode, RexNode> constantMap, MycatRel relNode, boolean forUpdate) {
HashMap<String, Object> varContext = new HashMap<>(2);
StreamMycatEnumerableRelImplementor mycatEnumerableRelImplementor = new StreamMycatEnumerableRelImplementor(varContext);
HashMap<String, MycatRelDatasourceSourceInfo> stat = new HashMap<>();
relNode.accept(new RelShuttleImpl() {
@Override
public RelNode visit(RelNode other) {
CopyMycatRowMetaData rowMetaData = new CopyMycatRowMetaData(new CalciteRowMetaData(other.getRowType().getFieldList()));
if (other instanceof MycatView) {
MycatView view = (MycatView) other;
MycatRelDatasourceSourceInfo rel = stat.computeIfAbsent(other.getDigest(), s -> {
return new MycatRelDatasourceSourceInfo(rowMetaData, view.getSQLTemplate(forUpdate), view);
});
rel.refCount += 1;
}
if (other instanceof MycatTransientSQLTableScan) {
MycatTransientSQLTableScan tableScan = (MycatTransientSQLTableScan) other;
MycatRelDatasourceSourceInfo rel = stat.computeIfAbsent(other.getDigest(), s -> {
return new MycatRelDatasourceSourceInfo(rowMetaData, new TextSqlNode(tableScan.getSql()), tableScan);
});
rel.refCount += 1;
}
if (other instanceof MycatSQLTableLookup) {
MycatView right = ((MycatSQLTableLookup) other).getRight();
right.accept(this);
}
return super.visit(other);
}
});
ClassDeclaration classDeclaration = mycatEnumerableRelImplementor.implementHybridRoot(relNode, EnumerableRel.Prefer.ARRAY);
String code = Expressions.toString(classDeclaration.memberDeclarations, "\n", false);
if (log.isDebugEnabled()) {
log.debug("----------------------------------------code----------------------------------------");
log.debug(code);
}
CodeContext codeContext = new CodeContext(classDeclaration.name, code);
CodeExecuterContext executerContext = CodeExecuterContext.of(constantMap, stat, varContext, relNode, codeContext);
return executerContext;
}
use of io.mycat.calcite.logical.MycatView in project Mycat2 by MyCATApache.
the class MycatAggDistinctRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
Aggregate topAggregate = call.rel(0);
MycatView mycatView = call.rel(2);
RelHint lastAggHint = HintTools.getLastPushAggHint(topAggregate.getHints());
if (lastAggHint != null) {
if ("push_down_agg_distinct".equalsIgnoreCase(lastAggHint.hintName)) {
if (topAggregate.getAggCallList().size() == 1 && topAggregate.getGroupSet().isEmpty()) {
List<AggregateCall> aggCallList = topAggregate.getAggCallList();
if (aggCallList.size() == 1) {
AggregateCall aggregateCall = aggCallList.get(0);
if (aggregateCall.getAggregation().kind == SqlKind.COUNT) {
Aggregate distinctAgg = call.rel(1);
if (distinctAgg.getAggCallList().isEmpty() && !distinctAgg.getGroupSet().isEmpty()) {
opt(call, topAggregate, mycatView);
return;
}
}
}
}
Aggregate aggregate = topAggregate;
MycatView input = mycatView;
SQLRBORewriter.aggregate(input, LocalAggregate.create(aggregate, input)).ifPresent(new Consumer<RelNode>() {
@Override
public void accept(RelNode res) {
call.transformTo(normalize(res));
}
});
return;
}
}
if (topAggregate.getAggCallList().isEmpty() && topAggregate.getGroupSets().size() == 1) {
RelMetadataQuery metadataQuery = call.getMetadataQuery();
if (metadataQuery.areColumnsUnique(mycatView, topAggregate.getGroupSet())) {
opt(call, topAggregate, mycatView);
return;
}
}
}
Aggregations