diff --git a/sbroad-cartridge/test_app/test/integration/acl_test.lua b/sbroad-cartridge/test_app/test/integration/acl_test.lua
index d88e37bf84674ecf18b1efa481a404efa0a8b03d..ddb295919bce358c2e89630dbdbe5518030626c5 100644
--- a/sbroad-cartridge/test_app/test/integration/acl_test.lua
+++ b/sbroad-cartridge/test_app/test/integration/acl_test.lua
@@ -22,7 +22,7 @@ g.test_drop_user = function()
 
     local _, err = api:call(
             "sbroad.execute",
-            { [[ DROP USER user ]], {} }
+            { [[ DROP USER user_name ]], {} }
     )
     t.assert_equals(
             string.format("%s", err),
diff --git a/sbroad-core/src/frontend/sql/ir/tests.rs b/sbroad-core/src/frontend/sql/ir/tests.rs
index 0a5f4c4f33801220d51c8a1ab07b68d739610c93..28d4d481c3a9f8553de6978d976c85e7081f2451 100644
--- a/sbroad-core/src/frontend/sql/ir/tests.rs
+++ b/sbroad-core/src/frontend/sql/ir/tests.rs
@@ -405,17 +405,16 @@ vtable_max_rows = 5000
     assert_eq!(expected_explain, plan.as_explain().unwrap());
 }
 
-// Check double angle quotation marks in the strings
 #[test]
-fn front_sql20() {
+fn front_sql_check_arbitrary_utf_in_single_quote_strings() {
     let input = r#"SELECT "identification_number" FROM "hash_testing"
-        WHERE "product_code" = '«123»'"#;
+        WHERE "product_code" = '«123»§#*&%@/// / // \\ ƵǖḘỺʥ ͑ ͑  ͕ΆΨѮښ ۞ܤ'"#;
 
     let plan = sql_to_optimized_ir(input, vec![]);
 
     let expected_explain = String::from(
         r#"projection ("hash_testing"."identification_number"::integer -> "identification_number")
-    selection ROW("hash_testing"."product_code"::string) = ROW('«123»'::string)
+    selection ROW("hash_testing"."product_code"::string) = ROW('«123»§#*&%@/// / // \\ ƵǖḘỺʥ ͑ ͑  ͕ΆΨѮښ ۞ܤ'::string)
         scan "hash_testing"
 execution options:
 sql_vdbe_max_steps = 45000
@@ -426,6 +425,26 @@ vtable_max_rows = 5000
     assert_eq!(expected_explain, plan.as_explain().unwrap());
 }
 
+#[test]
+fn front_sql_check_arbitraty_utf_in_identifiers() {
+    let input = r#"SELECT "id" "from", "id" as "select", "id"
+                               "123»*&%ښ۞@Ƶǖselect.""''\\"
+                                , "id" aц1&@$//Ƶǖ%^&*«»§*&%ښ۞@Ƶǖ FROM "test_space" *&%ښ۞@Ƶǖ"#;
+
+    let plan = sql_to_optimized_ir(input, vec![]);
+
+    let expected_explain = String::from(
+        r#"projection ("*&%ښ۞@ƵǕ"."id"::unsigned -> "from", "*&%ښ۞@ƵǕ"."id"::unsigned -> "select", "*&%ښ۞@ƵǕ"."id"::unsigned -> "123»*&%ښ۞@Ƶǖselect.""''\\", "*&%ښ۞@ƵǕ"."id"::unsigned -> "AЦ1&@$//ƵǕ%^&*«»§*&%ښ۞@ƵǕ")
+    scan "test_space" -> "*&%ښ۞@ƵǕ"
+execution options:
+sql_vdbe_max_steps = 45000
+vtable_max_rows = 5000
+"#,
+    );
+
+    assert_eq!(expected_explain, plan.as_explain().unwrap());
+}
+
 #[test]
 fn front_projection_with_scan_specification_under_scan() {
     let input = r#"SELECT "hash_testing".* FROM "hash_testing""#;
@@ -522,7 +541,7 @@ vtable_max_rows = 5000
 #[test]
 fn track_shard_col_pos() {
     let input = r#"
-    select "e", "bucket_id", "f" 
+    select "e", "bucket_id", "f"
     from "t2"
     where "e" + "f" = 3
     "#;
@@ -618,7 +637,7 @@ fn track_shard_col_pos() {
 fn front_sql_join_on_bucket_id1() {
     let input = r#"select * from "t2" join (
         select "bucket_id" from "test_space" where "id" = 1
-    ) as t_mv 
+    ) as t_mv
     on t_mv."bucket_id" = "t2"."bucket_id";
     "#;
 
@@ -647,7 +666,7 @@ vtable_max_rows = 5000
 fn front_sql_join_on_bucket_id2() {
     let input = r#"select * from "t2" join (
         select "bucket_id" from "test_space" where "id" = 1
-    ) as t_mv 
+    ) as t_mv
     on t_mv."bucket_id" = "t2"."bucket_id" or "t2"."e" = "t2"."f";
     "#;
 
@@ -676,7 +695,7 @@ vtable_max_rows = 5000
 #[test]
 fn front_sql_groupby_on_bucket_id() {
     let input = r#"
-    select b, count(*) from (select "bucket_id" as b from "t2") as t 
+    select b, count(*) from (select "bucket_id" as b from "t2") as t
     group by b
     "#;
 
@@ -700,7 +719,7 @@ vtable_max_rows = 5000
 #[test]
 fn front_sql_sq_on_bucket_id() {
     let input = r#"
-    select b, e from (select "bucket_id" as b, "e" as e from "t2") as t 
+    select b, e from (select "bucket_id" as b, "e" as e from "t2") as t
     where (b, e) in (select "bucket_id", "id" from "test_space")
     "#;
 
diff --git a/sbroad-core/src/frontend/sql/query.pest b/sbroad-core/src/frontend/sql/query.pest
index 2c6856bb0b5f3fc292d971b127781d2c785d6884..41745a956775f887d7ea34e55bbd5aaad6f84240 100644
--- a/sbroad-core/src/frontend/sql/query.pest
+++ b/sbroad-core/src/frontend/sql/query.pest
@@ -148,15 +148,33 @@ Query = { (SelectWithOptionalContinuation | Values | Insert | Update | Delete) ~
     Delete = { ^"delete" ~ ^"from" ~ ScanTable ~ (^"where" ~ DeleteFilter)? }
     	DeleteFilter = { Expr }
 
-// Note: it's atomic to silence inner rules.
-Identifier = @{ DoubleQuotedIdentifier | IdentifierInner  }
-    DoubleQuotedIdentifier = @{ ("\"" ~ IdentifierInner ~ "\"") }
-    IdentifierInner = @{ !(Keyword ~ ("(" | WHITESPACE | "," | EOF)) ~ (IdentifierNonDigit ~ (IdentifierNonDigit | ASCII_DIGIT)*) }
-        IdentifierNonDigit = _{ ('a'..'z' | 'A' .. 'Z' | 'А' .. 'Я' | 'а' .. 'я' | "-" | "_") }
-    Keyword = { ^"left" | ^"having" | ^"not" | ^"inner" | ^"group"
-                | ^"on" | ^"join" | ^"from" | ^"exists" | ^"except"
-                | ^"union" | ^"where" | ^"distinct" | ^"between" | ^"option"
-                | ^"values"}
+Identifier = @{ DelimitedIdentifier | RegularIdentifier  }
+    DelimitedIdentifier = @{ ("\"" ~ ((!("\"") ~ ANY) | "\"\"")* ~ "\"") }
+    RegularIdentifier = @{ !KeywordCoverage ~
+                            RegularIdentifierFirstApplicableSymbol ~
+                            RegularIdentifierApplicableSymbol* ~
+                            &IdentifierInapplicableSymbol }
+        RegularIdentifierFirstApplicableSymbol = { !(IdentifierInapplicableSymbol | ASCII_DIGIT) ~ ANY }
+        RegularIdentifierApplicableSymbol = { !IdentifierInapplicableSymbol ~ ANY }
+        IdentifierInapplicableSymbol = { WHITESPACE | "." | "," | "(" | EOF | ")" | "\"" }
+        KeywordCoverage = { Keyword ~ IdentifierInapplicableSymbol }
+            // Note: In case two keywords with the same prefix are met, shorter ones must go after longest.
+            //       E.g. ^"in" must go after ^"insert" because keywords traversal stops on the first match.
+            //       Please, try to keep the list in alphabetical order.
+            Keyword = {  ^"all" | ^"and" | ^"any" | ^"array" | ^"as"
+                        | ^"begin" | ^"between" | ^"boolean" | ^"bool"| ^"by"
+                        | ^"cast" | ^"char"
+                        | ^"decimal" | ^"distinct" | ^"double"
+                        | ^"end" | ^"except" | ^"exists"
+                        | ^"false" | ^"from" | ^"group"
+                        | ^"having" | ^"inner" | ^"integer" | ^"into" | ^"int" | ^"in" | ^"is"
+                        | ^"join" | ^"left" | ^"not" | ^"null" | ^"number"
+                        | ^"on" | ^"option" | ^"or" | ^"outer" | ^"primary"
+                        | ^"scalar" | ^"select" | ^"set" | ^"string"
+                        | ^"table" | ^"text" | ^"to" | ^"true"
+                        | ^"union" | ^"unsigned" | ^"using" | ^"uuid"
+                        | ^"values" | ^"varchar" | ^"where" | ^"with"
+                        }
 
 Expr = { ExprAtomValue ~ (ExprInfixOp ~ ExprAtomValue)* }
     ExprInfixOp = _{ Between | ArithInfixOp | CmpInfixOp | ConcatInfixOp | And | Or }
@@ -189,9 +207,7 @@ Expr = { ExprAtomValue ~ (ExprInfixOp ~ ExprAtomValue)* }
                 Double = @{ Integer ~ ("." ~ ASCII_DIGIT*)? ~ (^"e" ~ Integer) }
                 Integer = @{ ("+" | "-")? ~ ASCII_DIGIT+ }
                 Unsigned = @{ ASCII_DIGIT+ }
-                SingleQuotedString = @{ OnlyQuotesSequence | AnythingButQuotesSequence }
-                    OnlyQuotesSequence = @{ ("'" ~ "'")+ }
-                    AnythingButQuotesSequence = @{ "'" ~ (!("'") ~ ANY)* ~ "'" }
+                SingleQuotedString = @{ "'" ~ ((!("'") ~ ANY) | "''")* ~ "'" }
             Parameter = { PgParameter | TntParameter }
                 TntParameter = @{ "?" }
                 PgParameter = { "$" ~ Unsigned }