error messages after incorrect login. sendmessage. small refactoring

This commit is contained in:
Андреев Григорий 2024-08-26 18:04:03 +03:00
parent 5a07cadd4a
commit 807f0d0eab
29 changed files with 189 additions and 86 deletions

View File

@ -1,4 +1,4 @@
{% ELDEF main JSON pres JSON userinfo %} {% ELDEF main JSON pres JSON userinfo JSON errors %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{% WRITE pres.lang %}"> <html lang="{% WRITE pres.lang %}">
<head> <head>
@ -6,11 +6,15 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% WRITE pres.phr.decl.page-login %}</title> <title>{% WRITE pres.phr.decl.page-login %}</title>
<link rel="stylesheet" href="/assets/css/login.css"> <link rel="stylesheet" href="/assets/css/login.css">
</head> </head>
<body> <body>
{% PUT pass-pres-userinfo pres userinfo %} {% PUT pass-pres-userinfo pres userinfo %}
{% FOR msg IN errors %}
<div class="error-msg">
{% WRITE msg %}
</div>
{% ENDFOR %}
<div class="form-container"> <div class="form-container">
<h1 class="hide-cursor no-select">{% WRITE pres.phr.decl.enter %}</h1> <h1 class="hide-cursor no-select">{% WRITE pres.phr.decl.enter %}</h1>
<form action="/login" method="post" enctype="application/x-www-form-urlencoded"> <form action="/login" method="post" enctype="application/x-www-form-urlencoded">

View File

@ -1,4 +1,5 @@
dy { /* I have no idea what is going on here */
body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -50,28 +51,9 @@ button {
transition: background-color 0.3s; transition: background-color 0.3s;
} }
button:hover, .error-msg {
button:focus-visible {
background-color: #007bb5;
}
.hide-cursor::placeholder {
color: #000;
}
.hide-cursor {
caret-color: transparent;
}
.no-select {
-webkit-user-select: none; /* Для Safari */
-moz-user-select: none; /* Для Firefox */
user-select: none; /* Для всех остальных браузеров */
}
div {
color: red; color: red;
font-size: 15px; background-color: #ffc0c0;
margin-top: 10px; border-color: red;
display: none; border-radius: 5px;
} }

View File

@ -153,19 +153,19 @@ struct CAWebChat {
"backend_logic/when_login.cpp", "backend_logic/when_login.cpp",
"backend_logic/when_chat.cpp", "backend_logic/when_chat.cpp",
"backend_logic/when_user.cpp", "backend_logic/when_user.cpp",
"backend_logic/when_api_pollevents.cpp", "backend_logic/api_pollevents.cpp",
"backend_logic/when_api_getchatlist.cpp", "backend_logic/api_getchatlist.cpp",
"backend_logic/when_api_getchatinfo.cpp", "backend_logic/api_getchatinfo.cpp",
"backend_logic/when_api_getchatmemberlist.cpp", "backend_logic/api_getchatmemberlist.cpp",
"backend_logic/when_api_getuserinfo.cpp", "backend_logic/api_getuserinfo.cpp",
"backend_logic/when_api_getmessageinfo.cpp", "backend_logic/api_getmessageinfo.cpp",
"backend_logic/when_api_getmessageneighbours.cpp", "backend_logic/api_getmessageneighbours.cpp",
"backend_logic/when_api_sendmessage.cpp", "backend_logic/api_sendmessage.cpp",
"backend_logic/when_api_deletemessage.cpp", "backend_logic/api_deletemessage.cpp",
"backend_logic/when_api_addmembertochat.cpp", "backend_logic/api_addmembertochat.cpp",
"backend_logic/when_api_removememberfromchat.cpp", "backend_logic/api_removememberfromchat.cpp",
"backend_logic/when_api_createchat.cpp", "backend_logic/api_createchat.cpp",
"backend_logic/when_api_removechat.cpp", "backend_logic/api_removechat.cpp",
}; };
for (std::string& u: T.units) for (std::string& u: T.units)
u = "web_chat/iu9_ca_web_chat_lib/" + u; u = "web_chat/iu9_ca_web_chat_lib/" + u;

View File

@ -12,7 +12,9 @@
"page-login": "Вход", "page-login": "Вход",
"list-of-chat-rooms": "Список Чат-Коsмнат", "list-of-chat-rooms": "Список Чат-Коsмнат",
"name-of-room": "Название комнаты", "name-of-room": "Название комнаты",
"create-room": "Создать комнату" "create-room": "Создать комнату",
"incorrect-nickname-or-password": "Неправильный никнейм или пароль"
}, },
"ask" : { "ask" : {
"select-chat-room": "Выберете чат комнату" "select-chat-room": "Выберете чат комнату"

View File

@ -97,6 +97,37 @@ namespace iu9cawebchat {
} }
} }
int64_t event_polling_fill_chat_hist_entity_response(SqliteConnection& conn, json::JSON& hist_entity_response,
int64_t uid, int64_t chatId, int64_t LocalHistoryId) {
hist_entity_response["type"] = json::JSON("chat");
if (get_role_of_user_in_chat(conn, uid, chatId) == user_chat_role_deleted)
een9_THROW("internalapi/pollEvents: trying to access chat that user does not belong to");
hist_entity_response["chatId"] = json::JSON(chatId);
int64_t NewHistoryId = get_current_history_id_of_chat(conn, chatId);
hist_entity_response["HistoryId"] = json::JSON(NewHistoryId);
hist_entity_response["events"] = json::JSON(json::array);
std::vector<json::JSON>& events = hist_entity_response["events"].g().asArray();
/* Two classes of 'real events' can happen to chat: membership table change, message table change */
/* Here, I collect membership changes (related to this chat) */
internalapi_pollEvents_in_chat_collect_membership_events(conn, events, chatId, LocalHistoryId);
/* Here, I collect message changes (related to this chat) */
internalapi_pollEvents_in_chat_collect_messages_events(conn, events, chatId, LocalHistoryId);
return NewHistoryId;
}
int64_t event_polling_fill_chatlist_hist_entity_response(SqliteConnection& conn, json::JSON& hist_entity_response,
int64_t uid, int64_t LocalHistoryId) {
hist_entity_response["type"] = json::JSON("chatlist");
int64_t NewHistoryId = get_current_history_id_of_user_chatList(conn, uid);
hist_entity_response["HistotyId"] = json::JSON(NewHistoryId);
hist_entity_response["events"] = json::JSON(json::array);
std::vector<json::JSON>& events = hist_entity_response["events"].g().asArray();
internalapi_pollEvents_in_user_chatList_collect_events(conn, events, uid, LocalHistoryId);
return NewHistoryId;
}
json::JSON internalapi_pollEvents(SqliteConnection& conn, int64_t uid, const json::JSON& Sent) { json::JSON internalapi_pollEvents(SqliteConnection& conn, int64_t uid, const json::JSON& Sent) {
json::JSON Recv; json::JSON Recv;
Recv["status"] = json::JSON(0l); Recv["status"] = json::JSON(0l);
@ -106,27 +137,15 @@ namespace iu9cawebchat {
for (const json::JSON& hist_entity_request: req_scope) { for (const json::JSON& hist_entity_request: req_scope) {
updated.emplace_back(); updated.emplace_back();
json::JSON& hist_entity_response = updated.back(); json::JSON& hist_entity_response = updated.back();
hist_entity_response["type"] = hist_entity_request["type"].g();
hist_entity_response["events"] = json::JSON(json::array);
std::vector<json::JSON>& events = hist_entity_response["events"].g().asArray();
const int64_t LocalHistoryId = hist_entity_request["LocalHistoryId"].g().asInteger().get_int(); const int64_t LocalHistoryId = hist_entity_request["LocalHistoryId"].g().asInteger().get_int();
if (hist_entity_request["type"].g().asString() == "chat") { if (hist_entity_request["type"].g().asString() == "chat") {
int64_t chatId = hist_entity_request["chatId"].g().asInteger().get_int(); int64_t chatId = hist_entity_request["chatId"].g().asInteger().get_int();
if (get_role_of_user_in_chat(conn, uid, chatId) == user_chat_role_deleted) event_polling_fill_chat_hist_entity_response(conn, hist_entity_response, uid, chatId, LocalHistoryId);
een9_THROW("internalapi/pollEvents: trying to access chat that user does not belong to");
hist_entity_response["chatId"] = json::JSON(chatId);
hist_entity_response["HistoryId"] = json::JSON(get_current_history_id_of_chat(conn, chatId));
/* Two classes of 'real events' can happen to chat: membership table change, message table change */
/* Here, I collect membership changes (related to this chat) */
internalapi_pollEvents_in_chat_collect_membership_events(conn, events, chatId, LocalHistoryId);
/* Here, I collect message changes (related to this chat) */
internalapi_pollEvents_in_chat_collect_messages_events(conn, events, chatId, LocalHistoryId);
} else if (hist_entity_request["type"].g().asString() == "chatlist") { } else if (hist_entity_request["type"].g().asString() == "chatlist") {
hist_entity_response["HistotyId"] = json::JSON(get_current_history_id_of_user_chatList(conn, uid)); event_polling_fill_chatlist_hist_entity_response(conn, hist_entity_response, uid, LocalHistoryId);
internalapi_pollEvents_in_user_chatList_collect_events(conn, events, uid, LocalHistoryId);
} else } else
een9_THROW("Bad request"); een9_THROW("Bad request");
} }
return Recv; return Recv;
} }
} }

View File

@ -0,0 +1,48 @@
#include "server_data_interact.h"
#include <engine_engine_number_9/baza_throw.h>
#include "../str_fields.h"
namespace iu9cawebchat {
/* Throws excetion on failure
* Chat's HistoryId will increment after this operation, incremented
* if adding system message, uid is ignored
*/
int64_t insert_new_message(SqliteConnection& conn, int64_t uid, int64_t chatId,
const std::string& text, bool isSystem) {
int64_t chat_HistoryId_BEFORE_MSG = get_current_history_id_of_chat(conn, chatId);
if (chat_HistoryId_BEFORE_MSG > INT64_MAX - 100)
een9_THROW("please no");
SqliteStatement req(conn,
"INSERT INTO `message` (`chatId`, `previous`, `senderUserId`, `exists`, `isSystem`, `text`,"
"`chat_IncHistoryId`) VALUES (?1, ?2, ?3, 1, ?4, ?5, ?6)",
{{1, chatId}, {4, (int64_t)isSystem}, {6, chat_HistoryId_BEFORE_MSG + 1}}, {{5, text}});
int64_t chat_cur_last_msg_id = get_lastMsgId_of_chat(conn, chatId);
if (chat_cur_last_msg_id >= 0)
sqlite_stmt_bind_int64(req, 2, chat_cur_last_msg_id);
if (!isSystem)
sqlite_stmt_bind_int64(req, 3, uid);
int64_t MSG_ID = sqlite_trsess_last_insert_rowid(conn);
sqlite_nooutput(conn, "UPDATE `chat` SET `lastMsgId` = ?1, `it_HistoryId` = ?2 WHERE `id` = ?3",
{{1, MSG_ID}, {2, chat_HistoryId_BEFORE_MSG + 1}, {3, chatId}}, {});
return MSG_ID;
}
json::JSON internalapi_sendMessage(SqliteConnection& conn, int64_t uid, const json::JSON& Sent) {
int64_t chatId = Sent["chatId"].g().asInteger().get_int();
int64_t my_role_here = get_role_of_user_in_chat(conn, uid, chatId);
if (my_role_here == user_chat_role_deleted)
een9_THROW("Unauthorized user tries to access internalapi_getChatInfo");
if (my_role_here == user_chat_role_read_only)
een9_THROW("read-only user can't send messages");
const int64_t LocalHistoryId = Sent["LocalHistoryId"].g().asInteger().get_int();
std::string text = Sent["content"]["text"].g().asString();
if (!is_orthodox_string(text) || text.empty())
een9_THROW("Bad input text");
int64_t MSG_ID = insert_new_message(conn, uid, chatId, text, false);
json::JSON Recv;
Recv["status"] = json::JSON(0l);
json::JSON hist_ent_response = Recv["update"][0].g();
event_polling_fill_chat_hist_entity_response(conn, hist_ent_response, uid, chatId, LocalHistoryId);
return Recv;
}
}

View File

@ -25,13 +25,28 @@ namespace iu9cawebchat {
} }
} }
std::string RTEE(const std::string& el_name, std::string R200_pres_uinfo(const std::string& el_name, WorkerGuestData& wgd,
const json::JSON& config_presentation, WorkerGuestData& wgd, const json::JSON& config_presentation,
const json::JSON& userinfo) { const json::JSON& userinfo) {
std::string page = wgd.templater->render(el_name, {&config_presentation, &userinfo}); std::string page = wgd.templater->render(el_name, {&config_presentation, &userinfo});
return een9::form_http_server_response_200("text/html", page); return een9::form_http_server_response_200("text/html", page);
} }
std::string R200_pres_uinfo_msges(const std::string& el_name, WorkerGuestData& wgd,
const json::JSON& config_presentation,
const json::JSON& userinfo, const std::vector<HtmlMsgBox>& messages) {
json::JSON jmessages;
// todo: optimize
for (size_t i = 0; i < messages.size(); i++) {
jmessages[i]["class"] = json::JSON(messages[i].class_);
jmessages[i]["text"] = json::JSON(messages[i].text);
}
std::string page = wgd.templater->render(el_name, {&config_presentation, &userinfo, &jmessages});
return een9::form_http_server_response_200("text/html", page);
}
/* ========================= API =========================*/ /* ========================= API =========================*/
std::string when_internalapi(WorkerGuestData& wgd, const een9::ClientRequest& req, int64_t uid, std::string when_internalapi(WorkerGuestData& wgd, const een9::ClientRequest& req, int64_t uid,

View File

@ -27,10 +27,19 @@ namespace iu9cawebchat {
int64_t& ret_logged_in_user int64_t& ret_logged_in_user
); );
std::string RTEE(const std::string& el_name, std::string R200_pres_uinfo(const std::string& el_name, WorkerGuestData& wgd,
const json::JSON& config_presentation, WorkerGuestData& wgd, const json::JSON& config_presentation,
const json::JSON& userinfo); const json::JSON& userinfo);
struct HtmlMsgBox {
std::string class_;
std::string text;
};
std::string R200_pres_uinfo_msges(const std::string& el_name, WorkerGuestData& wgd,
const json::JSON& config_presentation,
const json::JSON& userinfo, const std::vector<HtmlMsgBox>& messages);
/* ========================== PAGES ================================== */ /* ========================== PAGES ================================== */
std::string when_page_list_rooms(WorkerGuestData& wgd, const json::JSON& config_presentation, std::string when_page_list_rooms(WorkerGuestData& wgd, const json::JSON& config_presentation,

View File

@ -118,5 +118,18 @@ namespace iu9cawebchat {
return user_chat_role_deleted; return user_chat_role_deleted;
} }
/* All the api calls processing is done in dedicated files */ int64_t get_lastMsgId_of_chat(SqliteConnection &conn, int64_t chatId) {
een9_ASSERT(chatId >= 0, "Are you crazy?");
SqliteStatement sql_req(conn,
"SELECT `lastMsgId` FROM `chat` WHERE `id` = ?1", {{1, chatId}}, {});
fsql_integer_or_null last_msg_id_col;
int status = sqlite_stmt_step(sql_req, {{0, &last_msg_id_col}}, {});
if (status == SQLITE_ROW) {
return last_msg_id_col.exist ? last_msg_id_col.value : -1;
}
een9_THROW("No such chat");
}
/* All the api calls processing is done in dedicated files.
* All functions related to polling are defined in api_pollevents.cpp */
} }

View File

@ -30,6 +30,7 @@ namespace iu9cawebchat {
}; };
RowUser_Content lookup_user_content(SqliteConnection& conn, int64_t uid); RowUser_Content lookup_user_content(SqliteConnection& conn, int64_t uid);
/* Does not make authorization check */
RowChat_Content lookup_chat_content(SqliteConnection& conn, int64_t chatId); RowChat_Content lookup_chat_content(SqliteConnection& conn, int64_t chatId);
struct RowMessage_Content { struct RowMessage_Content {
@ -44,9 +45,20 @@ namespace iu9cawebchat {
/* If prevMsgId is id of the last message in chat, and there is no message ahead of it, .first = -1 */ /* If prevMsgId is id of the last message in chat, and there is no message ahead of it, .first = -1 */
std::pair<int64_t, RowMessage_Content> lookup_message_content_rev_side(SqliteConnection& conn, int64_t chatId, int64_t prevMsgId); std::pair<int64_t, RowMessage_Content> lookup_message_content_rev_side(SqliteConnection& conn, int64_t chatId, int64_t prevMsgId);
/* Does not make authorization check */
int64_t get_role_of_user_in_chat(SqliteConnection& conn, int64_t userId, int64_t chatId); int64_t get_role_of_user_in_chat(SqliteConnection& conn, int64_t userId, int64_t chatId);
/* Does not make authorization check */
int64_t get_lastMsgId_of_chat(SqliteConnection& conn, int64_t chatId);
/* ============================= API ====================================*/ /* ============================= API ====================================*/
int64_t get_current_history_id_of_chat(SqliteConnection& conn, int64_t chatId);
int64_t get_current_history_id_of_user_chatList(SqliteConnection& conn, int64_t userId);
/* Returns HistoryId of chat (latest) */
int64_t event_polling_fill_chat_hist_entity_response(SqliteConnection& conn, json::JSON& hist_entity_response,
int64_t uid, int64_t chatId, int64_t LocalHistoryId);
/* Returns HistoryId of chat list (latest) */
int64_t event_polling_fill_chatlist_hist_entity_response(SqliteConnection& conn, json::JSON& hist_entity_response,
int64_t uid, int64_t LocalHistoryId);
json::JSON internalapi_pollEvents(SqliteConnection& conn, int64_t uid, const json::JSON& Sent); json::JSON internalapi_pollEvents(SqliteConnection& conn, int64_t uid, const json::JSON& Sent);
json::JSON internalapi_getChatList(SqliteConnection& conn, int64_t uid, const json::JSON& Sent); json::JSON internalapi_getChatList(SqliteConnection& conn, int64_t uid, const json::JSON& Sent);
json::JSON internalapi_getChatInfo(SqliteConnection& conn, int64_t uid, const json::JSON& Sent); json::JSON internalapi_getChatInfo(SqliteConnection& conn, int64_t uid, const json::JSON& Sent);
@ -54,7 +66,6 @@ namespace iu9cawebchat {
json::JSON internalapi_getUserInfo(SqliteConnection& conn, int64_t uid, const json::JSON& Sent); json::JSON internalapi_getUserInfo(SqliteConnection& conn, int64_t uid, const json::JSON& Sent);
json::JSON internalapi_getMessageInfo(SqliteConnection& conn, int64_t uid, const json::JSON& Sent); json::JSON internalapi_getMessageInfo(SqliteConnection& conn, int64_t uid, const json::JSON& Sent);
json::JSON internalapi_getMessageNeighbours(SqliteConnection& conn, int64_t uid, const json::JSON& Sent); json::JSON internalapi_getMessageNeighbours(SqliteConnection& conn, int64_t uid, const json::JSON& Sent);
// todo: write implementations of those new cool interfaces
json::JSON internalapi_sendMessage(SqliteConnection& conn, int64_t uid, const json::JSON& Sent); json::JSON internalapi_sendMessage(SqliteConnection& conn, int64_t uid, const json::JSON& Sent);
json::JSON internalapi_deleteMessage(SqliteConnection& conn, int64_t uid, const json::JSON& Sent); json::JSON internalapi_deleteMessage(SqliteConnection& conn, int64_t uid, const json::JSON& Sent);
json::JSON internalapi_addMemberToChat(SqliteConnection& conn, int64_t uid, const json::JSON& Sent); json::JSON internalapi_addMemberToChat(SqliteConnection& conn, int64_t uid, const json::JSON& Sent);

View File

@ -1,15 +0,0 @@
#include "server_data_interact.h"
#include <engine_engine_number_9/baza_throw.h>
namespace iu9cawebchat {
json::JSON internalapi_sendMessage(SqliteConnection& conn, int64_t uid, const json::JSON& Sent) {
int64_t chatId = Sent["chatId"].g().asInteger().get_int();
int64_t my_role_here = get_role_of_user_in_chat(conn, uid, chatId);
if (my_role_here == user_chat_role_deleted)
een9_THROW("Unauthorized user tries to access internalapi_getChatInfo");
json::JSON Recv;
Recv["status"] = json::JSON(0l);
// todo: WRITE THIS MORBID THING
return Recv;
}
}

View File

@ -3,6 +3,6 @@
namespace iu9cawebchat { namespace iu9cawebchat {
std::string when_page_chat(WorkerGuestData& wgd, const json::JSON& config_presentation, std::string when_page_chat(WorkerGuestData& wgd, const json::JSON& config_presentation,
const een9::ClientRequest& req, const json::JSON& userinfo) { const een9::ClientRequest& req, const json::JSON& userinfo) {
return RTEE("chat", config_presentation, wgd, userinfo); return R200_pres_uinfo("chat", config_presentation, wgd, userinfo);
} }
} }

View File

@ -6,6 +6,6 @@ namespace iu9cawebchat {
if (userinfo.isNull()) { if (userinfo.isNull()) {
return een9::form_http_server_response_303("/login"); return een9::form_http_server_response_303("/login");
} }
return RTEE("list-rooms", config_presentation, wgd, userinfo); return R200_pres_uinfo("list-rooms", config_presentation, wgd, userinfo);
} }
} }

View File

@ -25,14 +25,15 @@ namespace iu9cawebchat {
} catch(const std::exception& e){} } catch(const std::exception& e){}
if (uid < 0) { if (uid < 0) {
printf("Redirecting back to /login because of incorrect credentials\n"); printf("Redirecting back to /login because of incorrect credentials\n");
/* todo: Here I need to tell somehow to user (through fancy red box, maybe), that login was incorrect */ // class will be successfully ignored
return RTEE("login", config_presentation, wgd, userinfo); return R200_pres_uinfo_msges("login", wgd, config_presentation, userinfo, {{"",
config_presentation["phr"]["decl"]["incorrect-nickname-or-password"].g().asString()}});
} }
std::vector<std::pair<std::string, std::string>> response_hlines; std::vector<std::pair<std::string, std::string>> response_hlines;
LoginCookie new_login_cookie = create_login_cookie(nickname, password); LoginCookie new_login_cookie = create_login_cookie(nickname, password);
add_set_cookie_headers_to_login(login_cookies, response_hlines, new_login_cookie); add_set_cookie_headers_to_login(login_cookies, response_hlines, new_login_cookie);
return een9::form_http_server_response_303_spec_head("/", response_hlines); return een9::form_http_server_response_303_spec_head("/", response_hlines);
} }
return RTEE("login", config_presentation, wgd, userinfo); return R200_pres_uinfo_msges("login", wgd, config_presentation, userinfo, {});
} }
} }

View File

@ -3,6 +3,6 @@
namespace iu9cawebchat { namespace iu9cawebchat {
std::string when_page_user(WorkerGuestData& wgd, const json::JSON& config_presentation, std::string when_page_user(WorkerGuestData& wgd, const json::JSON& config_presentation,
const een9::ClientRequest& req, const json::JSON& userinfo) { const een9::ClientRequest& req, const json::JSON& userinfo) {
return RTEE("profile", config_presentation, wgd, userinfo); return R200_pres_uinfo("profile", config_presentation, wgd, userinfo);
} }
} }

View File

@ -64,7 +64,7 @@ namespace iu9cawebchat {
"`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," "`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
"`chatId` INTEGER REFERENCES `chat` NOT NULL," "`chatId` INTEGER REFERENCES `chat` NOT NULL,"
"`previous` INTEGER REFERENCES `message`," "`previous` INTEGER REFERENCES `message`,"
"`senderUserId` INTEGER REFERENCES `user` NOT NULL," "`senderUserId` INTEGER REFERENCES `user`,"
"`exists` BOOLEAN NOT NULL," "`exists` BOOLEAN NOT NULL,"
"`isSystem` BOOLEAN NOT NULL," "`isSystem` BOOLEAN NOT NULL,"
"`text` TEXT NOT NULL," "`text` TEXT NOT NULL,"

View File

@ -101,9 +101,14 @@ namespace iu9cawebchat {
sqlite3_finalize(stmt_obj); sqlite3_finalize(stmt_obj);
} }
void sqlite_stmt_bind_int64(SqliteStatement &stmt, int paramId, int64_t value) {
int ret = sqlite3_bind_int64(stmt.stmt_obj, paramId, value);
een9_ASSERT(ret == 0, "sqlite3_bind_int64");
}
int sqlite_stmt_step(SqliteStatement &stmt, int sqlite_stmt_step(SqliteStatement &stmt,
const std::vector<std::pair<int, fsql_integer_or_null *>> &ret_of_integer_or_null, const std::vector<std::pair<int, fsql_integer_or_null *>> &ret_of_integer_or_null,
const std::vector<std::pair<int, fsql_text8_or_null *>> &ret_of_text8_or_null) { const std::vector<std::pair<int, fsql_text8_or_null *>> &ret_of_text8_or_null) {
int ret = sqlite3_step(stmt.stmt_obj); int ret = sqlite3_step(stmt.stmt_obj);
if (ret == SQLITE_DONE) if (ret == SQLITE_DONE)
return ret; return ret;
@ -137,4 +142,9 @@ namespace iu9cawebchat {
} }
return SQLITE_ROW; return SQLITE_ROW;
} }
int64_t sqlite_trsess_last_insert_rowid(SqliteConnection& conn) {
int64_t res = sqlite3_last_insert_rowid(conn.hand);
return res;
}
} }

View File

@ -41,9 +41,13 @@ namespace iu9cawebchat {
~SqliteStatement(); ~SqliteStatement();
}; };
void sqlite_stmt_bind_int64(SqliteStatement& stmt, int paramId, int64_t value);
int sqlite_stmt_step(SqliteStatement& stmt, int sqlite_stmt_step(SqliteStatement& stmt,
const std::vector<std::pair<int, fsql_integer_or_null*>>& ret_of_integer_or_null, const std::vector<std::pair<int, fsql_integer_or_null*>>& ret_of_integer_or_null,
const std::vector<std::pair<int, fsql_text8_or_null*>>& ret_of_text8_or_null); const std::vector<std::pair<int, fsql_text8_or_null*>>& ret_of_text8_or_null);
int64_t sqlite_trsess_last_insert_rowid(SqliteConnection& conn);
} }
#endif #endif