sqlc-dev / sqlc-gen-typescript

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support mapping BIGINT to string in MySQL

yshrsmz opened this issue · comments

Currently sqlc-gen-typescript maps MySQL's BIGINT type to number type, but the max value of number type is far smaller than that of BIGINT.

node-mysql2 supports big numbers by converting it to string, so sqlc should also support mapping bigint to string.

https://github.com/mysqljs/mysql#connection-options

Here's a related quote from the doc

supportBigNumbers: When dealing with big numbers (BIGINT and DECIMAL columns) in the database, you should enable this option (Default: false).
bigNumberStrings: Enabling both supportBigNumbers and bigNumberStrings forces big numbers (BIGINT and DECIMAL columns) to be always returned as JavaScript String objects (Default: false). Enabling supportBigNumbers but leaving bigNumberStrings disabled will return big numbers as String objects only when they cannot be accurately represented with [JavaScript Number objects] (https://tc39.es/ecma262/#sec-ecmascript-language-types-number-type) (which happens when they exceed the [-2^53, +2^53] range), otherwise they will be returned as Number objects. This option is ignored if supportBigNumbers is disabled.

I think we can simply navigate users to enable those two options to use BIGING support.

It looks like the PostgreSQL counterpart is already treated as a string.

@kyleconroy Any idea on how we handle this case?
I can send a PR to make this happen.

The default types map to the default return values for the mysql2 library. mysql2 returns floats for bigints by default, which I think is the wrong choice. Instead, we should allow users to configure this (and a few other options) based on what you can pass to createPool.

- schema: "authors/mysql/schema.sql"
  queries: "authors/mysql/query.sql"
  engine: "mysql"
  codegen:
  - plugin: ts
    out: node-mysql2/src/db
    options:
      runtime: node
      driver: mysql2
      mysql2:
        big_number_strings: true
        date_strings: true

Do you have time to update #16 with that functionality?

@kyleconroy sure, will do that.

But I have a few questions

Should we support enabling supportBigNumbers and bigNumberStrings independently? This makes things a bit harder.

I think it's yes. I'm going to conditionally change bigint return type to number, number | string or string.

IMO we should update columnType() method to conditionally change bitint return type, but how?

To achieve this(and more configurable feature in the future) we need to pass options to columnType(), but currently it does not accept options parameter.

Change method signature to columnType(c?: Column, options: Options)

And updates everywhere. this can be a hussle.

Change drivers/mysql2.ts's default export to a "driver factory".

This is a combination of the first one.
To minimize the impact, create a driver factory method.

export default function createMysql2Driver(options: Mysql2Options): Driver {
  return {
    columnType: (c?: Column) => columnType(c, options),
    preamble,
    execDecl,
    manyDecl,
    oneDecl,
  }
}

This way, what we need is updating mysql2-related code for now.

or any other?

Should we support enabling supportBigNumbers and bigNumberStrings independently? This makes things a bit harder.

That's a good point. I think it's a good idea since we can generate the correct type signature.

Change columnType?

Yeah, I really don't want to have to change that signature. We should probably move away from drivers as modules and instead have them as classes. I'll do that once #13 is merged so that we don't create too much churn.

We should probably move away from drivers as modules and instead have them as classes.

That sounds good to me.
I'm going to wait for that change, then.

Okay, the refactor is done. The classes don't have constructors yet.