Skip to content

Commit 0b23813

Browse files
authored
bugfixes of ALTER USER in YQL parser (#15420)
1 parent f14b341 commit 0b23813

File tree

7 files changed

+322
-63
lines changed

7 files changed

+322
-63
lines changed

yql/essentials/sql/v1/SQLv1.g.in

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -845,8 +845,9 @@ role_name: an_id_or_type | bind_parameter;
845845
user_option: authentication_option | login_option;
846846

847847
authentication_option: password_option | hash_option;
848-
password_option: ENCRYPTED? PASSWORD expr;
849-
hash_option: HASH expr;
848+
password_option: ENCRYPTED? PASSWORD password_value;
849+
password_value: STRING_VALUE | NULL;
850+
hash_option: HASH STRING_VALUE;
850851
login_option: LOGIN | NOLOGIN;
851852

852853
grant_permissions_stmt: GRANT permission_name_target ON an_id_schema (COMMA an_id_schema)* TO role_name (COMMA role_name)* COMMA? (WITH GRANT OPTION)?;

yql/essentials/sql/v1/SQLv1Antlr4.g.in

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -844,8 +844,9 @@ role_name: an_id_or_type | bind_parameter;
844844
user_option: authentication_option | login_option;
845845

846846
authentication_option: password_option | hash_option;
847-
password_option: ENCRYPTED? PASSWORD expr;
848-
hash_option: HASH expr;
847+
password_option: ENCRYPTED? PASSWORD password_value;
848+
password_value: STRING_VALUE | NULL;
849+
hash_option: HASH STRING_VALUE;
849850
login_option: LOGIN | NOLOGIN;
850851

851852
grant_permissions_stmt: GRANT permission_name_target ON an_id_schema (COMMA an_id_schema)* TO role_name (COMMA role_name)* COMMA? (WITH GRANT OPTION)?;

yql/essentials/sql/v1/node.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,7 @@ namespace NSQLTranslationV1 {
13241324

13251325
struct TUserParameters : TRoleParameters {
13261326
TMaybe<TDeferredAtom> Password;
1327+
bool IsPasswordNull = false;
13271328
bool IsPasswordEncrypted = false;
13281329
std::optional<bool> CanLogin;
13291330
TMaybe<TDeferredAtom> Hash;

yql/essentials/sql/v1/query.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2021,7 +2021,7 @@ class TControlUser final : public TAstListNode {
20212021
options = L(options, Q(Y(Q("password"), password)));
20222022
} else if (Params->Hash) {
20232023
options = L(options, Q(Y(Q("hash"), hash)));
2024-
} else {
2024+
} else if (Params->IsPasswordNull) {
20252025
options = L(options, Q(Y(Q("nullPassword"))));
20262026
}
20272027

yql/essentials/sql/v1/sql_translation.cpp

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3820,35 +3820,44 @@ bool TSqlTranslation::RoleNameClause(const TRule_role_name& node, TDeferredAtom&
38203820
}
38213821

38223822
bool TSqlTranslation::PasswordParameter(const TRule_password_option& passwordOption, TUserParameters& result) {
3823-
// password_option: ENCRYPTED? PASSWORD expr;
3824-
TSqlExpression expr(Ctx, Mode);
3825-
TNodePtr password = expr.Build(passwordOption.GetRule_expr3());
3826-
if (!password) {
3827-
Error() << "Couldn't parse the password";
3828-
return false;
3823+
// password_option: ENCRYPTED? PASSWORD password_value;
3824+
// password_value: STRING_VALUE | NULL;
3825+
3826+
const auto& token = passwordOption.GetRule_password_value3().GetToken1();
3827+
TString stringValue(Ctx.Token(token));
3828+
3829+
if (to_lower(stringValue) == "null") {
3830+
result.IsPasswordNull = true;
3831+
} else {
3832+
auto password = StringContent(Ctx, Ctx.Pos(), stringValue);
3833+
3834+
if (!password) {
3835+
Error() << "Password should be enclosed into quotation marks.";
3836+
return false;
3837+
}
3838+
3839+
result.Password = TDeferredAtom(Ctx.Pos(), std::move(password->Content));
38293840
}
38303841

38313842
result.IsPasswordEncrypted = passwordOption.HasBlock1();
3832-
if (!password->IsNull()) {
3833-
result.Password = MakeAtomFromExpression(Ctx.Pos(), Ctx, password);
3834-
}
38353843

38363844
return true;
38373845
}
38383846

38393847
bool TSqlTranslation::HashParameter(const TRule_hash_option& hashOption, TUserParameters& result) {
3840-
// hash_option: HASH expr;
3841-
TSqlExpression expr(Ctx, Mode);
3842-
TNodePtr hash = expr.Build(hashOption.GetRule_expr2());
3848+
// hash_option: HASH STRING_VALUE;
3849+
3850+
const auto& token = hashOption.GetToken2();
3851+
TString stringValue(Ctx.Token(token));
3852+
3853+
auto hash = StringContent(Ctx, Ctx.Pos(), stringValue);
38433854

38443855
if (!hash) {
3845-
Error() << "Couldn't parse the hash of password";
3856+
Error() << "Hash should be enclosed into quotation marks.";
38463857
return false;
38473858
}
38483859

3849-
if (!hash->IsNull()) {
3850-
result.Hash = MakeAtomFromExpression(Ctx.Pos(), Ctx, hash);
3851-
}
3860+
result.Hash = TDeferredAtom(Ctx.Pos(), std::move(hash->Content));
38523861

38533862
return true;
38543863
}
@@ -3935,6 +3944,7 @@ bool TSqlTranslation::UserParameters(const std::vector<TRule_user_option>& optio
39353944
};
39363945

39373946
if (isCreateUser) {
3947+
result.IsPasswordNull = true;
39383948
result.CanLogin = true;
39393949
}
39403950

yql/essentials/sql/v1/sql_ut.cpp

Lines changed: 144 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5051,34 +5051,114 @@ select FormatType($f());
50515051
}
50525052

50535053
Y_UNIT_TEST(CreateAlterUserWithLoginNoLogin) {
5054-
auto reqCreateUser = SqlToYql(R"(
5055-
USE plato;
5056-
CREATE USER user1;
5057-
)");
5054+
{
5055+
auto reqCreateUser = SqlToYql(R"(
5056+
USE plato;
5057+
CREATE USER user1;
5058+
)");
50585059

5059-
UNIT_ASSERT(reqCreateUser.IsOk());
5060+
UNIT_ASSERT(reqCreateUser.IsOk());
50605061

5061-
auto reqAlterUser = SqlToYql(R"(
5062-
USE plato;
5063-
ALTER USER user1;
5064-
)");
5062+
TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
5063+
Y_UNUSED(word);
5064+
UNIT_ASSERT(line.find("nullPassword") != TString::npos);
5065+
};
50655066

5066-
UNIT_ASSERT(!reqAlterUser.IsOk());
5067-
UNIT_ASSERT_STRING_CONTAINS(reqAlterUser.Issues.ToString(), "Error: Unexpected token ';' : cannot match to any predicted input...");
5067+
TWordCountHive elementStat = {{TString("createUser"), 0}};
5068+
VerifyProgram(reqCreateUser, elementStat, verifyLine);
50685069

5069-
auto reqPasswordAndLogin = SqlToYql(R"(
5070-
USE plato;
5071-
CREATE USER user1 PASSWORD '123' LOGIN;
5072-
)");
5070+
UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 1);
5071+
}
50735072

5074-
UNIT_ASSERT(reqPasswordAndLogin.IsOk());
5073+
{
5074+
auto reqAlterUser = SqlToYql(R"(
5075+
USE plato;
5076+
ALTER USER user1;
5077+
)");
50755078

5076-
auto reqPasswordAndNoLogin = SqlToYql(R"(
5077-
USE plato;
5078-
CREATE USER user1 PASSWORD '123' NOLOGIN;
5079-
)");
5079+
UNIT_ASSERT(!reqAlterUser.IsOk());
5080+
UNIT_ASSERT_STRING_CONTAINS(reqAlterUser.Issues.ToString(), "Error: Unexpected token ';' : cannot match to any predicted input...");
5081+
}
5082+
5083+
{
5084+
auto reqCreateUserLogin = SqlToYql(R"(
5085+
USE plato;
5086+
CREATE USER user1 LOgin;
5087+
)");
5088+
5089+
UNIT_ASSERT(reqCreateUserLogin.IsOk());
5090+
5091+
TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
5092+
if (word == "createUser") {
5093+
UNIT_ASSERT(line.find("nullPassword") != TString::npos);
5094+
}
5095+
};
5096+
5097+
TWordCountHive elementStat = {{TString("alterUser"), 0}, {TString("createUser"), 0}};
5098+
VerifyProgram(reqCreateUserLogin, elementStat, verifyLine);
5099+
5100+
UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 1);
5101+
UNIT_ASSERT_VALUES_EQUAL(elementStat["alterUser"], 0);
5102+
}
5103+
5104+
{
5105+
auto reqAlterUserLogin = SqlToYql(R"(
5106+
USE plato;
5107+
ALTER USER user1 LOgin;
5108+
)");
5109+
5110+
UNIT_ASSERT(reqAlterUserLogin.IsOk());
5111+
5112+
TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
5113+
if (word == "alterUser") {
5114+
UNIT_ASSERT(line.find("nullPassword") == TString::npos);
5115+
}
5116+
};
5117+
5118+
TWordCountHive elementStat = {{TString("alterUser"), 0}, {TString("createUser"), 0}};
5119+
VerifyProgram(reqAlterUserLogin, elementStat, verifyLine);
5120+
5121+
UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 0);
5122+
UNIT_ASSERT_VALUES_EQUAL(elementStat["alterUser"], 1);
5123+
}
5124+
5125+
{
5126+
auto reqPasswordAndNoLogin = SqlToYql(R"(
5127+
USE plato;
5128+
CREATE USER user1 PASSWORD '123' NOLOGIN;
5129+
)");
5130+
5131+
UNIT_ASSERT(reqPasswordAndNoLogin.IsOk());
5132+
5133+
TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
5134+
Y_UNUSED(word);
5135+
UNIT_ASSERT(line.find("nullPassword") == TString::npos);
5136+
};
5137+
5138+
TWordCountHive elementStat = {{TString("createUser"), 0}};
5139+
VerifyProgram(reqPasswordAndNoLogin, elementStat, verifyLine);
5140+
5141+
UNIT_ASSERT_VALUES_EQUAL(elementStat["createUser"], 1);
5142+
}
5143+
5144+
{
5145+
auto reqAlterUserNullPassword = SqlToYql(R"(
5146+
USE plato;
5147+
ALTER USER user1 PASSWORD NULL;
5148+
)");
5149+
5150+
UNIT_ASSERT(reqAlterUserNullPassword.IsOk());
5151+
5152+
TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
5153+
Y_UNUSED(word);
5154+
UNIT_ASSERT(line.find("nullPassword") != TString::npos);
5155+
};
5156+
5157+
TWordCountHive elementStat = {{TString("alterUser"), 0}};
5158+
VerifyProgram(reqAlterUserNullPassword, elementStat, verifyLine);
50805159

5081-
UNIT_ASSERT(reqPasswordAndNoLogin.IsOk());
5160+
UNIT_ASSERT_VALUES_EQUAL(elementStat["alterUser"], 1);
5161+
}
50825162

50835163
auto reqLogin = SqlToYql(R"(
50845164
USE plato;
@@ -5169,6 +5249,49 @@ select FormatType($f());
51695249
UNIT_ASSERT(reqAlterUser.IsOk());
51705250
}
51715251

5252+
Y_UNIT_TEST(CreateUserQoutas) {
5253+
{
5254+
auto req = SqlToYql(R"(
5255+
use plato;
5256+
CREATE USER user1 PASSWORD passwd;
5257+
)");
5258+
5259+
TString error = "<main>:3:43: Error: Unexpected token 'passwd' : unexpected input : nothing is expected here\n\n";
5260+
UNIT_ASSERT_VALUES_EQUAL(Err2Str(req), error);
5261+
UNIT_ASSERT(!req.Root);
5262+
}
5263+
5264+
{
5265+
auto req = SqlToYql(R"(
5266+
use plato;
5267+
CREATE USER user2 PASSWORD NULL;
5268+
)");
5269+
5270+
UNIT_ASSERT(req.Root);
5271+
}
5272+
5273+
{
5274+
auto req = SqlToYql(R"(
5275+
use plato;
5276+
CREATE USER user3 PASSWORD '';
5277+
)");
5278+
5279+
UNIT_ASSERT(req.Root);
5280+
}
5281+
5282+
5283+
{
5284+
auto req = SqlToYql(R"(
5285+
use plato;
5286+
CREATE USER user1 PASSWORD 'password1';
5287+
CREATE USER user2 PASSWORD 'password2';
5288+
CREATE USER user3;
5289+
)");
5290+
5291+
UNIT_ASSERT(req.Root);
5292+
}
5293+
}
5294+
51725295
Y_UNIT_TEST(CreateAlterUserWithoutCluster) {
51735296
ExpectFailWithError("\n CREATE USER user ENCRYPTED PASSWORD 'foobar';", "<main>:2:2: Error: USE statement is missing - no default cluster is selected\n");
51745297
ExpectFailWithError("ALTER USER CURRENT_USER RENAME TO $foo;", "<main>:1:1: Error: USE statement is missing - no default cluster is selected\n");

0 commit comments

Comments
 (0)