Prisma 3.3.0版本$queryRaw处理带单引号字符串参数报错问题
问题原因
Prisma 3.x版本调整了$queryRaw的参数占位符解析规则,不会识别单引号/双引号包裹的字符串内部的占位符。你写的interval '${interval} day'中${interval}位于单引号内部,解析时会被当成普通字符串内容,不会被处理为参数占位符。从你提供的报错日志也可以看出,生成的SQL中interval '$2 day'的$2没有被替换,也没有被识别为有效占位符,因此Prisma认为你的查询只需要1个参数,实际传入了2个参数,就抛出了参数数量不匹配的错误。
是否属于版本Bug
该问题不属于功能性Bug,是Prisma官方为了提升SQL注入防护能力做的规则调整。2.x版本的解析逻辑会识别字符串内部的占位符,存在一定的安全隐患,3.x版本对该逻辑做了变更,属于非兼容更新。
可行解决方案
- 方案1:调整interval的写法,将数值参数挪到单引号外部,使用乘法计算时间间隔,完全兼容PostgreSQL语法,参数不在引号内可以被Prisma正常识别,示例SQL如下:
select count(id), status, "createdAt"::date from "ProjectLog" where "projectId" = (select id from "Project" where slug = ${id}) and "createdAt" > current_date - interval '1 day' * ${interval} group by "createdAt"::date, status;
- 方案2:将整个时间间隔字符串作为单个参数传递,不需要在SQL中拼接单位,示例如下:
// 构造带单位的参数值 const intervalStr = `${interval} day` // 执行查询 const result = await prisma.$queryRaw` select count(id), status, "createdAt"::date from "ProjectLog" where "projectId" = (select id from "Project" where slug = ${id}) and "createdAt" > current_date - interval ${intervalStr} group by "createdAt"::date, status; `
- 方案3:如果业务暂时无法调整SQL逻辑,可暂时降级Prisma到2.x稳定版本,不过该方案不推荐长期使用,无法获得新版本的功能和安全修复。
内容的提问来源于stack exchange,提问作者BardZH
相关产品推荐
相关产品推荐

