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

Forbid FOR UPDATE in DISTINCT and grouped queries

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