use of org.jooq.Update in project jOOQ by jOOQ.
the class DefaultParseContext method parseUpdate.
private final Query parseUpdate(WithImpl with, boolean parseResultQuery) {
parseKeyword("UPDATE", "UPD");
Field<Long> limit = null;
// T-SQL style TOP .. START AT
if (parseKeywordIf("TOP")) {
limit = (Field) parseField();
// [#8623] TODO Support this
// percent = parseKeywordIf("PERCENT") && requireProEdition();
}
Table<?> table = parseTable(() -> peekKeyword(KEYWORDS_IN_UPDATE_FROM));
scope(table);
UpdateSetFirstStep<?> s1 = (with == null ? dsl.update(table) : with.update(table));
List<Table<?>> from = parseKeywordIf("FROM") ? parseList(',', t -> parseTable(() -> peekKeyword(KEYWORDS_IN_UPDATE_FROM))) : null;
parseKeyword("SET");
UpdateFromStep<?> s2;
if (peek('(')) {
Row row = parseRow();
parse('=');
// TODO Can we extract a public API for this?
if (peekSelectOrWith(true))
((UpdateImpl<?>) s1).getDelegate().addValues0(row, parseWithOrSelect(row.size()));
else
((UpdateImpl<?>) s1).getDelegate().addValues0(row, parseRow(row.size()));
s2 = (UpdateFromStep<?>) s1;
} else {
Map<Field<?>, Object> map = parseSetClauseList();
s2 = s1.set(map);
}
UpdateWhereStep<?> s3 = from != null ? s2.from(from) : parseKeywordIf("FROM") ? s2.from(parseList(',', t -> parseTable(() -> peekKeyword(KEYWORDS_IN_UPDATE_FROM)))) : s2;
UpdateOrderByStep<?> s4 = parseKeywordIf("ALL") ? s3 : parseKeywordIf("WHERE") ? s3.where(parseCondition()) : s3;
UpdateLimitStep<?> s5 = parseKeywordIf("ORDER BY") ? s4.orderBy(parseList(',', c -> c.parseSortField())) : s4;
UpdateReturningStep<?> s6 = (limit != null || parseKeywordIf("LIMIT")) ? s5.limit(limit != null ? limit : (Field) parseField()) : s5;
return (parseResultQuery ? parseKeyword("RETURNING") : parseKeywordIf("RETURNING")) ? s6.returning(parseSelectList()) : s6;
}
use of org.jooq.Update in project jOOQ by jOOQ.
the class DefaultParseContext method parseInsert.
private final Query parseInsert(WithImpl with, boolean parseResultQuery) {
scopeStart();
parseKeyword("INSERT", "INS");
parseKeywordIf("INTO");
Table<?> table = parseTableNameIf();
if (table == null)
table = table(parseSelect());
Name alias;
if (parseKeywordIf("AS"))
table = table.as(parseIdentifier());
else if (!peekKeyword("DEFAULT VALUES", "SEL", "SELECT", "SET", "VALUES") && (alias = parseIdentifierIf()) != null)
table = table.as(alias);
scope(table);
InsertSetStep<?> s1 = (with == null ? dsl.insertInto(table) : with.insertInto(table));
Field<?>[] fields = null;
if (!peekSelectOrWith(true) && parseIf('(') && !parseIf(')')) {
fields = parseList(',', c -> parseField()).toArray(EMPTY_FIELD);
parse(')');
}
InsertOnDuplicateStep<?> onDuplicate;
InsertReturningStep<?> returning;
try {
// [#11821] The Teradata INSERT INTO t (1, 2) syntax can be recognised:
// When there are non-references fields
boolean hasExpressions = anyMatch(fields, f -> !(f instanceof TableField));
if (hasExpressions || parseKeywordIf("VALUES")) {
List<List<Field<?>>> allValues = new ArrayList<>();
if (hasExpressions) {
allValues.add(asList(fields));
fields = null;
}
valuesLoop: do {
if (hasExpressions && !parseIf(','))
break valuesLoop;
parse('(');
// [#6936] MySQL treats an empty VALUES() clause as the same thing as the standard DEFAULT VALUES
if (fields == null && parseIf(')'))
break valuesLoop;
List<Field<?>> values = parseList(',', c -> c.parseKeywordIf("DEFAULT") ? default_() : c.parseField());
if (fields != null && fields.length != values.size())
throw exception("Insert field size (" + fields.length + ") must match values size (" + values.size() + ")");
allValues.add(values);
parse(')');
} while (parseIf(','));
InsertValuesStepN<?> step2 = (fields != null) ? s1.columns(fields) : (InsertValuesStepN<?>) s1;
for (List<Field<?>> values : allValues) step2 = step2.values(values);
returning = onDuplicate = step2;
} else if (parseKeywordIf("SET")) {
Map<Field<?>, Object> map = parseSetClauseList();
returning = onDuplicate = s1.set(map);
} else if (peekSelectOrWith(true)) {
// [#10954] These are moved into the INSERT .. SELECT clause handling. They should not be necessary here
// either, but it seems we currently don't correctly implement nesting scopes?
scopeEnd(null);
scopeStart();
Select<?> select = parseWithOrSelect();
returning = onDuplicate = (fields == null) ? s1.select(select) : s1.columns(fields).select(select);
} else if (parseKeywordIf("DEFAULT VALUES")) {
if (fields != null)
throw notImplemented("DEFAULT VALUES without INSERT field list");
else
returning = onDuplicate = s1.defaultValues();
} else
throw expected("DEFAULT VALUES", "WITH", "SELECT", "SET", "VALUES");
if (parseKeywordIf("ON")) {
if (parseKeywordIf("DUPLICATE KEY UPDATE")) {
parseKeywordIf("SET");
InsertOnConflictWhereStep<?> where = onDuplicate.onDuplicateKeyUpdate().set(parseSetClauseList());
if (parseKeywordIf("WHERE"))
returning = where.where(parseCondition());
else
returning = where;
} else if (parseKeywordIf("DUPLICATE KEY IGNORE")) {
returning = onDuplicate.onDuplicateKeyIgnore();
} else if (parseKeywordIf("CONFLICT")) {
InsertOnConflictDoUpdateStep<?> doUpdate;
if (parseKeywordIf("ON CONSTRAINT")) {
doUpdate = onDuplicate.onConflictOnConstraint(parseName());
} else if (parseIf('(')) {
InsertOnConflictWhereIndexPredicateStep<?> where = onDuplicate.onConflict(parseList(',', c -> parseFieldName()));
parse(')');
doUpdate = parseKeywordIf("WHERE") ? where.where(parseCondition()) : where;
} else {
doUpdate = onDuplicate.onConflict();
}
parseKeyword("DO");
if (parseKeywordIf("NOTHING")) {
returning = doUpdate.doNothing();
} else if (parseKeywordIf("UPDATE SET")) {
InsertOnConflictWhereStep<?> where = doUpdate.doUpdate().set(parseSetClauseList());
if (parseKeywordIf("WHERE"))
returning = where.where(parseCondition());
else
returning = where;
} else
throw expected("NOTHING", "UPDATE");
} else
throw expected("CONFLICT", "DUPLICATE");
}
return (parseResultQuery ? parseKeyword("RETURNING") : parseKeywordIf("RETURNING")) ? returning.returning(parseSelectList()) : returning;
} finally {
scopeEnd(((InsertImpl) s1).getDelegate());
}
}
use of org.jooq.Update in project jOOQ by jOOQ.
the class DefaultParseContext method parseTableFactor.
private final Table<?> parseTableFactor(BooleanSupplier forbiddenKeywords) {
// [#7982] Postpone turning Select into a Table in case there is an alias
TableLike<?> result;
// TODO ONLY ( table primary )
if (parseFunctionNameIf("OLD TABLE")) {
parse('(');
Query query = parseQuery(false, false);
parse(')');
if (query instanceof Merge)
result = oldTable((Merge<?>) query);
else if (query instanceof Update)
result = oldTable((Update<?>) query);
else if (query instanceof Delete)
result = oldTable((Delete<?>) query);
else
throw expected("UPDATE", "DELETE", "MERGE");
} else if (parseFunctionNameIf("NEW TABLE")) {
parse('(');
Query query = parseQuery(false, false);
parse(')');
if (query instanceof Merge)
result = newTable((Merge<?>) query);
else if (query instanceof Insert)
result = newTable((Insert<?>) query);
else if (query instanceof Update)
result = newTable((Update<?>) query);
else
throw expected("INSERT", "UPDATE", "MERGE");
} else if (parseFunctionNameIf("FINAL TABLE")) {
parse('(');
Query query = parseQuery(false, false);
parse(')');
if (query instanceof Merge)
result = finalTable((Merge<?>) query);
else if (query instanceof Insert)
result = finalTable((Insert<?>) query);
else if (query instanceof Update)
result = finalTable((Update<?>) query);
else
throw expected("INSERT", "UPDATE", "MERGE");
} else if (parseFunctionNameIf("UNNEST", "TABLE")) {
parse('(');
if (parseFunctionNameIf("GENERATOR")) {
parse('(');
Field<?> tl = parseFunctionArgumentIf("TIMELIMIT");
Field<?> rc = parseFunctionArgumentIf("ROWCOUNT");
if (tl == null)
tl = parseFunctionArgumentIf("TIMELIMIT");
parse(')');
result = generateSeries(one(), (Field<Integer>) rc);
} else {
Field<?> f = parseField();
// Work around a missing feature in unnest()
if (!f.getType().isArray())
f = f.coerce(f.getDataType().getArrayDataType());
result = unnest(f);
}
parse(')');
} else if (parseFunctionNameIf("GENERATE_SERIES", "SYSTEM_RANGE")) {
parse('(');
Field from = toField(parseConcat());
parse(',');
Field to = toField(parseConcat());
Field step = parseIf(',') ? toField(parseConcat()) : null;
parse(')');
result = step == null ? generateSeries(from, to) : generateSeries(from, to, step);
} else if (parseFunctionNameIf("JSON_TABLE")) {
parse('(');
Field json = parseField();
parse(',');
Field path = toField(parseConcat());
JSONTableColumnsStep s1 = (JSONTableColumnsStep) jsonTable(json, path);
parseKeyword("COLUMNS");
parse('(');
do {
Name fieldName = parseIdentifier();
if (parseKeywordIf("FOR ORDINALITY")) {
s1 = s1.column(fieldName).forOrdinality();
} else {
JSONTableColumnPathStep s2 = s1.column(fieldName, parseDataType());
s1 = parseKeywordIf("PATH") ? s2.path(parseStringLiteral()) : s2;
}
} while (parseIf(','));
parse(')');
parse(')');
result = s1;
} else if (peekFunctionNameIf("VALUES")) {
result = parseTableValueConstructor();
} else if (parseFunctionNameIf("XMLTABLE")) {
parse('(');
XMLTablePassingStep s1 = xmltable((Field) toField(parseConcat()));
XMLPassingMechanism m = parseXMLPassingMechanismIf();
Field<XML> passing = m == null ? null : (Field<XML>) parseField();
XMLTableColumnsStep s2 = (XMLTableColumnsStep) (m == BY_REF ? s1.passingByRef(passing) : m == BY_VALUE ? s1.passingByValue(passing) : m == XMLPassingMechanism.DEFAULT ? s1.passing(passing) : s1);
parseKeyword("COLUMNS");
do {
Name fieldName = parseIdentifier();
if (parseKeywordIf("FOR ORDINALITY")) {
s2 = s2.column(fieldName).forOrdinality();
} else {
XMLTableColumnPathStep s3 = s2.column(fieldName, parseDataType());
s2 = parseKeywordIf("PATH") ? s3.path(parseStringLiteral()) : s3;
}
} while (parseIf(','));
parse(')');
result = s2;
} else if (parseIf('(')) {
// - A combination of the above: E.g. ((a join (select 1) on p) right join (((select 1)) union (select 2)) on q)
if (peekKeyword("SELECT", "SEL", "WITH")) {
SelectQueryImpl<Record> select = parseWithOrSelect();
parse(')');
result = parseQueryExpressionBody(null, null, select);
} else if (peekKeyword("VALUES")) {
result = parseTableValueConstructor();
parse(')');
} else {
result = parseJoinedTable(forbiddenKeywords);
parse(')');
}
} else {
result = parseTableName();
// TODO Sample clause
}
if (!ignoreProEdition() && parseKeywordIf("VERSIONS BETWEEN") && requireProEdition()) {
} else if (!ignoreProEdition() && peekKeyword("FOR") && !peekKeyword("FOR JSON") && !peekKeyword("FOR KEY SHARE") && !peekKeyword("FOR NO KEY UPDATE") && !peekKeyword("FOR SHARE") && !peekKeyword("FOR UPDATE") && !peekKeyword("FOR XML") && parseKeyword("FOR") && requireProEdition()) {
} else if (!ignoreProEdition() && parseKeywordIf("AS OF") && requireProEdition()) {
}
if (!ignoreProEdition() && parseKeywordIf("PIVOT") && requireProEdition()) {
}
// TODO UNPIVOT
result = parseCorrelationNameIf(result, forbiddenKeywords);
int p = position();
if (parseKeywordIf("WITH")) {
if (!ignoreProEdition() && parseIf('(') && requireProEdition()) {
} else
// [#10164] Without parens, WITH is part of the next statement in delimiter free statement batches
position(p);
}
return t(result);
}
Aggregations