#include "server_db_internal.h" Result(bool) Channel_exists(ServerQueries* q, i64 id){ Deferral(1); tsqlite_statement* st = q->channels.exists; Defer(tsqlite_statement_reset(st)); try_void(tsqlite_statement_bind_i64(st, "$id", id)); try(bool has_result, i, tsqlite_statement_step(st)); Return RESULT_VALUE(i, has_result); } Result(void) Channel_createOrUpdate(ServerQueries* q, i64 id, str name, str description) { Deferral(4); try_assert(id > 0); try_assert(name.len >= CHANNEL_NAME_SIZE_MIN && name.len <= CHANNEL_NAME_SIZE_MAX); try_assert(description.len <= CHANNEL_DESC_SIZE_MAX); tsqlite_statement* st = NULL; Defer(tsqlite_statement_reset(st)); try(bool channel_exists, i, Channel_exists(q, id)); if(channel_exists){ // update existing channel st = q->channels.update; } else { // insert new channel st = q->channels.insert; } try_void(tsqlite_statement_bind_i64(st, "$id", id)); try_void(tsqlite_statement_bind_str(st, "$name", name, NULL)); try_void(tsqlite_statement_bind_str(st, "$description", description, NULL)); try_void(tsqlite_statement_step(st)); Return RESULT_VOID; } Result(void) Channel_saveMessage(ServerQueries* q, i64 channel_id, i64 sender_id, Array(u8) content, DateTime* out_timestamp) { Deferral(1); try_assert(content.len >= MESSAGE_SIZE_MIN && content.len <= MESSAGE_SIZE_MAX); tsqlite_statement* st = q->messages.insert; Defer(tsqlite_statement_reset(st)); try_void(tsqlite_statement_bind_i64(st, "$channel_id", channel_id)); try_void(tsqlite_statement_bind_i64(st, "$sender_id", sender_id)); try_void(tsqlite_statement_bind_blob(st, "$content", content, NULL)); try(bool has_result, i, tsqlite_statement_step(st)); try_assert(has_result); try(i64 message_id, i, tsqlite_statement_getResult_i64(st)); str timestamp_str; try_void(tsqlite_statement_getResult_str(st, ×tamp_str)); try_void(DateTime_parse(timestamp_str.data, out_timestamp)); Return RESULT_VALUE(i, message_id); } Result(void) Channel_loadMessageBlock(ServerQueries* q, i64 channel_id, i64 first_message_id, u32 count, MessageBlockMeta* block_meta, Array(u8) block_data) { Deferral(1); try_assert(channel_id > 0); try_assert(block_data.len >= count * (sizeof(MessageMeta) + MESSAGE_SIZE_MAX)); if(count == 0){ Return RESULT_VOID; } tsqlite_statement* st = q->messages.get_block; Defer(tsqlite_statement_reset(st)); try_void(tsqlite_statement_bind_i64(st, "$channel_id", channel_id)); try_void(tsqlite_statement_bind_i64(st, "$first_message_id", first_message_id)); try_void(tsqlite_statement_bind_i64(st, "$count", count)); zeroStruct(block_meta); MessageMeta msg_meta = {0}; Array(u8) msg_content; str tmp_str = str_null; while(true){ try(bool has_result, i, tsqlite_statement_step(st)); if(!has_result) break; // id try(msg_meta.id, i, tsqlite_statement_getResult_i64(st)); // sender_id try(msg_meta.sender_id, i, tsqlite_statement_getResult_i64(st)); // content try_void(tsqlite_statement_getResult_blob(st, &msg_content)); // timestamp try_void(tsqlite_statement_getResult_str(st, &tmp_str)); try_void(DateTime_parse(tmp_str.data, &msg_meta.timestamp)); try(u32 write_n, u, MessageBlock_writeMessage(&msg_meta, msg_content, block_meta, &block_data)); try_assert(write_n > 0); } Return RESULT_VOID; }