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 | 565x 547x 547x 33532x 18x 18x 12x 12x 3x 3x 6x 3x 3x 3x 9x 33535x 33535x 33535x 176550x 101458x 75092x 33535x 101476x 101363x 18x 18x 15x 3x 3x 23x 222x | /**
* SQLite database executor
* Works with better-sqlite3 driver
*/
import type { SQL } from 'drizzle-orm'
import type { DrizzleDatabase } from '../types'
import { BaseDatabaseExecutor } from './base-executor'
export class SQLiteExecutor extends BaseDatabaseExecutor {
async execute<T = any[]>(query: SQL | any, numericFields?: string[]): Promise<T> {
// Handle Drizzle query objects directly
if (query && typeof query === 'object' && typeof query.execute === 'function') {
// This is a Drizzle query object, execute it directly
const result = await query.execute()
Eif (Array.isArray(result)) {
return result.map(row => this.convertNumericFields(row, numericFields)) as T
}
return result as T
}
// SQLite is synchronous, but we wrap in Promise for consistency
try {
// For SQLite with better-sqlite3, we need to execute through the Drizzle instance
// The query is already a prepared Drizzle SQL object that handles parameter binding
if (this.db.all) {
const result = this.db.all(query)
if (Array.isArray(result)) {
return result.map(row => this.convertNumericFields(row, numericFields)) as T
}
return result as T
} else if (this.db.run) {
// Fallback to run method if all is not available
const result = this.db.run(query)
return result as T
} else {
throw new Error('SQLite database instance must have an all() or run() method')
}
} catch (error) {
throw new Error(`SQLite execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`)
}
}
/**
* 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 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.)
Eif (!isNaN(parseFloat(value)) && isFinite(parseFloat(value))) {
return parseFloat(value)
}
}
// Return as-is for non-numeric values
return value
}
getEngineType(): 'sqlite' {
return 'sqlite'
}
}
/**
* Factory function for creating SQLite executors
*/
export function createSQLiteExecutor(
db: DrizzleDatabase,
schema?: any
): SQLiteExecutor {
return new SQLiteExecutor(db, schema, 'sqlite')
} |