private InternalTable buildColumns( Session session, String catalogName, Map<String, NullableValue> filters) { InternalTable.Builder table = InternalTable.builder(informationSchemaTableColumns(TABLE_COLUMNS)); for (Entry<QualifiedObjectName, List<ColumnMetadata>> entry : getColumnsList(session, catalogName, filters).entrySet()) { QualifiedObjectName tableName = entry.getKey(); int ordinalPosition = 1; for (ColumnMetadata column : entry.getValue()) { if (column.isHidden()) { continue; } table.add( tableName.getCatalogName(), tableName.getSchemaName(), tableName.getObjectName(), column.getName(), ordinalPosition, null, "YES", column.getType().getDisplayName(), column.getComment()); ordinalPosition++; } } return table.build(); }
@Override public void checkCanRenameColumn( TransactionId transactionId, Identity identity, QualifiedObjectName tableName) { if (shouldDenyPrivilege(identity.getUser(), tableName.getObjectName(), RENAME_COLUMN)) { denyRenameColumn(tableName.toString()); } super.checkCanRenameColumn(transactionId, identity, tableName); }
@Override public void checkCanSelectFromView( TransactionId transactionId, Identity identity, QualifiedObjectName viewName) { if (shouldDenyPrivilege(identity.getUser(), viewName.getObjectName(), SELECT_VIEW)) { denySelectView(viewName.toString()); } if (denyPrivileges.isEmpty()) { super.checkCanSelectFromView(transactionId, identity, viewName); } }
@Override public void checkCanDeleteFromTable( TransactionId transactionId, Identity identity, QualifiedObjectName tableName) { if (shouldDenyPrivilege(identity.getUser(), tableName.getObjectName(), DELETE_TABLE)) { denyDeleteTable(tableName.toString()); } if (denyPrivileges.isEmpty()) { super.checkCanDeleteFromTable(transactionId, identity, tableName); } }
@Override public void checkCanInsertIntoTable( TransactionId transactionId, Identity identity, QualifiedObjectName tableName) { if (shouldDenyPrivilege(identity.getUser(), tableName.getObjectName(), INSERT_TABLE)) { denyInsertTable(tableName.toString()); } if (denyPrivileges.isEmpty()) { super.checkCanInsertIntoTable(transactionId, identity, tableName); } }
@Override public void checkCanCreateViewWithSelectFromTable( TransactionId transactionId, Identity identity, QualifiedObjectName tableName) { if (shouldDenyPrivilege( identity.getUser(), tableName.getObjectName(), CREATE_VIEW_WITH_SELECT_TABLE)) { denySelectTable(tableName.toString()); } if (denyPrivileges.isEmpty()) { super.checkCanCreateViewWithSelectFromTable(transactionId, identity, tableName); } }
@Override public void checkCanRenameTable( TransactionId transactionId, Identity identity, QualifiedObjectName tableName, QualifiedObjectName newTableName) { if (shouldDenyPrivilege(identity.getUser(), tableName.getObjectName(), RENAME_TABLE)) { denyRenameTable(tableName.toString(), newTableName.toString()); } if (denyPrivileges.isEmpty()) { super.checkCanRenameTable(transactionId, identity, tableName, newTableName); } }
private InternalTable buildTables( Session session, String catalogName, Map<String, NullableValue> filters) { Set<QualifiedObjectName> tables = ImmutableSet.copyOf(getTablesList(session, catalogName, filters)); Set<QualifiedObjectName> views = ImmutableSet.copyOf(getViewsList(session, catalogName, filters)); InternalTable.Builder table = InternalTable.builder(informationSchemaTableColumns(TABLE_TABLES)); for (QualifiedObjectName name : union(tables, views)) { // if table and view names overlap, the view wins String type = views.contains(name) ? "VIEW" : "BASE TABLE"; table.add(name.getCatalogName(), name.getSchemaName(), name.getObjectName(), type); } return table.build(); }
@Override public CompletableFuture<?> execute( Call call, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine) { 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()); Procedure procedure = metadata.getProcedureRegistry().resolve(procedureName); // 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 = callArgument.getValue(); Type type = argument.getType(); Object value = evaluateConstantExpression(expression, type, metadata, session); 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(procedureName.getCatalogName())); } 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 completedFuture(null); }
private InternalTable buildPartitions( Session session, String catalogName, Map<String, NullableValue> filters) { QualifiedObjectName tableName = extractQualifiedTableName(catalogName, filters); InternalTable.Builder table = InternalTable.builder(informationSchemaTableColumns(TABLE_INTERNAL_PARTITIONS)); Optional<TableHandle> tableHandle = metadata.getTableHandle(session, tableName); if (!tableHandle.isPresent()) { throw new TableNotFoundException(tableName.asSchemaTableName()); } List<TableLayoutResult> layouts = metadata.getLayouts( session, tableHandle.get(), Constraint.<ColumnHandle>alwaysTrue(), Optional.empty()); if (layouts.size() == 1) { Map<ColumnHandle, String> columnHandles = ImmutableBiMap.copyOf(metadata.getColumnHandles(session, tableHandle.get())).inverse(); Map<ColumnHandle, MethodHandle> methodHandles = new HashMap<>(); for (ColumnHandle columnHandle : columnHandles.keySet()) { try { ColumnMetadata columnMetadata = metadata.getColumnMetadata(session, tableHandle.get(), columnHandle); Signature operator = metadata.getFunctionRegistry().getCoercion(columnMetadata.getType(), VARCHAR); MethodHandle methodHandle = metadata .getFunctionRegistry() .getScalarFunctionImplementation(operator) .getMethodHandle(); methodHandles.put(columnHandle, methodHandle); } catch (OperatorNotFoundException exception) { // Do not put the columnHandle in the map. } } TableLayout layout = Iterables.getOnlyElement(layouts).getLayout(); layout .getDiscretePredicates() .ifPresent( domains -> { int partitionNumber = 1; for (TupleDomain<ColumnHandle> domain : domains) { for (Entry<ColumnHandle, NullableValue> entry : TupleDomain.extractFixedValues(domain).get().entrySet()) { ColumnHandle columnHandle = entry.getKey(); String columnName = columnHandles.get(columnHandle); String value = null; if (entry.getValue().getValue() != null) { if (methodHandles.containsKey(columnHandle)) { try { value = ((Slice) methodHandles .get(columnHandle) .invokeWithArguments(entry.getValue().getValue())) .toStringUtf8(); } catch (Throwable throwable) { throw Throwables.propagate(throwable); } } else { // OperatorNotFoundException was thrown for this columnHandle value = "<UNREPRESENTABLE VALUE>"; } } table.add( catalogName, tableName.getSchemaName(), tableName.getObjectName(), partitionNumber, columnName, value); } partitionNumber++; } }); } return table.build(); }