Skip to content

Commit

Permalink
feat(client): order by multiple fields
Browse files Browse the repository at this point in the history
  • Loading branch information
timsuchanek committed Aug 3, 2020
1 parent 992c9c4 commit b1e1434
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 136 deletions.
19 changes: 9 additions & 10 deletions src/packages/client/fixtures/blog/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@ import { PrismaClient } from './@prisma/client'

const prisma = new PrismaClient({
errorFormat: 'pretty',
__internal: {
engine: {
enableEngineDebugMode: true,
},
},
} as any)
})

async function main() {
await prisma.connect()
const result = await (prisma as any).__internal_triggerPanic(true)
// const result = await prisma.queryRaw(`SELECT 1`)
console.log(result)
const x = await prisma.user.findMany({
orderBy: {
email: 'desc',
name: 'asc',
},
})
console.log(x)
prisma.disconnect()
}

main().catch((e) => {
Expand Down
34 changes: 0 additions & 34 deletions src/packages/client/src/__tests__/json-dmmf.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,40 +429,6 @@ test('JsonFilter should contain equals and not', async () => {
],
"name": "NullableJsonFilter",
},
Object {
"atLeastOne": true,
"atMostOne": true,
"fields": Array [
Object {
"inputType": Array [
Object {
"isList": false,
"isNullable": true,
"isRequired": false,
"kind": "enum",
"type": "OrderByArg",
},
],
"isRelationFilter": false,
"name": "id",
},
Object {
"inputType": Array [
Object {
"isList": false,
"isNullable": true,
"isRequired": false,
"kind": "enum",
"type": "OrderByArg",
},
],
"isRelationFilter": false,
"name": "field",
},
],
"isOrderType": true,
"name": "UserOrderByInput",
},
]
`)
})
38 changes: 22 additions & 16 deletions src/packages/client/src/__tests__/orderTransformation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('where transformation', () => {
const select = {
orderBy: {
email: 'asc',
// id: 'asc',
id: 'desc',
},
}
const document = makeDocument({
Expand All @@ -22,10 +22,12 @@ describe('where transformation', () => {
rootTypeName: 'query',
rootField: 'findManyUser',
})
document.validate(select)
expect(String(document)).toMatchInlineSnapshot(`
"query {
findManyUser(orderBy: {
email: asc
\\"email\\": \\"asc\\",
\\"id\\": \\"desc\\"
}) {
id
name
Expand All @@ -41,7 +43,10 @@ describe('where transformation', () => {
`)
expect(String(transformDocument(document))).toMatchInlineSnapshot(`
"query {
findManyUser(orderBy: email_ASC) {
findManyUser(orderBy: {
\\"email\\": \\"asc\\",
\\"id\\": \\"desc\\"
}) {
id
name
email
Expand Down Expand Up @@ -72,8 +77,8 @@ describe('where transformation', () => {
expect(String(document)).toMatchInlineSnapshot(`
"query {
findManyUser(orderBy: {
email: asc
id: asc
\\"email\\": \\"asc\\",
\\"id\\": \\"asc\\"
}) {
id
name
Expand All @@ -89,7 +94,10 @@ describe('where transformation', () => {
`)
expect(String(transformDocument(document))).toMatchInlineSnapshot(`
"query {
findManyUser(orderBy: email_ASC) {
findManyUser(orderBy: {
\\"email\\": \\"asc\\",
\\"id\\": \\"asc\\"
}) {
id
name
email
Expand Down Expand Up @@ -117,15 +125,13 @@ describe('where transformation', () => {
~~~~~~~~~~~~~~~
}
Argument orderBy of type UserOrderByInput needs exactly one argument, but you provided email and id. Please choose one. Available args:
type UserOrderByInput {
id?: OrderByArg
name?: OrderByArg
email?: OrderByArg
status?: OrderByArg
favoriteTree?: OrderByArg
locationId?: OrderByArg
Argument orderBy: Provided value
{
email: 'asc',
id: 'asc'
}
of type Json on prisma.findManyUser is not a enum.
→ Possible values: UserOrderByInput.id_ASC, UserOrderByInput.id_DESC, UserOrderByInput.name_ASC, UserOrderByInput.name_DESC, UserOrderByInput.email_ASC, UserOrderByInput.email_DESC, UserOrderByInput.status_ASC, UserOrderByInput.status_DESC, UserOrderByInput.favoriteTree_ASC, UserOrderByInput.favoriteTree_DESC, UserOrderByInput.locationId_ASC, UserOrderByInput.locationId_DESC
"
`)
Expand All @@ -144,7 +150,7 @@ describe('where transformation', () => {
})
expect(String(transformDocument(document))).toMatchInlineSnapshot(`
"query {
findManyUser {
findManyUser(orderBy: null) {
id
name
email
Expand Down Expand Up @@ -172,7 +178,7 @@ describe('where transformation', () => {
expect(String(transformDocument(document))).toMatchInlineSnapshot(`
"query {
findManyUser(orderBy: {
\\"id\\": null
}) {
id
name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ Invalid \`prisma.user.findMany()\` invocation in
The underlying table for model \`dev.User\` does not exist."
Error occurred during query execution:
ConnectorError(ConnectorError { user_facing_error: None, kind: TableDoesNotExist { table: \\"dev.User\\" } })"
`;

exports[`runtime new-line: new-line example should succeed 1`] = `"success"`;
Expand Down
25 changes: 13 additions & 12 deletions src/packages/client/src/runtime/externalToInternalDmmf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,19 @@ function transformArgs(args: ExternalDMMF.SchemaArg[]): DMMF.SchemaArg[] {
}

function fixOrderByEnum(arg: ExternalDMMF.SchemaArg): ExternalDMMF.SchemaArg {
if (arg.name === 'orderBy' && arg.inputType.type.endsWith('OrderByInput')) {
return {
name: arg.name,
inputType: {
isList: arg.inputType.isList,
isRequired: arg.inputType.isRequired,
isNullable: arg.inputType.isNullable,
type: arg.inputType.type,
kind: 'object',
},
}
}
// TODO: cleanup
// if (arg.name === 'orderBy' && arg.inputType.type.endsWith('OrderByInput')) {
// return {
// name: arg.name,
// inputType: {
// isList: arg.inputType.isList,
// isRequired: arg.inputType.isRequired,
// isNullable: arg.inputType.isNullable,
// type: arg.inputType.type,
// kind: 'object',
// },
// }
// }
return arg
}

Expand Down
14 changes: 5 additions & 9 deletions src/packages/client/src/runtime/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,8 @@ interface ArgOptions {

export class Arg {
public readonly key: string
public readonly value: ArgValue
// not readonly, as we later need to transform it
public value: ArgValue
public readonly error?: InvalidArgError
public readonly hasError: boolean
public readonly isEnum: boolean
Expand Down Expand Up @@ -947,14 +948,9 @@ export function transformDocument(document: Document): Document {
}
function transformOrderArg(arg: Arg) {
if (arg.value instanceof Args) {
const orderArg = arg.value.args[0]
if (orderArg && orderArg.value) {
return new Arg({
...arg,
isEnum: true,
value: `${orderArg.key}_${orderArg.value!.toString().toUpperCase()}`,
})
}
arg.value.args.forEach((arg) => {
arg.value = String(arg.value).toUpperCase()
})
}

return arg
Expand Down
73 changes: 19 additions & 54 deletions src/packages/client/src/runtime/transformDmmf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,31 @@ import { DMMF } from './dmmf-types'
import { Dictionary, uniqBy } from './utils/common'

export function transformDmmf(document: DMMF.Document): DMMF.Document {
const doc = transformOrderInputTypes(transformWhereInputTypes(document))
const doc = transformWhereInputTypes(document)
return {
datamodel: doc.datamodel,
mappings: doc.mappings,
schema: {
enums: doc.schema.enums,
enums: transformSortOrder(doc.schema.enums),
rootMutationType: doc.schema.rootMutationType,
rootQueryType: doc.schema.rootQueryType,
outputTypes: filterOutputTypes(doc.schema.outputTypes),
inputTypes: makeWhereUniqueInputsRequired(
filterInputTypes(doc.schema.inputTypes),
inputTypes: markOrderInputType(
makeWhereUniqueInputsRequired(filterInputTypes(doc.schema.inputTypes)),
),
},
}
}

function markOrderInputType(inputTypes: DMMF.InputType[]): DMMF.InputType[] {
return inputTypes.map((t) => {
if (t.name.endsWith('OrderByInput')) {
t.isOrderType = true
}
return t
})
}

function filterInputTypes(types: DMMF.InputType[]): DMMF.InputType[] {
return uniqBy(types, (o) => o.name)
}
Expand All @@ -26,57 +35,13 @@ function filterOutputTypes(types: DMMF.OutputType[]): DMMF.OutputType[] {
return uniqBy(types, (o) => o.name)
}

function transformOrderInputTypes(document: DMMF.Document): DMMF.Document {
const inputTypes: DMMF.InputType[] = document.schema.inputTypes
const enums: DMMF.Enum[] = [
{
name: 'OrderByArg',
values: ['asc', 'desc'],
},
]
for (const type of document.schema.enums) {
if (!type.name.endsWith('OrderByInput')) {
enums.push(type)
continue
}
const argNames = type.values.reduce<string[]>((acc, curr) => {
if (curr.endsWith('ASC')) {
const index = curr.lastIndexOf('_ASC')
acc.push(curr.slice(0, index))
}
return acc
}, [])
const inputType: DMMF.InputType = {
name: type.name,
atLeastOne: true,
atMostOne: true,
isOrderType: true,
fields: argNames.map((name) => ({
name,
inputType: [
{
type: 'OrderByArg',
isList: false,
isRequired: false,
isNullable: true,
kind: 'enum',
},
],
isRelationFilter: false,
})),
function transformSortOrder(enums: DMMF.Enum[]): DMMF.Enum[] {
return enums.map((e) => {
if (e.name === 'SortOrder') {
e.values = e.values.map((v) => v.toLowerCase())
}
inputTypes.push(inputType)
}

return {
datamodel: document.datamodel,
mappings: document.mappings,
schema: {
...document.schema,
inputTypes,
enums,
},
}
return e
})
}

function makeWhereUniqueInputsRequired(
Expand Down
1 change: 1 addition & 0 deletions src/packages/sdk/src/engineCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export async function getDMMF({
enableExperimental,
}: GetDMMFOptions): Promise<DMMF.Document> {
queryEnginePath = await resolveBinary('query-engine', queryEnginePath)
debug({ queryEnginePath })
let result
try {
let tempDatamodelPath: string | undefined = datamodelPath
Expand Down

0 comments on commit b1e1434

Please sign in to comment.