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

[FEATURE]: Add encoding to sql operator #3529

Open
1 task done
imhoffd opened this issue Nov 12, 2024 · 0 comments
Open
1 task done

[FEATURE]: Add encoding to sql operator #3529

imhoffd opened this issue Nov 12, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@imhoffd
Copy link

imhoffd commented Nov 12, 2024

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

The sql operator's mapWith method lets us specify mappers for decoding from the database, but there are use cases where we need to encode. See the example below.

  1. Add a decimalType custom type
import { Decimal } from 'decimal.js'
import { type CustomTypeParams, customType } from 'drizzle-orm/pg-core'

const decimalTypeParams: CustomTypeParams<{
  data: Decimal
  driverData: string | number
}> = {
  dataType() {
    return 'numeric(64, 32)'
  },

  toDriver(data) {
    return data.toString()
  },

  fromDriver(data): Decimal {
    return new Decimal(data)
  },
}

export const decimalType = customType(decimalTypeParams)
  1. Query a column that uses it
// Example A: works great
eq(myTable.myDecimalCol, new Decimal("0"))

// Example B: driver error: invalid input syntax for type numeric: ""0""
eq(sql`abs(${myTable.myDecimalCol})`, new Decimal("0"))

// Example C: works, but not ideal imo
eq(sql`abs(${myTable.myDecimalCol})`, new Decimal("0").toString())

The issue in example B appears to be that it's not using the custom type's toDriver function, which is reasonable. However, there's no way to make it use it.

This would be useful in functions that apply a SQL operator to a column value, but don't change its resultant type, e.g. it would be very useful to be able to write a function like this where the column's mapFromDriverValue and mapToDriverValue are applied:

import {
  type AnyColumn,
  type GetColumnData,
  type SQL,
  type SQLWrapper,
  Column,
  is,
  sql,
} from 'drizzle-orm'

export const abs: {
  <T>(column: SQL.Aliased<T>): SQL<T>
  <TColumn extends AnyColumn>(
    column: TColumn,
  ): SQL<GetColumnData<TColumn, 'raw'>>
  <T extends SQLWrapper>(column: Exclude<T, SQL.Aliased | Column>): SQL
} = (column: SQL.Aliased): SQL => {
  return sql`abs(${column})`.mapWith(
    is(column, Column) ? column : (v: unknown) => v,
  )
}

LMK if I'm missing something! Thanks!

@imhoffd imhoffd added the enhancement New feature or request label Nov 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant