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

[BUG]: Return type of timestamp with mode "string" using vercel-postgres is Date and not string #2058

Closed
kimdanielarthur-cowlabs opened this issue Mar 23, 2024 · 3 comments
Labels
bug Something isn't working duplicate This issue or pull request already exists

Comments

@kimdanielarthur-cowlabs
Copy link

kimdanielarthur-cowlabs commented Mar 23, 2024

What version of drizzle-orm are you using?

0.30.4

What version of drizzle-kit are you using?

0.20.14

Describe the Bug

with the column mode set to string on timestamp typescript infers string, but runtime returns Date at runtime
dueAt: timestamp("dueAt", {mode: "string"}).notNull(),

Intialising drizzle with drizzle from drizzle-orm/vercel-postgres

import {sql} from "@vercel/postgres";
import {drizzle as drizzleVercel} from "drizzle-orm/vercel-postgres";
drizzleVercel(sql, {schema})

I saw there was a mention in 0.30.0 that there was a fix to ensure that it returns string type, however it does not seem to apply to vercel-postgres or neon-serverless?

If i check drizzle-orm/pg-core/colums/timestamp.tsthere is no override for mapFromDriverValue on PgTimestampString should there be some kind of transformation happening here, or have i misunderstood the mode: "string"config?

If i modify drizzle-orm/pg-core/colums/timestamp.js in node_modules with mapFromDriverValue implementation as a test it will, naturally, return string in format as expected.

class PgTimestampString extends PgColumn {
    static [entityKind] = "PgTimestampString";
    withTimezone;
    precision;
    constructor(table, config) {
        super(table, config);
        this.withTimezone = config.withTimezone;
        this.precision = config.precision;
    }

    mapFromDriverValue = (value) => {
//not handling precision
        if (typeof value !== "string") {
            const f = (i) => (i < 10 ? `0${i}` : `${i}`);
            const y = `${value.getFullYear()}`;
            const m = f(value.getMonth() + 1);
            const d = f(value.getDate());
            const h = f(value.getHours());
            const mi = f(value.getMinutes());
            const s = f(value.getSeconds());
            return `${y}-${m}-${d} ${h}:${mi}:${s}`;
        }
        return value;
    };

    getSQLType() {
        const precision = this.precision === void 0 ? "" : `(${this.precision})`;
        return `timestamp${precision}${this.withTimezone ? " with time zone" : ""}`;
    }
}

After some more investigation:

  • If i switch to use a neon database and connect initialise drizzle through drizzle-orm/neon-serverlessthe return type is string as expected
  • if i connect to the same database using drizzle-orm/vercel-postgres the return type is Date
  • if i connect to my vercel database using the neon driver, it returns string as expected

Could it be related to these lines that setTypeParser are commented out in the vercel-postgres driver?

initMappers() {
		// types.setTypeParser(types.builtins.TIMESTAMPTZ, (val) => val);
		// types.setTypeParser(types.builtins.TIMESTAMP, (val) => val);
		// types.setTypeParser(types.builtins.DATE, (val) => val);
	}

If i try to enable setting of the type parsers in vercel-postgres/driver.js they have no affect.

However if i edit the VercelPool constructor in create-pool.ts of @vercel/postgres and add the setting of type parser directly there it works and string type is returned as expected:

// src/create-pool.ts
var VercelPool = class extends Pool {
    constructor(config) {
        var _a;
        super(config);
        this.Client = VercelClient;
        this.connectionString = (_a = config.connectionString) != null ? _a : "";
        types.setTypeParser(types.builtins.TIMESTAMPTZ, (val) => val);
        types.setTypeParser(types.builtins.TIMESTAMP, (val) => val);
        types.setTypeParser(types.builtins.DATE, (val) => val);
    }

I'll see if i can find a way to set those type parsers externally through the exported objects somehow.

A "workaround" is to just use drizzle-orm/neon-serverlessto connect to the vercel database which it seems to do underlying anyway.

Expected behavior

expect timestamp with mode:"string" to return string type at runtime

Environment & setup

"@vercel/postgres": "0.7.2",
"@neondatabase/serverless": "^0.9.0",
Vercel postgres database select version(): "PostgreSQL 16.2 on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit"

@kimdanielarthur-cowlabs kimdanielarthur-cowlabs added the bug Something isn't working label Mar 23, 2024
@kimdanielarthur-cowlabs kimdanielarthur-cowlabs changed the title [BUG]: Return type of timestamp with mode "string" using vercel-postgres or neon-serverless is Date and not string [BUG]: Return type of timestamp with mode "string" using vercel-postgres is Date and not string Mar 23, 2024
@realmikesolo
Copy link
Collaborator

Hello, @kimdanielarthur-cowlabs! This bug should be fixed in drizzle-orm@0.30.7

https://github.com/drizzle-team/drizzle-orm/releases/tag/0.30.7

Could you confirm it with your case and then we will close the issue

@kimdanielarthur-cowlabs
Copy link
Author

Nice one!

We have switched to use neon databases directly rather than vercel, for other reasons, and with that using the neon driver to connect. So won1t be able to test as easily. I'll see if I can get a test project set up

@realmikesolo
Copy link
Collaborator

I tested it in my repo and it works, so I close the issue. The bug was fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

2 participants