Skip to content

Commit

Permalink
Support where clauses in CREATE INDEX statements. Fixes #964
Browse files Browse the repository at this point in the history
  • Loading branch information
mpscholten committed Aug 6, 2021
1 parent 3cba14b commit 32f1fef
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 4 deletions.
2 changes: 1 addition & 1 deletion IHP/IDE/SchemaDesigner/Compiler.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ compileStatement CreateEnumType { name, values } = "CREATE TYPE " <> compileIden
compileStatement CreateExtension { name, ifNotExists } = "CREATE EXTENSION " <> (if ifNotExists then "IF NOT EXISTS " else "") <> "\"" <> compileIdentifier name <> "\";"
compileStatement AddConstraint { tableName, constraintName, constraint } = "ALTER TABLE " <> compileIdentifier tableName <> " ADD CONSTRAINT " <> compileIdentifier constraintName <> " " <> compileConstraint constraint <> ";"
compileStatement Comment { content } = "-- " <> content
compileStatement CreateIndex { indexName, unique, tableName, expressions } = "CREATE" <> (if unique then " UNIQUE " else " ") <> "INDEX " <> indexName <> " ON " <> tableName <> " (" <> (intercalate ", " (map compileExpression expressions)) <> ");"
compileStatement CreateIndex { indexName, unique, tableName, expressions, whereClause } = "CREATE" <> (if unique then " UNIQUE " else " ") <> "INDEX " <> indexName <> " ON " <> tableName <> " (" <> (intercalate ", " (map compileExpression expressions)) <> ")" <> (case whereClause of Just expression -> " WHERE " <> compileExpression expression; Nothing -> "") <> ";"
compileStatement CreateFunction { functionName, functionBody, orReplace } = "CREATE " <> (if orReplace then "OR REPLACE " else "") <> "FUNCTION " <> functionName <> "() RETURNS TRIGGER AS $$" <> functionBody <> "$$ language plpgsql;"
compileStatement UnknownStatement { raw } = raw <> ";"

Expand Down
5 changes: 4 additions & 1 deletion IHP/IDE/SchemaDesigner/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -428,8 +428,11 @@ createIndex = do
lexeme "ON"
tableName <- identifier
expressions <- between (char '(' >> space) (char ')' >> space) (expression `sepBy1` (char ',' >> space))
whereClause <- optional do
lexeme "WHERE"
expression
char ';'
pure CreateIndex { indexName, unique, tableName, expressions }
pure CreateIndex { indexName, unique, tableName, expressions, whereClause }

createFunction = do
lexeme "CREATE"
Expand Down
2 changes: 1 addition & 1 deletion IHP/IDE/SchemaDesigner/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ data Statement
| Comment { content :: Text }
-- | CREATE INDEX indexName ON tableName (columnName); CREATE INDEX indexName ON tableName (LOWER(columnName));
-- | CREATE UNIQUE INDEX name ON table (column [, ...]);
| CreateIndex { indexName :: Text, unique :: Bool, tableName :: Text, expressions :: [Expression] }
| CreateIndex { indexName :: Text, unique :: Bool, tableName :: Text, expressions :: [Expression], whereClause :: Maybe Expression }
-- | CREATE OR REPLACE FUNCTION functionName() RETURNS TRIGGER AS $$functionBody$$ language plpgsql;
| CreateFunction { functionName :: Text, functionBody :: Text, orReplace :: Bool }
deriving (Eq, Show)
Expand Down
20 changes: 19 additions & 1 deletion Test/IDE/SchemaDesigner/CompilerSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ tests = do
, unique = False
, tableName = "users"
, expressions = [VarExpression "user_name"]
, whereClause = Nothing
}
compileSql [statement] `shouldBe` sql

Expand All @@ -405,6 +406,7 @@ tests = do
, unique = False
, tableName = "users"
, expressions = [VarExpression "user_name", VarExpression "project_id"]
, whereClause = Nothing
}
compileSql [statement] `shouldBe` sql

Expand All @@ -415,6 +417,7 @@ tests = do
, unique = False
, tableName = "users"
, expressions = [CallExpression "LOWER" [VarExpression "email"]]
, whereClause = Nothing
}
compileSql [statement] `shouldBe` sql

Expand All @@ -425,6 +428,7 @@ tests = do
, unique = True
, tableName = "users"
, expressions = [VarExpression "user_name"]
, whereClause = Nothing
}
compileSql [statement] `shouldBe` sql

Expand Down Expand Up @@ -458,4 +462,18 @@ tests = do
it "should compile a decimal default value with a type-cast" do
let sql = "CREATE TABLE a (\n electricity_unit_price DOUBLE PRECISION DEFAULT 0.17::DOUBLE PRECISION NOT NULL\n);\n"
let statement = StatementCreateTable CreateTable { name = "a", columns = [Column {name = "electricity_unit_price", columnType = PDouble, defaultValue = Just (TypeCastExpression (DoubleExpression 0.17) PDouble), notNull = True, isUnique = False}], primaryKeyConstraint = PrimaryKeyConstraint [], constraints = [] }
compileSql [statement] `shouldBe` sql
compileSql [statement] `shouldBe` sql

it "should compile a partial index" do
let sql = cs [plain|CREATE UNIQUE INDEX unique_source_id ON listings (source, source_id) WHERE source IS NOT NULL AND source_id IS NOT NULL;\n|]
let index = CreateIndex
{ indexName = "unique_source_id"
, unique = True
, tableName = "listings"
, expressions = [ VarExpression "source", VarExpression "source_id" ]
, whereClause = Just (
AndExpression
(IsExpression (VarExpression "source") (NotExpression (VarExpression "NULL")))
(IsExpression (VarExpression "source_id") (NotExpression (VarExpression "NULL"))))
}
compileSql [index] `shouldBe` sql
16 changes: 16 additions & 0 deletions Test/IDE/SchemaDesigner/ParserSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -412,27 +412,31 @@ tests = do
, unique = False
, tableName = "users"
, expressions = [VarExpression "user_name"]
, whereClause = Nothing
}
it "should parse a CREATE INDEX statement with multiple columns" do
parseSql "CREATE INDEX users_index ON users (user_name, project_id);\n" `shouldBe` CreateIndex
{ indexName = "users_index"
, unique = False
, tableName = "users"
, expressions = [VarExpression "user_name", VarExpression "project_id"]
, whereClause = Nothing
}
it "should parse a CREATE INDEX statement with a LOWER call" do
parseSql "CREATE INDEX users_email_index ON users (LOWER(email));\n" `shouldBe` CreateIndex
{ indexName = "users_email_index"
, unique = False
, tableName = "users"
, expressions = [CallExpression "LOWER" [VarExpression "email"]]
, whereClause = Nothing
}
it "should parse a CREATE UNIQUE INDEX statement" do
parseSql "CREATE UNIQUE INDEX users_index ON users (user_name);\n" `shouldBe` CreateIndex
{ indexName = "users_index"
, unique = True
, tableName = "users"
, expressions = [VarExpression "user_name"]
, whereClause = Nothing
}

it "should parse a CREATE OR REPLACE FUNCTION ..() RETURNS TRIGGER .." do
Expand Down Expand Up @@ -465,6 +469,18 @@ tests = do
]
parseSqlStatements sql `shouldBe` statements

it "should parse a partial index" do
parseSql "CREATE UNIQUE INDEX unique_source_id ON listings (source, source_id) WHERE source IS NOT NULL AND source_id IS NOT NULL;" `shouldBe` CreateIndex
{ indexName = "unique_source_id"
, unique = True
, tableName = "listings"
, expressions = [ VarExpression "source", VarExpression "source_id" ]
, whereClause = Just (
AndExpression
(IsExpression (VarExpression "source") (NotExpression (VarExpression "NULL")))
(IsExpression (VarExpression "source_id") (NotExpression (VarExpression "NULL"))))
}


col :: Column
col = Column
Expand Down

0 comments on commit 32f1fef

Please sign in to comment.