circuithub / rel8

Hey! Hey! Can u rel8?
https://rel8.readthedocs.io
Other
154 stars 39 forks source link

Rel8 generates poorly-typed sql #192

Closed isovector closed 2 years ago

isovector commented 2 years ago

Given the following definitions:

newtype EdgeId = EdgeId
  { unEdgeId :: Int64
  }
  deriving newtype (Eq, Ord, Show, DBType, DBEq, DBOrd)

newtype DocId = DocId
  { unDocId :: Int64
  }
  deriving newtype (Eq, Ord, Show, DBType, DBEq, DBOrd)

data Discovery f = Discovery
  { d_docId :: Column f DocId
  , d_uri   :: Column f Text
  }
  deriving stock Generic
  deriving anyclass Rel8able

data Edges f = Edges
  { e_edgeId :: Column f EdgeId
  , e_src :: Column f DocId
  , e_dst :: Column f DocId
  }
  deriving stock Generic
  deriving anyclass Rel8able

the following Query (Discovery Expr):

do
  e <- do
    e <- each edgesSchema
    d <- each discoverySchema
    where_ $ e_src e ==. d_docId d &&. like (lit $ "%" <> t <> "%") (d_uri d)
    pure e
  d <- each discoverySchema
  where_ $ e_dst e ==. d_docId d
  pure d

produces the following sql:

SELECT
CAST("doc_id0_7" AS int8) as "d_docId",
CAST("uri1_7" AS text) as "d_uri"
FROM (SELECT
      *
      FROM (SELECT
            "id" as "id0_1",
            "src" as "src1_1",
            "dst" as "dst2_1"
            FROM "public"."edges" as "T1") as "T1",
           LATERAL
           (SELECT
            "doc_id" as "doc_id0_3",
            "uri" as "uri1_3"
            FROM "public"."discovery" as "T1") as "T2",
           LATERAL
           (SELECT
            "doc_id" as "doc_id0_7",
            "uri" as "uri1_7"
            FROM "public"."discovery" as "T1") as "T3"
      WHERE (("dst2_1") = ("doc_id0_7")) AND ((("src1_1") = ("doc_id0_3")) AND (CAST(("uri1_3") LIKE (CAST(E'%marginalrevolution.com%' AS text)) AS bool)))) as "T1"

which fails to run:

ERROR:  operator does not exist: text = bigint
LINE 21:       WHERE (("dst2_1") = ("doc_id0_7")) AND ((("src1_1") = ...
                                 ^
HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.
isovector commented 2 years ago

for what it's worth, the following sql succeeds:

SELECT
CAST("doc_id0_7" AS int8) as "d_docId",
CAST("uri1_7" AS text) as "d_uri"
FROM (SELECT
      *
      FROM (SELECT
            "id" as "id0_1",
            CAST("src" AS int8) as "src1_1",
            CAST("dst" AS int8) as "dst2_1"
            FROM "public"."edges" as "T1") as "T1",
           LATERAL
           (SELECT
            "doc_id" as "doc_id0_3",
            "uri" as "uri1_3"
            FROM "public"."discovery" as "T1") as "T2",
           LATERAL
           (SELECT
            "doc_id" as "doc_id0_7",
            "uri" as "uri1_7"
            FROM "public"."discovery" as "T1") as "T3"
      WHERE (("dst2_1") = ("doc_id0_7")) AND ((("src1_1") = ("doc_id0_3")) AND (CAST(("uri1_3") LIKE (CAST(E'%marginalrevolution.com%' AS text)) AS bool)))) as "T1"

with explicit type casts for src1_1 and dst2_1.

tomjaguarpaw commented 2 years ago

What is the type of the src column of "public"."edges" in your schema? The error message operator does not exist: text = bigint makes me think that it's a text. If so then your definition of e_src :: Column f DocId seems to be at odds with the schema.

isovector commented 2 years ago

Right you are; sorry about that!

ocharles commented 2 years ago

Thanks for helping there, @tomjaguarpaw!