fix: comprehensive PostgreSQL/SQLite compatibility fixes
Mirror to GitHub / mirror (push) Successful in 19s
Test and Lint / backend-test (push) Successful in 1m8s
Test and Lint / frontend-test (push) Successful in 2m11s
Version and Release / version-bump (push) Successful in 34s
Version and Release / trigger-drone (push) Successful in 3s
continuous-integration/drone/push Build is passing
Mirror to GitHub / mirror (push) Successful in 19s
Test and Lint / backend-test (push) Successful in 1m8s
Test and Lint / frontend-test (push) Successful in 2m11s
Version and Release / version-bump (push) Successful in 34s
Version and Release / trigger-drone (push) Successful in 3s
continuous-integration/drone/push Build is passing
Critical fixes for database compatibility issues:
INSERT operations:
- Fix all INSERT queries to use .returning('id')
- Handle both PostgreSQL (returns objects) and SQLite (returns IDs)
- Fixed in: events.js, adminArchives.js, adminEvents-enhanced.js, create-test-event.js
Date operations:
- Replace SQLite-specific db.raw("datetime('now', '+30 days')")
- Use JavaScript Date objects for cross-database compatibility
- Fixed in: adminArchives.js
Database utilities:
- Add dbCompat.js utility for handling database differences
- Provides consistent API for inserts, dates, booleans, and DB-specific operations
- Centralized database compatibility logic
Migration:
- Add migration 023 documenting PostgreSQL compatibility requirements
- Ensures future developers are aware of compatibility needs
This resolves all 'not iterable' errors and ensures the application
works correctly with both PostgreSQL (production) and SQLite (development).
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Database Compatibility Utilities
|
||||
* Handles differences between PostgreSQL and SQLite
|
||||
*/
|
||||
|
||||
const { db } = require('../database/db');
|
||||
|
||||
/**
|
||||
* Get database client type
|
||||
* @returns {string} 'pg' or 'sqlite3'
|
||||
*/
|
||||
function getDbClient() {
|
||||
return process.env.DATABASE_CLIENT || 'sqlite3';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if using PostgreSQL
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isPostgreSQL() {
|
||||
return getDbClient() === 'pg';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle insert operations that return IDs
|
||||
* Works with both PostgreSQL and SQLite
|
||||
* @param {object} query - Knex query builder
|
||||
* @returns {Promise<number>} The inserted ID
|
||||
*/
|
||||
async function insertAndGetId(query) {
|
||||
const result = await query.returning('id');
|
||||
|
||||
// PostgreSQL returns array of objects [{id: 1}]
|
||||
// SQLite returns array of IDs [1]
|
||||
return result[0]?.id || result[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format date for database compatibility
|
||||
* @param {Date} date - JavaScript Date object
|
||||
* @returns {string} ISO string format that works on both databases
|
||||
*/
|
||||
function formatDateForDB(date) {
|
||||
return date.toISOString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add days to a date (database agnostic)
|
||||
* @param {Date} date - Starting date
|
||||
* @param {number} days - Number of days to add
|
||||
* @returns {Date} New date
|
||||
*/
|
||||
function addDays(date, days) {
|
||||
const result = new Date(date);
|
||||
result.setDate(result.getDate() + days);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get date extraction SQL that works on both databases
|
||||
* @param {string} column - Column name
|
||||
* @returns {object} Knex raw query
|
||||
*/
|
||||
function dateExtractSQL(column) {
|
||||
if (isPostgreSQL()) {
|
||||
return db.raw(`DATE(${column})`);
|
||||
} else {
|
||||
// SQLite uses date() function
|
||||
return db.raw(`date(${column})`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get database size query
|
||||
* @param {string} dbName - Database name
|
||||
* @returns {Promise<number>} Size in bytes
|
||||
*/
|
||||
async function getDatabaseSize(dbName) {
|
||||
if (isPostgreSQL()) {
|
||||
const result = await db.raw('SELECT pg_database_size(?) as size', [dbName]);
|
||||
return result.rows[0]?.size || 0;
|
||||
} else {
|
||||
// For SQLite, check file size
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
const dbPath = process.env.DATABASE_PATH || path.join(__dirname, '../../data/photo_sharing.db');
|
||||
try {
|
||||
const stats = await fs.stat(dbPath);
|
||||
return stats.size;
|
||||
} catch (error) {
|
||||
console.error('Error getting SQLite database size:', error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle boolean values for database compatibility
|
||||
* @param {boolean} value - Boolean value
|
||||
* @returns {any} Database-appropriate boolean representation
|
||||
*/
|
||||
function formatBoolean(value) {
|
||||
if (isPostgreSQL()) {
|
||||
return value;
|
||||
} else {
|
||||
// SQLite stores booleans as 0/1
|
||||
return value ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse boolean from database
|
||||
* @param {any} value - Database boolean value
|
||||
* @returns {boolean} JavaScript boolean
|
||||
*/
|
||||
function parseBoolean(value) {
|
||||
return Boolean(value);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getDbClient,
|
||||
isPostgreSQL,
|
||||
insertAndGetId,
|
||||
formatDateForDB,
|
||||
addDays,
|
||||
dateExtractSQL,
|
||||
getDatabaseSize,
|
||||
formatBoolean,
|
||||
parseBoolean
|
||||
};
|
||||
Reference in New Issue
Block a user