stream-chat-react-native-core
Version:
The official React Native and Expo components for Stream Chat, a service for building chat applications
49 lines (43 loc) • 2.12 kB
text/typescript
import { Schema, tables } from '../schema';
import type { PreparedQueries, TableColumnNames, TableRow } from '../types';
/**
* Creates a simple upsert query for sqlite.
*
* @param {string} table Table name
* @param {Object} row Table row to insert or update.
* @param {Array} conflictCheckKeys Custom list of columns to check conflicts for - https://www.sqlite.org/lang_UPSERT.html. By default conflicts are checked on primary keys.
* @returns {string} Final upsert query for sqlite
*/
export const createUpsertQuery = <T extends keyof Schema>(
table: T,
row: Partial<TableRow<T>>,
conflictCheckKeys?: Array<TableColumnNames<T>>,
): PreparedQueries => {
const filteredRow: typeof row = {};
// In case of "DO UPDATE SET", we only want to update the properties which
// are provided, and not set undefined properties in database.
// E.g., channel date such as `own_capabilities` is only available in response of client.queryChannels or channel.query.
// But its not available in `event.channel`. And our mapper functions such as mapChannelToStorable will set fields which are not available as undefined.
// So when you execute upsert query for storable value of `event.channel` in `channels` table, it will
// unset ownCapabilities field for that channel in `channels` table.
for (const key in row) {
if (row[key] !== undefined) {
filteredRow[key] = row[key];
}
}
const fields = Object.keys(filteredRow) as (keyof typeof row)[];
const questionMarks = Array(Object.keys(fields).length).fill('?').join(',');
const conflictKeys = conflictCheckKeys || tables[table].primaryKey || [];
const conflictMatchersWithoutPK: string[] = (fields as string[])
.filter((f) => !(conflictKeys as string[]).includes(f))
.map((f) => `${f}=excluded.${f}`);
const conflictConstraint =
conflictKeys.length > 0
? `ON CONFLICT(${conflictKeys.join(',')}) DO UPDATE SET
${conflictMatchersWithoutPK.join(',')}`
: '';
return [
`INSERT INTO ${table} (${fields.join(',')}) VALUES (${questionMarks}) ${conflictConstraint}`,
Object.values(filteredRow),
];
};