@Override public Session getSession() { return stateMachine.getSession(); }
@Override public Session getSession() { return stateMachine.getSession(); }
@Override public ListenableFuture<?> execute(CreateTable statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { return internalExecute(statement, metadata, accessControl, stateMachine.getSession(), parameters); }
@Override public ListenableFuture<?> execute(Rollback statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); if (!session.getTransactionId().isPresent()) { throw new PrestoException(NOT_IN_TRANSACTION, "No transaction in progress"); } TransactionId transactionId = session.getTransactionId().get(); stateMachine.clearTransactionId(); transactionManager.asyncAbort(transactionId); return immediateFuture(null); }
@Override public ListenableFuture<?> execute(Commit statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); if (!session.getTransactionId().isPresent()) { throw new PrestoException(NOT_IN_TRANSACTION, "No transaction in progress"); } TransactionId transactionId = session.getTransactionId().get(); stateMachine.clearTransactionId(); return transactionManager.asyncCommit(transactionId); }
@Override public ListenableFuture<?> execute(Use statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); if (!statement.getCatalog().isPresent() && !session.getCatalog().isPresent()) { throw new SemanticException(CATALOG_NOT_SPECIFIED, statement, "Catalog must be specified when session catalog is not set"); } if (statement.getCatalog().isPresent()) { String catalog = statement.getCatalog().get().getValue().toLowerCase(ENGLISH); if (!metadata.getCatalogHandle(session, catalog).isPresent()) { throw new PrestoException(NOT_FOUND, "Catalog does not exist: " + catalog); } stateMachine.setSetCatalog(catalog); } stateMachine.setSetSchema(statement.getSchema().getValue().toLowerCase(ENGLISH)); return immediateFuture(null); } }
@Override public ListenableFuture<?> execute(DropTable statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getTableName()); Optional<TableHandle> tableHandle = metadata.getTableHandle(session, tableName); if (!tableHandle.isPresent()) { if (!statement.isExists()) { throw new SemanticException(MISSING_TABLE, statement, "Table '%s' does not exist", tableName); } return immediateFuture(null); } accessControl.checkCanDropTable(session.getRequiredTransactionId(), session.getIdentity(), tableName); metadata.dropTable(session, tableHandle.get()); return immediateFuture(null); } }
@Override public ListenableFuture<?> execute(ResetSession statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { List<String> parts = statement.getName().getParts(); if (parts.size() > 2) { throw new SemanticException(INVALID_SESSION_PROPERTY, statement, "Invalid session property '%s'", statement.getName()); } // validate the property name if (parts.size() == 1) { metadata.getSessionPropertyManager().getSystemSessionPropertyMetadata(parts.get(0)) .orElseThrow(() -> new SemanticException(INVALID_SESSION_PROPERTY, statement, "Session property %s does not exist", statement.getName())); } else { ConnectorId connectorId = metadata.getCatalogHandle(stateMachine.getSession(), parts.get(0)) .orElseThrow(() -> new SemanticException(MISSING_CATALOG, statement, "Catalog %s does not exist", parts.get(0))); metadata.getSessionPropertyManager().getConnectorSessionPropertyMetadata(connectorId, parts.get(1)) .orElseThrow(() -> new SemanticException(INVALID_SESSION_PROPERTY, statement, "Session property %s does not exist", statement.getName())); } stateMachine.addResetSessionProperties(statement.getName().toString()); return immediateFuture(null); } }
@Override public ListenableFuture<?> execute(StartTransaction statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); if (!session.isClientTransactionSupport()) { throw new PrestoException(StandardErrorCode.INCOMPATIBLE_CLIENT, "Client does not support transactions"); } if (session.getTransactionId().isPresent()) { throw new PrestoException(StandardErrorCode.NOT_SUPPORTED, "Nested transactions not supported"); } Optional<IsolationLevel> isolationLevel = extractIsolationLevel(statement); Optional<Boolean> readOnly = extractReadOnly(statement); TransactionId transactionId = transactionManager.beginTransaction( isolationLevel.orElse(TransactionManager.DEFAULT_ISOLATION), readOnly.orElse(TransactionManager.DEFAULT_READ_ONLY), false); stateMachine.setStartedTransactionId(transactionId); // Since the current session does not contain this new transaction ID, we need to manually mark it as inactive // when this statement completes. transactionManager.trySetInactive(transactionId); return immediateFuture(null); }
@Override public ListenableFuture<?> execute(DropView statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); QualifiedObjectName name = createQualifiedObjectName(session, statement, statement.getName()); Optional<ViewDefinition> view = metadata.getView(session, name); if (!view.isPresent()) { if (!statement.isExists()) { throw new SemanticException(MISSING_TABLE, statement, "View '%s' does not exist", name); } return immediateFuture(null); } accessControl.checkCanDropView(session.getRequiredTransactionId(), session.getIdentity(), name); metadata.dropView(session, name); return immediateFuture(null); } }
@Override public ListenableFuture<?> execute(DropSchema statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { if (statement.isCascade()) { throw new PrestoException(NOT_SUPPORTED, "CASCADE is not yet supported for DROP SCHEMA"); } Session session = stateMachine.getSession(); CatalogSchemaName schema = createCatalogSchemaName(session, statement, Optional.of(statement.getSchemaName())); if (!metadata.schemaExists(session, schema)) { if (!statement.isExists()) { throw new SemanticException(MISSING_SCHEMA, statement, "Schema '%s' does not exist", schema); } return immediateFuture(null); } accessControl.checkCanDropSchema(session.getRequiredTransactionId(), session.getIdentity(), schema); metadata.dropSchema(session, schema); return immediateFuture(null); } }
@Override public ListenableFuture<?> execute(CreateView statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); QualifiedObjectName name = createQualifiedObjectName(session, statement, statement.getName()); accessControl.checkCanCreateView(session.getRequiredTransactionId(), session.getIdentity(), name); String sql = getFormattedSql(statement.getQuery(), sqlParser, Optional.of(parameters)); Analysis analysis = analyzeStatement(statement, session, metadata, accessControl, parameters, stateMachine.getWarningCollector()); List<ViewColumn> columns = analysis.getOutputDescriptor(statement.getQuery()) .getVisibleFields().stream() .map(field -> new ViewColumn(field.getName().get(), field.getType())) .collect(toImmutableList()); String data = codec.toJson(new ViewDefinition(sql, session.getCatalog(), session.getSchema(), columns, Optional.of(session.getUser()))); metadata.createView(session, name, data, statement.isReplace()); return immediateFuture(null); }
@Override public ListenableFuture<?> execute(RenameTable statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getSource()); Optional<TableHandle> tableHandle = metadata.getTableHandle(session, tableName); if (!tableHandle.isPresent()) { throw new SemanticException(MISSING_TABLE, statement, "Table '%s' does not exist", tableName); } QualifiedObjectName target = createQualifiedObjectName(session, statement, statement.getTarget()); if (!metadata.getCatalogHandle(session, target.getCatalogName()).isPresent()) { throw new SemanticException(MISSING_CATALOG, statement, "Target catalog '%s' does not exist", target.getCatalogName()); } if (metadata.getTableHandle(session, target).isPresent()) { throw new SemanticException(TABLE_ALREADY_EXISTS, statement, "Target table '%s' already exists", target); } if (!tableName.getCatalogName().equals(target.getCatalogName())) { throw new SemanticException(NOT_SUPPORTED, statement, "Table rename across catalogs is not supported"); } accessControl.checkCanRenameTable(session.getRequiredTransactionId(), session.getIdentity(), tableName, target); metadata.renameTable(session, tableHandle.get(), target); return immediateFuture(null); } }
private PlanRoot doAnalyzeQuery() { // time analysis phase stateMachine.beginAnalysis(); // plan query PlanNodeIdAllocator idAllocator = new PlanNodeIdAllocator(); LogicalPlanner logicalPlanner = new LogicalPlanner(stateMachine.getSession(), planOptimizers, idAllocator, metadata, sqlParser, statsCalculator, costCalculator, stateMachine.getWarningCollector()); Plan plan = logicalPlanner.plan(analysis); queryPlan.set(plan); // extract inputs List<Input> inputs = new InputExtractor(metadata, stateMachine.getSession()).extractInputs(plan.getRoot()); stateMachine.setInputs(inputs); // extract output Optional<Output> output = new OutputExtractor().extractOutput(plan.getRoot()); stateMachine.setOutput(output); // fragment the plan SubPlan fragmentedPlan = planFragmenter.createSubPlans(stateMachine.getSession(), plan, false); // record analysis time stateMachine.endAnalysis(); boolean explainAnalyze = analysis.getStatement() instanceof Explain && ((Explain) analysis.getStatement()).isAnalyze(); return new PlanRoot(fragmentedPlan, !explainAnalyze, extractConnectors(analysis)); }
@Test public void testRollback() { TransactionManager transactionManager = createTestTransactionManager(); Session session = sessionBuilder() .setTransactionId(transactionManager.beginTransaction(false)) .build(); QueryStateMachine stateMachine = createQueryStateMachine("ROLLBACK", session, transactionManager); assertTrue(stateMachine.getSession().getTransactionId().isPresent()); assertEquals(transactionManager.getAllTransactionInfos().size(), 1); getFutureValue(new RollbackTask().execute(new Rollback(), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); assertTrue(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); assertTrue(transactionManager.getAllTransactionInfos().isEmpty()); }
@Test public void testNonTransactionalClient() { Session session = sessionBuilder().build(); TransactionManager transactionManager = createTestTransactionManager(); QueryStateMachine stateMachine = createQueryStateMachine("START TRANSACTION", session, transactionManager); assertFalse(stateMachine.getSession().getTransactionId().isPresent()); try { getFutureValue(new StartTransactionTask().execute(new StartTransaction(ImmutableList.of()), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); fail(); } catch (PrestoException e) { assertEquals(e.getErrorCode(), INCOMPATIBLE_CLIENT.toErrorCode()); } assertTrue(transactionManager.getAllTransactionInfos().isEmpty()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); }
@Test public void testStartTransaction() { Session session = sessionBuilder() .setClientTransactionSupport() .build(); TransactionManager transactionManager = createTestTransactionManager(); QueryStateMachine stateMachine = createQueryStateMachine("START TRANSACTION", session, transactionManager); assertFalse(stateMachine.getSession().getTransactionId().isPresent()); getFutureValue(new StartTransactionTask().execute(new StartTransaction(ImmutableList.of()), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); assertFalse(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertTrue(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); assertEquals(transactionManager.getAllTransactionInfos().size(), 1); TransactionInfo transactionInfo = transactionManager.getTransactionInfo(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().get()); assertFalse(transactionInfo.isAutoCommitContext()); }
@Test public void testCommit() { TransactionManager transactionManager = createTestTransactionManager(); Session session = sessionBuilder() .setTransactionId(transactionManager.beginTransaction(false)) .build(); QueryStateMachine stateMachine = createQueryStateMachine("COMMIT", session, transactionManager); assertTrue(stateMachine.getSession().getTransactionId().isPresent()); assertEquals(transactionManager.getAllTransactionInfos().size(), 1); getFutureValue(new CommitTask().execute(new Commit(), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); assertTrue(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); assertTrue(transactionManager.getAllTransactionInfos().isEmpty()); }
@Test public void testStartTransactionTooManyAccessModes() { Session session = sessionBuilder() .setClientTransactionSupport() .build(); TransactionManager transactionManager = createTestTransactionManager(); QueryStateMachine stateMachine = createQueryStateMachine("START TRANSACTION", session, transactionManager); assertFalse(stateMachine.getSession().getTransactionId().isPresent()); try { getFutureValue(new StartTransactionTask().execute( new StartTransaction(ImmutableList.of(new TransactionAccessMode(true), new TransactionAccessMode(true))), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); fail(); } catch (SemanticException e) { assertEquals(e.getCode(), INVALID_TRANSACTION_MODE); } assertTrue(transactionManager.getAllTransactionInfos().isEmpty()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); }
@Override public ListenableFuture<?> execute(RenameSchema statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); CatalogSchemaName source = createCatalogSchemaName(session, statement, Optional.of(statement.getSource())); CatalogSchemaName target = new CatalogSchemaName(source.getCatalogName(), statement.getTarget().getValue()); if (!metadata.schemaExists(session, source)) { throw new SemanticException(MISSING_SCHEMA, statement, "Schema '%s' does not exist", source); } if (metadata.schemaExists(session, target)) { throw new SemanticException(SCHEMA_ALREADY_EXISTS, statement, "Target schema '%s' already exists", target); } accessControl.checkCanRenameSchema(session.getRequiredTransactionId(), session.getIdentity(), source, statement.getTarget().getValue()); metadata.renameSchema(session, source, statement.getTarget().getValue()); return immediateFuture(null); } }