use of org.jooq.Condition in project jOOQ by jOOQ.
the class ParserImpl method parsePredicate.
private static final Condition parsePredicate(ParserContext ctx) {
if (parseKeywordIf(ctx, "EXISTS")) {
parse(ctx, '(');
Select<?> select = parseSelect(ctx);
parse(ctx, ')');
return exists(select);
} else {
// TODO row value expressions
Field left;
Comparator comp;
boolean not;
left = parseFieldConcat(ctx, null);
not = parseKeywordIf(ctx, "NOT");
if (!not && (comp = parseComparatorIf(ctx)) != null) {
boolean all = parseKeywordIf(ctx, "ALL");
boolean any = !all && (parseKeywordIf(ctx, "ANY") || parseKeywordIf(ctx, "SOME"));
if (all || any)
parse(ctx, '(');
Condition result = all ? left.compare(comp, DSL.all(parseSelect(ctx))) : any ? left.compare(comp, DSL.any(parseSelect(ctx))) : left.compare(comp, parseFieldConcat(ctx, null));
if (all || any)
parse(ctx, ')');
return result;
} else if (!not && parseKeywordIf(ctx, "IS")) {
not = parseKeywordIf(ctx, "NOT");
if (parseKeywordIf(ctx, "NULL"))
return not ? left.isNotNull() : left.isNull();
parseKeyword(ctx, "DISTINCT FROM");
Field right = parseFieldConcat(ctx, null);
return not ? left.isNotDistinctFrom(right) : left.isDistinctFrom(right);
} else if (parseKeywordIf(ctx, "IN")) {
Condition result;
parse(ctx, '(');
if (peekKeyword(ctx, "SELECT"))
result = not ? left.notIn(parseSelect(ctx)) : left.in(parseSelect(ctx));
else
result = not ? left.notIn(parseFields(ctx)) : left.in(parseFields(ctx));
parse(ctx, ')');
return result;
} else if (parseKeywordIf(ctx, "BETWEEN")) {
boolean symmetric = parseKeywordIf(ctx, "SYMMETRIC");
Field r1 = parseFieldConcat(ctx, null);
parseKeyword(ctx, "AND");
Field r2 = parseFieldConcat(ctx, null);
return symmetric ? not ? left.notBetweenSymmetric(r1, r2) : left.betweenSymmetric(r1, r2) : not ? left.notBetween(r1, r2) : left.between(r1, r2);
} else if (parseKeywordIf(ctx, "LIKE")) {
Field right = parseFieldConcat(ctx, null);
boolean escape = parseKeywordIf(ctx, "ESCAPE");
char character = escape ? parseCharacterLiteral(ctx) : ' ';
return escape ? not ? left.notLike(right, character) : left.like(right, character) : not ? left.notLike(right) : left.like(right);
}
}
throw ctx.exception();
}
use of org.jooq.Condition in project jOOQ by jOOQ.
the class ParserImpl method parseQueryPrimary.
private static final SelectQueryImpl<Record> parseQueryPrimary(ParserContext ctx) {
if (parseIf(ctx, '(')) {
SelectQueryImpl<Record> result = parseSelect(ctx);
parse(ctx, ')');
return result;
}
parseKeyword(ctx, "SELECT");
boolean distinct = parseKeywordIf(ctx, "DISTINCT") || parseKeywordIf(ctx, "UNIQUE");
Long limit = null;
Long offset = null;
if (!distinct)
parseKeywordIf(ctx, "ALL");
if (parseKeywordIf(ctx, "TOP")) {
limit = parseUnsignedInteger(ctx);
if (parseKeywordIf(ctx, "START AT"))
offset = parseUnsignedInteger(ctx);
}
List<Field<?>> select = parseSelectList(ctx);
List<Table<?>> from = null;
Condition startWith = null;
Condition connectBy = null;
boolean connectByNoCycle = false;
Condition where = null;
List<GroupField> groupBy = null;
Condition having = null;
if (parseKeywordIf(ctx, "FROM"))
from = parseTables(ctx);
// TODO is there a better way?
if (from != null && from.size() == 1 && from.get(0).getName().equalsIgnoreCase("dual"))
from = null;
if (parseKeywordIf(ctx, "START WITH")) {
startWith = parseCondition(ctx);
parseKeyword(ctx, "CONNECT BY");
connectByNoCycle = parseKeywordIf(ctx, "NOCYCLE");
connectBy = parseCondition(ctx);
} else if (parseKeywordIf(ctx, "CONNECT BY")) {
connectByNoCycle = parseKeywordIf(ctx, "NOCYCLE");
connectBy = parseCondition(ctx);
if (parseKeywordIf(ctx, "START WITH"))
startWith = parseCondition(ctx);
}
if (parseKeywordIf(ctx, "WHERE"))
where = parseCondition(ctx);
if (parseKeywordIf(ctx, "GROUP BY")) {
if (parseIf(ctx, '(')) {
parse(ctx, ')');
groupBy = emptyList();
} else if (parseKeywordIf(ctx, "ROLLUP")) {
parse(ctx, '(');
groupBy = singletonList(rollup(parseFields(ctx).toArray(EMPTY_FIELD)));
parse(ctx, ')');
} else if (parseKeywordIf(ctx, "CUBE")) {
parse(ctx, '(');
groupBy = singletonList(cube(parseFields(ctx).toArray(EMPTY_FIELD)));
parse(ctx, ')');
} else if (parseKeywordIf(ctx, "GROUPING SETS")) {
List<List<Field<?>>> fieldSets = new ArrayList<List<Field<?>>>();
parse(ctx, '(');
do {
parse(ctx, '(');
if (parseIf(ctx, ')')) {
fieldSets.add(Collections.<Field<?>>emptyList());
} else {
fieldSets.add(parseFields(ctx));
parse(ctx, ')');
}
} while (parseIf(ctx, ','));
parse(ctx, ')');
groupBy = singletonList(groupingSets(fieldSets.toArray((Collection[]) EMPTY_COLLECTION)));
} else {
groupBy = (List) parseFields(ctx);
if (parseKeywordIf(ctx, "WITH ROLLUP"))
groupBy = singletonList(rollup(groupBy.toArray(EMPTY_FIELD)));
}
}
if (parseKeywordIf(ctx, "HAVING"))
having = parseCondition(ctx);
// TODO support WINDOW
SelectQueryImpl<Record> result = (SelectQueryImpl<Record>) ctx.dsl.selectQuery();
if (distinct)
result.setDistinct(distinct);
if (select.size() > 0)
result.addSelect(select);
if (from != null)
result.addFrom(from);
if (connectBy != null)
if (connectByNoCycle)
result.addConnectByNoCycle(connectBy);
else
result.addConnectBy(connectBy);
if (startWith != null)
result.setConnectByStartWith(startWith);
if (where != null)
result.addConditions(where);
if (groupBy != null)
result.addGroupBy(groupBy);
if (having != null)
result.addHaving(having);
if (limit != null)
if (offset != null)
result.addLimit((int) (long) offset, (int) (long) limit);
else
result.addLimit((int) (long) limit);
return result;
}
use of org.jooq.Condition in project jOOQ by jOOQ.
the class ParserImpl method parseField.
private static final Field<?> parseField(ParserContext ctx, Type type) {
if (B.is(type)) {
Field<?> r = parseFieldAnd(ctx);
Condition c = null;
while (parseKeywordIf(ctx, "OR")) c = ((c == null) ? condition((Field) r) : c).or((Field) parseFieldAnd(ctx));
return c == null ? r : field(c);
} else {
return parseFieldConcat(ctx, type);
}
}
use of org.jooq.Condition in project jOOQ by jOOQ.
the class ParserImpl method parseAlterTable.
private static final DDLQuery parseAlterTable(ParserContext ctx) {
boolean ifExists = parseKeywordIf(ctx, "IF EXISTS");
Table<?> tableName = parseTableName(ctx);
parseWhitespaceIf(ctx);
AlterTableStep s1 = ifExists ? ctx.dsl.alterTableIfExists(tableName) : ctx.dsl.alterTable(tableName);
switch(ctx.character()) {
case 'a':
case 'A':
if (parseKeywordIf(ctx, "ADD")) {
ConstraintTypeStep constraint = null;
if (parseKeywordIf(ctx, "CONSTRAINT"))
constraint = constraint(parseIdentifier(ctx));
if (parseKeywordIf(ctx, "PRIMARY KEY")) {
parse(ctx, '(');
Field<?>[] fieldNames = parseFieldNames(ctx).toArray(EMPTY_FIELD);
parse(ctx, ')');
return constraint == null ? s1.add(primaryKey(fieldNames)) : s1.add(constraint.primaryKey(fieldNames));
} else if (parseKeywordIf(ctx, "UNIQUE")) {
parse(ctx, '(');
Field<?>[] fieldNames = parseFieldNames(ctx).toArray(EMPTY_FIELD);
parse(ctx, ')');
return constraint == null ? s1.add(unique(fieldNames)) : s1.add(constraint.unique(fieldNames));
} else if (parseKeywordIf(ctx, "FOREIGN KEY")) {
parse(ctx, '(');
Field<?>[] referencing = parseFieldNames(ctx).toArray(EMPTY_FIELD);
parse(ctx, ')');
parseKeyword(ctx, "REFERENCES");
Table<?> referencedTable = parseTableName(ctx);
parse(ctx, '(');
Field<?>[] referencedFields = parseFieldNames(ctx).toArray(EMPTY_FIELD);
parse(ctx, ')');
if (referencing.length != referencedFields.length)
throw ctx.exception();
return constraint == null ? s1.add(foreignKey(referencing).references(referencedTable, referencedFields)) : s1.add(constraint.foreignKey(referencing).references(referencedTable, referencedFields));
} else if (parseKeywordIf(ctx, "CHECK")) {
parse(ctx, '(');
Condition condition = parseCondition(ctx);
parse(ctx, ')');
return constraint == null ? s1.add(check(condition)) : s1.add(constraint.check(condition));
} else if (constraint != null) {
throw ctx.unexpectedToken();
} else {
parseKeywordIf(ctx, "COLUMN");
// The below code is taken from CREATE TABLE, with minor modifications as
// https://github.com/jOOQ/jOOQ/issues/5317 has not yet been implemented
// Once implemented, we might be able to factor out the common logic into
// a new parseXXX() method.
String fieldName = parseIdentifier(ctx);
DataType type = parseDataType(ctx);
boolean nullable = false;
boolean defaultValue = false;
boolean unique = false;
for (; ; ) {
if (!nullable) {
if (parseKeywordIf(ctx, "NULL")) {
type = type.nullable(true);
nullable = true;
continue;
} else if (parseKeywordIf(ctx, "NOT NULL")) {
type = type.nullable(false);
nullable = true;
continue;
}
}
if (!defaultValue) {
if (parseKeywordIf(ctx, "DEFAULT")) {
type = type.defaultValue(parseField(ctx));
defaultValue = true;
continue;
}
}
if (!unique) {
if (parseKeywordIf(ctx, "PRIMARY KEY")) {
throw ctx.unexpectedToken();
} else if (parseKeywordIf(ctx, "UNIQUE")) {
throw ctx.unexpectedToken();
}
}
if (parseKeywordIf(ctx, "CHECK")) {
throw ctx.unexpectedToken();
}
break;
}
return s1.add(field(name(fieldName), type), type);
}
}
break;
case 'd':
case 'D':
if (parseKeywordIf(ctx, "DROP")) {
if (parseKeywordIf(ctx, "COLUMN")) {
Field<?> field = parseFieldName(ctx);
boolean cascade = parseKeywordIf(ctx, "CASCADE");
boolean restrict = !cascade && parseKeywordIf(ctx, "RESTRICT");
AlterTableDropStep s2 = s1.dropColumn(field);
AlterTableFinalStep s3 = cascade ? s2.cascade() : restrict ? s2.restrict() : s2;
return s3;
} else if (parseKeywordIf(ctx, "CONSTRAINT")) {
String constraint = parseIdentifier(ctx);
return s1.dropConstraint(constraint);
}
}
break;
case 'r':
case 'R':
if (parseKeywordIf(ctx, "RENAME")) {
if (parseKeywordIf(ctx, "TO")) {
String newName = parseIdentifier(ctx);
return s1.renameTo(newName);
} else if (parseKeywordIf(ctx, "COLUMN")) {
String oldName = parseIdentifier(ctx);
parseKeyword(ctx, "TO");
String newName = parseIdentifier(ctx);
return s1.renameColumn(oldName).to(newName);
} else if (parseKeywordIf(ctx, "CONSTRAINT")) {
String oldName = parseIdentifier(ctx);
parseKeyword(ctx, "TO");
String newName = parseIdentifier(ctx);
return s1.renameConstraint(oldName).to(newName);
}
}
break;
}
throw ctx.unexpectedToken();
}
use of org.jooq.Condition in project jOOQ by jOOQ.
the class SelectQueryImpl method toSQLReference0.
/**
* This method renders the main part of a query without the LIMIT clause.
* This part is common to any type of limited query
*/
@SuppressWarnings("unchecked")
private final void toSQLReference0(Context<?> context, Field<?>[] originalFields, Field<?>[] alternativeFields) {
SQLDialect dialect = context.dialect();
SQLDialect family = dialect.family();
int unionOpSize = unionOp.size();
// The SQL standard specifies:
//
// <query expression> ::=
// [ <with clause> ] <query expression body>
// [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
//
// Depending on the dialect and on various syntax elements, parts of the above must be wrapped in
// synthetic parentheses
boolean wrapQueryExpressionInDerivedTable;
boolean wrapQueryExpressionBodyInDerivedTable = false;
wrapQueryExpressionInDerivedTable = false || // interpreted as the (missing) INSERT column list's parens.
(context.data(DATA_INSERT_SELECT_WITHOUT_INSERT_COLUMN_LIST) != null && unionOpSize > 0);
if (wrapQueryExpressionInDerivedTable)
context.keyword("select").sql(" *").formatSeparator().keyword("from").sql(" (").formatIndentStart().formatNewLine();
// all databases, we need to wrap relevant subqueries in parentheses.
if (unionOpSize > 0) {
for (int i = unionOpSize - 1; i >= 0; i--) {
switch(unionOp.get(i)) {
case EXCEPT:
context.start(SELECT_EXCEPT);
break;
case EXCEPT_ALL:
context.start(SELECT_EXCEPT_ALL);
break;
case INTERSECT:
context.start(SELECT_INTERSECT);
break;
case INTERSECT_ALL:
context.start(SELECT_INTERSECT_ALL);
break;
case UNION:
context.start(SELECT_UNION);
break;
case UNION_ALL:
context.start(SELECT_UNION_ALL);
break;
}
unionParenthesis(context, "(");
}
}
// SELECT clause
// -------------
context.start(SELECT_SELECT).keyword("select").sql(' ');
// [#1493] Oracle hints come directly after the SELECT keyword
if (!StringUtils.isBlank(hint)) {
context.sql(hint).sql(' ');
}
if (!distinctOn.isEmpty()) {
context.keyword("distinct on").sql(" (").visit(distinctOn).sql(") ");
} else if (distinct) {
context.keyword("distinct").sql(' ');
}
context.declareFields(true);
// non-ambiguous column names as ambiguous column names are not allowed in subqueries
if (alternativeFields != null) {
if (wrapQueryExpressionBodyInDerivedTable && originalFields.length < alternativeFields.length)
context.visit(new SelectFieldList(Arrays.copyOf(alternativeFields, alternativeFields.length - 1)));
else
context.visit(new SelectFieldList(alternativeFields));
} else // arrays explicitly, as the subquery doesn't form an implicit RVE
if (context.subquery() && dialect == H2 && context.data(DATA_ROW_VALUE_EXPRESSION_PREDICATE_SUBQUERY) != null) {
Object data = context.data(DATA_ROW_VALUE_EXPRESSION_PREDICATE_SUBQUERY);
try {
context.data(DATA_ROW_VALUE_EXPRESSION_PREDICATE_SUBQUERY, null);
context.sql('(').visit(getSelect1()).sql(')');
} finally {
context.data(DATA_ROW_VALUE_EXPRESSION_PREDICATE_SUBQUERY, data);
}
} else // The default behaviour
{
context.visit(getSelect1());
}
context.declareFields(false).end(SELECT_SELECT);
// only in top level SELECTs
if (!context.subquery() && !asList().contains(family)) {
context.start(SELECT_INTO);
Table<?> actualInto = (Table<?>) context.data(DATA_SELECT_INTO_TABLE);
if (actualInto == null)
actualInto = into;
if (actualInto != null && context.data(DATA_OMIT_INTO_CLAUSE) == null && asList(HSQLDB, POSTGRES).contains(family)) {
context.formatSeparator().keyword("into").sql(' ').visit(actualInto);
}
context.end(SELECT_INTO);
}
// FROM and JOIN clauses
// ---------------------
context.start(SELECT_FROM).declareTables(true);
// [#....] Some SQL dialects do not require a FROM clause. Others do and
// jOOQ generates a "DUAL" table or something equivalent.
// See also org.jooq.impl.Dual for details.
boolean hasFrom = !getFrom().isEmpty() || asList(CUBRID, DERBY, FIREBIRD, HSQLDB, MARIADB, MYSQL).contains(family);
List<Condition> semiAntiJoinPredicates = null;
if (hasFrom) {
Object previousCollect = context.data(DATA_COLLECT_SEMI_ANTI_JOIN, true);
Object previousCollected = context.data(DATA_COLLECTED_SEMI_ANTI_JOIN, null);
context.formatSeparator().keyword("from").sql(' ').visit(getFrom());
semiAntiJoinPredicates = (List<Condition>) context.data(DATA_COLLECTED_SEMI_ANTI_JOIN, previousCollected);
context.data(DATA_COLLECT_SEMI_ANTI_JOIN, previousCollect);
}
context.declareTables(false).end(SELECT_FROM);
// WHERE clause
// ------------
context.start(SELECT_WHERE);
if (getWhere().getWhere() instanceof TrueCondition && semiAntiJoinPredicates == null)
;
else {
ConditionProviderImpl where = new ConditionProviderImpl();
if (semiAntiJoinPredicates != null)
where.addConditions(semiAntiJoinPredicates);
if (!(getWhere().getWhere() instanceof TrueCondition))
where.addConditions(getWhere());
context.formatSeparator().keyword("where").sql(' ').visit(where);
}
context.end(SELECT_WHERE);
// CONNECT BY clause
// -----------------
// CUBRID supports this clause only as [ START WITH .. ] CONNECT BY
// Oracle also knows the CONNECT BY .. [ START WITH ] alternative
// syntax
context.start(SELECT_START_WITH);
if (!(getConnectByStartWith().getWhere() instanceof TrueCondition)) {
context.formatSeparator().keyword("start with").sql(' ').visit(getConnectByStartWith());
}
context.end(SELECT_START_WITH);
context.start(SELECT_CONNECT_BY);
if (!(getConnectBy().getWhere() instanceof TrueCondition)) {
context.formatSeparator().keyword("connect by");
if (connectByNoCycle) {
context.sql(' ').keyword("nocycle");
}
context.sql(' ').visit(getConnectBy());
}
context.end(SELECT_CONNECT_BY);
// GROUP BY and HAVING clause
// --------------------------
context.start(SELECT_GROUP_BY);
if (grouping) {
context.formatSeparator().keyword("group by").sql(' ');
// [#1665] Empty GROUP BY () clauses need parentheses
if (getGroupBy().isEmpty()) {
// [#1681] Use the constant field from the dummy table Sybase ASE, Ingres
if (asList().contains(family)) {
context.sql("empty_grouping_dummy_table.dual");
} else // references, as in the ORDER BY clause!
if (asList(DERBY).contains(family)) {
context.sql('0');
} else // [#4447] CUBRID can't handle subqueries in GROUP BY
if (family == CUBRID) {
context.sql("1 + 0");
} else // [#4292] Some dialects don't support empty GROUP BY () clauses
if (asList(FIREBIRD, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE).contains(family)) {
context.sql('(').visit(DSL.select(one())).sql(')');
} else // Few dialects support the SQL standard "grand total" (i.e. empty grouping set)
{
context.sql("()");
}
} else {
context.visit(getGroupBy());
}
}
context.end(SELECT_GROUP_BY);
// HAVING clause
// -------------
context.start(SELECT_HAVING);
if (!(getHaving().getWhere() instanceof TrueCondition)) {
context.formatSeparator().keyword("having").sql(' ').visit(getHaving());
}
context.end(SELECT_HAVING);
// WINDOW clause
// -------------
context.start(SELECT_WINDOW);
if (!getWindow().isEmpty() && asList(POSTGRES).contains(family)) {
context.formatSeparator().keyword("window").sql(' ').declareWindows(true).visit(getWindow()).declareWindows(false);
}
context.end(SELECT_WINDOW);
// ORDER BY clause for local subselect
// -----------------------------------
toSQLOrderBy(context, originalFields, alternativeFields, false, wrapQueryExpressionBodyInDerivedTable, orderBy, limit);
// --------------------------------------------
if (unionOpSize > 0) {
unionParenthesis(context, ")");
for (int i = 0; i < unionOpSize; i++) {
CombineOperator op = unionOp.get(i);
for (Select<?> other : union.get(i)) {
context.formatSeparator().keyword(op.toSQL(dialect)).sql(' ');
unionParenthesis(context, "(");
context.visit(other);
unionParenthesis(context, ")");
}
// [#1658] Close parentheses opened previously
if (i < unionOpSize - 1)
unionParenthesis(context, ")");
switch(unionOp.get(i)) {
case EXCEPT:
context.end(SELECT_EXCEPT);
break;
case EXCEPT_ALL:
context.end(SELECT_EXCEPT_ALL);
break;
case INTERSECT:
context.end(SELECT_INTERSECT);
break;
case INTERSECT_ALL:
context.end(SELECT_INTERSECT_ALL);
break;
case UNION:
context.end(SELECT_UNION);
break;
case UNION_ALL:
context.end(SELECT_UNION_ALL);
break;
}
}
}
// ORDER BY clause for UNION
// -------------------------
boolean qualify = context.qualify();
try {
context.qualify(false);
toSQLOrderBy(context, originalFields, alternativeFields, wrapQueryExpressionInDerivedTable, wrapQueryExpressionBodyInDerivedTable, unionOrderBy, unionLimit);
} finally {
context.qualify(qualify);
}
}
Aggregations