node.js - Hur lägger man till "FETCH FIRST n ROWS ONLY" med Kysely DB-frågebuilder?


Mitt favoritverktyg för databaser att använda med TypeScript-baserade projekt är Prisma. Dock använder ett av projekten Kysely, en typ-säker databasfrågebyggare.

Jag försöker förbereda en fråga som skulle hantera keyset-paginering med Kysely query builder, men jag kan inte lista ut hur man lägger till FETCH FIRST n ROWS ONLY i frågan om det ens är möjligt.

Kysely-dokumentation: https://kysely.dev/docs/category/select

Några idéer eller förslag?

import { Kysely, sql } from "kysely";

const DB = new Kysely<Database>({...});

const query = DB
  .selectFrom("cl")
  .selectAll()
  .where(sql`(created_at, id)`, '>', `('${keyFromCreatedAt}', '${keyFromId}')`)
  // ¿¿¿ Something to insert FETCH FIRST n ROWS ONLY? ???
  ;

const res = query.execute();

Svar #1

För det första kan du använda LIMIT-klausulen (SelectQueryBuilder.limit(n)) som ett alternativ för FETCH FIRST n ROWS ONLY, beroende på vilken dialekt du använder. Om du måste använda FETCH FIRST n ENDAST RADER bör du implementera din egen QueryCompiler.

Det tar inte mycket tid. Allt är redan implementerat i DefaultQueryCompiler. Allt du behöver göra är att utöka det och åsidosätta en enskild metod. Till exempel åsidosätter PostgresQueryCompiler en enskild metod från DefaultQueryCompiler.

export class PostgresQueryCompiler extends DefaultQueryCompiler {
  protected override sanitizeIdentifier(identifier: string): string {
    return identifier.replace(ID_WRAP_REGEX, '""')
  }
}

Definiera din anpassade QueryCompiler och åsidosätt visitLimit-metoden för att ändra beteendet hos limit().

class MyQueryCompiler extends PostgresQueryCompiler {
  protected visitLimit(node: LimitNode) {
    this.append("fetch next ")
    this.visitNode(node.limit);
    this.append(" rows only")
  }
}

Sedan utökar en Dialect-klass och överskriver createQueryCompiler()-metoden för att använda QueryCompiler.

class MyDialect extends PostgresDialect {
  createQueryCompiler(): QueryCompiler {
    return new MyQueryCompiler();
  }
}

Skicka det till Kysely-konstruktorn för att använda det.

const db = new Kysely<DB>({
  dialect:new MyDialect(...),
})

PostgresQueryCompiler och PostgresDialect är bara exempel. Du kan åsidosätta vilken dialekt du vill.

Fullständigt exempel:

import {
  Kysely, LimitNode,
  PostgresDialect, PostgresQueryCompiler,
  QueryCompiler
} from "kysely";

class MyQueryCompiler extends PostgresQueryCompiler {
  protected visitLimit(node: LimitNode) {
    this.append("fetch next ")
    this.visitNode(node.limit);
    this.append(" rows only")
  }
}

class MyDialect extends PostgresDialect {
  createQueryCompiler(): QueryCompiler {
    return new MyQueryCompiler();
  }
}

const db = new Kysely<any>({
  dialect: new MyDialect({} as any),
})

const {sql} = db.selectFrom("table").select(["a", "b"]).limit(10).offset(20).compile()
console.log(sql) // select "a", "b" from "table" fetch next $1 rows only offset $2

Relaterade artiklar