Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 7x 7x 2x 2x 2x 5x 1x 4x 4x 3x 1x 5x 5x 5x 9x 5x 4x 5x 33x 31x 27x 25x 10x 10x 10x 8x 2x 2x 15x 15x 7x 8x 6x 2x 1x 31x | /**
* PostgreSQL database executor
* Works with postgres.js and Neon drivers
*/
import type { SQL } from 'drizzle-orm'
import type { DrizzleDatabase } from '../types'
import { BaseDatabaseExecutor } from './base-executor'
export class PostgresExecutor extends BaseDatabaseExecutor {
async execute<T = any[]>(query: SQL | any, numericFields?: string[]): Promise<T> {
// Handle Drizzle query objects directly
Eif (query && typeof query === 'object') {
// Check for various execution methods that Drizzle queries might have
if (typeof query.execute === 'function') {
const result = await query.execute()
Eif (Array.isArray(result)) {
return result.map(row => this.convertNumericFields(row, numericFields)) as T
}
return result as T
}
}
// Handle raw SQL objects
if (!this.db.execute) {
throw new Error('PostgreSQL database instance must have an execute method')
}
const result = await this.db.execute(query)
// Convert numeric strings to numbers for PostgreSQL results
if (Array.isArray(result)) {
return result.map(row => this.convertNumericFields(row, numericFields)) as T
}
return result as T
}
/**
* Convert numeric string fields to numbers (only for measure fields)
*/
private convertNumericFields(row: any, numericFields?: string[]): any {
Iif (!row || typeof row !== 'object') return row
const converted: any = {}
for (const [key, value] of Object.entries(row)) {
// Only convert measure fields to numbers
// Dimensions and time dimensions should keep their original types
if (numericFields && numericFields.includes(key)) {
converted[key] = this.coerceToNumber(value)
} else {
converted[key] = value
}
}
return converted
}
/**
* Coerce a value to a number if it represents a numeric type
*/
private coerceToNumber(value: any): any {
// Handle null/undefined - preserve null values for aggregations
if (value == null) return value
// Already a number
if (typeof value === 'number') return value
// Handle BigInt values from COUNT operations
if (typeof value === 'bigint') return Number(value)
// Handle PostgreSQL-specific types (numeric, decimal objects)
if (value && typeof value === 'object') {
// Check if it has a numeric toString() method
Eif (typeof value.toString === 'function') {
const stringValue = value.toString()
if (/^-?\d+(\.\d+)?$/.test(stringValue)) {
return stringValue.includes('.') ? parseFloat(stringValue) : parseInt(stringValue, 10)
}
}
// Check for common PostgreSQL numeric type properties
Iif (value.constructor?.name === 'Numeric' ||
value.constructor?.name === 'Decimal' ||
'digits' in value ||
'sign' in value) {
const stringValue = value.toString()
return parseFloat(stringValue)
}
// If it's an object but doesn't look numeric, return as-is
return value
}
// Handle string representations of numbers
Eif (typeof value === 'string') {
// Check for exact numeric strings
if (/^-?\d+(\.\d+)?$/.test(value)) {
return value.includes('.') ? parseFloat(value) : parseInt(value, 10)
}
// Check for other numeric formats (scientific notation, etc.)
if (!isNaN(parseFloat(value)) && isFinite(parseFloat(value))) {
return parseFloat(value)
}
}
// Return as-is for non-numeric values
return value
}
getEngineType(): 'postgres' {
return 'postgres'
}
}
/**
* Factory function for creating PostgreSQL executors
*/
export function createPostgresExecutor(
db: DrizzleDatabase,
schema?: any
): PostgresExecutor {
return new PostgresExecutor(db, schema, 'postgres')
} |