From f9012db7e04ac77fe0b4b19643ad241b2515441f Mon Sep 17 00:00:00 2001 From: Rohan Nair Date: Tue, 6 Aug 2024 11:28:33 -0400 Subject: [PATCH] lowercase the email index --- .../migrations/0005_aromatic_moon_knight.sql | 2 + .../lib/db/migrations/meta/0005_snapshot.json | 471 ++++++++++++++++++ .../src/lib/db/migrations/meta/_journal.json | 7 + apps/api/src/lib/db/schema/users.ts | 16 +- 4 files changed, 493 insertions(+), 3 deletions(-) create mode 100644 apps/api/src/lib/db/migrations/0005_aromatic_moon_knight.sql create mode 100644 apps/api/src/lib/db/migrations/meta/0005_snapshot.json diff --git a/apps/api/src/lib/db/migrations/0005_aromatic_moon_knight.sql b/apps/api/src/lib/db/migrations/0005_aromatic_moon_knight.sql new file mode 100644 index 0000000..67af654 --- /dev/null +++ b/apps/api/src/lib/db/migrations/0005_aromatic_moon_knight.sql @@ -0,0 +1,2 @@ +DROP INDEX IF EXISTS "user_email_idx";--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "user_email_idx" ON "users" USING btree (lower("email")); \ No newline at end of file diff --git a/apps/api/src/lib/db/migrations/meta/0005_snapshot.json b/apps/api/src/lib/db/migrations/meta/0005_snapshot.json new file mode 100644 index 0000000..e0b6731 --- /dev/null +++ b/apps/api/src/lib/db/migrations/meta/0005_snapshot.json @@ -0,0 +1,471 @@ +{ + "id": "9e18586d-7bad-46b5-8b43-8aa82fce5137", + "prevId": "28b2c6a9-1f19-4432-848f-a6738bc7b593", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.categories": { + "name": "categories", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "category_name_idx": { + "name": "category_name_idx", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "category_slug_idx": { + "name": "category_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.links": { + "name": "links", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "url": { + "name": "url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "image_url": { + "name": "image_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "varchar", + "primaryKey": false, + "notNull": true, + "default": "'submitted'" + }, + "status_reason": { + "name": "status_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cleaned": { + "name": "cleaned", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "summary": { + "name": "summary", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "link_title_idx": { + "name": "link_title_idx", + "columns": [ + { + "expression": "title", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "search_index": { + "name": "search_index", + "columns": [ + { + "expression": "(\n setweight(to_tsvector('english', \"title\"), 'A') ||\n setweight(to_tsvector('english', \"cleaned\"), 'B')\n )", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "links_url_unique": { + "name": "links_url_unique", + "nullsNotDistinct": false, + "columns": [ + "url" + ] + } + } + }, + "public.links_tags": { + "name": "links_tags", + "schema": "", + "columns": { + "link_id": { + "name": "link_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "tag_id": { + "name": "tag_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "links_tags_link_id_tag_id_pk": { + "name": "links_tags_link_id_tag_id_pk", + "columns": [ + "link_id", + "tag_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.links_users": { + "name": "links_users", + "schema": "", + "columns": { + "link_id": { + "name": "link_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "category_id": { + "name": "category_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "links_users_link_id_user_id_pk": { + "name": "links_users_link_id_user_id_pk", + "columns": [ + "link_id", + "user_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.tags": { + "name": "tags", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "tag_name_idx": { + "name": "tag_name_idx", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "password_hash": { + "name": "password_hash", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "given_name": { + "name": "given_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "family_name": { + "name": "family_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_email_idx": { + "name": "user_email_idx", + "columns": [ + { + "expression": "lower(\"email\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/api/src/lib/db/migrations/meta/_journal.json b/apps/api/src/lib/db/migrations/meta/_journal.json index 2865970..02d306b 100644 --- a/apps/api/src/lib/db/migrations/meta/_journal.json +++ b/apps/api/src/lib/db/migrations/meta/_journal.json @@ -36,6 +36,13 @@ "when": 1722957435034, "tag": "0004_bizarre_captain_marvel", "breakpoints": true + }, + { + "idx": 5, + "version": "7", + "when": 1722958066662, + "tag": "0005_aromatic_moon_knight", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/api/src/lib/db/schema/users.ts b/apps/api/src/lib/db/schema/users.ts index bfb4c7c..3e63250 100644 --- a/apps/api/src/lib/db/schema/users.ts +++ b/apps/api/src/lib/db/schema/users.ts @@ -1,6 +1,12 @@ import { categories, linksUsers, tags } from '@/lib/db/schema' -import { relations } from 'drizzle-orm' -import { index, pgTable, timestamp, varchar } from 'drizzle-orm/pg-core' +import { relations, sql, type SQL } from 'drizzle-orm' +import { + index, + pgTable, + timestamp, + varchar, + type AnyPgColumn, +} from 'drizzle-orm/pg-core' import { createInsertSchema, createSelectSchema } from 'drizzle-zod' import type { z } from 'zod' @@ -26,10 +32,14 @@ export const users = pgTable( updatedAt: timestamp('updated_at').defaultNow().notNull(), }, (t) => ({ - userEmailIdx: index('user_email_idx').on(t.email), + userEmailIdx: index('user_email_idx').on(lower(t.email)), }), ) +export function lower(email: AnyPgColumn): SQL { + return sql`lower(${email})` +} + export const usersRelations = relations(users, ({ many }) => ({ links: many(linksUsers), tags: many(tags),