/** * Creates a table based on a select on another type and inserts the data (currently not possible to * perform this action 'WITH NO DATA'. * @param sql * @param createAsSelect * @param index * @return the number of rows inserted * @throws SQLException */ public int execute(String sql, CreateTableAsSelect createAsSelect, String index) throws SQLException { if(!createAsSelect.isWithData()) throw new SQLException("Not yet possible to create table as select without data (create emtpy table, " + "insert data and delete it will have the same effect"); // first create the index SqlParser parser = new SqlParser(); int queryIdx = sql.toLowerCase().indexOf(" as "); try{ String createSql = sql.substring(0, queryIdx)+" (_id String)" ; CreateTable create = (CreateTable)parser.createStatement(createSql); this.execute(createSql, create, index); }catch(SQLException sqle) { throw sqle; }catch(Exception e){ throw new SQLException("Unable to create table due to: "+e.getMessage(), e); } // secondly add the documents from the query String insertSql = "INSERT INTO "+createAsSelect.getName().toString()+" "+sql.substring(queryIdx+4); Insert insert = (Insert)parser.createStatement(insertSql); int res = this.execute(insertSql, insert, index); this.statement.getConnection().getTypeMap(); // trigger a reload of the table&column set for the connection return res; }
@Override protected Void visitCreateTable(CreateTable node, Integer indent) { builder.append("CREATE TABLE "); if (node.isNotExists()) { builder.append("IF NOT EXISTS "); } builder.append(node.getName()) .append(" ("); Joiner.on(", ").appendTo(builder, transform(node.getElements(), element -> element.getName() + " " + element.getType())); builder.append(")"); if (!node.getProperties().isEmpty()) { builder.append(" WITH ("); Joiner.on(", ").appendTo(builder, transform(node.getProperties().entrySet(), entry -> entry.getKey() + " = " + formatExpression(entry.getValue()))); builder.append(")"); } return null; }
@Override protected Void visitCreateTable(CreateTable node, Integer indent) { builder.append("CREATE TABLE ") .append(genDottedName(node.getName())) .append(" AS "); process(node.getQuery(), indent); builder.append("WITH DATA"); return null; }
@Override protected Void visitCreateTable(CreateTable node, Integer indent) { builder.append("CREATE TABLE ") .append(genDottedName(node.getName())) .append(" AS "); process(node.getQuery(), indent); builder.append("WITH NO DATA"); return null; }
@Override public int executeUpdate(String sql) throws SQLException { //System.out.println("QUERY: ["+sql+"]"); sql = sql.replaceAll("\r", " ").replaceAll("\n", " ").trim(); // custom stuff to support UPDATE statements since Presto does not parse it if(sql.toLowerCase().startsWith("update")){ return updateState.execute(sql); } com.facebook.presto.sql.tree.Statement statement = parser.createStatement(sql); if(statement instanceof Query) throw new SQLException("A regular query cannot be executed as an Update"); if(statement instanceof Insert){ //if(connection.getSchema() == null) throw new SQLException("No active index set for this driver. Pleas specify an active index or alias by executing 'USE <index/alias>' first"); return updateState.execute(sql, (Insert)statement, connection.getSchema()); }else if(statement instanceof Delete){ if(connection.getSchema() == null) throw new SQLException("No active index set for this driver. Pleas specify an active index or alias by executing 'USE <index/alias>' first"); return updateState.execute(sql, (Delete)statement, connection.getSchema()); }else if(statement instanceof CreateTable){ return updateState.execute(sql, (CreateTable)statement, connection.getSchema()); }else if(statement instanceof CreateTableAsSelect){ return updateState.execute(sql, (CreateTableAsSelect)statement, connection.getSchema()); }else if(statement instanceof CreateView){ return updateState.execute(sql, (CreateView)statement, connection.getSchema()); }else if(statement instanceof Use){ connection.setSchema( ((Use)statement).getSchema()); //connection.getTypeMap(); // updates the type mappings found in properties return 0; }else if(statement instanceof DropTable){ return updateState.execute(sql, (DropTable)statement); }else if(statement instanceof DropView){ return updateState.execute(sql, (DropView)statement); }throw new SQLFeatureNotSupportedException("Unable to parse provided update sql"); }
/** * Executes the {@link BulkRequest} being hold by this state. * @return an integer indicator for each executed request: Statement.SUCCESS_NO_INFO for success, * else Statement.EXECUTE_FAILED) */ public int[] executeBulk(){ int[] result = new int[bulkList.size()]; SqlParser parser = new SqlParser(); for(int i=0; i<bulkList.size(); i++) try{ String sql = bulkList.get(i); com.facebook.presto.sql.tree.Statement st = parser.createStatement(sql); if(st instanceof DropTable){ this.execute(sql, (DropTable)st); }else if(st instanceof DropView){ this.execute(sql, (DropView)st); }else if(st instanceof CreateTable){ this.execute(sql, (CreateTable)st, this.statement.getConnection().getSchema()); }else if(st instanceof CreateTableAsSelect){ this.execute(sql, (CreateTableAsSelect)st, this.statement.getConnection().getSchema()); }else if(st instanceof CreateView){ this.execute(sql, (CreateView)st, this.statement.getConnection().getSchema()); }else if(st instanceof Delete){ this.execute(sql, (Delete)st, this.statement.getConnection().getSchema()); }else if(st instanceof Insert){ this.execute(sql, (Insert)st, this.statement.getConnection().getSchema()); } result[i]= Statement.SUCCESS_NO_INFO; }catch (Exception e){ result[i] = Statement.EXECUTE_FAILED; } this.clearBulk(); return result; }
@Override public CompletableFuture<?> execute(CreateTable statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine) { checkArgument(!statement.getElements().isEmpty(), "no columns for table"); Session session = stateMachine.getSession(); QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getName()); Optional<TableHandle> tableHandle = metadata.getTableHandle(session, tableName); if (tableHandle.isPresent()) { if (!statement.isNotExists()) { throw new SemanticException(TABLE_ALREADY_EXISTS, statement, "Table '%s' already exists", tableName); } return completedFuture(null); } List<ColumnMetadata> columns = new ArrayList<>(); for (TableElement element : statement.getElements()) { Type type = metadata.getType(parseTypeSignature(element.getType())); if ((type == null) || type.equals(UNKNOWN)) { throw new SemanticException(TYPE_MISMATCH, element, "Unknown type for column '%s' ", element.getName()); } columns.add(new ColumnMetadata(element.getName(), type, false)); } accessControl.checkCanCreateTable(session.getRequiredTransactionId(), session.getIdentity(), tableName); Map<String, Object> properties = metadata.getTablePropertyManager().getTableProperties( tableName.getCatalogName(), statement.getProperties(), session, metadata); TableMetadata tableMetadata = new TableMetadata( tableName.getCatalogName(), new ConnectorTableMetadata(tableName.asSchemaTableName(), columns, properties, session.getUser(), false)); metadata.createTable(session, tableName.getCatalogName(), tableMetadata); return completedFuture(null); }
@Test public void testCreateTable() throws Exception { assertStatement("CREATE TABLE foo (a VARCHAR, b BIGINT)", new CreateTable(QualifiedName.of("foo"), ImmutableList.of(new TableElement("a", "VARCHAR"), new TableElement("b", "BIGINT")), false, ImmutableMap.of())); assertStatement("CREATE TABLE IF NOT EXISTS bar (c TIMESTAMP)", new CreateTable(QualifiedName.of("bar"), ImmutableList.of(new TableElement("c", "TIMESTAMP")), true, ImmutableMap.of())); }
@Override protected CatalogSchemaContext visitCreateTable(CreateTable node, CatalogSchemaContext context) { references.add(qualifiedNameToTable(node.getName(), context)); visitCreateTable(node, context); return context; }
@Override public String explain(CreateTable statement) { return "CREATE TABLE " + statement.getName(); }
@Override public Node visitCreateTable(SqlBaseParser.CreateTableContext context) { return new CreateTable(getLocation(context), getQualifiedName(context.qualifiedName()), visit(context.tableElement(), TableElement.class), context.EXISTS() != null, processTableProperties(context.tableProperties())); }