{"version":3,"file":"builder.mjs","names":[],"sources":["../../src/sql/builder.ts"],"sourcesContent":["import { PgIdentifier } from \"./pg-identifier\";\n\nexport type PostgresQueryBuilderCommand =\n  | \"bitmapscan\"\n  | \"indexscan\"\n  | \"seqscan\";\n\nexport class PostgresQueryBuilder {\n  private readonly commands: Record<string, string> = {};\n  private isIntrospection: boolean = false;\n  private explainFlags: string[] = [];\n  private _preamble = 0;\n  private parameters: Record<Parameter, number> = {};\n  // substitution for `limit $1` -> `limit 5`\n  private limitSubstitution?: number;\n\n  constructor(private query: string) {}\n\n  get preamble(): number {\n    return this._preamble;\n  }\n\n  static createIndex(definition: string, name?: PgIdentifier) {\n    if (name) {\n      return new PostgresQueryBuilder(\n        `create index \"${name}\" on ${definition};`,\n      );\n    }\n    return new PostgresQueryBuilder(`create index on ${definition};`);\n  }\n\n  enable(command: PostgresQueryBuilderCommand, value: boolean = true): this {\n    const commandString = `enable_${command}`;\n    if (value) {\n      this.commands[commandString] = \"on\";\n    } else {\n      this.commands[commandString] = \"off\";\n    }\n    return this;\n  }\n\n  withQuery(query: string): this {\n    this.query = query;\n    return this;\n  }\n\n  introspect(): this {\n    this.isIntrospection = true;\n    return this;\n  }\n\n  explain(flags: string[]): this {\n    this.explainFlags = flags;\n    return this;\n  }\n\n  parameterize(parameters: Record<Parameter, number>) {\n    Object.assign(this.parameters, parameters);\n    return this;\n  }\n\n  replaceLimit(limit: number) {\n    this.limitSubstitution = limit;\n    return this;\n  }\n\n  build(): string {\n    let commands = this.generateSetCommands();\n    commands += this.generateExplain().query;\n    if (this.isIntrospection) {\n      commands += \" -- @qd_introspection\";\n    }\n    return commands;\n  }\n\n  /** Return the \"set a=b\" parts of the command in the query separate from the explain select ... part */\n  buildParts() {\n    const commands = this.generateSetCommands();\n    const explain = this.generateExplain();\n    this._preamble = explain.preamble;\n    if (this.isIntrospection) {\n      explain.query += \" -- @qd_introspection\";\n    }\n    return { commands, query: explain.query };\n  }\n\n  private generateSetCommands() {\n    let commands = \"\";\n    for (const key in this.commands) {\n      const value = this.commands[key];\n      commands += `set local ${key}=${value};\\n`;\n    }\n    return commands;\n  }\n\n  private generateExplain() {\n    let finalQuery = \"\";\n    if (this.explainFlags.length > 0) {\n      finalQuery += `explain (${this.explainFlags.join(\", \")}) `;\n    }\n    const query = this.substituteQuery();\n    const semicolon = query.endsWith(\";\") ? \"\" : \";\";\n\n    const preamble = finalQuery.length;\n    finalQuery += `${query}${semicolon}`;\n    return { query: finalQuery, preamble };\n  }\n\n  private substituteQuery() {\n    let query = this.query;\n    if (this.limitSubstitution !== undefined) {\n      query = query.replace(\n        /(limit)\\s+\\$\\d+/gi,\n        `$1 ${this.limitSubstitution}`,\n      );\n    }\n    for (const [key, value] of Object.entries(this.parameters)) {\n      query = query.replaceAll(`\\\\$${key}`, value.toString());\n    }\n    return query;\n  }\n}\n\nexport type Parameter = `$${string}`;\n"],"mappings":";;;AAOA,IAAa,uBAAb,MAAa,qBAAqB;CAShC,YAAY,OAAuB;AAAf,OAAA,QAAA;wBARH,YAAmC,EAAE,CAAC;wBAC/C,mBAA2B,MAAM;wBACjC,gBAAyB,EAAE,CAAC;wBAC5B,aAAY,EAAE;wBACd,cAAwC,EAAE,CAAC;wBAE3C,qBAAA,KAAA,EAA2B;;CAInC,IAAI,WAAmB;AACrB,SAAO,KAAK;;CAGd,OAAO,YAAY,YAAoB,MAAqB;AAC1D,MAAI,KACF,QAAO,IAAI,qBACT,iBAAiB,KAAK,OAAO,WAAW,GACzC;AAEH,SAAO,IAAI,qBAAqB,mBAAmB,WAAW,GAAG;;CAGnE,OAAO,SAAsC,QAAiB,MAAY;EACxE,MAAM,gBAAgB,UAAU;AAChC,MAAI,MACF,MAAK,SAAS,iBAAiB;MAE/B,MAAK,SAAS,iBAAiB;AAEjC,SAAO;;CAGT,UAAU,OAAqB;AAC7B,OAAK,QAAQ;AACb,SAAO;;CAGT,aAAmB;AACjB,OAAK,kBAAkB;AACvB,SAAO;;CAGT,QAAQ,OAAuB;AAC7B,OAAK,eAAe;AACpB,SAAO;;CAGT,aAAa,YAAuC;AAClD,SAAO,OAAO,KAAK,YAAY,WAAW;AAC1C,SAAO;;CAGT,aAAa,OAAe;AAC1B,OAAK,oBAAoB;AACzB,SAAO;;CAGT,QAAgB;EACd,IAAI,WAAW,KAAK,qBAAqB;AACzC,cAAY,KAAK,iBAAiB,CAAC;AACnC,MAAI,KAAK,gBACP,aAAY;AAEd,SAAO;;;CAIT,aAAa;EACX,MAAM,WAAW,KAAK,qBAAqB;EAC3C,MAAM,UAAU,KAAK,iBAAiB;AACtC,OAAK,YAAY,QAAQ;AACzB,MAAI,KAAK,gBACP,SAAQ,SAAS;AAEnB,SAAO;GAAE;GAAU,OAAO,QAAQ;GAAO;;CAG3C,sBAA8B;EAC5B,IAAI,WAAW;AACf,OAAK,MAAM,OAAO,KAAK,UAAU;GAC/B,MAAM,QAAQ,KAAK,SAAS;AAC5B,eAAY,aAAa,IAAI,GAAG,MAAM;;AAExC,SAAO;;CAGT,kBAA0B;EACxB,IAAI,aAAa;AACjB,MAAI,KAAK,aAAa,SAAS,EAC7B,eAAc,YAAY,KAAK,aAAa,KAAK,KAAK,CAAC;EAEzD,MAAM,QAAQ,KAAK,iBAAiB;EACpC,MAAM,YAAY,MAAM,SAAS,IAAI,GAAG,KAAK;EAE7C,MAAM,WAAW,WAAW;AAC5B,gBAAc,GAAG,QAAQ;AACzB,SAAO;GAAE,OAAO;GAAY;GAAU;;CAGxC,kBAA0B;EACxB,IAAI,QAAQ,KAAK;AACjB,MAAI,KAAK,sBAAsB,KAAA,EAC7B,SAAQ,MAAM,QACZ,qBACA,MAAM,KAAK,oBACZ;AAEH,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,WAAW,CACxD,SAAQ,MAAM,WAAW,MAAM,OAAO,MAAM,UAAU,CAAC;AAEzD,SAAO"}