Skip to content

Commit

Permalink
IGNITE-15455 SQL Calcite: Add support for statistics sql commands (ap…
Browse files Browse the repository at this point in the history
  • Loading branch information
ivandasch authored Aug 24, 2022
1 parent b57d331 commit 9b90f4e
Show file tree
Hide file tree
Showing 26 changed files with 16,229 additions and 14,049 deletions.
16 changes: 15 additions & 1 deletion modules/calcite/src/main/codegen/config.fmpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ data: {
"org.apache.ignite.lang.IgniteUuid",
"org.apache.calcite.sql.ddl.SqlDdlNodes",
"org.apache.ignite.internal.processors.query.calcite.sql.*",
"org.apache.ignite.internal.processors.query.calcite.sql.stat.*",
]

# List of new keywords. Example: "DATABASES", "TABLES". If the keyword is
Expand Down Expand Up @@ -66,7 +67,12 @@ data: {
"SERVICE"
"COMPUTE"
"ASYNC"
"QUERY"
"QUERY",
"STATISTICS",
"REFRESH",
"ANALYZE",
"MAX_CHANGED_PARTITION_ROWS_PERCENT",
"TOTAL"
]

# List of non-reserved keywords to add;
Expand Down Expand Up @@ -96,6 +102,11 @@ data: {
"COMPUTE"
"ASYNC"
"QUERY"
"STATISTICS",
"REFRESH",
"ANALYZE",
"MAX_CHANGED_PARTITION_ROWS_PERCENT",
"TOTAL",

# The following keywords are reserved in core Calcite,
# are reserved in some version of SQL,
Expand Down Expand Up @@ -621,6 +632,9 @@ data: {
"SqlKillQuery()",
"SqlCommitTransaction()",
"SqlRollbackTransaction()"
"SqlStatisticsAnalyze()"
"SqlStatisticsRefresh()"
"SqlStatisticsDrop()"
]

# List of methods for parsing extensions to "CREATE [OR REPLACE]" calls.
Expand Down
141 changes: 139 additions & 2 deletions modules/calcite/src/main/codegen/includes/parserImpls.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ SqlNodeList WithCreateTableOptionList() :
(
<QUOTED_IDENTIFIER>
{
return IgniteSqlCreateTable.parseOptionList(
return IgniteSqlCreateTableOption.parseOptionList(
SqlParserUtil.stripQuotes(token.image, DQ, DQ, DQDQ, quotedCasing),
getPos().withQuoting(true)
);
Expand Down Expand Up @@ -584,7 +584,7 @@ SqlNode SqlKillQuery():
}
{
<KILL> { s = span(); } <QUERY>
isAsync= IsAsyncOpt()
isAsync = IsAsyncOpt()
<QUOTED_STRING> {
String rawQueryId = SqlParserUtil.parseString(token.image);
SqlCharStringLiteral queryIdLiteral = SqlLiteral.createCharString(rawQueryId, getPos());
Expand Down Expand Up @@ -615,3 +615,140 @@ SqlNode SqlRollbackTransaction():
return new IgniteSqlRollback(s.end(this));
}
}

IgniteSqlStatisticsTable StatisticsTable():
{
final Span s = Span.of();
final SqlIdentifier id;
final SqlNodeList columnList;
}
{
id = CompoundIdentifier()
(
columnList = ParenthesizedSimpleIdentifierList()
|
{ columnList = null; }
)
{
return new IgniteSqlStatisticsTable(id, columnList, s.end(this));
}
}

SqlNodeList StatisticsTables():
{
final Span s = Span.of();
List<SqlNode> tbls = new ArrayList<SqlNode>();
SqlNode tbl;
}
{
tbl = StatisticsTable() { tbls.add(tbl); }
(
<COMMA> tbl = StatisticsTable() { tbls.add(tbl); }
)*
{
return new SqlNodeList(tbls, s.end(this));
}
}

SqlNodeList WithStatisticsAnalyzeOptionList() :
{
List<SqlNode> list = new ArrayList<SqlNode>();
final Span s;
}
{
[
<WITH> { s = span(); }
(
StatisticsAnalyzeOption(list)
(
<COMMA> { s.add(this); } StatisticsAnalyzeOption(list)
)*
{
return new SqlNodeList(list, s.end(this));
}
|
<QUOTED_IDENTIFIER>
{
return IgniteSqlStatisticsAnalyzeOption.parseOptionList(
SqlParserUtil.stripQuotes(token.image, DQ, DQ, DQDQ, quotedCasing),
getPos().withQuoting(true)
);
}
)
]
{ return null; }
}

SqlLiteral StatisticsAnalyzeOptionKey() :
{
}
{
<DISTINCT> { return SqlLiteral.createSymbol(IgniteSqlStatisticsAnalyzeOptionEnum.DISTINCT, getPos()); }
|
<TOTAL> { return SqlLiteral.createSymbol(IgniteSqlStatisticsAnalyzeOptionEnum.TOTAL, getPos()); }
|
<SIZE> { return SqlLiteral.createSymbol(IgniteSqlStatisticsAnalyzeOptionEnum.SIZE, getPos()); }
|
<NULLS> { return SqlLiteral.createSymbol(IgniteSqlStatisticsAnalyzeOptionEnum.NULLS, getPos()); }
|
<MAX_CHANGED_PARTITION_ROWS_PERCENT> { return SqlLiteral.createSymbol(IgniteSqlStatisticsAnalyzeOptionEnum.MAX_CHANGED_PARTITION_ROWS_PERCENT, getPos()); }
}

void StatisticsAnalyzeOption(List<SqlNode> list) :
{
final Span s;
final SqlLiteral key;
final SqlNode val;
}
{
key = StatisticsAnalyzeOptionKey() { s = span(); }
<EQ>
(
val = Literal()
|
val = SimpleIdentifier()
) {
list.add(new IgniteSqlStatisticsAnalyzeOption(key, val, s.end(this)));
}
}

SqlNode SqlStatisticsDrop():
{
final Span s;
SqlNodeList tablesList;
}
{
<DROP> <STATISTICS> { s = span(); }
tablesList = StatisticsTables()
{
return new IgniteSqlStatisticsDrop(tablesList, s.end(this));
}
}

SqlNode SqlStatisticsRefresh():
{
final Span s;
SqlNodeList tablesList;
}
{
<REFRESH> <STATISTICS> { s = span(); }
tablesList = StatisticsTables()
{
return new IgniteSqlStatisticsRefresh(tablesList, s.end(this));
}
}

SqlNode SqlStatisticsAnalyze():
{
final Span s;
SqlNodeList tablesList;
SqlNodeList optionsList;
}
{
<ANALYZE> { s = span(); }
tablesList = StatisticsTables()
optionsList = WithStatisticsAnalyzeOptionList()
{
return new IgniteSqlStatisticsAnalyze(tablesList, optionsList, s.end(this));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlDdl;
import org.apache.calcite.sql.SqlIdentifier;
Expand All @@ -42,12 +44,19 @@
import org.apache.ignite.internal.processors.query.calcite.sql.kill.IgniteSqlKillScanQuery;
import org.apache.ignite.internal.processors.query.calcite.sql.kill.IgniteSqlKillService;
import org.apache.ignite.internal.processors.query.calcite.sql.kill.IgniteSqlKillTransaction;
import org.apache.ignite.internal.processors.query.calcite.sql.stat.IgniteSqlStatisticsAnalyze;
import org.apache.ignite.internal.processors.query.calcite.sql.stat.IgniteSqlStatisticsCommand;
import org.apache.ignite.internal.processors.query.calcite.sql.stat.IgniteSqlStatisticsDrop;
import org.apache.ignite.internal.processors.query.calcite.sql.stat.IgniteSqlStatisticsRefresh;
import org.apache.ignite.internal.processors.query.stat.StatisticsTarget;
import org.apache.ignite.internal.sql.command.SqlAlterTableCommand;
import org.apache.ignite.internal.sql.command.SqlAlterUserCommand;
import org.apache.ignite.internal.sql.command.SqlAnalyzeCommand;
import org.apache.ignite.internal.sql.command.SqlCommand;
import org.apache.ignite.internal.sql.command.SqlCreateIndexCommand;
import org.apache.ignite.internal.sql.command.SqlCreateUserCommand;
import org.apache.ignite.internal.sql.command.SqlDropIndexCommand;
import org.apache.ignite.internal.sql.command.SqlDropStatisticsCommand;
import org.apache.ignite.internal.sql.command.SqlDropUserCommand;
import org.apache.ignite.internal.sql.command.SqlIndexColumn;
import org.apache.ignite.internal.sql.command.SqlKillComputeTaskCommand;
Expand All @@ -56,6 +65,8 @@
import org.apache.ignite.internal.sql.command.SqlKillScanQueryCommand;
import org.apache.ignite.internal.sql.command.SqlKillServiceCommand;
import org.apache.ignite.internal.sql.command.SqlKillTransactionCommand;
import org.apache.ignite.internal.sql.command.SqlRefreshStatitsicsCommand;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.lang.IgniteUuid;

import static org.apache.ignite.internal.processors.query.calcite.util.PlanUtils.deriveObjectName;
Expand All @@ -75,7 +86,8 @@ public static boolean isSupported(SqlNode sqlCmd) {
|| sqlCmd instanceof IgniteSqlCreateUser
|| sqlCmd instanceof IgniteSqlAlterUser
|| sqlCmd instanceof IgniteSqlDropUser
|| sqlCmd instanceof IgniteSqlKill;
|| sqlCmd instanceof IgniteSqlKill
|| sqlCmd instanceof IgniteSqlStatisticsCommand;
}

/**
Expand Down Expand Up @@ -106,6 +118,8 @@ else if (cmd instanceof IgniteSqlDropUser)
return convertDropUser((IgniteSqlDropUser)cmd, pctx);
else if (cmd instanceof IgniteSqlKill)
return convertKill((IgniteSqlKill)cmd, pctx);
else if (cmd instanceof IgniteSqlStatisticsCommand)
return convertStatistics((IgniteSqlStatisticsCommand)cmd, pctx);

throw new IgniteSQLException("Unsupported native operation [" +
"cmdName=" + (cmd == null ? null : cmd.getClass().getSimpleName()) + "; " +
Expand Down Expand Up @@ -226,4 +240,38 @@ else if (cmd instanceof IgniteSqlKillQuery) {
"querySql=\"" + pctx.query() + "\"]", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
}

/** */
private static SqlCommand convertStatistics(IgniteSqlStatisticsCommand cmd, PlanningContext pctx) {
List<StatisticsTarget> targets = cmd.tables().stream().map(t -> {
String schemaName = deriveSchemaName(t.name(), pctx);
String tblName = deriveObjectName(t.name(), pctx, "table name");

if (F.isEmpty(t.columns()))
return new StatisticsTarget(schemaName, tblName);

String[] columns = t.columns().stream().map(SqlNode::toString).toArray(String[]::new);

return new StatisticsTarget(schemaName, tblName, columns);
}).collect(Collectors.toList());

if (cmd instanceof IgniteSqlStatisticsAnalyze) {
if (F.isEmpty(((IgniteSqlStatisticsAnalyze)cmd).options()))
return new SqlAnalyzeCommand(targets);

Map<String, String> params = ((IgniteSqlStatisticsAnalyze)cmd).options().stream().collect(
Collectors.toMap(o -> o.key().toString(), o -> o.value().toString()));

return new SqlAnalyzeCommand(targets, params);
}
else if (cmd instanceof IgniteSqlStatisticsRefresh)
return new SqlRefreshStatitsicsCommand(targets);
else if (cmd instanceof IgniteSqlStatisticsDrop)
return new SqlDropStatisticsCommand(targets);
else {
throw new IgniteSQLException("Unsupported native operation [" +
"cmdName=" + (cmd == null ? null : cmd.getClass().getSimpleName()) + "; " +
"querySql=\"" + pctx.query() + "\"]", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,13 @@
import org.apache.calcite.sql.SqlCreate;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlLiteral;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlSpecialOperator;
import org.apache.calcite.sql.SqlUtil;
import org.apache.calcite.sql.SqlWriter;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.util.ImmutableNullableList;
import org.apache.ignite.internal.processors.query.calcite.util.IgniteResource;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
Expand Down Expand Up @@ -134,38 +131,4 @@ public SqlNodeList createOptionList() {
public boolean ifNotExists() {
return ifNotExists;
}

/**
* Parse option list. Used for H2-based "create table" syntax.
*
* @return Parsed option list.
*/
public static SqlNodeList parseOptionList(String opts, SqlParserPos pos) {
SqlNodeList list = new SqlNodeList(pos);

String[] pairs = opts.split(",");

for (String pair : pairs) {
String[] keyVal = pair.split("=");

if (keyVal.length != 2)
throw SqlUtil.newContextException(pos, IgniteResource.INSTANCE.cannotParsePair(pair));

String key = keyVal[0].trim();
String val = keyVal[1].trim();

IgniteSqlCreateTableOptionEnum optionKey = IgniteSqlCreateTableOptionEnum.valueOf(key.toUpperCase());

if (optionKey == null)
throw SqlUtil.newContextException(pos, IgniteResource.INSTANCE.illegalOption(key));

list.add(new IgniteSqlCreateTableOption(
SqlLiteral.createSymbol(optionKey, pos),
new SqlIdentifier(val, pos),
pos
));
}

return list;
}
}
Loading

0 comments on commit 9b90f4e

Please sign in to comment.