Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IGNITE-22732 Transaction aware SQL (#11438) #11544

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
5 changes: 4 additions & 1 deletion .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion docs/_docs/monitoring-metrics/system-views.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -645,8 +645,9 @@ This view exposes information about SQL views.
[{table_opts}]
|===
|NAME | TYPE | DESCRIPTION
|NAME | string | Name
|SCHEMA | string | Schema
|NAME | string | Name
|SQL | string | SQL query for view
|DESCRIPTION | string | Description
|===

Expand Down
60 changes: 60 additions & 0 deletions docs/_docs/sql-reference/ddl.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,66 @@ DROP INDEX idx_person_name;
----


== CREATE VIEW

Creates an user definded SQL view.


[source,sql]
----
CREATE [OR REPLACE] VIEW [schemaName.]viewName AS query
----

Parameters:

* `schemaName` - the name of the schema, where to create view.
* `viewName` - the name of the view to create.
* `OR REPLACE` - replace view if a view with the specified name already exists.
* `query` - valid SQL query.

Schema changes applied by this command are persisted on disk if link:persistence/native-persistence[Ignite persistence] is enabled. Thus, the changes can survive full cluster restarts.

[discrete]
=== Examples
Create a view:


[source,sql]
----
CREATE VIEW adult AS SELECT * FROM person WHERE age >= 18;
----


== DROP VIEW

Deletes an existing user defined SQL view.


[source,sql]
----
DROP VIEW [IF EXISTS] [schemaName.]viewName
----

Parameters:

* `schemaName` - the schema of the view to drop.
* `viewName` - the name of the view to drop.
* `IF EXISTS` - do not throw an error if a view with the specified name does not exist.

Schema changes applied by this command are persisted on disk if link:persistence/native-persistence[Ignite persistence] is enabled. Thus, the changes can survive full cluster restarts.


[discrete]
=== Examples
Drop a view:


[source,sql]
----
DROP VIEW adult;
----


== CREATE USER

The command creates a user with a given name and password.
Expand Down
2 changes: 1 addition & 1 deletion modules/calcite/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<checker.version>3.10.0</checker.version>
<failureaccess.version>1.0.1</failureaccess.version>
<immutables.version>2.8.2</immutables.version>
<janino.version>3.1.8</janino.version>
<janino.version>3.1.12</janino.version>
<javacc-maven-plugin>2.4</javacc-maven-plugin>
<jsonpath.version>2.9.0</jsonpath.version>
<reflections.version>0.10.2</reflections.version>
Expand Down
6 changes: 4 additions & 2 deletions modules/calcite/src/main/codegen/config.fmpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,8 @@ data: {
createStatementParserMethods: [
"SqlCreateTable",
"SqlCreateIndex",
"SqlCreateUser"
"SqlCreateUser",
"SqlCreateView"
]

# List of methods for parsing extensions to "DROP" calls.
Expand All @@ -459,7 +460,8 @@ data: {
dropStatementParserMethods: [
"SqlDropTable",
"SqlDropIndex",
"SqlDropUser"
"SqlDropUser",
"SqlDropView"
]

# List of methods for parsing extensions to "ALTER <scope>" calls.
Expand Down
38 changes: 38 additions & 0 deletions modules/calcite/src/main/codegen/includes/parserImpls.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ SqlCreate SqlCreateTable(Span s, boolean replace) :
final SqlNode query;
}
{
{
if (replace)
throw SqlUtil.newContextException(getPos(), IgniteResource.INSTANCE.unsupportedClause("REPLACE"));
}

<TABLE>
ifNotExists = IfNotExistsOpt()
id = CompoundIdentifier()
Expand Down Expand Up @@ -258,6 +263,11 @@ SqlCreate SqlCreateIndex(Span s, boolean replace) :
SqlNumericLiteral inlineSize = null;
}
{
{
if (replace)
throw SqlUtil.newContextException(getPos(), IgniteResource.INSTANCE.unsupportedClause("REPLACE"));
}

<INDEX>
ifNotExists = IfNotExistsOpt()
[ idxId = SimpleIdentifier() ]
Expand Down Expand Up @@ -412,6 +422,11 @@ SqlCreate SqlCreateUser(Span s, boolean replace) :
final SqlNode password;
}
{
{
if (replace)
throw SqlUtil.newContextException(getPos(), IgniteResource.INSTANCE.unsupportedClause("REPLACE"));
}

<USER> user = SimpleIdentifier()
<WITH> <PASSWORD> password = StringLiteral() {
return new IgniteSqlCreateUser(s.end(this), user, SqlLiteral.unchain(password));
Expand Down Expand Up @@ -752,3 +767,26 @@ SqlNode SqlStatisticsAnalyze():
return new IgniteSqlStatisticsAnalyze(tablesList, optionsList, s.end(this));
}
}

SqlCreate SqlCreateView(Span s, boolean replace) :
{
final SqlIdentifier id;
final SqlNode query;
}
{
<VIEW> id = CompoundIdentifier()
<AS> query = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY) {
return SqlDdlNodes.createView(s.end(this), replace, id, null, query);
}
}

SqlDrop SqlDropView(Span s, boolean replace) :
{
final boolean ifExists;
final SqlIdentifier id;
}
{
<VIEW> ifExists = IfExistsOpt() id = CompoundIdentifier() {
return SqlDdlNodes.dropView(s.end(this), ifExists, id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@
import org.apache.ignite.events.SqlQueryExecutionEvent;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.processors.GridProcessorAdapter;
import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal;
import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
import org.apache.ignite.internal.processors.failure.FailureProcessor;
import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
import org.apache.ignite.internal.processors.query.IgniteSQLException;
Expand Down Expand Up @@ -120,6 +122,7 @@
import org.jetbrains.annotations.Nullable;

import static org.apache.ignite.IgniteSystemProperties.getLong;
import static org.apache.ignite.configuration.TransactionConfiguration.TX_AWARE_QUERIES_SUPPORTED_MODES;
import static org.apache.ignite.events.EventType.EVT_SQL_QUERY_EXECUTION;

/** */
Expand Down Expand Up @@ -486,6 +489,8 @@ private <T> List<T> parseAndProcessQuery(
String sql,
Object... params
) throws IgniteSQLException {
ensureTransactionModeSupported(qryCtx);

SchemaPlus schema = schemaHolder.schema(schemaName);

assert schema != null : "Schema not found: " + schemaName;
Expand Down Expand Up @@ -588,7 +593,32 @@ private Object contextKey(QueryContext qryCtx) {

SqlFieldsQuery sqlFieldsQry = qryCtx.unwrap(SqlFieldsQuery.class);

return sqlFieldsQry != null ? F.asList(sqlFieldsQry.isLocal(), sqlFieldsQry.isEnforceJoinOrder()) : null;
return sqlFieldsQry != null
? F.asList(sqlFieldsQry.isLocal(), sqlFieldsQry.isEnforceJoinOrder(), queryTransactionVersion(qryCtx) == null)
: null;
}

/** */
private static GridCacheVersion queryTransactionVersion(@Nullable QueryContext qryCtx) {
return qryCtx == null ? null : qryCtx.unwrap(GridCacheVersion.class);
}

/** */
private void ensureTransactionModeSupported(@Nullable QueryContext qryCtx) {
if (!ctx.config().getTransactionConfiguration().isTxAwareQueriesEnabled())
return;

GridCacheVersion ver = queryTransactionVersion(qryCtx);

if (ver == null)
return;

final GridNearTxLocal userTx = ctx.cache().context().tm().tx(ver);

if (TX_AWARE_QUERIES_SUPPORTED_MODES.contains(userTx.isolation()))
return;

throw new IllegalStateException("Transaction isolation mode not supported for SQL queries: " + userTx.isolation());
}

/** */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ protected AbstractIndexScan(
/** {@inheritDoc} */
@Override public synchronized Iterator<Row> iterator() {
if (ranges == null)
return new IteratorImpl(idx.find(null, null, true, true, indexQueryContext()));
return new IteratorImpl(indexCursor(null, null, true, true));

IgniteClosure<RangeCondition<Row>, IteratorImpl> clo = range -> {
IdxRow lower = range.lower() == null ? null : row2indexRow(range.lower());
IdxRow upper = range.upper() == null ? null : row2indexRow(range.upper());

return new IteratorImpl(
idx.find(lower, upper, range.lowerInclude(), range.upperInclude(), indexQueryContext()));
indexCursor(lower, upper, range.lowerInclude(), range.upperInclude()));
};

if (!ranges.multiBounds()) {
Expand All @@ -88,6 +88,11 @@ protected AbstractIndexScan(
return F.flat(F.iterator(ranges, clo, true));
}

/** */
protected GridCursor<IdxRow> indexCursor(IdxRow lower, IdxRow upper, boolean lowerInclude, boolean upperInclude) {
return idx.find(lower, upper, lowerInclude, upperInclude, indexQueryContext());
}

/** */
protected abstract IdxRow row2indexRow(Row bound);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ private ExecutionContext<?> baseInboxContext(UUID nodeId, UUID qryId, long fragm
NoOpMemoryTracker.INSTANCE,
NoOpIoTracker.INSTANCE,
0,
ImmutableMap.of());
ImmutableMap.of(),
null);
}
}
Loading