-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
rawQueryArgsMapper.ts
129 lines (109 loc) · 4.18 KB
/
rawQueryArgsMapper.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import Debug from '@prisma/debug'
import type { ErrorCapturingDriverAdapter } from '@prisma/driver-adapter-utils'
import { Sql } from 'sql-template-tag'
import { MiddlewareArgsMapper } from '../../getPrismaClient'
import { mssqlPreparedStatement } from '../../utils/mssqlPreparedStatement'
import { serializeRawParameters } from '../../utils/serializeRawParameters'
import { RawQueryArgs } from './RawQueryArgs'
const ALTER_RE = /^(\s*alter\s)/i
const debug = Debug('prisma:client')
// TODO also check/disallow for CREATE, DROP
export function checkAlter(activeProvider: string, query: string, values: unknown[], invalidCall: string) {
if (activeProvider !== 'postgresql' && activeProvider !== 'cockroachdb') {
return
}
if (values.length > 0 && ALTER_RE.exec(query)) {
// See https://github.com/prisma/prisma-client-js/issues/940 for more info
throw new Error(`Running ALTER using ${invalidCall} is not supported
Using the example below you can still execute your query with Prisma, but please note that it is vulnerable to SQL injection attacks and requires you to take care of input sanitization.
Example:
await prisma.$executeRawUnsafe(\`ALTER USER prisma WITH PASSWORD '\${password}'\`)
More Information: https://pris.ly/d/execute-raw
`)
}
}
type RawQueryArgsMapperInput = {
clientMethod: string
activeProvider: string
activeProviderFlavour?: ErrorCapturingDriverAdapter['flavour']
}
export const rawQueryArgsMapper =
({ clientMethod, activeProvider, activeProviderFlavour }: RawQueryArgsMapperInput) =>
(args: RawQueryArgs) => {
if (activeProviderFlavour !== undefined) {
// When using the driver adapter, we need to use the flavour of the adapter,
// in order to avoid enumerating all the possible `@prisma/*` provider names.
activeProvider = activeProviderFlavour
}
// TODO Clean up types
let queryString = ''
let parameters: { values: string; __prismaRawParameters__: true } | undefined
if (Array.isArray(args)) {
// If this was called as prisma.$executeRaw(<SQL>, [...values]), assume it is a pre-prepared SQL statement, and forward it without any changes
const [query, ...values] = args
queryString = query
parameters = {
values: serializeRawParameters(values || []),
__prismaRawParameters__: true,
}
} else {
// If this was called as prisma.$executeRaw`<SQL>` try to generate a SQL prepared statement
switch (activeProvider) {
case 'sqlite':
case 'mysql': {
queryString = args.sql
parameters = {
values: serializeRawParameters(args.values),
__prismaRawParameters__: true,
}
break
}
case 'cockroachdb':
case 'postgresql':
case 'postgres': {
queryString = args.text
parameters = {
values: serializeRawParameters(args.values),
__prismaRawParameters__: true,
}
break
}
case 'sqlserver': {
queryString = mssqlPreparedStatement(args)
parameters = {
values: serializeRawParameters(args.values),
__prismaRawParameters__: true,
}
break
}
default: {
throw new Error(`The ${activeProvider} provider does not support ${clientMethod}`)
}
}
}
if (parameters?.values) {
debug(`prisma.${clientMethod}(${queryString}, ${parameters.values})`)
} else {
debug(`prisma.${clientMethod}(${queryString})`)
}
return { query: queryString, parameters }
}
type MiddlewareRawArgsTemplateString = [string[], ...unknown[]]
type MiddlewareRawArgsSql = [Sql]
export const templateStringMiddlewareArgsMapper: MiddlewareArgsMapper<Sql, MiddlewareRawArgsTemplateString> = {
requestArgsToMiddlewareArgs(sql) {
return [sql.strings, ...sql.values]
},
middlewareArgsToRequestArgs(requestArgs) {
const [strings, ...values] = requestArgs
return new Sql(strings, values)
},
}
export const sqlMiddlewareArgsMapper: MiddlewareArgsMapper<Sql, MiddlewareRawArgsSql> = {
requestArgsToMiddlewareArgs(sql) {
return [sql]
},
middlewareArgsToRequestArgs(requestArgs) {
return requestArgs[0]
},
}