/** Generates the scalar column AST nodes for a given array of SQL columns */ public static void generateScalarColumns(HqlSqlWalkerNode node, String sqlColumns[], int i) { if (sqlColumns.length == 1) { generateSingleScalarColumn(node, i); } else { ASTFactory factory = node.getASTFactory(); AST n = node; n.setText(sqlColumns[0]); // Use the DOT node to emit the first column name. // Create the column names, folled by the column aliases. for (int j = 0; j < sqlColumns.length; j++) { if (j > 0) { n = ASTUtil.createSibling(factory, SqlTokenTypes.SQL_TOKEN, sqlColumns[j], n); } n = ASTUtil.createSibling( factory, SqlTokenTypes.SELECT_COLUMNS, " as " + NameGenerator.scalarName(i, j), n); } } }
/** * Returns an equivalent tree for (NOT (a relop b) ), for example: * * <pre> * (NOT (GT a b) ) => (LE a b) * </pre> * * @param x The sub tree to transform, the parent is assumed to be NOT. * @return AST - The equivalent sub-tree. */ public AST negateNode(AST x) { // TODO: switch statements are always evil! We already had bugs because // of forgotten token types. Use polymorphism for this! switch (x.getType()) { case OR: x.setType(AND); x.setText("{and}"); negateNode(x.getFirstChild()); negateNode(x.getFirstChild().getNextSibling()); return x; case AND: x.setType(OR); x.setText("{or}"); negateNode(x.getFirstChild()); negateNode(x.getFirstChild().getNextSibling()); return x; case EQ: x.setType(NE); x.setText("{not}" + x.getText()); return x; // (NOT (EQ a b) ) => (NE a b) case NE: x.setType(EQ); x.setText("{not}" + x.getText()); return x; // (NOT (NE a b) ) => (EQ a b) case GT: x.setType(LE); x.setText("{not}" + x.getText()); return x; // (NOT (GT a b) ) => (LE a b) case LT: x.setType(GE); x.setText("{not}" + x.getText()); return x; // (NOT (LT a b) ) => (GE a b) case GE: x.setType(LT); x.setText("{not}" + x.getText()); return x; // (NOT (GE a b) ) => (LT a b) case LE: x.setType(GT); x.setText("{not}" + x.getText()); return x; // (NOT (LE a b) ) => (GT a b) case LIKE: x.setType(NOT_LIKE); x.setText("{not}" + x.getText()); return x; // (NOT (LIKE a b) ) => (NOT_LIKE a b) case NOT_LIKE: x.setType(LIKE); x.setText("{not}" + x.getText()); return x; // (NOT (NOT_LIKE a b) ) => (LIKE a b) case IN: x.setType(NOT_IN); x.setText("{not}" + x.getText()); return x; case NOT_IN: x.setType(IN); x.setText("{not}" + x.getText()); return x; case IS_NULL: x.setType(IS_NOT_NULL); x.setText("{not}" + x.getText()); return x; // (NOT (IS_NULL a b) ) => (IS_NOT_NULL a b) case IS_NOT_NULL: x.setType(IS_NULL); x.setText("{not}" + x.getText()); return x; // (NOT (IS_NOT_NULL a b) ) => (IS_NULL a b) case BETWEEN: x.setType(NOT_BETWEEN); x.setText("{not}" + x.getText()); return x; // (NOT (BETWEEN a b) ) => (NOT_BETWEEN a b) case NOT_BETWEEN: x.setType(BETWEEN); x.setText("{not}" + x.getText()); return x; // (NOT (NOT_BETWEEN a b) ) => (BETWEEN a b) /* This can never happen because this rule will always eliminate the child NOT. case NOT: return x.getFirstChild(); // (NOT (NOT x) ) => (x) */ default: return super.negateNode(x); // Just add a 'not' parent. } }