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 | 551x 545x 545x 33530x 6x 6x 4x 4x 1x 1x 2x 1x 1x 1x 3x 33531x 33531x 33531x 176542x 101454x 75088x 33531x 101460x 101351x 8x 8x 7x 1x 1x 21x 194x | /**
* 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')
} |