Using CITEXT With Knex.js
I’ve been working on the backend for a side project with Express, Objection.js,
and Knex. As with most projects, users needed to have the ability to register with an email.
I wanted my database to enforce the constraints and have valid indexes on the email{:sql} column.
[email protected]{:sql} and [email protected]{:sql} are the same per RFC822. A users
should not be blocked from logging in due to the difference in casing on their email. We could call lower(email){:sql} ourselves but that skips the index we already have. Thankfully, we have access to CITEXT{:sql}.
CITEXT
CITEXT is a PostgreSQL data type for case insensitive text. When dealing with emails, I have found it better to use CITEXT. Running lower(column){:sql} manually is not ideal on every SQL query. This is compounded when you have a unique index on a column as the index will reference the case sensitive value.
Limitations
- It doesn’t handle unicode case insensitivity well.
- Not as efficient as
text{:sql}, due to making copies of the data to make it lower case. - Doesn’t work well if you want case sensitivity sometimes.
Even with these limitations, email is still a good fit for citext{:sql}.
Knex Migration
I decided to use Objection.js for my ORM which in turn uses Knex for queries and migrations. Let’s create a new migration via:
knex migrate:make ChangeEmailToCITextOnUsers
Let’s update our existing table to use citext{:sql} on email{:sql}. To do that, we need to enable the extension. Knex doesn’t have a way to do that directly but they do allow you to pass raw SQL.
exports.up = (knex) => {
return knex.schema
.raw('CREATE EXTENSION IF NOT EXISTS CITEXT') // Enables CITEXT on this database without throwing errors
.alterTable('User', (t) => {
t.specificType('email', 'CITEXT').notNullable().alter()
})
}
exports.down = (knex) =>
knex.schema.alterTable('User', (t) => {
t.string('email').notNullable().alter()
})
To use a type not available via Knex’s DSL, we can use specificType(column, type){:sql}. Running the migration using knex migrate:latest{:sh} will update our table to use CITEXT{:sql}:

No comments yet. Share on Mastodon and see your comment or write a post on your blog if you support Webmentions
No reposts yet. Share on Mastodon and see your repost or write a post on your blog if you support Webmentions
No likes yet. Share on Mastodon and see your like or write a post on your blog if you support Webmentions
No bookmarks yet. Share on Mastodon and see your bookmark or write a post on your blog if you support Webmentions
Powered by Webmentions