針對更靈活的資料訪問操作,tcaplusdb 支援條件操作的能力,具備以下能力:
generic 表和 list 表都支援條件操作。
這裡分別定義兩種型別的表,用於本章節示例,為了更直觀說明條件過濾和更新。本章節以protobuf協議作為示例,但tdr協議同樣支援條件過濾和更新,使用類似。
syntax = "proto3";package mytcaplustable;
import "tcaplusservice.optionv1.proto";
message user
int32 id = 1;
string name = 2;
int32 rank = 3;
repeated int64 gameids = 4;
repeated mail mailbox = 5;
}
syntax = "proto3";支援記錄級別的條件過濾,只有滿足條件,才對指定的(乙個或多個)記錄進行操作,包括對記錄修改、刪除或查詢等。package mytcaplustable;
import "tcaplusservice.optionv1.proto";
message list_user
int32 id = 1;
string name = 2;
int32 rank = 3;
repeated int64 gameids = 4;
repeated mail mailbox = 5;
}
若沒有條件過濾,對於 generic 表,通過主鍵查詢或操作乙個記錄,若對應主鍵不存在,則返回錯誤碼 txhdb_err_record_not_exist。
而條件則在這基礎上再加一層過濾,對於 generic 表,主鍵 key 對應存在基礎上,必須條件滿足才能查詢或操作對應的記錄,否則返回錯誤碼 common_err_condition_not_matched。
key + condition,相當於 sql 中的where
語句,雖然能力比 sql 還差不少,但已經提供一定程度的靈活能力。 特別是對於「讀判斷-然後寫」的原子操作場景特別有用,條件更新的初衷就是解決這個問題的。
例如,對於 user 表,若 gameids 陣列不包含 101 這個元素,那麼在該陣列插入 101,那麼應用**會寫成如下
user u;上述**存在幾個問題// 設定主鍵
u.set_id(1);
u.set_name("a");
int ret = api.get(&u);
// ...
if (!find(u.gameids(), 101)) // find是應用實現的函式,在陣列中找是否存在某元素
針對上述問題,條件更新可以解決一些互動多、非原子等問題,示例條件操作**如下:
user u;上述**,// 設定主鍵
u.set_id(1);
u.set_name("a");
// 先判斷gameids是否已經包含101,若不存在(條件不滿足)再插入101
int ret = api.updateitem(&u, "push gameids#[-1][$ = 101]", "gameids not contains($==101)");
if (ret == common_err_condition_not_matched) // 條件不滿足,說明gameids已經存在101了
"gameids not contains($==101)"
就是過濾條件,而"push gameids#[-1][$ = 101]"
是陣列操作語句,後文介紹,這裡指在 gameids 陣列尾部插入 101。
tcaplusdb 提供的一些 protobuf api 新增了const std::string &condition
入參,用於指定過濾條件,支援 condition 的介面以及新增的錯誤碼詳見後文的附錄。
一些介面的使用示例如下,更多的示例可見詳細 example。
// tcaplus_coroutine_pb_api.h過濾條件是類 sql 的 where 語句的語法,已支援以下幾種過濾能力int set(::google::protobuf::message *msg, const std::string &operation = "", const std::string &condition = "");
int fieldinc(const std::set<:string> &dottedpaths, ::google::protobuf::message *msg, const std::string &operation = "", const std::string &condition = "");
int tr**erse(::google::protobuf::message *msg, const std::string &condition, tcaplustr**ersecallback *cb);
// example.cpp
user u;
// 設定主鍵
u.set_id(1);
u.set_name("a");
// 設定其他內容
// ...
// 當rank>100,才執行set操作,若條件不滿足會返回對應的錯誤碼
int ret = api.set(&u, "", "rank > 100");
if (ret == common_err_condition_not_matched) // 條件不滿足的情況
// 設定遞增的步長
u.set_rank(1);
// 當rank達到上限100之後,不在對rank遞增,否則 +1
std::set<:string> dottedpaths;
dottedpaths.insert("rank");
ret = api.fieldinc(dottedpaths, &u, "", "rank < 100");
// 遍歷2021-01-01年之後修改過的記錄,這裡$.lastaccesstime是記錄的內建屬性,表示記錄的最後更新時間
int ret = api.tr**erse(&u, "$.lastaccesstime >= \"2021-01-01\"", &tr**ersecallback);
完整語法如下
condition_expr ::=比較操作符優先順序條件過濾的效能和 1)條件表示式、2)表的模式 有關,滿足以下規則時,有針對性的效能優化(僅供參考,內部實現可能會調整):array contains '(' condition ')'
| array not contains '(' condition ')'
| condition
condition ::=
operand
| operand comparator operand
| condition and condition
| condition or condition
| not condition
| operand bitwise_op operand
comparator ::=
==| =
| <
| >
| <=
| >=
| !=
bitwise_op ::=&
array ::=
identifier
operand ::=
identifier
| number
| string
| $| $.lastaccesstime
TcaplusDB知識庫 PB表定義示例
以下是protobuf表game players.proto的示例,您可以將檔案上傳到控制台並建立該錶。syntax proto3 指定protobuf語言版本,proto3.匯入tcaplusdb公共定義服務 import tcaplusservice.optionv1.proto message...
TcaplusDB知識庫 TDR表資料型別有哪些
目前對於c c c 語言,支援的基本資料型別如下表所示 型別名分類 儲存長度 位元組 取值範圍 byte位元組1 char 單位元組字元 1tinyint整數1 128 127 tinyuint整數1 0 255 smallint整數2 32768 32767 smalluint整數2 0 6553...
打造「個人知識庫」
在以前舉辦的巡迴講座時有許多讀得就問到同乙個問題,就是如何有效記往這些平常在工作摸索或者從書中,或與交流中得到的經驗與方法。說經常在工作遇到某些問題似曾相識,卻想不起以前的解決方法了,很是苦惱。其實這是每個人都會遇到的,不是個人問題。特別是對於我們網管這個行業,所涉及的知識面非常廣,可以說沒有人能把...