{"version":3,"file":"sql-expression.mjs","names":[],"sources":["../../src/internal/sql-expression.ts"],"sourcesContent":["import type * as SqlClient from \"effect/sql/SqlClient\";\nimport * as Statement from \"effect/sql/Statement\";\n\nimport { PersistenceMappingError } from \"./mapping-error\";\nimport { Column, identifier, Table } from \"./sql-table\";\n\n/** Pure mapped SQL. Compilation binds values through the executing client's\n * dialect; expressions neither acquire a client nor execute a query. */\nexport class SqlExpression {\n  constructor(readonly compile: (client: SqlClient.SqlClient) => Statement.Fragment) {}\n}\n\nconst quoted = (client: SqlClient.SqlClient, name: string) => {\n  if (name.includes(\"\\0\"))\n    // oxlint-disable-next-line effect/no-untyped-throw -- SQL expression compilation must synchronously return a Fragment; workflow adapters capture mapping failures.\n    throw PersistenceMappingError.make({ operation: \"mapping\", cause: \"NUL in SQL identifier\" });\n\n  return client.literal(identifier(name));\n};\n\nconst tableName = (client: SqlClient.SqlClient, name: string, schema?: string) =>\n  schema === undefined\n    ? quoted(client, name)\n    : client`${quoted(client, schema)}.${quoted(client, name)}`;\n\nconst value = (client: SqlClient.SqlClient, input: unknown): Statement.Fragment => {\n  if (Statement.isFragment(input)) return input;\n  if (input instanceof SqlExpression) return input.compile(client);\n  if (input instanceof Table) return tableName(client, input.name, input.schema);\n  if (input instanceof Column)\n    return client`${tableName(client, input.tableName, input.schema)}.${quoted(client, input.options.name)}`;\n\n  return Statement.fragment([\n    Statement.parameter(\n      typeof input === \"boolean\"\n        ? client.onDialectOrElse({ sqlite: () => Number(input), orElse: () => input })\n        : input,\n    ),\n  ]);\n};\n\n/** Reject foreign expression handles at the metadata boundary. */\nexport const compileSqlExpression = (\n  client: SqlClient.SqlClient,\n  expression: unknown,\n): Statement.Fragment => {\n  if (\n    !Statement.isFragment(expression) &&\n    !(expression instanceof SqlExpression) &&\n    !(expression instanceof Table) &&\n    !(expression instanceof Column)\n  )\n    // oxlint-disable-next-line effect/no-untyped-throw -- SQL expression compilation must synchronously return a Fragment; workflow adapters capture mapping failures.\n    throw PersistenceMappingError.make({\n      operation: \"mapping\",\n      cause: \"Expected a SQL expression\",\n    });\n\n  return value(client, expression);\n};\n\nconst template = (parts: TemplateStringsArray, ...values: ReadonlyArray<unknown>) =>\n  new SqlExpression((client) =>\n    client.join(\n      \"\",\n      false,\n    )(\n      parts.flatMap((part, index) =>\n        index === 0\n          ? [client.literal(part)]\n          : [value(client, values[index - 1]), client.literal(part)],\n      ),\n    ),\n  );\n\nexport const sql = Object.assign(template, {\n  join: (values: ReadonlyArray<unknown>, separator: SqlExpression = template``) =>\n    new SqlExpression((client) =>\n      client.join(\n        \"\",\n        false,\n      )(\n        values.flatMap((input, index) =>\n          index === 0 ? [value(client, input)] : [separator.compile(client), value(client, input)],\n        ),\n      ),\n    ),\n});\n\nexport const eq = (left: unknown, right: unknown): SqlExpression => sql`${left} = ${right}`;\n\nexport const and = (...expressions: ReadonlyArray<SqlExpression | undefined>) => {\n  const present = expressions.filter((expression) => expression !== undefined);\n\n  return present.length === 0 ? undefined : sql`(${sql.join(present, sql` AND `)})`;\n};\n"],"mappings":";;;;;;AAQA,IAAa,gBAAb,MAA2B;CACJ;CAArB,YAAY,SAAuE;EAA9D,KAAA,UAAA;CAA+D;AACtF;AAEA,MAAM,UAAU,QAA6B,SAAiB;CAC5D,IAAI,KAAK,SAAS,IAAI,GAEpB,MAAM,wBAAwB,KAAK;EAAE,WAAW;EAAW,OAAO;CAAwB,CAAC;CAE7F,OAAO,OAAO,QAAQ,WAAW,IAAI,CAAC;AACxC;AAEA,MAAM,aAAa,QAA6B,MAAc,WAC5D,WAAW,KAAA,IACP,OAAO,QAAQ,IAAI,IACnB,MAAM,GAAG,OAAO,QAAQ,MAAM,EAAE,GAAG,OAAO,QAAQ,IAAI;AAE5D,MAAM,SAAS,QAA6B,UAAuC;CACjF,IAAI,UAAU,WAAW,KAAK,GAAG,OAAO;CACxC,IAAI,iBAAiB,eAAe,OAAO,MAAM,QAAQ,MAAM;CAC/D,IAAI,iBAAiB,OAAO,OAAO,UAAU,QAAQ,MAAM,MAAM,MAAM,MAAM;CAC7E,IAAI,iBAAiB,QACnB,OAAO,MAAM,GAAG,UAAU,QAAQ,MAAM,WAAW,MAAM,MAAM,EAAE,GAAG,OAAO,QAAQ,MAAM,QAAQ,IAAI;CAEvG,OAAO,UAAU,SAAS,CACxB,UAAU,UACR,OAAO,UAAU,YACb,OAAO,gBAAgB;EAAE,cAAc,OAAO,KAAK;EAAG,cAAc;CAAM,CAAC,IAC3E,KACN,CACF,CAAC;AACH;;AAGA,MAAa,wBACX,QACA,eACuB;CACvB,IACE,CAAC,UAAU,WAAW,UAAU,KAChC,EAAE,sBAAsB,kBACxB,EAAE,sBAAsB,UACxB,EAAE,sBAAsB,SAGxB,MAAM,wBAAwB,KAAK;EACjC,WAAW;EACX,OAAO;CACT,CAAC;CAEH,OAAO,MAAM,QAAQ,UAAU;AACjC;AAEA,MAAM,YAAY,OAA6B,GAAG,WAChD,IAAI,eAAe,WACjB,OAAO,KACL,IACA,KACF,CAAC,CACC,MAAM,SAAS,MAAM,UACnB,UAAU,IACN,CAAC,OAAO,QAAQ,IAAI,CAAC,IACrB,CAAC,MAAM,QAAQ,OAAO,QAAQ,EAAE,GAAG,OAAO,QAAQ,IAAI,CAAC,CAC7D,CACF,CACF;AAEF,MAAa,MAAM,OAAO,OAAO,UAAU,EACzC,OAAO,QAAgC,YAA2B,QAAQ,OACxE,IAAI,eAAe,WACjB,OAAO,KACL,IACA,KACF,CAAC,CACC,OAAO,SAAS,OAAO,UACrB,UAAU,IAAI,CAAC,MAAM,QAAQ,KAAK,CAAC,IAAI,CAAC,UAAU,QAAQ,MAAM,GAAG,MAAM,QAAQ,KAAK,CAAC,CACzF,CACF,CACF,EACJ,CAAC;AAED,MAAa,MAAM,MAAe,UAAkC,GAAG,GAAG,KAAK,KAAK;AAEpF,MAAa,OAAO,GAAG,gBAA0D;CAC/E,MAAM,UAAU,YAAY,QAAQ,eAAe,eAAe,KAAA,CAAS;CAE3E,OAAO,QAAQ,WAAW,IAAI,KAAA,IAAY,GAAG,IAAI,IAAI,KAAK,SAAS,GAAG,OAAO,EAAE;AACjF"}