@@ -82,10 +82,10 @@ process.on('exit', () => sqlite.close());
8282
8383``` typescript
8484// ❌ Bad: Fetch all columns
85- const users = await db .select ().from (users );
85+ const allUsers = await db .select ().from (users );
8686
8787// ✅ Good: Fetch only needed columns
88- const users = await db .select ({
88+ const userSummaries = await db .select ({
8989 id: users .id ,
9090 email: users .email ,
9191 name: users .name ,
@@ -172,9 +172,9 @@ export default {
172172 async fetch(request : Request , env : Env ): Promise <Response > {
173173 const db = drizzle (env .DB );
174174
175- const users = await db .select ().from (users ).limit (10 );
175+ const edgeUsers = await db .select ().from (users ).limit (10 );
176176
177- return Response .json (users );
177+ return Response .json (edgeUsers );
178178 },
179179};
180180```
@@ -191,9 +191,9 @@ export async function GET() {
191191 const sql = neon (process .env .DATABASE_URL ! );
192192 const db = drizzle (sql );
193193
194- const users = await db .select ().from (users );
194+ const edgeUsers = await db .select ().from (users );
195195
196- return Response .json (users );
196+ return Response .json (edgeUsers );
197197}
198198```
199199
@@ -267,7 +267,7 @@ async function getCachedData<T>(
267267}
268268
269269// Usage
270- const users = await getCachedData (
270+ const cachedUsers = await getCachedData (
271271 ' users:all' ,
272272 () => db .select ().from (users ),
273273 600
@@ -283,8 +283,8 @@ CREATE MATERIALIZED VIEW user_stats AS
283283SELECT
284284 u.id,
285285 u.name,
286- COUNT(p.id) AS post_count,
287- COUNT(c.id) AS comment_count
286+ COUNT(DISTINCT p.id) AS post_count,
287+ COUNT(DISTINCT c.id) AS comment_count
288288FROM users u
289289LEFT JOIN posts p ON p.author_id = u.id
290290LEFT JOIN comments c ON c.user_id = u.id
@@ -298,8 +298,8 @@ export const userStats = pgMaterializedView('user_stats').as((qb) =>
298298 qb .select ({
299299 id: users .id ,
300300 name: users .name ,
301- postCount: sql <number >` COUNT(${posts .id }) ` ,
302- commentCount: sql <number >` COUNT(${comments .id }) ` ,
301+ postCount: sql <number >` COUNT(DISTINCT ${posts .id }) ` ,
302+ commentCount: sql <number >` COUNT(DISTINCT ${comments .id }) ` ,
303303 })
304304 .from (users )
305305 .leftJoin (posts , eq (posts .authorId , users .id ))
@@ -323,17 +323,29 @@ import { copyFrom } from 'pg-copy-streams';
323323import { pipeline } from ' stream/promises' ;
324324import { Readable } from ' stream' ;
325325
326- async function bulkInsert(data : any []) {
326+ function encodeCsvField(value : string ): string {
327+ if (value .includes (' \0 ' )) {
328+ throw new Error (' COPY CSV fields cannot contain NUL bytes' );
329+ }
330+
331+ const escaped = value .replace (/ "/ g , ' ""' );
332+ return / [",\r\n \u0001 -\u001f \u007f ] / .test (value )
333+ ? ` "${escaped }" `
334+ : escaped ;
335+ }
336+
337+ async function bulkInsert(data : Array <{ email: string ; name: string }>) {
327338 const client = await pool .connect ();
328339
329340 try {
330341 const stream = client .query (
331342 copyFrom (` COPY users (email, name) FROM STDIN WITH (FORMAT csv) ` )
332343 );
333344
334- const input = Readable .from (
335- data .map (row => ` ${row .email },${row .name }\n ` )
336- );
345+ const input = Readable .from (data .map ((row ) => [
346+ encodeCsvField (row .email ),
347+ encodeCsvField (row .name ),
348+ ].join (' ,' ) + ' \n ' ));
337349
338350 await pipeline (input , stream );
339351 } finally {
@@ -376,10 +388,10 @@ export async function handler() {
376388 const pool = new Pool ({ connectionString: process .env .DATABASE_URL });
377389 const db = drizzle (pool );
378390
379- const users = await db .select ().from (users );
391+ const requestUsers = await db .select ().from (users );
380392
381393 await pool .end ();
382- return users ;
394+ return requestUsers ;
383395}
384396
385397// ✅ Good: Reuse connection across warm starts
@@ -394,8 +406,8 @@ export async function handler() {
394406 cachedDb = drizzle (pool );
395407 }
396408
397- const users = await cachedDb .select ().from (users );
398- return users ;
409+ const warmUsers = await cachedDb .select ().from (users );
410+ return warmUsers ;
399411}
400412```
401413
@@ -410,7 +422,7 @@ const sql = neon(process.env.DATABASE_URL!);
410422const db = drizzle (sql );
411423
412424// Each query is a single HTTP request
413- const users = await db .select ().from (users );
425+ const httpUsers = await db .select ().from (users );
414426```
415427
416428## Read Replicas
@@ -447,8 +459,16 @@ import { drizzle } from 'drizzle-orm/node-postgres';
447459const db = drizzle (pool , {
448460 logger: {
449461 logQuery(query : string , params : unknown []) {
462+ const safeParams = params .map ((param ) => {
463+ if (param === null || typeof param === ' number' || typeof param === ' boolean' ) {
464+ return param ;
465+ }
466+
467+ return ' [REDACTED]' ;
468+ });
469+
450470 console .log (' Query:' , query );
451- console .log (' Params:' , params );
471+ console .log (' Params:' , safeParams );
452472 console .time (' query' );
453473 },
454474 },
@@ -512,7 +532,7 @@ async function measureQuery<T>(
512532}
513533
514534// Usage
515- const users = await measureQuery (
535+ const measuredUsers = await measureQuery (
516536 ' fetchUsers' ,
517537 db .select ().from (users ).limit (100 )
518538);
@@ -571,13 +591,16 @@ sqlite.pragma('mmap_size = 30000000000'); // 30GB mmap
571591// Disable for bulk inserts
572592const stmt = sqlite .prepare (' INSERT INTO users (email, name) VALUES (?, ?)' );
573593
574- const insertMany = sqlite .transaction ((users ) => {
575- for (const user of users ) {
594+ const insertMany = sqlite .transaction ((userRows : Array <{ email : string ; name : string }> ) => {
595+ for (const user of userRows ) {
576596 stmt .run (user .email , user .name );
577597 }
578598});
579599
580- insertMany (users ); // 100x faster than individual inserts
600+ const userRows = [
601+ { email: ' user@example.com' , name: ' User' },
602+ ];
603+ insertMany (userRows ); // 100x faster than individual inserts
581604```
582605
583606## Best Practices Summary
0 commit comments