sql >> Databáze >  >> RDS >> SQLite

Jak zacházet s booleovskými hodnotami v SQLite pomocí JavaScript proxy

Problém s Booleany v SQLite

Pokud jste někdy pracovali s SQLite, měli byste si být vědomi podporovaných datových typů a Boolean není jedním z nich. Přesněji, jak je uvedeno zde:

2.1. Booleovský datový typ

SQLite nemá samostatnou booleovskou třídu úložiště. Místo toho jsou booleovské hodnoty uloženy jako celá čísla 0 (nepravda) a 1 (pravda).

SQLite rozpoznává klíčová slova „TRUE“ a „FALSE“ od verze 3.23.0 (2018-04-02), ale tato klíčová slova jsou ve skutečnosti pouze alternativní hláskování pro celočíselné literály 1 a 0.

Většina knihoven JavaScriptu pro SQLite3 nepodporuje TRUE a FALSE klíčová slova a vyžadují, abyste připravili příkazy v kódu pomocí celých čísel. Například v better-sqlite3 byste museli udělat toto:

const payload = {
  isActive: 1, // <======
  username: 'Brad',
  password: '1234',
  email: '[email protected]',
};

const result = database
  .prepare(
    `INSERT INTO accounts(isActive, username, password, email) VALUES(@isActive, @username, @password, @email) `
  )
  .run({ bucketID, taskSiteID, name, username, password, email }).changes;

Pomocí number místo boolean napříč celou vaší aplikací by to znamenalo pro vývojáře hrozný zážitek (a navíc pravděpodobně spotřeboval více paměti).

K transformaci booleovských hodnot objektů můžete použít pomocnou funkci vlastnosti na čísla (Ve skutečnosti jsem to udělal jednou, v minulosti), ale pak byste to museli ručně spustit před každým dotazem. Fuj. Nebylo by skvělé, kdyby tato logika byla provedena na pozadí pokaždé, když jsme připravili a spustili prohlášení?

Vítejte ES6 proxy 👋 

Jednou z novějších funkcí JavaScriptu je Proxy objekt. Proxy jsou v podstatě "pasti", které zachycují operace s objekty, jako jsou getry, nastavovače a volání funkcí. Pomocí Proxy můžeme upravit knihovnu obalu SQLite JS tak, aby spouštěla ​​naši vlastní logiku, něco jako middleware.

Zápis pomocné funkce

Pro usnadnění vývoje budeme používat mapValues &isPlainObject obslužné funkce z lodash , ale můžete samozřejmě kódovat své vlastní. Funkce níže bude mapovat objekt (hloubka jedné úrovně) a převádět hodnoty typu boolean zadejte number .

import { mapValues } from 'lodash';

const booleanEntriesToNumbers = (object) =>
  mapValues(object, (value) =>
    typeof value === 'boolean' ? Number(value) : value
  );

Použití proxy k zachycení dotazů

Níže importujeme better-sqlite3 knihovnu a vytvořte novou instanci databáze. Poté přepíšeme výchozí prepare metoda s naší vlastní, která zase přepíše metody run , get a all vytvořením nového proxy pro každého. Můžete samozřejmě vytvořit proxy pro jakoukoli jinou metodu, kterou chcete.

import Database from 'better-sqlite3';

// Create new database instance
const db = new Database(dbFilePath);

// We will use this function to override the default "prepare" method
const proxiedPrepare = new Proxy(db.prepare, {
    apply: (prepare, prepareThisArg, [stringStatement]) => {
      const statement = prepare.call(prepareThisArg, stringStatement);

      // Override the default "run" method
      statement.run = new Proxy(statement.run, {
        apply: (run, runThisArg, args) => {
          const mappedArgs = args.map((arg) =>
            isPlainObject(arg) ? booleanEntriesToNumbers(arg) : arg
          );

          return run.call(runThisArg, ...mappedArgs);
        },
      });

      // Override the default "get" method
      statement.get = new Proxy(statement.get, {
        apply: (get, getThisArg, args) => {
          const mappedArgs = args.map((arg) =>
            isPlainObject(arg) ? booleanEntriesToNumbers(arg) : arg
          );

          return get.call(getThisArg, ...mappedArgs);
        },
      });

      // Override the default "all" method
      statement.all = new Proxy(statement.all, {
        apply: (all, allThisArg, args) => {
          const mappedArgs = args.map((arg) =>
            isPlainObject(arg) ? booleanEntriesToNumbers(arg) : arg
          );

          return all.call(allThisArg, ...mappedArgs);
        },
      });

      return statement;
    },
  });

// Override the default "prepare" method
db.prepare = proxiedPrepare;

V podstatě jednou zavoláte prepare je spuštěna metoda, řekneme JavaScriptu:Počkejte! Chceme upravit toto volání funkce. Namísto provádění logiky, kterou zamýšlel původní vývojář, místo toho chceme nejprve provést naši vlastní logiku (což je mapování užitečného zatížení objektu). Po provedení naší vlastní logiky vrátíme výsledek volání původní metody pomocí call svázat this argument. Pokud si chcete přečíst více o tom, jak fungují proxy, čtěte zde. Pro naši implementaci jsme použili apply metoda zde.

Děkuji za přečtení tohoto příspěvku, doufám, že to pomohlo někomu, kdo pracuje s SQLite v JavaScriptu 👊


  1. Použití HHVM s WordPress

  2. 3 způsoby, jak získat jazyk aktuální relace na serveru SQL (T-SQL)

  3. Průvodce návrhem databáze pro RBAC v MySQL

  4. Nejlepší fóra o výkonu SQL Serveru pro nápovědu k nejobtížnějším otázkám