This commit is contained in:
2026-03-18 17:10:46 +07:00
parent 9f9d41f14a
commit 9fa65ba4af
2 changed files with 201 additions and 46 deletions

View File

@@ -166,20 +166,24 @@ app.get('/api/tables', requireAuth, async (req, res) => {
}
});
// Get table data with pagination and search
// Get table data with pagination, search, filters and sort
app.get('/api/tables/:tableName/data', requireAuth, async (req, res) => {
const { tableName } = req.params;
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const search = req.query.search || '';
const filters = req.query.filters ? JSON.parse(req.query.filters) : [];
const sortColumn = req.query.sortColumn || '';
const sortDirection = req.query.sortDirection || 'ASC';
const offset = (page - 1) * limit;
try {
let whereClause = '';
let params = [limit, offset];
let paramIndex = 3; // $1=limit, $2=offset, $3+ for conditions
// Search
if (search) {
// Get column names for search
const columnsResult = await pool.query(`
SELECT column_name
FROM information_schema.columns
@@ -188,20 +192,88 @@ app.get('/api/tables/:tableName/data', requireAuth, async (req, res) => {
`, [tableName]);
const columns = columnsResult.rows.map(row => row.column_name);
const searchConditions = columns.map(col => `CAST("${col}" AS TEXT) ILIKE $${params.length + 1}`).join(' OR ');
const searchConditions = columns.map(col => `CAST("${col}" AS TEXT) ILIKE $${paramIndex}`).join(' OR ');
whereClause = `WHERE ${searchConditions}`;
params.push(`%${search}%`);
paramIndex++;
}
// Filters
if (filters.length > 0) {
const filterConditions = filters.map(filter => {
const { column, operator, value } = filter;
let condition = '';
switch (operator) {
case '=':
condition = `"${column}" = $${paramIndex}`;
params.push(value);
paramIndex++;
break;
case '!=':
condition = `"${column}" != $${paramIndex}`;
params.push(value);
paramIndex++;
break;
case '>':
condition = `"${column}" > $${paramIndex}`;
params.push(value);
paramIndex++;
break;
case '<':
condition = `"${column}" < $${paramIndex}`;
params.push(value);
paramIndex++;
break;
case '>=':
condition = `"${column}" >= $${paramIndex}`;
params.push(value);
paramIndex++;
break;
case '<=':
condition = `"${column}" <= $${paramIndex}`;
params.push(value);
paramIndex++;
break;
case 'LIKE':
condition = `"${column}" LIKE $${paramIndex}`;
params.push(`%${value}%`);
paramIndex++;
break;
case 'ILIKE':
condition = `"${column}" ILIKE $${paramIndex}`;
params.push(`%${value}%`);
paramIndex++;
break;
case 'IS NULL':
condition = `"${column}" IS NULL`;
break;
case 'IS NOT NULL':
condition = `"${column}" IS NOT NULL`;
break;
}
return condition;
}).filter(c => c).join(' AND ');
whereClause = whereClause ? `${whereClause} AND ${filterConditions}` : `WHERE ${filterConditions}`;
}
// Get total count
const countResult = await pool.query(`SELECT COUNT(*) as total FROM "${tableName}" ${whereClause}`, params.slice(2));
const total = parseInt(countResult.rows[0].total);
// Build ORDER BY
let orderBy = 'ORDER BY (SELECT NULL)'; // Default no order
if (sortColumn) {
orderBy = `ORDER BY "${sortColumn}" ${sortDirection}`;
}
// Get data
const result = await pool.query(`
SELECT * FROM "${tableName}"
${whereClause}
ORDER BY (SELECT NULL) -- No specific order, but consistent
${orderBy}
LIMIT $1 OFFSET $2
`, params);