Skip to content

Commit

Permalink
optimize useQueryData
Browse files Browse the repository at this point in the history
  • Loading branch information
vwh committed Aug 11, 2024
1 parent c198a9f commit 59c45cc
Showing 1 changed file with 83 additions and 96 deletions.
179 changes: 83 additions & 96 deletions src/hooks/useQueryData.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect, useCallback } from "react";
import { useState, useEffect, useCallback, useMemo } from "react";
import useSQLiteStore from "@/store/useSQLiteStore";

import { mapQueryResults } from "@/lib/sqlite";
Expand Down Expand Up @@ -31,116 +31,103 @@ export function useQueryData(
const [columns, setColumns] = useState<string[]>([]);
const [isQueryLoading, setIsQueryLoading] = useState(true);

// Only god knows what this does but it is the main useEffect for all the site
useEffect(() => {
if (db && tableName) {
setIsQueryLoading(true);
(async () => {
try {
const columnInfoQuery = `PRAGMA table_info("${tableName}");`;
const columnInfoResult: QueryExecResult[] = query(columnInfoQuery);
const columnInfo = columnInfoResult[0].values.map((row) => ({
name: row[1] as string,
type: row[2] as string
}));
const cleanFilters = useMemo(() => {
return Object.fromEntries(
Object.entries(filters).filter(([, value]) => value !== "")
);
}, [filters]);

// Construct the query string with BLOB columns converted to hex
const columnSelects = columnInfo
.map((col) =>
col.type.toUpperCase() === "BLOB"
? `hex(${col.name}) as ${col.name}`
: col.name
)
.join(", ");
const filterQuery = useMemo(() => {
return Object.entries(cleanFilters)
.map(([key, value]) => `LOWER(${key}) LIKE LOWER('%${value}%')`)
.join(" AND ");
}, [cleanFilters]);

const cleanFilters = Object.fromEntries(
Object.entries(filters).filter(([, value]) => value !== "")
);
// Construct the count query string
let countQueryString = `SELECT COUNT(*) as count FROM "${tableName}"`;
if (Object.keys(cleanFilters).length > 0) {
const filterQuery = Object.entries(cleanFilters)
.map(([key, value]) => {
return `LOWER(${key}) LIKE LOWER('%${value}%')`;
})
.join(" AND ");
countQueryString = `SELECT COUNT(*) as count FROM "${tableName}" WHERE ${filterQuery}`;
}
// Fetch data effect
useEffect(() => {
if (!db || !tableName) return;

// Execute the count query
const countResult: QueryExecResult[] = query(countQueryString);
const totalRows = countResult[0].values[0][0] as number;
setTotalRows(totalRows);
const fetchData = async () => {
setIsQueryLoading(true);
try {
// Fetch column info
const columnInfoQuery = `PRAGMA table_info("${tableName}");`;
const columnInfoResult: QueryExecResult[] = query(columnInfoQuery);
const columnInfo = columnInfoResult[0].values.map((row) => ({
name: row[1] as string,
type: row[2] as string
}));

// Construct the data query string
let queryString = `SELECT ${columnSelects} FROM "${tableName}"`;
if (Object.keys(cleanFilters).length > 0) {
const filterQuery = Object.entries(cleanFilters)
.map(([key, value]) => {
return `LOWER(${key}) LIKE LOWER('%${value}%')`;
})
.join(" AND ");
queryString += ` WHERE ${filterQuery}`;
}
// optimize blob columns
const columnSelects = columnInfo
.map((col) =>
col.type.toUpperCase() === "BLOB"
? `hex(${col.name}) as ${col.name}`
: col.name
)
.join(", ");

if (orderBy)
queryString += ` ORDER BY "${orderBy}" ${orderByDirection}`;
queryString += ` LIMIT ${rowsPerPage} OFFSET ${page};`;
// Count query
const countQueryString = `SELECT COUNT(*) as count FROM "${tableName}"${
filterQuery ? ` WHERE ${filterQuery}` : ""
}`;
const countResult: QueryExecResult[] = query(countQueryString);
const totalRows = countResult[0].values[0][0] as number;
setTotalRows(totalRows);

const tableResult: QueryExecResult[] = query(queryString);
const { data, columns } = mapQueryResults(tableResult);
setColumns(columns);
setData(data);
setQueryError(null);
setCustomQuery(queryString);
unShiftToQueryHistory(queryString);
} catch (error) {
if (error instanceof Error) setQueryError(error.message);
} finally {
setIsQueryLoading(false);
}
})();
}
}, [
db,
tableName,
page,
rowsPerPage,
setQueryError,
query,
unShiftToQueryHistory,
filters,
setTotalRows,
orderBy,
orderByDirection
]);
let queryString = `SELECT ${columnSelects} FROM "${tableName}"`;
if (filterQuery) queryString += ` WHERE ${filterQuery}`;
if (orderBy)
queryString += ` ORDER BY "${orderBy}" ${orderByDirection}`;

const handleCustomQuery = useCallback(() => {
if (customQuery.trim() === "") {
setQueryError(null);
return;
}
setIsQueryLoading(true);
(async () => {
try {
const tableName = tables[parseInt(selectedTable)].name;
const customResult: QueryExecResult[] = query(
// @ used to represent the current table name
// Just for a shorter query :/
customQuery.replace("@", `"${tableName}"`)
);
const { data, columns } = mapQueryResults(customResult);
queryString += ` LIMIT ${rowsPerPage} OFFSET ${page};`;

const tableResult: QueryExecResult[] = query(queryString);
const { data, columns } = mapQueryResults(tableResult);
setColumns(columns);
setData(data);
setIsCustomQuery(true);
setQueryError(null);
setCustomQuery(queryString);
unShiftToQueryHistory(queryString);
} catch (error) {
if (error instanceof Error) setQueryError(error.message);
} finally {
setIsQueryLoading(false);
}
})();
}, [customQuery, query, setQueryError, setIsCustomQuery]);
};

fetchData();
}, [db, tableName, page, rowsPerPage, filterQuery, orderByDirection]);

const handleCustomQuery = useCallback(() => {
if (customQuery.trim() === "") {
setQueryError(null);
return;
}
setIsQueryLoading(true);
try {
const tableName = tables[parseInt(selectedTable)].name;
const customResult: QueryExecResult[] = query(
customQuery.replace("@", `"${tableName}"`)
);
const { data, columns } = mapQueryResults(customResult);
setColumns(columns);
setData(data);
setIsCustomQuery(true);
setQueryError(null);
} catch (error) {
if (error instanceof Error) setQueryError(error.message);
} finally {
setIsQueryLoading(false);
}
}, [
customQuery,
query,
setQueryError,
setIsCustomQuery,
tables,
selectedTable
]);

return {
data,
Expand Down

0 comments on commit 59c45cc

Please sign in to comment.