Skip to main content
Glama

Prisma MCP Server

Official
by prisma
Apache 2.0
4
44,192
  • Linux
  • Apple
render-query.test.ts18.4 kB
import type { PlaceholderFormat, QueryPlanDbQuery } from '../query-plan' import { GeneratorRegistry } from './generators' import { renderQuery } from './render-query' import { ScopeBindings } from './scope' const TEST_MAX_CHUNK_SIZE = 10 test('no template', () => { expect( renderQuery( { type: 'rawSql', sql: 'SELECT * FROM users WHERE id = $1', args: [1], argTypes: [{ arity: 'scalar', scalarType: 'int' }], } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, ), ).toEqual([ { sql: 'SELECT * FROM users WHERE id = $1', args: [1], argTypes: [{ arity: 'scalar', scalarType: 'int' }], }, ]) }) test('no template and scalar list parameter', () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'SELECT * FROM users WHERE id = ' }, { type: 'parameter' }, { type: 'stringChunk', chunk: ' AND numbers = ' }, { type: 'parameter' }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [1, [1, 2, 3]], argTypes: [ { arity: 'scalar', scalarType: 'int' }, { arity: 'list', scalarType: 'int' }, ], chunkable: true, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, ), ).toEqual([ { sql: 'SELECT * FROM users WHERE id = $1 AND numbers = $2', args: [1, [1, 2, 3]], argTypes: [ { arity: 'scalar', scalarType: 'int' }, { arity: 'list', scalarType: 'int' }, ], }, ]) }) test('transforms IN template', () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'SELECT * FROM users WHERE "userId" IN ' }, { type: 'parameterTuple' }, { type: 'stringChunk', chunk: ' OFFSET ' }, { type: 'parameter' }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [[1, 2, 3], 0], argTypes: [ { arity: 'scalar', scalarType: 'int' }, { arity: 'scalar', scalarType: 'int' }, ], chunkable: true, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, ), ).toEqual([ { sql: 'SELECT * FROM users WHERE "userId" IN ($1,$2,$3) OFFSET $4', args: [1, 2, 3, 0], argTypes: Array.from({ length: 4 }, () => ({ arity: 'scalar', scalarType: 'int' })), }, ]) }) test('transforms IN template with empty list', () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'SELECT * FROM users WHERE "userId" IN ' }, { type: 'parameterTuple' }, { type: 'stringChunk', chunk: ' OFFSET ' }, { type: 'parameter' }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [[], 0], argTypes: [ { arity: 'scalar', scalarType: 'int' }, { arity: 'scalar', scalarType: 'int' }, ], chunkable: true, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, ), ).toEqual([ { sql: 'SELECT * FROM users WHERE "userId" IN (NULL) OFFSET $1', args: [0], argTypes: [{ arity: 'scalar', scalarType: 'int' }], }, ]) }) test('handles singleton list in IN template', () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'SELECT * FROM users WHERE "userId" IN ' }, { type: 'parameterTuple' }, { type: 'stringChunk', chunk: ' OFFSET ' }, { type: 'parameter' }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [[1], 0], argTypes: Array.from({ length: 2 }, () => ({ arity: 'scalar', scalarType: 'int' })), chunkable: true, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, ), ).toEqual([ { sql: 'SELECT * FROM users WHERE "userId" IN ($1) OFFSET $2', args: [1, 0], argTypes: Array.from({ length: 2 }, () => ({ arity: 'scalar', scalarType: 'int' })), }, ]) }) test('treats non-array element as a singleton list in IN template', () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'SELECT * FROM users WHERE "userId" IN ' }, { type: 'parameterTuple' }, { type: 'stringChunk', chunk: ' OFFSET ' }, { type: 'parameter' }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [1, 0], argTypes: Array.from({ length: 2 }, () => ({ arity: 'scalar', scalarType: 'int' })), chunkable: true, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, ), ).toEqual([ { sql: 'SELECT * FROM users WHERE "userId" IN ($1) OFFSET $2', args: [1, 0], argTypes: Array.from({ length: 2 }, () => ({ arity: 'scalar', scalarType: 'int' })), }, ]) }) test("transforms IN template, doesn't touch scalar list", () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'SELECT * FROM users WHERE "userId" IN ' }, { type: 'parameterTuple' }, { type: 'stringChunk', chunk: ' AND numbers = ' }, { type: 'parameter' }, { type: 'stringChunk', chunk: ' OFFSET ' }, { type: 'parameter' }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [[1, 2, 3], [1, 2, 3], 0], argTypes: [ { arity: 'scalar', scalarType: 'int' }, { arity: 'list', scalarType: 'int' }, { arity: 'scalar', scalarType: 'int' }, ], chunkable: true, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, ), ).toEqual([ { sql: 'SELECT * FROM users WHERE "userId" IN ($1,$2,$3) AND numbers = $4 OFFSET $5', args: [1, 2, 3, [1, 2, 3], 0], argTypes: [ ...Array.from({ length: 3 }, () => ({ arity: 'scalar', scalarType: 'int' })), { arity: 'list', scalarType: 'int' }, { arity: 'scalar', scalarType: 'int' }, ], }, ]) }) test('transforms INSERT VALUES template', () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'INSERT INTO "public"."_CategoryToPost" ("A", "B") VALUES ' }, { type: 'parameterTupleList', itemPrefix: '(', itemSeparator: ',', itemSuffix: ')', groupSeparator: ',', }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [ [ [1, 2], [3, 4], ], ], argTypes: Array.from({ length: 2 }, () => ({ arity: 'scalar', scalarType: 'int' })), chunkable: true, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, ), ).toEqual([ { sql: 'INSERT INTO "public"."_CategoryToPost" ("A", "B") VALUES ($1,$2),($3,$4)', args: [1, 2, 3, 4], argTypes: Array.from({ length: 4 }, () => ({ arity: 'scalar', scalarType: 'int' })), }, ]) }) test('chunking an INSERT with a large parameterTupleList', () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'INSERT INTO "public"."Table" VALUES ' }, { type: 'parameterTupleList', itemPrefix: '(', itemSeparator: ',', itemSuffix: ')', groupSeparator: ',', }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [ [ Array.from({ length: 5 }, (_, i) => i + 1), Array.from({ length: 5 }, (_, i) => i + 6), Array.from({ length: 5 }, (_, i) => i + 11), Array.from({ length: 5 }, (_, i) => i + 16), Array.from({ length: 5 }, (_, i) => i + 21), ], ], argTypes: Array.from({ length: 5 }, () => ({ arity: 'scalar', scalarType: 'int' })), chunkable: true, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, TEST_MAX_CHUNK_SIZE, ), ).toMatchObject([ { sql: expect.stringMatching(/^INSERT INTO "public"\."Table" VALUES (\((\$[0-9]+,?){5}\),?){2}$/), args: Array.from({ length: 10 }, (_, i) => i + 1), argTypes: Array.from({ length: 10 }, () => ({ arity: 'scalar', scalarType: 'int' })), }, { sql: expect.stringMatching(/^INSERT INTO "public"\."Table" VALUES (\((\$[0-9]+,?){5}\),?){2}$/), args: Array.from({ length: 10 }, (_, i) => i + 11), argTypes: Array.from({ length: 10 }, () => ({ arity: 'scalar', scalarType: 'int' })), }, { sql: expect.stringMatching(/^INSERT INTO "public"\."Table" VALUES (\((\$[0-9]+,?){5}\),?){1}$/), args: Array.from({ length: 5 }, (_, i) => i + 21), argTypes: Array.from({ length: 5 }, () => ({ arity: 'scalar', scalarType: 'int' })), }, ]) }) test('chunking a UNION ALL with a large parameterTupleList', () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'SELECT * FROM [User] WHERE "banned" = ' }, { type: 'parameter' }, { type: 'stringChunk', chunk: ' AND "id" IN (SELECT ' }, { type: 'parameterTupleList', itemPrefix: '', itemSeparator: ',', itemSuffix: '', groupSeparator: ' UNION ALL SELECT ', }, { type: 'stringChunk', chunk: ') AND ("name" = ' }, { type: 'parameter' }, { type: 'stringChunk', chunk: ' OR "name" = ' }, { type: 'parameter' }, { type: 'stringChunk', chunk: ')' }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [false, Array.from({ length: 5 }, (_, i) => [i + 1, i + 2]), 'John Doe', 'Jane Doe'], argTypes: [ { arity: 'scalar', scalarType: 'boolean' }, { arity: 'scalar', scalarType: 'int' }, { arity: 'scalar', scalarType: 'string' }, { arity: 'scalar', scalarType: 'string' }, ], chunkable: true, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, TEST_MAX_CHUNK_SIZE, ), ).toMatchObject([ { sql: expect.stringMatching( /^SELECT \* FROM \[User\] WHERE "banned" = \$1 AND "id" IN \(SELECT ((\$[0-9]+,?){2}( UNION ALL SELECT )?){3}\) AND \("name" = \$8 OR "name" = \$9\)$/, ), args: [false, ...Array.from({ length: 3 }, (_, i) => [i + 1, i + 2]).flat(), 'John Doe', 'Jane Doe'], argTypes: [ { arity: 'scalar', scalarType: 'boolean' }, ...Array.from({ length: 6 }, () => ({ arity: 'scalar', scalarType: 'int' })), { arity: 'scalar', scalarType: 'string' }, { arity: 'scalar', scalarType: 'string' }, ], }, { sql: expect.stringMatching( /^SELECT \* FROM \[User\] WHERE "banned" = \$1 AND "id" IN \(SELECT ((\$[0-9]+,?){2}( UNION ALL SELECT )?){2}\) AND \("name" = \$6 OR "name" = \$7\)$/, ), args: [false, ...Array.from({ length: 2 }, (_, i) => [i + 4, i + 5]).flat(), 'John Doe', 'Jane Doe'], argTypes: [ { arity: 'scalar', scalarType: 'boolean' }, ...Array.from({ length: 4 }, () => ({ arity: 'scalar', scalarType: 'int' })), { arity: 'scalar', scalarType: 'string' }, { arity: 'scalar', scalarType: 'string' }, ], }, ]) }) test('chunking a SELECT..IN with a large parameterTuple', () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'SELECT FROM "public"."User" WHERE "banned" = ' }, { type: 'parameter' }, { type: 'stringChunk', chunk: ' AND "id" IN ' }, { type: 'parameterTuple' }, { type: 'stringChunk', chunk: ' AND "name" = ' }, { type: 'parameter' }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [false, Array.from({ length: 10 }, (_, i) => i + 1), 'John Doe'], argTypes: [ { arity: 'scalar', scalarType: 'boolean' }, { arity: 'scalar', scalarType: 'int' }, { arity: 'scalar', scalarType: 'string' }, ], chunkable: true, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, TEST_MAX_CHUNK_SIZE, ), ).toMatchObject([ { sql: expect.stringMatching( /^SELECT FROM "public"\."User" WHERE "banned" = \$1 AND "id" IN \((\$[0-9]+,?){8}\) AND "name" = \$10$/, ), args: [false, ...Array.from({ length: 8 }, (_, i) => i + 1), 'John Doe'], argTypes: [ { arity: 'scalar', scalarType: 'boolean' }, ...Array.from({ length: 8 }, () => ({ arity: 'scalar', scalarType: 'int' })), { arity: 'scalar', scalarType: 'string' }, ], }, { sql: expect.stringMatching( /^SELECT FROM "public"\."User" WHERE "banned" = \$1 AND "id" IN \((\$[0-9]+,?){2}\) AND "name" = \$4/, ), args: [false, ...Array.from({ length: 2 }, (_, i) => i + 9), 'John Doe'], argTypes: [ { arity: 'scalar', scalarType: 'boolean' }, ...Array.from({ length: 2 }, () => ({ arity: 'scalar', scalarType: 'int' })), { arity: 'scalar', scalarType: 'string' }, ], }, ]) }) test('chunking a SELECT..IN with multiple parameterTuples', () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'SELECT FROM "public"."User" WHERE "id" IN ' }, { type: 'parameterTuple', }, { type: 'stringChunk', chunk: ' AND "age" IN ' }, { type: 'parameterTuple' }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [Array.from({ length: 10 }, (_, i) => i + 1), Array.from({ length: 4 }, (_, i) => i + 1)], argTypes: [ { arity: 'scalar', scalarType: 'int' }, { arity: 'scalar', scalarType: 'int' }, { arity: 'scalar', scalarType: 'int' }, ], chunkable: true, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, TEST_MAX_CHUNK_SIZE, ), ).toMatchObject([ { sql: expect.stringMatching( /^SELECT FROM "public"\."User" WHERE "id" IN \((\$[0-9]+,?){6}\) AND "age" IN \((\$[0-9]+,?){4}\)$/, ), args: [...Array.from({ length: 6 }, (_, i) => i + 1), ...Array.from({ length: 4 }, (_, i) => i + 1)], argTypes: Array.from({ length: 10 }, () => ({ arity: 'scalar', scalarType: 'int' })), }, { sql: expect.stringMatching( /^SELECT FROM "public"\."User" WHERE "id" IN \((\$[0-9]+,?){4}\) AND "age" IN \((\$[0-9]+,?){4}\)$/, ), args: [...Array.from({ length: 4 }, (_, i) => i + 7), ...Array.from({ length: 4 }, (_, i) => i + 1)], argTypes: Array.from({ length: 8 }, () => ({ arity: 'scalar', scalarType: 'int' })), }, ]) }) test('a SELECT..IN with a large parameterTuple that is not chunkable', () => { expect( renderQuery( { type: 'templateSql', fragments: [ { type: 'stringChunk', chunk: 'SELECT FROM "public"."User" WHERE "banned" = ' }, { type: 'parameter' }, { type: 'stringChunk', chunk: ' AND "id" IN ' }, { type: 'parameterTuple' }, { type: 'stringChunk', chunk: ' AND "name" = ' }, { type: 'parameter' }, ], placeholderFormat: { prefix: '$', hasNumbering: true, } satisfies PlaceholderFormat, args: [false, Array.from({ length: 3000 }, (_, i) => i + 1), 'John Doe'], argTypes: [ { arity: 'scalar', scalarType: 'boolean' }, { arity: 'scalar', scalarType: 'int' }, { arity: 'scalar', scalarType: 'string' }, ], chunkable: false, } satisfies QueryPlanDbQuery, {} as ScopeBindings, {}, TEST_MAX_CHUNK_SIZE, ), ).toMatchObject([ { sql: expect.stringMatching( /^SELECT FROM "public"\."User" WHERE "banned" = \$1 AND "id" IN \((\$[0-9]+,?){3000}\) AND "name" = \$3002$/, ), args: [false, ...Array.from({ length: 3000 }, (_, i) => i + 1), 'John Doe'], argTypes: [ { arity: 'scalar', scalarType: 'boolean' }, ...Array.from({ length: 3000 }, () => ({ arity: 'scalar', scalarType: 'int' })), { arity: 'scalar', scalarType: 'string' }, ], }, ]) }) test('executes a generator', () => { const generators = new GeneratorRegistry() expect( renderQuery( { type: 'rawSql', sql: 'INSERT INTO users (id, name) VALUES ($1, $2)', args: [ { prisma__type: 'generatorCall', prisma__value: { name: 'uuid', args: [4] } }, { prisma__type: 'generatorCall', prisma__value: { name: 'now', args: [] } }, ], argTypes: [ { arity: 'scalar', scalarType: 'datetime' }, { arity: 'scalar', scalarType: 'datetime' }, ], } satisfies QueryPlanDbQuery, {} as ScopeBindings, generators.snapshot(), ), ).toMatchObject([ { sql: 'INSERT INTO users (id, name) VALUES ($1, $2)', args: [expect.any(String), expect.any(String)], argTypes: [ { arity: 'scalar', scalarType: 'datetime' }, { arity: 'scalar', scalarType: 'datetime' }, ], }, ]) })

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/prisma/prisma'

If you have feedback or need assistance with the MCP directory API, please join our Discord server