drizzle-team / drizzle-team/drizzle-orm

[BUG]: Field Mapping Not Working in Prisma Extension

Open
#5,270 5 comments 1 reaction 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
35.8k
Forks
1.6k
Avg merge
2d 7h
Merged PRs (30d)
4

Description

### Report hasn't been filed before.

- [x] I have verified that the bug I'm about to report hasn't been filed before.

### What version of `drizzle-orm` are you using?

0.44.7

### What version of `drizzle-kit` are you using?

N/A

### Other packages

"prisma": "^7.2.0"

### Describe the Bug

Note: I have used Claude to help me draft this bug report, but I have spent a few hours identifying the bug and working on the fix before drafting this.

## Description

The Prisma adapter for drizzle-orm (`drizzle-orm/prisma/pg`) does not respect field aliases in select queries. When using a column alias in a `.select()` query, the returned result uses the database column name instead of the specified alias.

## Environment

- **drizzle-orm version**: 0.44.7
- **@prisma/client version**: 7.2.0
- **Database**: PostgreSQL
- **Node.js version**: (as applicable)

## Expected Behavior

When selecting a column with an alias:

```typescript
const [result] = await prisma.$drizzle
.select({
id: schema.partners.partnerId,
})
.from(schema.partners)
.limit(1);

console.log(result);
// Expected: { id: '...' }
```

The result should have the key `id` as specified in the select object.

## Actual Behavior

The result uses the database column name instead:

```typescript
console.log(result);
// Actual: { partnerId: '...' }
```

The definition of the table and the column are irrelevant, as I have tested this with many tables/columns of different types.

## Reproduction

### Minimal Example

```typescript
import { PrismaPgDatabase } from 'drizzle-orm/prisma/pg';
import { pgTable, text } from 'drizzle-orm/pg-core';

// Define schema with a column that has a different name than the alias
const partners = pgTable('Partner', {
partnerId: text('partnerId').primaryKey(),
name: text('name'),
});

// Create drizzle instance
const db = new PrismaPgDatabase(prismaClient, undefined);

// Query with alias
const [result] = await db
.select({
id: partners.partnerId, // Alias 'id' for column 'partnerId'
})
.from(partners)
.limit(1);

// Bug: result has { partnerId: '...' } instead of { id: '...' }
expect(result).toHaveProperty('id'); // ❌ Fails
expect(result).toHaveProperty('partnerId'); // ✅ Passes (unexpected)
```

### Test Case

```typescript
test('field mapping should work with aliases', async () => {
const [result] = await prisma.$drizzle
.select({
id: schema.partners.partnerId,
})
.from(schema.partners)
.limit(1);

expect(result).toHaveProperty('id'); // Currently fails
});
```

## Root Cause

The issue is in `drizzle-orm/prisma/pg/session.js`. The `PrismaPgSession.prepareQuery()` method doesn't accept or pass the `fields` parameter that contains the field mapping information. This causes the `PrismaPgPreparedQuery` to not have access to the alias mappings.

When Prisma executes `$queryRawUnsafe()`, it returns results with the actual database column names. Without the field mapping information, drizzle cannot transform these column names to the user-specified aliases.

## Proposed Fix

The fix involves three changes to `drizzle-orm/prisma/pg/session.js`:

### 1. Update `PrismaPgPreparedQuery` constructor to accept field mapping parameters

```javascript
class PrismaPgPreparedQuery extends PgPreparedQuery {
constructor(prisma, query, logger, fields, name, isResponseInArrayMode, customResultMapper, queryMetadata, cacheConfig) {
super(query, void 0, queryMetadata, cacheConfig);
this.prisma = prisma;
this.logger = logger;
this.fields = fields;
this._isResponseInArrayMode = isResponseInArrayMode;
this.customResultMapper = customResultMapper;
}
// ...
}
```

### 2. Add field mapping logic in the `execute` method

```javascript
execute(placeholderValues) {
const params = fillPlaceholders(this.query.params, placeholderValues ?? {});
this.logger.logQuery(this.query.sql, params);
return this.prisma.$queryRawUnsafe(this.query.sql, ...params).then(rawResult => {
// Map database column names to the aliased field names
if (this.fields && Array.isArray(rawResult)) {
return rawResult.map(row => {
const mappedRow = {};
for (const field of this.fields) {
// field.field.name is the actual database column name
// field.path is the alias (the key the user wants in the result)
const dbColumnName = field.field.name;
const aliasName = field.path[0];
if (row.hasOwnProperty(dbColumnName)) {
mappedRow[aliasName] = row[dbColumnName];
}
}
return Object.keys(mappedRow).length > 0 ? mappedRow : row;
});
}
return rawResult;
});
}
```

### 3. Update `PrismaPgSession.prepareQuery()` to accept and pass the parameters

```javascript
prepareQuery(query, fields, name, isResponseInArrayMode, customResultMapper, queryMetadata, cacheConfig) {
return new PrismaPgPreparedQuery(
this.prisma,
query,
this.logger,
fields,
name,
isResponseInArrayMode,
customResultMapper,
queryMetadata,
cacheConfig
);
}
```

### 4. Update `isResponseInArrayMode()` to use the parameter

```javascript
isResponseInArrayMode() {
return this._isResponseInArrayMode;
}
```

## Additional Context

This issue affects any query using the Prisma adapter where field aliases are specified. The problem is that the Prisma adapter implementation doesn't follow the same pattern as other drizzle drivers (like `node-postgres`), which properly handle the `fields` parameter for mapping.

The `fields` array contains objects with:
- `field.field.name`: The actual database column name
- `field.path`: An array where the first element is the user-specified alias

## Verification

After applying the fix, the test passes:

```typescript
test('field mapping works', async () => {
const [result] = await prisma.$drizzle
.select({
id: schema.partners.partnerId,
})
.from(schema.partners)
.limit(1);
expect(result).toHaveProperty('id'); // ✅ Now passes
});
```

## References

- Similar implementation in node-postgres adapter: `drizzle-orm/node-postgres/session.js`

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.