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 | 556x 556x 551x 540x 33483x 5x 1x 4x 4x 3x 1x 33486x 33486x 33486x 176338x 101312x 75026x 33486x 101340x 101237x 84796x 84794x 10x 10x 10x 8x 2x 2x 84784x 84784x 84776x 8x 6x 2x 21x 206x | /**
* 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')
} |