| 475 | } |
| 476 | |
| 477 | executeAiSQL(sql: string): { |
| 478 | columns: string[] |
| 479 | rows: unknown[][] |
| 480 | rowCount: number |
| 481 | duration: number |
| 482 | limited: boolean |
| 483 | } { |
| 484 | const db = this.getDb() |
| 485 | const start = Date.now() |
| 486 | const trimmed = sql.trim() |
| 487 | const isSelect = /^SELECT/i.test(trimmed) |
| 488 | |
| 489 | if (isSelect) { |
| 490 | const stmt = db.prepare(trimmed) |
| 491 | const rows = stmt.all() as Record<string, unknown>[] |
| 492 | const duration = Date.now() - start |
| 493 | const columns = rows.length > 0 ? Object.keys(rows[0]) : [] |
| 494 | return { |
| 495 | columns, |
| 496 | rows: rows.map((r) => columns.map((c) => r[c])), |
| 497 | rowCount: rows.length, |
| 498 | duration, |
| 499 | limited: false, |
| 500 | } |
| 501 | } else { |
| 502 | const result = db.prepare(trimmed).run() |
| 503 | const duration = Date.now() - start |
| 504 | return { |
| 505 | columns: ['changes', 'lastInsertRowid'], |
| 506 | rows: [[result.changes, Number(result.lastInsertRowid)]], |
| 507 | rowCount: 1, |
| 508 | duration, |
| 509 | limited: false, |
| 510 | } |
| 511 | } |
| 512 | } |
| 513 | |
| 514 | // ==================== 对话管理 ==================== |
| 515 | |