Builder Bench · Level 5 of 7

Where OR goes

City is Oslo AND name is Ann OR Bob. Bob lives in Rome.

main.ts
import { Entity, PrimaryGeneratedColumn, Column, Brackets } from "typeorm";import { connect } from "./db"; @Entity()class Author {  @PrimaryGeneratedColumn() id: number;  @Column() name: string;  @Column() city: string;} async function main() {  const db = await connect([Author]);  await db.query(`INSERT INTO "author" (name, city) VALUES ('Ann', 'Oslo'), ('Bob', 'Rome'), ('Cat', 'Oslo')`);  const repo = db.getRepository(Author);  const loose = await repo.createQueryBuilder("a")    .where("a.city = :c", { c: "Oslo" })    .andWhere("a.name = :n1", { n1: "Ann" })    .orWhere("a.name = :n2", { n2: "Bob" })    .getMany();  console.log("no brackets: " + loose.map((a) => a.name).join(","));  const tight = await repo.createQueryBuilder("a")    .where("a.city = :c", { c: "Oslo" })    .andWhere(new Brackets((w) => {      w.where("a.name = :n1", { n1: "Ann" }).orWhere("a.name = :n2", { n2: "Bob" });    }))    .getMany();  console.log("brackets: " + tight.map((a) => a.name).join(","));}main();
db.ts 38 lines
import "reflect-metadata";import { DataSource } from "typeorm"; let show = false; /** One short line per statement: the verb and the table, enough to count what a call costs. */function short(sql: string): string {  const s = sql.replace(/\s+/g, " ").trim();  if (/last_insert_rowid/i.test(s)) return "SELECT new id";  if (/^SELECT DISTINCT "distinctAlias"/i.test(s)) return "SELECT ids (paging)";  const verb = (s.match(/^(SELECT|INSERT INTO|UPDATE|DELETE FROM|BEGIN TRANSACTION|COMMIT|ROLLBACK)/i)?.[0] ?? s.split(" ")[0]).toUpperCase();  const table = s.match(/(?:FROM|INTO|UPDATE)\s+"(\w+)"/i)?.[1];  return table ? verb + " " + table + (/ JOIN /i.test(s) ? " JOIN" : "") : verb;} /** An in-memory SQLite database that prints one line for every SQL statement it runs. */export async function connect(entities: Function[]): Promise<DataSource> {  const db = new DataSource({    type: "sqljs",    entities,    synchronize: true,    logging: true,    logger: {      logQuery: (q: string) => {        if (show) console.log("SQL " + short(q));      },      logQueryError: () => {},      logQuerySlow: () => {},      logSchemaBuild: () => {},      logMigration: () => {},      log: () => {},    },  });  await db.initialize();  show = true;  return db;} 

1. Predict the output

Tap the lines in the order you think they print.

  1. 1…
  2. 2…
  3. 3…
  4. 4…
  5. 5…