I once had to work with a project which used MariaDB connector for Node.js, and for some reasons it was necessary to add Knex query builder to it. Honestly, I am not a big fan of query builders, because I know SQL pretty well, and usually it is faster for me to write a query in SQL than use a query builder. But sometimes you have to obey someone else’s decisions 🙂

The main issue was that Knex does not support MariaDB connector out of the box: it supports only a few drivers, and MariaDB is unfortunately not one of them (you can use either mysql or mysql2).

However, because the project used mariadb, I did not want to switch to mysql or mysql2, and decided to write a MariaDB client for Knex.

It turned out that there had been no simple way to extend Knex: even the list of supported clients was immutable:

const SUPPORTED_CLIENTS = Object.freeze(
  [
    'mssql',
    'mysql',
    'mysql2',
    'oracledb',
    'postgres',
    'redshift',
    'sqlite3',
  ].concat(keys(CLIENT_ALIASES))
);

And if you try to pass anything else as client, you get an error: “Error: knex: Unknown configuration option ‘client’ value XXX. Note that it is case-sensitive, check documentation for supported values.

The official documentation was unhelpful there, so I had to dig into the code.

It turned out that:

  1. If no parameters are passed to Knex, it uses a generic client (whatever it means).
  2. If config.client is a function, and is derived from Client, the function will be used as a client.
  3. Otherwise, client name is taken from config.client or config.dialect and is expected to be a string. If the name is not in SUPPORTED_CLIENTS, Knex throws an exception, otherwise it loads the client from dialects/<client>/index.js.

To create a client (or dialect), I had to use the second option. Fortunately, mariadb connector can be compatible with mysql and mysql2: it provides a callback API for compatibility reasons. This means that I don’t have to write everything from scratch, and it should be enough to rewrite the existing mysql2 dialect.

Basically, I had to re-implement only two things: _driver() and validateConnection() methods. The first one returns the driver (or connector) — mariadb in my case, and the second one checks whether the connection is valid (mariadb does that differently).

And here is the final code:

const Client_MySQL = require('knex/src/dialects/mysql/index');

class Client_MariaDB extends Client_MySQL {
  driverName = 'mariadb';

  _driver () {
    return require('mariadb/callback');
  }

  validateConnection (connection) {
    return connection.isValid();
  }
};

module.exports = Client_MariaDB;
MariaDB Driver for Knex
Tagged on:                         

2 thoughts on “MariaDB Driver for Knex

Leave a Reply

Your email address will not be published. Required fields are marked *