提交 7500ae66 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Forbid FOR UPDATE in DISTINCT and grouped queries

上级 fc0670d5
......@@ -175,6 +175,7 @@
90142=Step size must not be zero
90143=Row {1} not found in primary index {0}
90144=Authenticator not enabled on database {0}
90145=FOR UPDATE is not allowed in DISTINCT or grouped select
HY000=General error: {0}
HY004=Unknown data type: {0}
HYC00=Feature not supported: {0}
......
......@@ -2030,8 +2030,20 @@ public class ErrorCode {
*/
public static final int AUTHENTICATOR_NOT_AVAILABLE = 90144;
/**
* The error with code <code>90145</code> is thrown when trying to execute a
* SELECT statement with non-window aggregates, DISTINCT, GROUP BY, or
* HAVING clauses together with FOR UPDATE clause.
*
* <pre>
* SELECT DISTINCT NAME FOR UPDATE;
* SELECT MAX(VALUE) FOR UPDATE;
* </pre>
*/
public static final int FOR_UPDATE_IS_NOT_ALLOWED_IN_DISTICT_OR_GROUPED_SELECT = 90145;
// next is 90145
// next is 90146
private ErrorCode() {
// utility class
......
......@@ -442,10 +442,14 @@ public class Select extends Query {
int rowNumber = 0;
setCurrentRowNumber(0);
int sampleSize = getSampleSizeValue(session);
ArrayList<Row> forUpdateRows = this.isForUpdateMvcc ? Utils.<Row>newSmallArrayList() : null;
while (topTableFilter.next()) {
setCurrentRowNumber(rowNumber + 1);
if (isConditionMet()) {
rowNumber++;
if (forUpdateRows != null) {
topTableFilter.lockRowAdd(forUpdateRows);
}
groupData.nextSource();
updateAgg(columnCount, stage);
if (sampleSize > 0 && rowNumber >= sampleSize) {
......@@ -453,6 +457,9 @@ public class Select extends Query {
}
}
}
if (forUpdateRows != null) {
topTableFilter.lockRows(forUpdateRows);
}
groupData.done();
}
......@@ -764,16 +771,7 @@ public class Select extends Query {
topTableFilter.reset();
boolean exclusive = isForUpdate && !isForUpdateMvcc;
if (isForUpdateMvcc) {
if (isGroupQuery) {
throw DbException.getUnsupportedException(
"MVCC=TRUE && FOR UPDATE && GROUP");
} else if (isAnyDistinct()) {
throw DbException.getUnsupportedException(
"MVCC=TRUE && FOR UPDATE && DISTINCT");
} else if (isQuickAggregateQuery) {
throw DbException.getUnsupportedException(
"MVCC=TRUE && FOR UPDATE && AGGREGATE");
} else if (topTableFilter.getJoin() != null) {
if (topTableFilter.getJoin() != null) {
throw DbException.getUnsupportedException(
"MVCC=TRUE && FOR UPDATE && JOIN");
}
......@@ -1451,6 +1449,9 @@ public class Select extends Query {
@Override
public void setForUpdate(boolean b) {
if (b && (isAnyDistinct() || isGroupQuery)) {
throw DbException.get(ErrorCode.FOR_UPDATE_IS_NOT_ALLOWED_IN_DISTICT_OR_GROUPED_SELECT);
}
this.isForUpdate = b;
if (session.getDatabase().getSettings().selectForUpdateMvcc &&
session.getDatabase().isMVStore()) {
......
......@@ -566,6 +566,7 @@ public class DbException extends RuntimeException {
case CAN_ONLY_ASSIGN_TO_VARIABLE_1:
case PUBLIC_STATIC_JAVA_METHOD_NOT_FOUND_1:
case JAVA_OBJECT_SERIALIZER_CHANGE_WITH_DATA_TABLE:
case FOR_UPDATE_IS_NOT_ALLOWED_IN_DISTICT_OR_GROUPED_SELECT:
return new JdbcSQLSyntaxErrorException(message, sql, state, errorCode, cause, stackTrace);
case HEX_STRING_ODD_1:
case HEX_STRING_WRONG_1:
......
......@@ -175,6 +175,7 @@
90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
90145=#FOR UPDATE is not allowed in DISTINCT or grouped select
HY000=Obecná chyba: {0}
HY004=Neznámý datový typ: {0}
HYC00=Vlastnost není podporována: {0}
......
......@@ -175,6 +175,7 @@
90142=Schrittgrösse darf nicht 0 sein
90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
90145=#FOR UPDATE is not allowed in DISTINCT or grouped select
HY000=Allgemeiner Fehler: {0}
HY004=Unbekannter Datentyp: {0}
HYC00=Dieses Feature wird nicht unterstützt: {0}
......
......@@ -175,6 +175,7 @@
90142=Step size must not be zero
90143=Row {1} not found in primary index {0}
90144=Authenticator not enabled on database {0}
90145=FOR UPDATE is not allowed in DISTINCT or grouped select
HY000=General error: {0}
HY004=Unknown data type: {0}
HYC00=Feature not supported: {0}
......
......@@ -175,6 +175,7 @@
90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
90145=#FOR UPDATE is not allowed in DISTINCT or grouped select
HY000=Error General : {0}
HY004=Tipo de dato desconocido : {0}
HYC00=Caracteristica no soportada: {0}
......
......@@ -175,6 +175,7 @@
90142=La taille de l''étape ne doit pas être de 0
90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
90145=#FOR UPDATE is not allowed in DISTINCT or grouped select
HY000=Erreur générale: {0}
HY004=Type de données inconnu: {0}
HYC00=Fonctionnalité non supportée: {0}
......
......@@ -175,6 +175,7 @@
90142=ステップサイズに0は指定できません
90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
90145=#FOR UPDATE is not allowed in DISTINCT or grouped select
HY000=一般エラー: {0}
HY004=不明なデータ型: {0}
HYC00=機能はサポートされていません: {0}
......
......@@ -175,6 +175,7 @@
90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
90145=#FOR UPDATE is not allowed in DISTINCT or grouped select
HY000=Błąd ogólny: {0}
HY004=Nieznany typ danych: {0}
HYC00=Cecha nie jest wspierana: {0}
......
......@@ -175,6 +175,7 @@
90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
90145=#FOR UPDATE is not allowed in DISTINCT or grouped select
HY000=Erro geral: {0}
HY004=Tipo de dados desconhecido: {0}
HYC00=Recurso não suportado: {0}
......
......@@ -175,6 +175,7 @@
90142=Размер шага не должен быть равен нулю
90143=Строка {1} не найдена в первичном индексе {0}
90144=Внешняя аутентификация не включена в базе данных {0}
90145=FOR UPDATE не допускается в запросе с DISTINCT или запросе с группировкой
HY000=Внутренняя ошибка: {0}
HY004=Неизвестный тип данных: {0}
HYC00=Данная функция не поддерживается: {0}
......
......@@ -175,6 +175,7 @@
90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
90145=#FOR UPDATE is not allowed in DISTINCT or grouped select
HY000=Všeobecná chyba: {0}
HY004=Neznámy dátový typ: {0}
HYC00=Vlastnosť nie je podporovaná: {0}
......
......@@ -175,6 +175,7 @@
90142=#Step size must not be zero
90143=#Row {1} not found in primary index {0}
90144=#Authenticator not enabled on database {0}
90145=#FOR UPDATE is not allowed in DISTINCT or grouped select
HY000=常规错误: {0}
HY004=位置数据类型: {0}
HYC00=不支持的特性: {0}
......
......@@ -407,3 +407,35 @@ SELECT * EXCEPT (T1.A, T2.D) FROM TEST1 T1, TEST2 T2;
DROP TABLE TEST1, TEST2;
> ok
CREATE TABLE TEST(ID INT PRIMARY KEY, VALUE INT NOT NULL);
> ok
INSERT INTO TEST VALUES (1, 1), (2, 1), (3, 2);
> update count: 3
SELECT ID, VALUE FROM TEST FOR UPDATE;
> ID VALUE
> -- -----
> 1 1
> 2 1
> 3 2
> rows: 3
SELECT DISTINCT VALUE FROM TEST FOR UPDATE;
> exception FOR_UPDATE_IS_NOT_ALLOWED_IN_DISTICT_OR_GROUPED_SELECT
SELECT DISTINCT ON(VALUE) ID, VALUE FROM TEST FOR UPDATE;
> exception FOR_UPDATE_IS_NOT_ALLOWED_IN_DISTICT_OR_GROUPED_SELECT
SELECT SUM(VALUE) FROM TEST FOR UPDATE;
> exception FOR_UPDATE_IS_NOT_ALLOWED_IN_DISTICT_OR_GROUPED_SELECT
SELECT ID FROM TEST GROUP BY VALUE FOR UPDATE;
> exception FOR_UPDATE_IS_NOT_ALLOWED_IN_DISTICT_OR_GROUPED_SELECT
SELECT 1 FROM TEST HAVING TRUE FOR UPDATE;
> exception FOR_UPDATE_IS_NOT_ALLOWED_IN_DISTICT_OR_GROUPED_SELECT
DROP TABLE TEST;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论