update to sqlite database WIP

This commit is contained in:
DocNR 2025-02-04 17:50:40 -05:00
parent 00a8157c7c
commit 855c034a35
3 changed files with 108 additions and 178 deletions

View File

@ -1,89 +1,24 @@
// types/sqlite.ts
// Database interfaces
export interface SQLite {
rows: {
_array: any[];
length: number;
item: (idx: number) => any;
};
rowsAffected: number;
insertId?: number;
}
// Transaction interfaces
export interface SQLiteCallback {
(transaction: SQLTransaction, resultSet: SQLite): void;
}
export interface SQLErrorCallback {
(transaction: SQLTransaction, error: Error): boolean;
}
export interface SQLTransaction {
executeSql: (
sqlStatement: string,
args?: (string | number | null)[],
callback?: SQLiteCallback,
errorCallback?: SQLErrorCallback
) => void;
}
// Database error interfaces
export interface SQLError extends Error {
code?: number;
}
// Database open options
export interface SQLiteOpenOptions {
enableChangeListener?: boolean;
useNewConnection?: boolean;
}
// Result interfaces
export interface SQLiteRunResult {
insertId: number;
rowsAffected: number;
}
export interface SQLiteRow {
[key: string]: any;
}
export interface SQLiteResultSet {
insertId?: number;
rowsAffected: number;
rows: {
length: number;
_array: SQLiteRow[];
item: (index: number) => SQLiteRow;
};
}
// Transaction callbacks
export interface TransactionCallback {
(tx: SQLTransaction): void;
}
export interface TransactionErrorCallback {
(error: SQLError): void;
}
export interface TransactionSuccessCallback {
(): void;
}
// Database static type
export interface Database {
transaction(
callback: TransactionCallback,
error?: TransactionErrorCallback,
success?: TransactionSuccessCallback
): void;
readTransaction(
callback: TransactionCallback,
error?: TransactionErrorCallback,
success?: TransactionSuccessCallback
): void;
closeAsync(): Promise<void>;
}
export interface SQLiteRow {
[key: string]: any;
}
export interface SQLiteResult<T = SQLiteRow> {
rows: {
_array: T[];
length: number;
item: (idx: number) => T;
};
rowsAffected: number;
insertId?: number;
}
export interface SQLiteError extends Error {
code?: number;
}
export interface SQLiteStatement {
executeSync<T>(params?: any[]): T[] | null;
finalizeSync(): void;
}

View File

@ -1,119 +1,105 @@
// utils/db/db-service.ts
import * as SQLite from 'expo-sqlite';
import {
SQLite as SQLiteResult,
SQLTransaction,
SQLiteCallback,
SQLErrorCallback,
SQLError,
TransactionCallback,
TransactionErrorCallback,
TransactionSuccessCallback
openDatabaseSync,
SQLiteDatabase
} from 'expo-sqlite';
import {
SQLiteResult,
SQLiteError,
SQLiteRow
} from '@/types/sqlite';
export class DbService {
private db: SQLite.SQLiteDatabase;
private db: SQLiteDatabase | null = null;
constructor(dbName: string) {
this.db = SQLite.openDatabaseSync(dbName);
try {
this.db = openDatabaseSync(dbName);
console.log('Database opened:', this.db);
} catch (error) {
console.error('Error opening database:', error);
throw error;
}
}
async executeSql(sql: string, params: (string | number | null)[] = []): Promise<SQLiteResult> {
return new Promise((resolve, reject) => {
this.db.withTransactionAsync(async (tx) => {
tx.executeSql(
sql,
params,
(_, result) => resolve(result),
(_, error) => {
console.error('SQL Error:', error);
reject(error);
return false;
}
);
}).catch(error => {
console.error('Transaction Error:', error);
reject(error);
});
});
async executeSql<T extends SQLiteRow = any>(
sql: string,
params: (string | number | null)[] = []
): Promise<SQLiteResult<T>> {
if (!this.db) {
throw new Error('Database not initialized');
}
try {
const statement = this.db.prepareSync(sql);
const result = statement.executeSync<T>(params);
statement.finalizeSync();
return {
rows: {
_array: Array.isArray(result) ? result : [],
length: Array.isArray(result) ? result.length : 0,
item: (idx: number) => (Array.isArray(result) ? result[idx] : null) as T
},
rowsAffected: Array.isArray(result) ? result.length : 0,
insertId: undefined // SQLite doesn't provide this directly
};
} catch (error) {
console.error('SQL Error:', error, sql, params);
throw error;
}
}
async executeWrite(sql: string, params: (string | number | null)[] = []): Promise<SQLiteResult> {
return this.executeSql(sql, params);
async executeWrite<T extends SQLiteRow = any>(
sql: string,
params: (string | number | null)[] = []
): Promise<SQLiteResult<T>> {
return this.executeSql<T>(sql, params);
}
async executeWriteMany(queries: { sql: string; args?: (string | number | null)[] }[]): Promise<SQLiteResult[]> {
return new Promise((resolve, reject) => {
const results: SQLiteResult[] = [];
this.db.withTransactionAsync(async (tx) => {
try {
for (const query of queries) {
await new Promise<void>((resolveQuery, rejectQuery) => {
tx.executeSql(
query.sql,
query.args || [],
(_, result) => {
results.push(result);
resolveQuery();
},
(_, error) => {
console.error('SQL Error:', error);
rejectQuery(error);
return false;
}
);
});
}
resolve(results);
} catch (error) {
console.error('Transaction Error:', error);
reject(error);
}
}).catch(error => {
console.error('Transaction Error:', error);
reject(error);
});
});
}
async executeWriteMany<T extends SQLiteRow = any>(
queries: Array<{
sql: string;
args?: (string | number | null)[]
}>
): Promise<SQLiteResult<T>[]> {
if (!this.db) {
throw new Error('Database not initialized');
}
async withTransaction<T>(
callback: (tx: SQLTransaction) => Promise<T>
): Promise<T> {
return new Promise((resolve, reject) => {
this.db.withTransactionAsync(async (tx) => {
try {
const result = await callback(tx);
resolve(result);
} catch (error) {
console.error('Transaction Error:', error);
reject(error);
}
}).catch(error => {
console.error('Transaction Error:', error);
reject(error);
});
});
const results: SQLiteResult<T>[] = [];
for (const query of queries) {
try {
const result = await this.executeSql<T>(query.sql, query.args || []);
results.push(result);
} catch (error) {
console.error('Error executing query:', query, error);
throw error;
}
}
return results;
}
async tableExists(tableName: string): Promise<boolean> {
try {
const result = await this.executeSql(
const result = await this.executeSql<{ name: string }>(
`SELECT name FROM sqlite_master WHERE type='table' AND name=?`,
[tableName]
);
return result.rows.length > 0;
return result.rows._array.length > 0;
} catch (error) {
console.error('Error checking table existence:', error);
return false;
}
}
async close(): Promise<void> {
async initialize(): Promise<void> {
try {
await this.db.closeAsync();
await this.executeSql('PRAGMA foreign_keys = ON;');
} catch (error) {
console.error('Error closing database:', error);
console.error('Error initializing database:', error);
throw error;
}
}

View File

@ -203,10 +203,19 @@ class Schema {
}
private async setVersion(version: number): Promise<void> {
await this.db.executeSql(
'INSERT INTO schema_version (version, updated_at) VALUES (?, ?)',
[version, Date.now()]
);
try {
await this.db.executeSql(
'DELETE FROM schema_version WHERE version = ?',
[version]
);
await this.db.executeSql(
'INSERT INTO schema_version (version, updated_at) VALUES (?, ?)',
[version, Date.now()]
);
} catch (error) {
console.error('Error setting schema version:', error);
throw error;
}
}
}