diff --git a/Test/SchemaCompilerSpec.hs b/Test/SchemaCompilerSpec.hs index b89b2f137..02c4d7ff5 100644 --- a/Test/SchemaCompilerSpec.hs +++ b/Test/SchemaCompilerSpec.hs @@ -471,6 +471,31 @@ tests = do builder |> QueryBuilder.filterWhere (#id, id) {-# INLINE filterWhereId #-} |] + it "should not use DEFAULT for array columns" do + let statement = StatementCreateTable CreateTable + { name = "users" + , columns = + [ Column "id" PUUID Nothing True True Nothing + , Column {name = "keywords", columnType = PArray PText, defaultValue = Just (VarExpression "NULL"), notNull = False, isUnique = False, generator = Nothing} + ] + , primaryKeyConstraint = PrimaryKeyConstraint ["id"] + , constraints = [] + , unlogged = False + } + let compileOutput = compileStatementPreview [statement] statement |> Text.strip + + getInstanceDecl "CanCreate" compileOutput `shouldBe` [trimming| + instance CanCreate User where + create :: (?modelContext :: ModelContext) => User -> IO User + create model = do + sqlQuerySingleRow "INSERT INTO users (id, keywords) VALUES (?, ? :: TEXT[]) RETURNING id, keywords" ((model.id, model.keywords)) + createMany [] = pure [] + createMany models = do + sqlQuery (Query $ "INSERT INTO users (id, keywords) VALUES " <> (ByteString.intercalate ", " (List.map (\_ -> "(?, ? :: TEXT[])") models)) <> " RETURNING id, keywords") (List.concat $ List.map (\model -> [toField (model.id), toField (model.keywords)]) models) + createRecordDiscardResult :: (?modelContext :: ModelContext) => User -> IO () + createRecordDiscardResult model = do + sqlExecDiscardResult "INSERT INTO users (id, keywords) VALUES (?, ? :: TEXT[])" ((model.id, model.keywords)) + |] describe "compileStatementPreview for table with arbitrarily named primary key" do let statements = parseSqlStatements [trimming| CREATE TABLE things ( diff --git a/ihp-ide/IHP/SchemaCompiler.hs b/ihp-ide/IHP/SchemaCompiler.hs index 260a13fe9..31237b3c8 100644 --- a/ihp-ide/IHP/SchemaCompiler.hs +++ b/ihp-ide/IHP/SchemaCompiler.hs @@ -551,9 +551,18 @@ compileCreate table@(CreateTable { name, columns }) = values = commaSep (map columnPlaceholder writableColumns) toBinding column@(Column { name }) = - if hasExplicitOrImplicitDefault column - then "fieldWithDefault #" <> columnNameToFieldName name <> " model" - else "model." <> columnNameToFieldName name + if hasExplicitOrImplicitDefault column && not isArrayColumn + then "fieldWithDefault #" <> columnNameToFieldName name <> " model" + else "model." <> columnNameToFieldName name + where + -- We cannot use DEFAULT with array columns as postgres will throw an error: + -- + -- > DEFAULT is not allowed in this context + -- + -- To walk around this error, we explicitly specify an empty array. + isArrayColumn = case column.columnType of + PArray _ -> True + _ -> False bindings :: [Text]