Skip to content

2.0.0-beta1 feedback #137

Description

@beverloo

Hi Juan!

2.0.0 looks great! I had a play around with the beta today and ran into three minor issues that I wanted to share. All were straightforward to work around. (commit)

To be clear, I'm not requesting any changes, I only wanted to provide some signal :)

buildFragmentWithArgs w/ noTableOrViewRequired

The buildFragmentWithArgs method on a connection no longer seems to allow argument-less fragments that don't require a table or view. Take the following example:

export class MyConnection extends MariaDBConnection<'DBConnection'> {
  currentZonedDateTime = this.buildFragmentWithArgs().as(() =>
    this.fragmentWithType<ZonedDateTime>('customLocalDateTime', 'ZonedDateTime', 'required')
        .sql`current_timestamp`);
}

This now triggers the following TypeScript error:

Type 'CustomLocalDateTimeValueSource<"mariaDB:MyConnection/noTableOrViewRequired/", ZonedDateTime, ZonedDateTime, "required">' is not assignable to type 'ValueSourceOf<"mariaDB:MyConnection/">'.
  Types of property '[source]' are incompatible.
    Type '"mariaDB:MyConnection/noTableOrViewRequired/"' is not assignable to type '"mariaDB:MyConnection/"'.ts(2322)

The following workaround seems to work well, but I still found it a bit surprising as the zero-argument variant of buildFragmentWithArgs exists, which is recommended for reusable fragments.

currentZonedDateTime = () =>
    this.fragmentWithType<ZonedDateTime>('customLocalDateTime', 'ZonedDateTime', 'required')
        .sql`current_timestamp`;

Nested projections can now be null

Take the following select:

const result = await db.selectFrom(tEvents)
    .where(tEvents.eventId.equals(100))
    .select({
        group: {
            column: tEvents.eventLocation,  // nullable column
        },
    })
    .executeSelectOne();

This evalutes to the following types:

  • 1.x: { group?: { column: string | undefined } | undefined }
  • 2.0: { group?: { column: string | undefined } | null | undefined }

I'm curious why null is significant, and how it differs from undefined?

I've tried a few things to try to trigger a null value, but without success. (group either has a value or is omitted altogether, so practically speaking the behaviour matches { group?: { column: string } } but that'd really complex to type.)

ExecutableInsert & friends not being exported anymore

Technically they're still in the "__UNSUPPORTED__" directory though :P

I used these to effectively compose a complicated transaction, the mutations in which have to be decided upon as part of a complicated diffing process with the following output:

interface Mutations {
    created: ExecutableInsert<typeof tEvents, any>[],
    updated: ExecutableUpdate<typeof tEvents, any>[],
    deleted: ExecutableUpdate<typeof tEvents, any>[],
}

I suppose that I was holding this wrong, and that the recommended approach would be to apply low-level transaction management here? I.e.

try {
    await db.beginTransaction();
    // Decide on and immediately execute all mutations
    await db.commit();
catch (error) {
    await db.rollback();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions