Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide escape hatch for sql.fragment and similar entities #285

Open
gajus opened this issue Dec 1, 2024 · 2 comments
Open

Provide escape hatch for sql.fragment and similar entities #285

gajus opened this issue Dec 1, 2024 · 2 comments

Comments

@gajus
Copy link
Contributor

gajus commented Dec 1, 2024

Slonik has a concept of SQL fragments (https://github.com/gajus/slonik?tab=readme-ov-file#sqlfragment)

There are effectively fragments of query that would not have a type, e.g.

const whereFragment = sql.fragment`
  WHERE bar = 'baz';
`;

sql.typeAlias('id')`
  SELECT id
  FROM foo
  ${whereFragment}
`

Supporting this requires the ability to exclude fragment from type matching (or even the whole query).

safeql.configs.connections({
  overrides: {
    types: {
      array: 'ListSqlToken',
      date: 'DateSqlToken',
      json: 'JsonSqlToken',
      jsonb: 'JsonBinarySqlToken',
      timestamp: 'TimestampSqlToken',
+      // obvious not, but this appears to be not used anywhere, and I still need to provide a valid type
+      timestamptz: 'SqlFragmentToken',
      uuid: '`${string}-${string}-${string}-${string}-${string}`',
    },
  },

I've tried working around this by assigning a random type, but this causes queries to fail, e.g.

Invalid Query: column "location" is of type geometry but expression is of type timestamp with time zone

Note that there might be multiple that need an escape hatch.

@karlhorky
Copy link
Collaborator

karlhorky commented Dec 1, 2024

@gajus yeah, would be nice to get support for fragments and similar. There is a feature in Postgres.js called "interpolation" or "sql() helpers" and there's an issue from @Eprince-hub over here:

Do you think this issue is similar enough that it can supersede your issue 285 here? (maybe with the additional input / API suggestion from your issue above added as a new comment in 101?)

@Newbie012
Copy link
Collaborator

Hi @gajus! It might not be the answer you were looking for, but perhaps it will help to shed some light:

When I initially released SafeQL, I thought it would be enough to solve library-specific issues with generic solutions to keep it library-agnostic. However, as I started to receive more feedback, I realized that some libraries, such as Slonik, Drizzle, Postgres.js (and others), required more complex customization (such as fragments) that I couldn't address with a generic solution. Additionally, there were other core issues, such as the constraint to use ESLint, and so on.

At its current stage, SafeQL isn't as pluggable and customizable as I would like it to be. I'm currently working on a new rewrite that aims to address these issues by splitting the core into multiple presets and utilities that can be easily customized and extended as custom presets

It should look something like this:

// safeql.config.ts

import { defineConfig } from "@ts-safeql/safeql";
import { sqlTagPreset } from "@ts-safeql/presets/sql-tag";
import { slonikPreset } from "@ts-safeql/presets/slonik";

export default defineConfig({
  // ...
  presets: [
    sqlTagPreset({
      tagNames: ["sql"],
      files: "src/**/*.ts",
      // ... other options
    }),
    slonikPreset({
      // ... Slonik specific options
    }),
  ],
})

And each preset will handle its own custom logic.

I can't promise a release date as I'm working on this project in my free time. However, I already have a working POC (with minimal features and type inference compared to SafeQL) which I might release as a separate package in the future to gather some initial feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants