use of io.mycat.prototypeserver.mysql.HackRouter in project Mycat2 by MyCATApache.
the class ExplainSQLHandler method onExecute.
@Override
@SneakyThrows
protected Future<Void> onExecute(SQLRequest<MySqlExplainStatement> request, MycatDataContext dataContext, Response response) {
MySqlExplainStatement explainAst = request.getAst();
explainAst.accept0(new MySqlASTVisitorAdapter() {
@Override
public boolean visit(SQLExprTableSource x) {
if (x.getSchema() == null) {
x.setSchema(dataContext.getDefaultSchema());
}
return super.visit(x);
}
});
if (explainAst.isDescribe()) {
SQLName tableName = explainAst.getTableName();
if (tableName instanceof SQLIdentifierExpr && dataContext.getDefaultSchema() != null) {
explainAst.setTableName(new SQLPropertyExpr(new SQLIdentifierExpr(dataContext.getDefaultSchema()), ((SQLIdentifierExpr) tableName).getName()));
}
return response.proxySelectToPrototype(explainAst.toUnformattedString(), Collections.emptyList());
}
SQLStatement statement = request.getAst().getStatement();
boolean forUpdate = false;
if (statement instanceof SQLSelectStatement) {
forUpdate = ((SQLSelectStatement) explainAst.getStatement()).getSelect().getFirstQueryBlock().isForUpdate();
}
ResultSetBuilder builder = ResultSetBuilder.create().addColumnInfo("plan", JDBCType.VARCHAR);
try {
HackRouter hackRouter = new HackRouter(statement, dataContext);
if (hackRouter.analyse()) {
Pair<String, String> plan = hackRouter.getPlan();
builder.addObjectRowPayload(Arrays.asList("targetName: " + plan.getKey() + " sql: " + plan.getValue()));
} else {
List<SQLCommentHint> hints = explainAst.getHints();
if (hints != null) {
statement.setHeadHints(hints);
}
DrdsSqlWithParams drdsSqlWithParams = DrdsRunnerHelper.preParse(statement, dataContext.getDefaultSchema());
Plan plan;
if (statement instanceof SQLInsertStatement || statement instanceof SQLUpdateStatement || statement instanceof SQLDeleteStatement) {
plan = UpdateSQLHandler.getPlan(drdsSqlWithParams);
} else {
plan = DrdsRunnerHelper.getPlan(drdsSqlWithParams);
}
List<String> explain = plan.explain(dataContext, drdsSqlWithParams, true);
for (String s1 : explain) {
builder.addObjectRowPayload(Arrays.asList(s1));
}
}
} catch (Throwable th) {
LOGGER.error("", th);
builder.addObjectRowPayload(Arrays.asList(th.toString()));
}
return response.sendResultSet(RowIterable.create(builder.build()));
}
use of io.mycat.prototypeserver.mysql.HackRouter in project Mycat2 by MyCATApache.
the class CreateViewSQLHandler method onExecute.
@Override
protected Future<Void> onExecute(SQLRequest<SQLCreateViewStatement> request, MycatDataContext dataContext, Response response) {
LockService lockService = MetaClusterCurrent.wrapper(LockService.class);
SQLCreateViewStatement ast = request.getAst();
resolveSQLExprTableSource(ast.getTableSource(), dataContext);
return lockService.lock(DDL_LOCK, new Supplier<Future<Void>>() {
@Override
public Future<Void> get() {
String schemaName = Optional.ofNullable(ast.getSchema()).orElse(dataContext.getDefaultSchema());
schemaName = SQLUtils.normalize(schemaName);
String viewName = SQLUtils.normalize(ast.getName().getSimpleName());
SQLSelect subQuery = ast.getSubQuery();
SQLSelectStatement sqlSelectStatement = new SQLSelectStatement();
sqlSelectStatement.setSelect(subQuery);
List<String> aliasList = Optional.ofNullable(ast.getColumns()).orElse(Collections.emptyList()).stream().map(i -> SQLUtils.normalize(i.toString())).collect(Collectors.toList());
HackRouter hackRouter = new HackRouter(sqlSelectStatement, dataContext);
boolean distSql = !hackRouter.analyse();
try (MycatRouterConfigOps ops = ConfigUpdater.getOps()) {
if (!distSql) {
Pair<String, String> plan = hackRouter.getPlan();
JdbcConnectionManager jdbcConnectionManager = MetaClusterCurrent.wrapper(JdbcConnectionManager.class);
try (DefaultConnection connection = jdbcConnectionManager.getConnection(plan.getKey())) {
Connection rawConnection = connection.getRawConnection();
Statement statement = rawConnection.createStatement();
statement.setMaxRows(0);
MycatRowMetaData metaData = connection.executeQuery(plan.getValue()).getMetaData();
if (!aliasList.isEmpty()) {
metaData = RenameMycatRowMetaData.of(metaData, aliasList);
}
String createTableSql = PrototypeService.generateSql(schemaName, viewName, metaData.metaData());
ops.putNormalTable(schemaName, viewName, (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(createTableSql));
statement.close();
try {
SQLSelectStatement phySQLSelectStatement = (SQLSelectStatement) SQLUtils.parseSingleMysqlStatement(plan.getValue());
ast.setSubQuery(phySQLSelectStatement.getSelect());
// 建立物理视图
JdbcUtils.execute(rawConnection, ast.toString());
} catch (Throwable throwable) {
LOGGER.error("build phy view fail", throwable);
}
}
} else {
ops.addView(schemaName, viewName, ast.toString());
}
ops.commit();
return response.sendOk();
} catch (Throwable throwable) {
return Future.failedFuture(throwable);
}
}
});
}
use of io.mycat.prototypeserver.mysql.HackRouter in project Mycat2 by MyCATApache.
the class ShardingSQLHandler method onExecute.
@Override
protected Future<Void> onExecute(SQLRequest<SQLSelectStatement> request, MycatDataContext dataContext, Response response) {
Optional<Future<Void>> op = Optional.empty();
if (dataContext.isDebug()) {
op = testExample(request, dataContext, response);
if (op.isPresent())
return op.get();
}
DrdsSqlWithParams drdsSqlWithParams = DrdsRunnerHelper.preParse(request.getAst(), dataContext.getDefaultSchema());
HackRouter hackRouter = new HackRouter(drdsSqlWithParams.getParameterizedStatement(), dataContext);
try {
if (hackRouter.analyse()) {
Pair<String, String> plan = hackRouter.getPlan();
return response.proxySelect(Collections.singletonList(plan.getKey()), plan.getValue(), drdsSqlWithParams.getParams());
} else {
return DrdsRunnerHelper.runOnDrds(dataContext, drdsSqlWithParams, response);
}
} catch (Throwable throwable) {
LOGGER.error(request.getAst().toString(), throwable);
return Future.failedFuture(throwable);
}
}
use of io.mycat.prototypeserver.mysql.HackRouter in project Mycat2 by MyCATApache.
the class UpdateSQLHandler method updateHandler.
@SneakyThrows
public static Future<Void> updateHandler(SQLStatement sqlStatement, MycatDataContext dataContext, SQLTableSource tableSourceArg, Response receiver) {
boolean insert = sqlStatement instanceof SQLInsertStatement;
if (tableSourceArg instanceof SQLExprTableSource) {
SQLExprTableSource tableSource = (SQLExprTableSource) tableSourceArg;
String schemaName = Optional.ofNullable(tableSource.getSchema() == null ? dataContext.getDefaultSchema() : tableSource.getSchema()).map(i -> SQLUtils.normalize(i)).orElse(null);
String tableName = SQLUtils.normalize(tableSource.getTableName());
if (schemaName == null) {
return receiver.sendError("unknown schema", MySQLErrorCode.ER_UNKNOWN_ERROR);
}
tableSource.setSchema(schemaName);
SchemaHandler schemaHandler;
MetadataManager metadataManager = MetaClusterCurrent.wrapper(MetadataManager.class);
Optional<NameMap<SchemaHandler>> handlerMapOptional = Optional.ofNullable(metadataManager.getSchemaMap());
Optional<String> targetNameOptional = Optional.ofNullable(metadataManager.getPrototype());
if (!handlerMapOptional.isPresent()) {
if (targetNameOptional.isPresent()) {
if (insert) {
DrdsSqlWithParams drdsSqlWithParams = MycatPreparedStatementUtil.outputToParameterizedProxySql((MySqlInsertStatement) sqlStatement);
return receiver.proxyInsert(Collections.singletonList(targetNameOptional.get()), drdsSqlWithParams.getParameterizedSQL(), drdsSqlWithParams.getParams());
} else {
DrdsSqlWithParams drdsSqlWithParams = DrdsRunnerHelper.preParse(sqlStatement, dataContext.getDefaultSchema());
return receiver.proxyUpdate(Collections.singletonList(targetNameOptional.get()), drdsSqlWithParams.getParameterizedSQL(), drdsSqlWithParams.getParams());
}
} else {
return receiver.sendError(new MycatException("Unable to route:" + sqlStatement));
}
} else {
NameMap<SchemaHandler> handlerMap = handlerMapOptional.get();
schemaHandler = Optional.ofNullable(handlerMap.get(schemaName)).orElseGet(() -> {
if (dataContext.getDefaultSchema() == null) {
// 可能schemaName有值,但是值名不是配置的名字
throw new MycatException("unknown schema:" + schemaName);
}
return handlerMap.get(dataContext.getDefaultSchema());
});
if (schemaHandler == null) {
return receiver.sendError(new MycatException("Unable to route:" + sqlStatement));
}
}
String defaultTargetName = schemaHandler.defaultTargetName();
NameMap<TableHandler> tableMap = schemaHandler.logicTables();
TableHandler tableHandler = tableMap.get(tableName);
// /////////////////////////////common///////////////////////////////
if (tableHandler == null) {
if (insert) {
DrdsSqlWithParams drdsSqlWithParams = MycatPreparedStatementUtil.outputToParameterizedProxySql((MySqlInsertStatement) sqlStatement);
return receiver.proxyInsert(Collections.singletonList(Objects.requireNonNull(defaultTargetName, "can not route :" + drdsSqlWithParams)), drdsSqlWithParams.getParameterizedSQL(), drdsSqlWithParams.getParams());
} else {
DrdsSqlWithParams drdsSqlWithParams = DrdsRunnerHelper.preParse(sqlStatement, null);
return receiver.proxyUpdate(Collections.singletonList(Objects.requireNonNull(defaultTargetName, "can not route :" + drdsSqlWithParams)), drdsSqlWithParams.getParameterizedSQL(), drdsSqlWithParams.getParams());
}
}
switch(tableHandler.getType()) {
case NORMAL:
DrdsSqlWithParams drdsSqlWithParams;
if (insert) {
drdsSqlWithParams = MycatPreparedStatementUtil.outputToParameterizedProxySql((MySqlInsertStatement) sqlStatement);
} else {
drdsSqlWithParams = DrdsRunnerHelper.preParse(sqlStatement, dataContext.getDefaultSchema());
}
HackRouter hackRouter = new HackRouter(drdsSqlWithParams.getParameterizedStatement(), dataContext);
if (hackRouter.analyse()) {
Pair<String, String> plan = hackRouter.getPlan();
if (insert) {
return receiver.proxyInsert(Collections.singletonList(plan.getKey()), plan.getValue(), drdsSqlWithParams.getParams());
} else {
return receiver.proxyUpdate(Collections.singletonList(plan.getKey()), plan.getValue(), drdsSqlWithParams.getParams());
}
}
break;
default:
break;
}
DrdsSqlWithParams drdsSqlWithParams = DrdsRunnerHelper.preParse(sqlStatement, dataContext.getDefaultSchema());
return executeUpdate(drdsSqlWithParams, dataContext, receiver, schemaName);
}
DrdsSqlWithParams drdsSqlWithParams = insert ? MycatPreparedStatementUtil.outputToParameterizedProxySql((MySqlInsertStatement) sqlStatement) : DrdsRunnerHelper.preParse(sqlStatement, dataContext.getDefaultSchema());
HackRouter hackRouter = new HackRouter(drdsSqlWithParams.getParameterizedStatement(), dataContext);
if (hackRouter.analyse()) {
Pair<String, String> plan = hackRouter.getPlan();
if (insert) {
return receiver.proxyInsert(Collections.singletonList(plan.getKey()), plan.getValue(), drdsSqlWithParams.getParams());
} else {
return receiver.proxyUpdate(Collections.singletonList(plan.getKey()), plan.getValue(), drdsSqlWithParams.getParams());
}
}
return receiver.sendError(new MycatException("can not route " + sqlStatement));
}
Aggregations