use of com.facebook.presto.sql.analyzer.SemanticException in project presto by prestodb.
the class CallTask method execute.
@Override
public ListenableFuture<?> execute(Call call, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) {
if (!stateMachine.isAutoCommit()) {
throw new PrestoException(NOT_SUPPORTED, "Procedures cannot be called within a transaction (use autocommit mode)");
}
Session session = stateMachine.getSession();
QualifiedObjectName procedureName = createQualifiedObjectName(session, call, call.getName());
ConnectorId connectorId = metadata.getCatalogHandle(stateMachine.getSession(), procedureName.getCatalogName()).orElseThrow(() -> new SemanticException(MISSING_CATALOG, call, "Catalog %s does not exist", procedureName.getCatalogName()));
Procedure procedure = metadata.getProcedureRegistry().resolve(connectorId, procedureName.asSchemaTableName());
// map declared argument names to positions
Map<String, Integer> positions = new HashMap<>();
for (int i = 0; i < procedure.getArguments().size(); i++) {
positions.put(procedure.getArguments().get(i).getName(), i);
}
// per specification, do not allow mixing argument types
Predicate<CallArgument> hasName = argument -> argument.getName().isPresent();
boolean anyNamed = call.getArguments().stream().anyMatch(hasName);
boolean allNamed = call.getArguments().stream().allMatch(hasName);
if (anyNamed && !allNamed) {
throw new SemanticException(INVALID_PROCEDURE_ARGUMENTS, call, "Named and positional arguments cannot be mixed");
}
// get the argument names in call order
Map<String, CallArgument> names = new LinkedHashMap<>();
for (int i = 0; i < call.getArguments().size(); i++) {
CallArgument argument = call.getArguments().get(i);
if (argument.getName().isPresent()) {
String name = argument.getName().get();
if (names.put(name, argument) != null) {
throw new SemanticException(INVALID_PROCEDURE_ARGUMENTS, argument, "Duplicate procedure argument: %s", name);
}
if (!positions.containsKey(name)) {
throw new SemanticException(INVALID_PROCEDURE_ARGUMENTS, argument, "Unknown argument name: %s", name);
}
} else if (i < procedure.getArguments().size()) {
names.put(procedure.getArguments().get(i).getName(), argument);
} else {
throw new SemanticException(INVALID_PROCEDURE_ARGUMENTS, call, "Too many arguments for procedure");
}
}
// verify argument count
if (names.size() < positions.size()) {
throw new SemanticException(INVALID_PROCEDURE_ARGUMENTS, call, "Too few arguments for procedure");
}
// get argument values
Object[] values = new Object[procedure.getArguments().size()];
for (Entry<String, CallArgument> entry : names.entrySet()) {
CallArgument callArgument = entry.getValue();
int index = positions.get(entry.getKey());
Argument argument = procedure.getArguments().get(index);
Expression expression = ExpressionTreeRewriter.rewriteWith(new ParameterRewriter(parameters), callArgument.getValue());
Type type = metadata.getType(argument.getType());
checkCondition(type != null, INVALID_PROCEDURE_DEFINITION, "Unknown procedure argument type: %s", argument.getType());
Object value = evaluateConstantExpression(expression, type, metadata, session, parameters);
values[index] = toTypeObjectValue(session, type, value);
}
// validate arguments
MethodType methodType = procedure.getMethodHandle().type();
for (int i = 0; i < procedure.getArguments().size(); i++) {
if ((values[i] == null) && methodType.parameterType(i).isPrimitive()) {
String name = procedure.getArguments().get(i).getName();
throw new PrestoException(INVALID_PROCEDURE_ARGUMENT, "Procedure argument cannot be null: " + name);
}
}
// insert session argument
List<Object> arguments = new ArrayList<>();
Iterator<Object> valuesIterator = asList(values).iterator();
for (Class<?> type : methodType.parameterList()) {
if (ConnectorSession.class.isAssignableFrom(type)) {
arguments.add(session.toConnectorSession(connectorId));
} else {
arguments.add(valuesIterator.next());
}
}
try {
procedure.getMethodHandle().invokeWithArguments(arguments);
} catch (Throwable t) {
if (t instanceof InterruptedException) {
Thread.currentThread().interrupt();
}
propagateIfInstanceOf(t, PrestoException.class);
throw new PrestoException(PROCEDURE_CALL_FAILED, t);
}
return immediateFuture(null);
}
use of com.facebook.presto.sql.analyzer.SemanticException in project presto by prestodb.
the class CreateSchemaTask method execute.
@Override
public ListenableFuture<?> execute(CreateSchema statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) {
Session session = stateMachine.getSession();
CatalogSchemaName schema = createCatalogSchemaName(session, statement, Optional.of(statement.getSchemaName()));
// TODO: validate that catalog exists
accessControl.checkCanCreateSchema(session.getRequiredTransactionId(), session.getIdentity(), schema);
if (metadata.schemaExists(session, schema)) {
if (!statement.isNotExists()) {
throw new SemanticException(SCHEMA_ALREADY_EXISTS, statement, "Schema '%s' already exists", schema);
}
return immediateFuture(null);
}
ConnectorId connectorId = metadata.getCatalogHandle(session, schema.getCatalogName()).orElseThrow(() -> new PrestoException(NOT_FOUND, "Catalog does not exist: " + schema.getCatalogName()));
Map<String, Object> properties = metadata.getSchemaPropertyManager().getProperties(connectorId, schema.getCatalogName(), statement.getProperties(), session, metadata, parameters);
metadata.createSchema(session, schema, properties);
return immediateFuture(null);
}
use of com.facebook.presto.sql.analyzer.SemanticException in project presto by prestodb.
the class DropTableTask method execute.
@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);
}
use of com.facebook.presto.sql.analyzer.SemanticException in project presto by prestodb.
the class SqlQueryManager method createQuery.
@Override
public QueryInfo createQuery(SessionSupplier sessionSupplier, String query) {
requireNonNull(sessionSupplier, "sessionFactory is null");
requireNonNull(query, "query is null");
checkArgument(!query.isEmpty(), "query must not be empty string");
QueryId queryId = queryIdGenerator.createNextQueryId();
Session session = null;
QueryExecution queryExecution;
Statement statement;
try {
session = sessionSupplier.createSession(queryId, transactionManager, accessControl, sessionPropertyManager);
if (query.length() > maxQueryLength) {
int queryLength = query.length();
query = query.substring(0, maxQueryLength);
throw new PrestoException(QUERY_TEXT_TOO_LARGE, format("Query text length (%s) exceeds the maximum length (%s)", queryLength, maxQueryLength));
}
Statement wrappedStatement = sqlParser.createStatement(query);
statement = unwrapExecuteStatement(wrappedStatement, sqlParser, session);
List<Expression> parameters = wrappedStatement instanceof Execute ? ((Execute) wrappedStatement).getParameters() : emptyList();
validateParameters(statement, parameters);
QueryExecutionFactory<?> queryExecutionFactory = executionFactories.get(statement.getClass());
if (queryExecutionFactory == null) {
throw new PrestoException(NOT_SUPPORTED, "Unsupported statement type: " + statement.getClass().getSimpleName());
}
if (statement instanceof Explain && ((Explain) statement).isAnalyze()) {
Statement innerStatement = ((Explain) statement).getStatement();
if (!(executionFactories.get(innerStatement.getClass()) instanceof SqlQueryExecutionFactory)) {
throw new PrestoException(NOT_SUPPORTED, "EXPLAIN ANALYZE only supported for statements that are queries");
}
}
queryExecution = queryExecutionFactory.createQueryExecution(queryId, query, session, statement, parameters);
} catch (ParsingException | PrestoException | SemanticException e) {
// This is intentionally not a method, since after the state change listener is registered
// it's not safe to do any of this, and we had bugs before where people reused this code in a method
URI self = locationFactory.createQueryLocation(queryId);
// if session creation failed, create a minimal session object
if (session == null) {
session = Session.builder(new SessionPropertyManager()).setQueryId(queryId).setIdentity(sessionSupplier.getIdentity()).build();
}
Optional<ResourceGroupId> resourceGroup = Optional.empty();
if (e instanceof QueryQueueFullException) {
resourceGroup = Optional.of(((QueryQueueFullException) e).getResourceGroup());
}
QueryExecution execution = new FailedQueryExecution(queryId, query, resourceGroup, session, self, transactionManager, queryExecutor, metadata, e);
QueryInfo queryInfo = null;
try {
queries.put(queryId, execution);
queryInfo = execution.getQueryInfo();
queryMonitor.queryCreatedEvent(queryInfo);
queryMonitor.queryCompletedEvent(queryInfo);
stats.queryFinished(queryInfo);
} finally {
// execution MUST be added to the expiration queue or there will be a leak
expirationQueue.add(execution);
}
return queryInfo;
}
QueryInfo queryInfo = queryExecution.getQueryInfo();
queryMonitor.queryCreatedEvent(queryInfo);
queryExecution.addFinalQueryInfoListener(finalQueryInfo -> {
try {
QueryInfo info = queryExecution.getQueryInfo();
stats.queryFinished(info);
queryMonitor.queryCompletedEvent(info);
} finally {
expirationQueue.add(queryExecution);
}
});
addStatsListener(queryExecution);
queries.put(queryId, queryExecution);
// start the query in the background
queueManager.submit(statement, queryExecution, queryExecutor);
return queryInfo;
}
use of com.facebook.presto.sql.analyzer.SemanticException in project presto by prestodb.
the class DropViewTask method execute.
@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);
}
Aggregations