#define TDBHINTUSIZ 256 // unit size of the hint string
#define TDBORDRATIO 0.2 // ratio of records to use the order index
-enum { // enumeration for duplication behavior
- TDBPDOVER, // overwrite an existing value
- TDBPDKEEP, // keep the existing value
- TDBPDCAT // concatenate values
+enum { // enumeration for duplication behavior
+ TDBPDOVER, // overwrite an existing value
+ TDBPDKEEP, // keep the existing value
+ TDBPDCAT // concatenate values
};
-typedef struct { // type of structure for a sort record
- const char *kbuf; // pointer to the primary key
- int ksiz; // size of the primary key
- char *vbuf; // pointer to the value
- int vsiz; // size of the value
+typedef struct { // type of structure for a sort record
+ const char *kbuf; // pointer to the primary key
+ int ksiz; // size of the primary key
+ char *vbuf; // pointer to the value
+ int vsiz; // size of the value
} TDBSORTREC;
-typedef struct { // type of structure for a full-text search unit
- TCLIST *tokens; // q-gram tokens
- bool sign; // positive sign
+typedef struct { // type of structure for a full-text search unit
+ TCLIST *tokens; // q-gram tokens
+ bool sign; // positive sign
} TDBFTSUNIT;
-typedef struct { // type of structure for a full-text string occurrence
- const char *pkbuf; // primary key string
- int32_t pksiz; // size of the primary key
- int32_t off; // offset of the token
- uint16_t seq; // sequence number
- uint16_t hash; // hash value for counting sort
+typedef struct { // type of structure for a full-text string occurrence
+ const char *pkbuf; // primary key string
+ int32_t pksiz; // size of the primary key
+ int32_t off; // offset of the token
+ uint16_t seq; // sequence number
+ uint16_t hash; // hash value for counting sort
} TDBFTSSTROCR;
-typedef struct { // type of structure for a full-text number occurrence
- int64_t pkid; // primery key number
- int32_t off; // offset of the token
- uint16_t seq; // sequence number
- uint16_t hash; // hash value for counting sort
+typedef struct { // type of structure for a full-text number occurrence
+ int64_t pkid; // primery key number
+ int32_t off; // offset of the token
+ uint16_t seq; // sequence number
+ uint16_t hash; // hash value for counting sort
} TDBFTSNUMOCR;
static bool tctdboutimpl(TCTDB *tdb, const char *pkbuf, int pksiz);
static TCMAP *tctdbgetimpl(TCTDB *tdb, const void *pkbuf, int pksiz);
static char *tctdbgetonecol(TCTDB *tdb, const void *pkbuf, int pksiz,
- const void *nbuf, int nsiz, int *sp);
+ const void *nbuf, int nsiz, int *sp);
static double tctdbaddnumber(TCTDB *tdb, const void *pkbuf, int pksiz, double num);
static bool tctdboptimizeimpl(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
static bool tctdbvanishimpl(TCTDB *tdb);
static bool tctdbcopyimpl(TCTDB *tdb, const char *path);
static char* tctdbmaprowldr(TCLIST *tokens, const char *pkbuf, int pksz,
- const char *rowdata, int rowdatasz,
- const char* cname, int cnamesz,
- void *op, int *vsz);
+ const char *rowdata, int rowdatasz,
+ const char* cname, int cnamesz,
+ void *op, int *vsz);
static bool tctdbsetindeximpl(TCTDB *tdb, const char *name, int type, TDBRVALOADER rvldr, void* rvldrop);
static int64_t tctdbgenuidimpl(TCTDB *tdb, int64_t inc);
static TCLIST *tctdbqrysearchimpl(TDBQRY *qry);
static int tdbcmpsortrecnumdesc(const TDBSORTREC *a, const TDBSORTREC *b);
static uint16_t tctdbidxhash(const char *pkbuf, int pksiz);
static bool tctdbidxputone(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz, uint16_t hash,
- const char *vbuf, int vsiz);
+ const char *vbuf, int vsiz);
static bool tctdbidxputtoken(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz,
- const char *vbuf, int vsiz);
+ const char *vbuf, int vsiz);
static bool tctdbidxputtoken2(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz, TCLIST *tokens);
static bool tctdbidxputqgram(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz,
- const char *vbuf, int vsiz);
+ const char *vbuf, int vsiz);
static bool tctdbidxoutone(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz, uint16_t hash,
- const char *vbuf, int vsiz);
+ const char *vbuf, int vsiz);
static bool tctdbidxouttoken(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz,
- const char *vbuf, int vsiz);
+ const char *vbuf, int vsiz);
static bool tctdbidxouttoken2(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz, TCLIST *tokens);
static bool tctdbidxoutqgram(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz,
- const char *vbuf, int vsiz);
+ const char *vbuf, int vsiz);
static bool tctdbidxsyncicc(TCTDB *tdb, TDBIDX *idx, bool all);
static int tctdbidxcmpkey(const char **a, const char **b);
static TCMAP *tctdbidxgetbyfts(TCTDB *tdb, TDBIDX *idx, TDBCOND *cond, TCXSTR *hint);
static void tctdbidxgetbyftsunion(TDBIDX *idx, const TCLIST *tokens, bool sign,
- TCMAP *ores, TCMAP *nres, TCXSTR *hint);
+ TCMAP *ores, TCMAP *nres, TCXSTR *hint);
static int tctdbidxftscmpstrocr(TDBFTSSTROCR *a, TDBFTSSTROCR *b);
static int tctdbidxftscmpnumocr(TDBFTSNUMOCR *a, TDBFTSNUMOCR *b);
static TDBFTSUNIT *tctdbftsparseexpr(const char *expr, int esiz, int op, int *np);
* API
*************************************************************************************************/
-
/* Get the message string corresponding to an error code. */
-const char *tctdberrmsg(int ecode){
- return tcerrmsg(ecode);
+const char *tctdberrmsg(int ecode) {
+ return tcerrmsg(ecode);
}
-
/* Create a table database object. */
-TCTDB *tctdbnew(void){
- TCTDB *tdb;
- TCMALLOC(tdb, sizeof(*tdb));
- tctdbclear(tdb);
- tdb->hdb = tchdbnew();
- tchdbtune(tdb->hdb, TDBDEFBNUM, TDBDEFAPOW, TDBDEFFPOW, 0);
- tchdbsetxmsiz(tdb->hdb, TDBDEFXMSIZ);
- return tdb;
+TCTDB *tctdbnew(void) {
+ TCTDB *tdb;
+ TCMALLOC(tdb, sizeof (*tdb));
+ tctdbclear(tdb);
+ tdb->hdb = tchdbnew();
+ tchdbtune(tdb->hdb, TDBDEFBNUM, TDBDEFAPOW, TDBDEFFPOW, 0);
+ tchdbsetxmsiz(tdb->hdb, TDBDEFXMSIZ);
+ return tdb;
}
-
/* Delete a table database object. */
-void tctdbdel(TCTDB *tdb){
- assert(tdb);
- if(tdb->open) tctdbclose(tdb);
- tchdbdel(tdb->hdb);
- if(tdb->mmtx){
- pthread_rwlock_destroy(tdb->mmtx);
- TCFREE(tdb->mmtx);
- }
- TCFREE(tdb);
+void tctdbdel(TCTDB *tdb) {
+ assert(tdb);
+ if (tdb->open) tctdbclose(tdb);
+ tchdbdel(tdb->hdb);
+ if (tdb->mmtx) {
+ pthread_rwlock_destroy(tdb->mmtx);
+ TCFREE(tdb->mmtx);
+ }
+ TCFREE(tdb);
}
-
/* Get the last happened error code of a table database object. */
-int tctdbecode(TCTDB *tdb){
- assert(tdb);
- return tchdbecode(tdb->hdb);
+int tctdbecode(TCTDB *tdb) {
+ assert(tdb);
+ return tchdbecode(tdb->hdb);
}
-
/* Set mutual exclusion control of a table database object for threading. */
-bool tctdbsetmutex(TCTDB *tdb){
- assert(tdb);
- if(tdb->mmtx || tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- TCMALLOC(tdb->mmtx, sizeof(pthread_rwlock_t));
- bool err = false;
- if(pthread_rwlock_init(tdb->mmtx, NULL) != 0) err = true;
- if(err){
- TCFREE(tdb->mmtx);
- tdb->mmtx = NULL;
- return false;
- }
- return tchdbsetmutex(tdb->hdb);
+bool tctdbsetmutex(TCTDB *tdb) {
+ assert(tdb);
+ if (tdb->mmtx || tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ TCMALLOC(tdb->mmtx, sizeof (pthread_rwlock_t));
+ bool err = false;
+ if (pthread_rwlock_init(tdb->mmtx, NULL) != 0) err = true;
+ if (err) {
+ TCFREE(tdb->mmtx);
+ tdb->mmtx = NULL;
+ return false;
+ }
+ return tchdbsetmutex(tdb->hdb);
}
-
/* Set the tuning parameters of a table database object. */
-bool tctdbtune(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
- assert(tdb);
- if(tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- tdb->opts = opts;
- uint8_t hopts = 0;
- if(opts & TDBTLARGE) hopts |= HDBTLARGE;
- if(opts & TDBTDEFLATE) hopts |= HDBTDEFLATE;
- if(opts & TDBTBZIP) hopts |= HDBTBZIP;
- if(opts & TDBTTCBS) hopts |= HDBTTCBS;
- if(opts & TDBTEXCODEC) hopts |= HDBTEXCODEC;
- bnum = (bnum > 0) ? bnum : TDBDEFBNUM;
- apow = (apow >= 0) ? apow : TDBDEFAPOW;
- fpow = (fpow >= 0) ? fpow : TDBDEFFPOW;
- return tchdbtune(tdb->hdb, bnum, apow, fpow, hopts);
+bool tctdbtune(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts) {
+ assert(tdb);
+ if (tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ tdb->opts = opts;
+ uint8_t hopts = 0;
+ if (opts & TDBTLARGE) hopts |= HDBTLARGE;
+ if (opts & TDBTDEFLATE) hopts |= HDBTDEFLATE;
+ if (opts & TDBTBZIP) hopts |= HDBTBZIP;
+ if (opts & TDBTTCBS) hopts |= HDBTTCBS;
+ if (opts & TDBTEXCODEC) hopts |= HDBTEXCODEC;
+ bnum = (bnum > 0) ? bnum : TDBDEFBNUM;
+ apow = (apow >= 0) ? apow : TDBDEFAPOW;
+ fpow = (fpow >= 0) ? fpow : TDBDEFFPOW;
+ return tchdbtune(tdb->hdb, bnum, apow, fpow, hopts);
}
-
/* Set the caching parameters of a table database object. */
-bool tctdbsetcache(TCTDB *tdb, int32_t rcnum, int32_t lcnum, int32_t ncnum){
- assert(tdb);
- if(tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- if(lcnum > 0) tdb->lcnum = lcnum;
- if(ncnum > 0) tdb->ncnum = ncnum;
- return tchdbsetcache(tdb->hdb, rcnum);
+bool tctdbsetcache(TCTDB *tdb, int32_t rcnum, int32_t lcnum, int32_t ncnum) {
+ assert(tdb);
+ if (tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ if (lcnum > 0) tdb->lcnum = lcnum;
+ if (ncnum > 0) tdb->ncnum = ncnum;
+ return tchdbsetcache(tdb->hdb, rcnum);
}
-
/* Set the size of the extra mapped memory of a table database object. */
-bool tctdbsetxmsiz(TCTDB *tdb, int64_t xmsiz){
- assert(tdb);
- if(tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- return tchdbsetxmsiz(tdb->hdb, xmsiz);
+bool tctdbsetxmsiz(TCTDB *tdb, int64_t xmsiz) {
+ assert(tdb);
+ if (tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ return tchdbsetxmsiz(tdb->hdb, xmsiz);
}
-
/* Set the unit step number of auto defragmentation of a table database object. */
-bool tctdbsetdfunit(TCTDB *tdb, int32_t dfunit){
- assert(tdb);
- if(tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- return tchdbsetdfunit(tdb->hdb, dfunit);
+bool tctdbsetdfunit(TCTDB *tdb, int32_t dfunit) {
+ assert(tdb);
+ if (tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ return tchdbsetdfunit(tdb->hdb, dfunit);
}
-
/* Open a database file and connect a table database object. */
-bool tctdbopen(TCTDB *tdb, const char *path, int omode){
- assert(tdb && path);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbopen(TCTDB *tdb, const char *path, int omode) {
+ assert(tdb && path);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tctdbopenimpl(tdb, path, omode);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tctdbopenimpl(tdb, path, omode);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Close a table database object. */
-bool tctdbclose(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbclose(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tctdbcloseimpl(tdb);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tctdbcloseimpl(tdb);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Store a record into a table database object. */
-bool tctdbput(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols){
- assert(tdb && pkbuf && pksiz >= 0 && cols);
- int vsiz;
- if(tcmapget(cols, "", 0, &vsiz)){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbput(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols) {
+ assert(tdb && pkbuf && pksiz >= 0 && cols);
+ int vsiz;
+ if (tcmapget(cols, "", 0, &vsiz)) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDOVER);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDOVER);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Store a string record into a table database object with a zero separated column string. */
-bool tctdbput2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz){
- assert(tdb && pkbuf && pksiz >= 0 && cbuf && csiz >= 0);
- TCMAP *cols = tcstrsplit4(cbuf, csiz);
- bool rv = tctdbput(tdb, pkbuf, pksiz, cols);
- tcmapdel(cols);
- return rv;
+bool tctdbput2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz) {
+ assert(tdb && pkbuf && pksiz >= 0 && cbuf && csiz >= 0);
+ TCMAP *cols = tcstrsplit4(cbuf, csiz);
+ bool rv = tctdbput(tdb, pkbuf, pksiz, cols);
+ tcmapdel(cols);
+ return rv;
}
-
/* Store a string record into a table database object with a tab separated column string. */
-bool tctdbput3(TCTDB *tdb, const char *pkstr, const char *cstr){
- assert(tdb && pkstr && cstr);
- TCMAP *cols = tcstrsplit3(cstr, "\t");
- bool rv = tctdbput(tdb, pkstr, strlen(pkstr), cols);
- tcmapdel(cols);
- return rv;
+bool tctdbput3(TCTDB *tdb, const char *pkstr, const char *cstr) {
+ assert(tdb && pkstr && cstr);
+ TCMAP *cols = tcstrsplit3(cstr, "\t");
+ bool rv = tctdbput(tdb, pkstr, strlen(pkstr), cols);
+ tcmapdel(cols);
+ return rv;
}
-
/* Store a new record into a table database object. */
-bool tctdbputkeep(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols){
- assert(tdb && pkbuf && pksiz >= 0 && cols);
- int vsiz;
- if(tcmapget(cols, "", 0, &vsiz)){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbputkeep(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols) {
+ assert(tdb && pkbuf && pksiz >= 0 && cols);
+ int vsiz;
+ if (tcmapget(cols, "", 0, &vsiz)) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDKEEP);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDKEEP);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Store a new string record into a table database object with a zero separated column string. */
-bool tctdbputkeep2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz){
- assert(tdb && pkbuf && pksiz >= 0 && cbuf && csiz >= 0);
- TCMAP *cols = tcstrsplit4(cbuf, csiz);
- bool rv = tctdbputkeep(tdb, pkbuf, pksiz, cols);
- tcmapdel(cols);
- return rv;
+bool tctdbputkeep2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz) {
+ assert(tdb && pkbuf && pksiz >= 0 && cbuf && csiz >= 0);
+ TCMAP *cols = tcstrsplit4(cbuf, csiz);
+ bool rv = tctdbputkeep(tdb, pkbuf, pksiz, cols);
+ tcmapdel(cols);
+ return rv;
}
-
/* Store a new string record into a table database object with a tab separated column string. */
-bool tctdbputkeep3(TCTDB *tdb, const char *pkstr, const char *cstr){
- assert(tdb && pkstr && cstr);
- TCMAP *cols = tcstrsplit3(cstr, "\t");
- bool rv = tctdbputkeep(tdb, pkstr, strlen(pkstr), cols);
- tcmapdel(cols);
- return rv;
+bool tctdbputkeep3(TCTDB *tdb, const char *pkstr, const char *cstr) {
+ assert(tdb && pkstr && cstr);
+ TCMAP *cols = tcstrsplit3(cstr, "\t");
+ bool rv = tctdbputkeep(tdb, pkstr, strlen(pkstr), cols);
+ tcmapdel(cols);
+ return rv;
}
-
/* Concatenate columns of the existing record in a table database object. */
-bool tctdbputcat(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols){
- assert(tdb && pkbuf && pksiz >= 0 && cols);
- int vsiz;
- if(tcmapget(cols, "", 0, &vsiz)){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbputcat(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols) {
+ assert(tdb && pkbuf && pksiz >= 0 && cols);
+ int vsiz;
+ if (tcmapget(cols, "", 0, &vsiz)) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDCAT);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDCAT);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Concatenate columns in a table database object with a zero separated column string. */
-bool tctdbputcat2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz){
- assert(tdb && pkbuf && pksiz >= 0 && cbuf && csiz >= 0);
- TCMAP *cols = tcstrsplit4(cbuf, csiz);
- bool rv = tctdbputcat(tdb, pkbuf, pksiz, cols);
- tcmapdel(cols);
- return rv;
+bool tctdbputcat2(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz) {
+ assert(tdb && pkbuf && pksiz >= 0 && cbuf && csiz >= 0);
+ TCMAP *cols = tcstrsplit4(cbuf, csiz);
+ bool rv = tctdbputcat(tdb, pkbuf, pksiz, cols);
+ tcmapdel(cols);
+ return rv;
}
-
/* Concatenate columns in a table database object with with a tab separated column string. */
-bool tctdbputcat3(TCTDB *tdb, const char *pkstr, const char *cstr){
- assert(tdb && pkstr && cstr);
- TCMAP *cols = tcstrsplit3(cstr, "\t");
- bool rv = tctdbputcat(tdb, pkstr, strlen(pkstr), cols);
- tcmapdel(cols);
- return rv;
+bool tctdbputcat3(TCTDB *tdb, const char *pkstr, const char *cstr) {
+ assert(tdb && pkstr && cstr);
+ TCMAP *cols = tcstrsplit3(cstr, "\t");
+ bool rv = tctdbputcat(tdb, pkstr, strlen(pkstr), cols);
+ tcmapdel(cols);
+ return rv;
}
-
/* Remove a record of a table database object. */
-bool tctdbout(TCTDB *tdb, const void *pkbuf, int pksiz){
- assert(tdb && pkbuf && pksiz >= 0);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbout(TCTDB *tdb, const void *pkbuf, int pksiz) {
+ assert(tdb && pkbuf && pksiz >= 0);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tctdboutimpl(tdb, pkbuf, pksiz);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tctdboutimpl(tdb, pkbuf, pksiz);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Remove a string record of a table database object. */
-bool tctdbout2(TCTDB *tdb, const char *pkstr){
- assert(tdb && pkstr);
- return tctdbout(tdb, pkstr, strlen(pkstr));
+bool tctdbout2(TCTDB *tdb, const char *pkstr) {
+ assert(tdb && pkstr);
+ return tctdbout(tdb, pkstr, strlen(pkstr));
}
-
/* Retrieve a record in a table database object. */
-TCMAP *tctdbget(TCTDB *tdb, const void *pkbuf, int pksiz){
- assert(tdb && pkbuf && pksiz >= 0);
- if(!TDBLOCKMETHOD(tdb, false)) return NULL;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+TCMAP *tctdbget(TCTDB *tdb, const void *pkbuf, int pksiz) {
+ assert(tdb && pkbuf && pksiz >= 0);
+ if (!TDBLOCKMETHOD(tdb, false)) return NULL;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return NULL;
+ }
+ TCMAP *rv = tctdbgetimpl(tdb, pkbuf, pksiz);
TDBUNLOCKMETHOD(tdb);
- return NULL;
- }
- TCMAP *rv = tctdbgetimpl(tdb, pkbuf, pksiz);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Retrieve a record in a table database object as a zero separated column string. */
-char *tctdbget2(TCTDB *tdb, const void *pkbuf, int pksiz, int *sp){
- assert(tdb && pkbuf && pksiz >= 0 && sp);
- TCMAP *cols = tctdbget(tdb, pkbuf, pksiz);
- if(!cols) return NULL;
- char *cbuf = tcstrjoin4(cols, sp);
- tcmapdel(cols);
- return cbuf;
+char *tctdbget2(TCTDB *tdb, const void *pkbuf, int pksiz, int *sp) {
+ assert(tdb && pkbuf && pksiz >= 0 && sp);
+ TCMAP *cols = tctdbget(tdb, pkbuf, pksiz);
+ if (!cols) return NULL;
+ char *cbuf = tcstrjoin4(cols, sp);
+ tcmapdel(cols);
+ return cbuf;
}
-
/* Retrieve a string record in a table database object as a tab separated column string. */
-char *tctdbget3(TCTDB *tdb, const char *pkstr){
- assert(tdb && pkstr);
- TCMAP *cols = tctdbget(tdb, pkstr, strlen(pkstr));
- if(!cols) return NULL;
- char *cstr = tcstrjoin3(cols, '\t');
- tcmapdel(cols);
- return cstr;
+char *tctdbget3(TCTDB *tdb, const char *pkstr) {
+ assert(tdb && pkstr);
+ TCMAP *cols = tctdbget(tdb, pkstr, strlen(pkstr));
+ if (!cols) return NULL;
+ char *cstr = tcstrjoin3(cols, '\t');
+ tcmapdel(cols);
+ return cstr;
}
-
/* Get the size of the value of a record in a table database object. */
-int tctdbvsiz(TCTDB *tdb, const void *pkbuf, int pksiz){
- assert(tdb && pkbuf && pksiz >= 0);
- if(!TDBLOCKMETHOD(tdb, false)) return -1;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+int tctdbvsiz(TCTDB *tdb, const void *pkbuf, int pksiz) {
+ assert(tdb && pkbuf && pksiz >= 0);
+ if (!TDBLOCKMETHOD(tdb, false)) return -1;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return -1;
+ }
+ int rv = tchdbvsiz(tdb->hdb, pkbuf, pksiz);
TDBUNLOCKMETHOD(tdb);
- return -1;
- }
- int rv = tchdbvsiz(tdb->hdb, pkbuf, pksiz);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Get the size of the value of a string record in a table database object. */
-int tctdbvsiz2(TCTDB *tdb, const char *pkstr){
- assert(tdb && pkstr);
- return tctdbvsiz(tdb, pkstr, strlen(pkstr));
+int tctdbvsiz2(TCTDB *tdb, const char *pkstr) {
+ assert(tdb && pkstr);
+ return tctdbvsiz(tdb, pkstr, strlen(pkstr));
}
-
/* Initialize the iterator of a table database object. */
-bool tctdbiterinit(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbiterinit(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tchdbiterinit(tdb->hdb);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tchdbiterinit(tdb->hdb);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Get the next primary key of the iterator of a table database object. */
-void *tctdbiternext(TCTDB *tdb, int *sp){
- assert(tdb && sp);
- if(!TDBLOCKMETHOD(tdb, true)) return NULL;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+void *tctdbiternext(TCTDB *tdb, int *sp) {
+ assert(tdb && sp);
+ if (!TDBLOCKMETHOD(tdb, true)) return NULL;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return NULL;
+ }
+ char *rv = tchdbiternext(tdb->hdb, sp);
TDBUNLOCKMETHOD(tdb);
- return NULL;
- }
- char *rv = tchdbiternext(tdb->hdb, sp);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Get the next primary key string of the iterator of a table database object. */
-char *tctdbiternext2(TCTDB *tdb){
- assert(tdb);
- int pksiz;
- return tctdbiternext(tdb, &pksiz);
+char *tctdbiternext2(TCTDB *tdb) {
+ assert(tdb);
+ int pksiz;
+ return tctdbiternext(tdb, &pksiz);
}
-
/* Get the columns of the next record of the iterator of a table database object. */
-TCMAP *tctdbiternext3(TCTDB *tdb){
- assert(tdb);
- TCXSTR *kstr = tcxstrnew();
- TCXSTR *vstr = tcxstrnew();
- TCMAP *cols = NULL;
- if(tchdbiternext3(tdb->hdb, kstr, vstr)){
- cols = tcmapload(TCXSTRPTR(vstr), TCXSTRSIZE(vstr));
- tcmapput(cols, "", 0, TCXSTRPTR(kstr), TCXSTRSIZE(kstr));
- }
- tcxstrdel(vstr);
- tcxstrdel(kstr);
- return cols;
+TCMAP *tctdbiternext3(TCTDB *tdb) {
+ assert(tdb);
+ TCXSTR *kstr = tcxstrnew();
+ TCXSTR *vstr = tcxstrnew();
+ TCMAP *cols = NULL;
+ if (tchdbiternext3(tdb->hdb, kstr, vstr)) {
+ cols = tcmapload(TCXSTRPTR(vstr), TCXSTRSIZE(vstr));
+ tcmapput(cols, "", 0, TCXSTRPTR(kstr), TCXSTRSIZE(kstr));
+ }
+ tcxstrdel(vstr);
+ tcxstrdel(kstr);
+ return cols;
}
-
/* Get forward matching primary keys in a table database object. */
-TCLIST *tctdbfwmkeys(TCTDB *tdb, const void *pbuf, int psiz, int max){
- assert(tdb && pbuf && psiz >= 0);
- if(!TDBLOCKMETHOD(tdb, true)) return tclistnew();
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+TCLIST *tctdbfwmkeys(TCTDB *tdb, const void *pbuf, int psiz, int max) {
+ assert(tdb && pbuf && psiz >= 0);
+ if (!TDBLOCKMETHOD(tdb, true)) return tclistnew();
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return tclistnew();
+ }
+ TCLIST *rv = tchdbfwmkeys(tdb->hdb, pbuf, psiz, max);
TDBUNLOCKMETHOD(tdb);
- return tclistnew();
- }
- TCLIST *rv = tchdbfwmkeys(tdb->hdb, pbuf, psiz, max);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Get forward matching string primary keys in a table database object. */
-TCLIST *tctdbfwmkeys2(TCTDB *tdb, const char *pstr, int max){
- assert(tdb && pstr);
- return tctdbfwmkeys(tdb, pstr, strlen(pstr), max);
+TCLIST *tctdbfwmkeys2(TCTDB *tdb, const char *pstr, int max) {
+ assert(tdb && pstr);
+ return tctdbfwmkeys(tdb, pstr, strlen(pstr), max);
}
-
/* Add an integer to a column of a record in a table database object. */
-int tctdbaddint(TCTDB *tdb, const void *pkbuf, int pksiz, int num){
- assert(tdb && pkbuf && pksiz >= 0);
- if(!TDBLOCKMETHOD(tdb, true)) return INT_MIN;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+int tctdbaddint(TCTDB *tdb, const void *pkbuf, int pksiz, int num) {
+ assert(tdb && pkbuf && pksiz >= 0);
+ if (!TDBLOCKMETHOD(tdb, true)) return INT_MIN;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return INT_MIN;
+ }
+ double rv = tctdbaddnumber(tdb, pkbuf, pksiz, num);
TDBUNLOCKMETHOD(tdb);
- return INT_MIN;
- }
- double rv = tctdbaddnumber(tdb, pkbuf, pksiz, num);
- TDBUNLOCKMETHOD(tdb);
- return isnan(rv) ? INT_MIN : (int)rv;
+ return isnan(rv) ? INT_MIN : (int) rv;
}
-
/* Add a real number to a column of a record in a table database object. */
-double tctdbadddouble(TCTDB *tdb, const void *pkbuf, int pksiz, double num){
- assert(tdb && pkbuf && pksiz >= 0);
- if(!TDBLOCKMETHOD(tdb, true)) return INT_MIN;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+double tctdbadddouble(TCTDB *tdb, const void *pkbuf, int pksiz, double num) {
+ assert(tdb && pkbuf && pksiz >= 0);
+ if (!TDBLOCKMETHOD(tdb, true)) return INT_MIN;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return INT_MIN;
+ }
+ double rv = tctdbaddnumber(tdb, pkbuf, pksiz, num);
TDBUNLOCKMETHOD(tdb);
- return INT_MIN;
- }
- double rv = tctdbaddnumber(tdb, pkbuf, pksiz, num);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Synchronize updated contents of a table database object with the file and the device. */
-bool tctdbsync(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode || tdb->tran){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbsync(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode || tdb->tran) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tctdbmemsync(tdb, true);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tctdbmemsync(tdb, true);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Optimize the file of a table database object. */
-bool tctdboptimize(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode || tdb->tran){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdboptimize(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode || tdb->tran) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ TDBTHREADYIELD(tdb);
+ bool rv = tctdboptimizeimpl(tdb, bnum, apow, fpow, opts);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- TDBTHREADYIELD(tdb);
- bool rv = tctdboptimizeimpl(tdb, bnum, apow, fpow, opts);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Remove all records of a table database object. */
-bool tctdbvanish(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode || tdb->tran){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbvanish(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode || tdb->tran) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ TDBTHREADYIELD(tdb);
+ bool rv = tctdbvanishimpl(tdb);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- TDBTHREADYIELD(tdb);
- bool rv = tctdbvanishimpl(tdb);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Copy the database file of a table database object. */
-bool tctdbcopy(TCTDB *tdb, const char *path){
- assert(tdb && path);
- if(!TDBLOCKMETHOD(tdb, false)) return false;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbcopy(TCTDB *tdb, const char *path) {
+ assert(tdb && path);
+ if (!TDBLOCKMETHOD(tdb, false)) return false;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ TDBTHREADYIELD(tdb);
+ bool rv = tctdbcopyimpl(tdb, path);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- TDBTHREADYIELD(tdb);
- bool rv = tctdbcopyimpl(tdb, path);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Begin the transaction of a table database object. */
-bool tctdbtranbegin(TCTDB *tdb){
- assert(tdb);
- for(double wsec = 1.0 / sysconf_SC_CLK_TCK; true; wsec *= 2){
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- TDBUNLOCKMETHOD(tdb);
- return false;
- }
- if(!tdb->tran) break;
- TDBUNLOCKMETHOD(tdb);
- if(wsec > 1.0) wsec = 1.0;
- tcsleep(wsec);
- }
- if(!tctdbtranbeginimpl(tdb)){
+bool tctdbtranbegin(TCTDB *tdb) {
+ assert(tdb);
+ for (double wsec = 1.0 / sysconf_SC_CLK_TCK; true; wsec *= 2) {
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ if (!tdb->tran) break;
+ TDBUNLOCKMETHOD(tdb);
+ if (wsec > 1.0) wsec = 1.0;
+ tcsleep(wsec);
+ }
+ if (!tctdbtranbeginimpl(tdb)) {
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ tdb->tran = true;
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- tdb->tran = true;
- TDBUNLOCKMETHOD(tdb);
- return true;
+ return true;
}
-
/* Commit the transaction of a table database object. */
-bool tctdbtrancommit(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode || !tdb->tran){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbtrancommit(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode || !tdb->tran) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ tdb->tran = false;
+ bool err = false;
+ if (!tctdbtrancommitimpl(tdb)) err = true;
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- tdb->tran = false;
- bool err = false;
- if(!tctdbtrancommitimpl(tdb)) err = true;
- TDBUNLOCKMETHOD(tdb);
- return !err;
+ return !err;
}
-
/* Abort the transaction of a table database object. */
-bool tctdbtranabort(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode || !tdb->tran){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbtranabort(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode || !tdb->tran) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ tdb->tran = false;
+ bool err = false;
+ if (!tctdbtranabortimpl(tdb)) err = true;
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- tdb->tran = false;
- bool err = false;
- if(!tctdbtranabortimpl(tdb)) err = true;
- TDBUNLOCKMETHOD(tdb);
- return !err;
+ return !err;
}
-
/* Get the file path of a table database object. */
-const char *tctdbpath(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, false)) return NULL;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+const char *tctdbpath(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, false)) return NULL;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return NULL;
+ }
+ const char *rv = tchdbpath(tdb->hdb);
TDBUNLOCKMETHOD(tdb);
- return NULL;
- }
- const char *rv = tchdbpath(tdb->hdb);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Get the number of records of a table database object. */
-uint64_t tctdbrnum(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, false)) return 0;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+uint64_t tctdbrnum(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, false)) return 0;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return 0;
+ }
+ uint64_t rv = tchdbrnum(tdb->hdb);
TDBUNLOCKMETHOD(tdb);
- return 0;
- }
- uint64_t rv = tchdbrnum(tdb->hdb);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Get the size of the database file of a table database object. */
-uint64_t tctdbfsiz(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, false)) return 0;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+uint64_t tctdbfsiz(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, false)) return 0;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return 0;
+ }
+ uint64_t rv = tchdbfsiz(tdb->hdb);
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ rv += tcbdbfsiz(idx->db);
+ break;
+ }
+ }
TDBUNLOCKMETHOD(tdb);
- return 0;
- }
- uint64_t rv = tchdbfsiz(tdb->hdb);
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- rv += tcbdbfsiz(idx->db);
- break;
- }
- }
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Set a column index to a table database object. */
-bool tctdbsetindex(TCTDB *tdb, const char *name, int type){
- return tctdbsetindexrldr(tdb, name, type, tctdbmaprowldr, NULL);
+bool tctdbsetindex(TCTDB *tdb, const char *name, int type) {
+ return tctdbsetindexrldr(tdb, name, type, tctdbmaprowldr, NULL);
}
-bool tctdbsetindexrldr(TCTDB *tdb, const char *name, int type, TDBRVALOADER rvldr, void* rvldrop){
- assert(tdb && name);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode || tdb->tran){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbsetindexrldr(TCTDB *tdb, const char *name, int type, TDBRVALOADER rvldr, void* rvldrop) {
+ assert(tdb && name);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode || tdb->tran) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool err = false;
+ double iccsync = tdb->iccsync;
+ tdb->iccsync = 1.0;
+ if (!tctdbsetindeximpl(tdb, name, type, rvldr, rvldrop)) err = true;
+ if (!tctdbmemsync(tdb, false)) err = true;
+ tdb->iccsync = iccsync;
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool err = false;
- double iccsync = tdb->iccsync;
- tdb->iccsync = 1.0;
- if(!tctdbsetindeximpl(tdb, name, type, rvldr, rvldrop)) err = true;
- if(!tctdbmemsync(tdb, false)) err = true;
- tdb->iccsync = iccsync;
- TDBUNLOCKMETHOD(tdb);
- return !err;
+ return !err;
}
-
/* Generate a unique ID number of a table database object. */
-int64_t tctdbgenuid(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, true)) return -1;
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+int64_t tctdbgenuid(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, true)) return -1;
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return -1;
+ }
+ int64_t rv = tctdbgenuidimpl(tdb, 1);
TDBUNLOCKMETHOD(tdb);
- return -1;
- }
- int64_t rv = tctdbgenuidimpl(tdb, 1);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Create a query object. */
-TDBQRY *tctdbqrynew(TCTDB *tdb){
- assert(tdb);
- TDBQRY *qry;
- TCMALLOC(qry, sizeof(*qry));
- qry->tdb = tdb;
- TCMALLOC(qry->conds, sizeof(qry->conds[0]) * 2);
- qry->cnum = 0;
- qry->oname = NULL;
- qry->otype = TDBQOSTRASC;
- qry->max = INT_MAX;
- qry->skip = 0;
- qry->hint = tcxstrnew3(TDBHINTUSIZ);
- qry->count = 0;
- return qry;
+TDBQRY *tctdbqrynew(TCTDB *tdb) {
+ assert(tdb);
+ TDBQRY *qry;
+ TCMALLOC(qry, sizeof (*qry));
+ qry->tdb = tdb;
+ TCMALLOC(qry->conds, sizeof (qry->conds[0]) * 2);
+ qry->cnum = 0;
+ qry->oname = NULL;
+ qry->otype = TDBQOSTRASC;
+ qry->max = INT_MAX;
+ qry->skip = 0;
+ qry->hint = tcxstrnew3(TDBHINTUSIZ);
+ qry->count = 0;
+ return qry;
}
-
/* Delete a query object. */
-void tctdbqrydel(TDBQRY *qry){
- assert(qry);
- tcxstrdel(qry->hint);
- TCFREE(qry->oname);
- TDBCOND *conds = qry->conds;
- int cnum = qry->cnum;
- for(int i = 0; i < cnum; i++){
- TDBCOND *cond = conds + i;
- if(cond->ftsunits){
- TDBFTSUNIT *ftsunits = cond->ftsunits;
- int ftsnum = cond->ftsnum;
- for(int j = 0; j < ftsnum; j++){
- TDBFTSUNIT *ftsunit = ftsunits + j;
- tclistdel(ftsunit->tokens);
- }
- TCFREE(ftsunits);
- }
- if(cond->regex){
- regfree(cond->regex);
- TCFREE(cond->regex);
- }
- TCFREE(cond->expr);
- TCFREE(cond->name);
- }
- TCFREE(conds);
- TCFREE(qry);
+void tctdbqrydel(TDBQRY *qry) {
+ assert(qry);
+ tcxstrdel(qry->hint);
+ TCFREE(qry->oname);
+ TDBCOND *conds = qry->conds;
+ int cnum = qry->cnum;
+ for (int i = 0; i < cnum; i++) {
+ TDBCOND *cond = conds + i;
+ if (cond->ftsunits) {
+ TDBFTSUNIT *ftsunits = cond->ftsunits;
+ int ftsnum = cond->ftsnum;
+ for (int j = 0; j < ftsnum; j++) {
+ TDBFTSUNIT *ftsunit = ftsunits + j;
+ tclistdel(ftsunit->tokens);
+ }
+ TCFREE(ftsunits);
+ }
+ if (cond->regex) {
+ regfree(cond->regex);
+ TCFREE(cond->regex);
+ }
+ TCFREE(cond->expr);
+ TCFREE(cond->name);
+ }
+ TCFREE(conds);
+ TCFREE(qry);
}
-
/* Add a narrowing condition to a query object. */
-void tctdbqryaddcond(TDBQRY *qry, const char *name, int op, const char *expr){
- assert(qry && name && expr);
- int cnum = qry->cnum;
- TCREALLOC(qry->conds, qry->conds, sizeof(qry->conds[0]) * (cnum + 1));
- TDBCOND *cond = qry->conds + cnum;
- int nsiz = strlen(name);
- int esiz = strlen(expr);
- TCMEMDUP(cond->name, name, nsiz);
- cond->nsiz = nsiz;
- bool sign = true;
- if(op & TDBQCNEGATE){
- op &= ~TDBQCNEGATE;
- sign = false;
- }
- bool noidx = false;
- if(op & TDBQCNOIDX){
- op &= ~TDBQCNOIDX;
- noidx = true;
- }
- cond->op = op;
- cond->sign = sign;
- cond->noidx = noidx;
- TCMEMDUP(cond->expr, expr, esiz);
- cond->esiz = esiz;
- cond->regex = NULL;
- if(op == TDBQCSTRRX){
- const char *rxstr = expr;
- int rxopt = REG_EXTENDED | REG_NOSUB;
- if(*rxstr == '*'){
- rxopt |= REG_ICASE;
- rxstr++;
- }
- regex_t rxbuf;
- if(regcomp(&rxbuf, rxstr, rxopt) == 0){
- TCMALLOC(cond->regex, sizeof(rxbuf));
- memcpy(cond->regex, &rxbuf, sizeof(rxbuf));
- }
- }
- cond->ftsunits = NULL;
- cond->ftsnum = 0;
- if(op >= TDBQCFTSPH && op <= TDBQCFTSEX){
- cond->op = TDBQCFTSPH;
- cond->ftsunits = tctdbftsparseexpr(expr, esiz, op, &(cond->ftsnum));
- }
- qry->cnum++;
+void tctdbqryaddcond(TDBQRY *qry, const char *name, int op, const char *expr) {
+ assert(qry && name && expr);
+ int cnum = qry->cnum;
+ TCREALLOC(qry->conds, qry->conds, sizeof (qry->conds[0]) * (cnum + 1));
+ TDBCOND *cond = qry->conds + cnum;
+ int nsiz = strlen(name);
+ int esiz = strlen(expr);
+ TCMEMDUP(cond->name, name, nsiz);
+ cond->nsiz = nsiz;
+ bool sign = true;
+ if (op & TDBQCNEGATE) {
+ op &= ~TDBQCNEGATE;
+ sign = false;
+ }
+ bool noidx = false;
+ if (op & TDBQCNOIDX) {
+ op &= ~TDBQCNOIDX;
+ noidx = true;
+ }
+ cond->op = op;
+ cond->sign = sign;
+ cond->noidx = noidx;
+ TCMEMDUP(cond->expr, expr, esiz);
+ cond->esiz = esiz;
+ cond->regex = NULL;
+ if (op == TDBQCSTRRX) {
+ const char *rxstr = expr;
+ int rxopt = REG_EXTENDED | REG_NOSUB;
+ if (*rxstr == '*') {
+ rxopt |= REG_ICASE;
+ rxstr++;
+ }
+ regex_t rxbuf;
+ if (regcomp(&rxbuf, rxstr, rxopt) == 0) {
+ TCMALLOC(cond->regex, sizeof (rxbuf));
+ memcpy(cond->regex, &rxbuf, sizeof (rxbuf));
+ }
+ }
+ cond->ftsunits = NULL;
+ cond->ftsnum = 0;
+ if (op >= TDBQCFTSPH && op <= TDBQCFTSEX) {
+ cond->op = TDBQCFTSPH;
+ cond->ftsunits = tctdbftsparseexpr(expr, esiz, op, &(cond->ftsnum));
+ }
+ qry->cnum++;
}
-
/* Set the order of a query object. */
-void tctdbqrysetorder(TDBQRY *qry, const char *name, int type){
- assert(qry && name);
- if(qry->oname) TCFREE(qry->oname);
- qry->oname = tcstrdup(name);
- qry->otype = type;
+void tctdbqrysetorder(TDBQRY *qry, const char *name, int type) {
+ assert(qry && name);
+ if (qry->oname) TCFREE(qry->oname);
+ qry->oname = tcstrdup(name);
+ qry->otype = type;
}
-
/* Set the limit number of records of the result of a query object. */
-void tctdbqrysetlimit(TDBQRY *qry, int max, int skip){
- assert(qry);
- qry->max = (max >= 0) ? max : INT_MAX;
- qry->skip = (skip > 0) ? skip : 0;
+void tctdbqrysetlimit(TDBQRY *qry, int max, int skip) {
+ assert(qry);
+ qry->max = (max >= 0) ? max : INT_MAX;
+ qry->skip = (skip > 0) ? skip : 0;
}
-
/* Execute the search of a query object. */
-TCLIST *tctdbqrysearch(TDBQRY *qry){
- assert(qry);
- TCTDB *tdb = qry->tdb;
- if(!TDBLOCKMETHOD(tdb, false)) return tclistnew();
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+TCLIST *tctdbqrysearch(TDBQRY *qry) {
+ assert(qry);
+ TCTDB *tdb = qry->tdb;
+ if (!TDBLOCKMETHOD(tdb, false)) return tclistnew();
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return tclistnew();
+ }
+ TCLIST *rv = tctdbqrysearchimpl(qry);
TDBUNLOCKMETHOD(tdb);
- return tclistnew();
- }
- TCLIST *rv = tctdbqrysearchimpl(qry);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Remove each record corresponding to a query object. */
-bool tctdbqrysearchout(TDBQRY *qry){
- assert(qry);
- return tctdbqryproc(qry, tctdbqryprocoutcb, NULL);
+bool tctdbqrysearchout(TDBQRY *qry) {
+ assert(qry);
+ return tctdbqryproc(qry, tctdbqryprocoutcb, NULL);
}
-
/* Process each record corresponding to a query object. */
-bool tctdbqryproc(TDBQRY *qry, TDBQRYPROC proc, void *op){
- assert(qry && proc);
- TCTDB *tdb = qry->tdb;
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool err = false;
- int64_t getnum = 0;
- int64_t putnum = 0;
- int64_t outnum = 0;
- TCLIST *res = tctdbqrysearchimpl(qry);
- int rnum = TCLISTNUM(res);
- for(int i = 0; i < rnum; i++){
- const char *pkbuf;
- int pksiz;
- TCLISTVAL(pkbuf, res, i, pksiz);
- TCMAP *cols = tctdbgetimpl(tdb, pkbuf, pksiz);
- if(!cols){
- err = true;
- continue;
- }
- getnum++;
- int flags = proc(pkbuf, pksiz, cols, op);
- if(flags & TDBQPPUT){
- if(tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDOVER)){
- putnum++;
- } else {
- err = true;
- }
- } else if(flags & TDBQPOUT){
- if(tctdboutimpl(tdb, pkbuf, pksiz)){
- outnum++;
- } else {
- err = true;
- }
+bool tctdbqryproc(TDBQRY *qry, TDBQRYPROC proc, void *op) {
+ assert(qry && proc);
+ TCTDB *tdb = qry->tdb;
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
}
- tcmapdel(cols);
- if(flags & TDBQPSTOP) break;
- }
- tclistdel(res);
- tcxstrprintf(qry->hint, "post treatment: get=%" PRIdMAX ", put=%" PRIdMAX ", out=%" PRIdMAX "\n",
- (long long)getnum, (long long)putnum, (long long)outnum);
- TDBUNLOCKMETHOD(tdb);
- return !err;
+ bool err = false;
+ int64_t getnum = 0;
+ int64_t putnum = 0;
+ int64_t outnum = 0;
+ TCLIST *res = tctdbqrysearchimpl(qry);
+ int rnum = TCLISTNUM(res);
+ for (int i = 0; i < rnum; i++) {
+ const char *pkbuf;
+ int pksiz;
+ TCLISTVAL(pkbuf, res, i, pksiz);
+ TCMAP *cols = tctdbgetimpl(tdb, pkbuf, pksiz);
+ if (!cols) {
+ err = true;
+ continue;
+ }
+ getnum++;
+ int flags = proc(pkbuf, pksiz, cols, op);
+ if (flags & TDBQPPUT) {
+ if (tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDOVER)) {
+ putnum++;
+ } else {
+ err = true;
+ }
+ } else if (flags & TDBQPOUT) {
+ if (tctdboutimpl(tdb, pkbuf, pksiz)) {
+ outnum++;
+ } else {
+ err = true;
+ }
+ }
+ tcmapdel(cols);
+ if (flags & TDBQPSTOP) break;
+ }
+ tclistdel(res);
+ tcxstrprintf(qry->hint, "post treatment: get=%" PRIdMAX ", put=%" PRIdMAX ", out=%" PRIdMAX "\n",
+ (long long) getnum, (long long) putnum, (long long) outnum);
+ TDBUNLOCKMETHOD(tdb);
+ return !err;
}
-
/* Get the hint string of a query object. */
-const char *tctdbqryhint(TDBQRY *qry){
- assert(qry);
- return tcxstrptr(qry->hint);
+const char *tctdbqryhint(TDBQRY *qry) {
+ assert(qry);
+ return tcxstrptr(qry->hint);
}
-
/* Retrieve records with multiple query objects and get the set of the result. */
-TCLIST *tctdbmetasearch(TDBQRY **qrys, int num, int type){
- assert(qrys && num >= 0);
- if(num < 1) return tclistnew2(1);
- if(num < 2) return tctdbqrysearch(qrys[0]);
- const char *oname = qrys[0]->oname;
- int onsiz = oname ? strlen(oname) : 0;
- int otype = qrys[0]->otype;
- TCMAP *uset = tcmapnew();
- if(type == TDBMSUNION){
- for(int i = 0; i < num; i++){
- TDBQRY *qry = qrys[i];
- TCTDB *tdb = qry->tdb;
- int omax = qry->max;
- int oskip = qry->skip;
- if(qry->max < INT_MAX - qry->skip) qry->max += qry->skip;
- qry->skip = 0;
- TCLIST *res = tctdbqrysearch(qry);
- qry->max = omax;
- qry->skip = oskip;
- int rnum = TCLISTNUM(res);
- for(int j = 0; j < rnum; j++){
+TCLIST *tctdbmetasearch(TDBQRY **qrys, int num, int type) {
+ assert(qrys && num >= 0);
+ if (num < 1) return tclistnew2(1);
+ if (num < 2) return tctdbqrysearch(qrys[0]);
+ const char *oname = qrys[0]->oname;
+ int onsiz = oname ? strlen(oname) : 0;
+ int otype = qrys[0]->otype;
+ TCMAP *uset = tcmapnew();
+ if (type == TDBMSUNION) {
+ for (int i = 0; i < num; i++) {
+ TDBQRY *qry = qrys[i];
+ TCTDB *tdb = qry->tdb;
+ int omax = qry->max;
+ int oskip = qry->skip;
+ if (qry->max < INT_MAX - qry->skip) qry->max += qry->skip;
+ qry->skip = 0;
+ TCLIST *res = tctdbqrysearch(qry);
+ qry->max = omax;
+ qry->skip = oskip;
+ int rnum = TCLISTNUM(res);
+ for (int j = 0; j < rnum; j++) {
+ const char *pkbuf;
+ int pksiz;
+ TCLISTVAL(pkbuf, res, j, pksiz);
+ if (oname) {
+ int csiz;
+ char *cbuf = tctdbget4(tdb, pkbuf, pksiz, oname, onsiz, &csiz);
+ if (cbuf) {
+ tcmapput4(uset, pkbuf, pksiz, "=", 1, cbuf, csiz);
+ TCFREE(cbuf);
+ } else {
+ tcmapput(uset, pkbuf, pksiz, "*", 1);
+ }
+ } else {
+ tcmapputkeep(uset, pkbuf, pksiz, "", 0);
+ }
+ }
+ tclistdel(res);
+ }
+ } else if (type == TDBMSISECT) {
+ int omax = qrys[0]->max;
+ int oskip = qrys[0]->skip;
+ qrys[0]->max = INT_MAX;
+ qrys[0]->skip = 0;
+ TCLIST *res = tctdbqrysearch(qrys[0]);
+ qrys[0]->max = omax;
+ qrys[0]->skip = oskip;
+ int rnum = TCLISTNUM(res);
+ for (int i = 0; i < rnum; i++) {
+ const char *pkbuf;
+ int pksiz;
+ TCLISTVAL(pkbuf, res, i, pksiz);
+ tcmapputkeep(uset, pkbuf, pksiz, "", 0);
+ }
+ tclistdel(res);
+ for (int i = 1; i < num; i++) {
+ TDBQRY *qry = qrys[i];
+ if (TCMAPRNUM(uset) < 1) {
+ tcxstrclear(qry->hint);
+ tcxstrprintf(qry->hint, "omitted\n");
+ continue;
+ }
+ omax = qry->max;
+ oskip = qry->skip;
+ qry->max = INT_MAX;
+ qry->skip = 0;
+ res = tctdbqrysearch(qry);
+ qry->max = omax;
+ qry->skip = oskip;
+ rnum = TCLISTNUM(res);
+ TCMAP *nset = tcmapnew2(tclmin(TCMAPRNUM(uset), rnum) + 1);
+ for (int j = 0; j < rnum; j++) {
+ const char *pkbuf;
+ int pksiz;
+ TCLISTVAL(pkbuf, res, j, pksiz);
+ int vsiz;
+ if (tcmapget(uset, pkbuf, pksiz, &vsiz)) tcmapputkeep(nset, pkbuf, pksiz, "", 0);
+ }
+ tcmapdel(uset);
+ uset = nset;
+ tclistdel(res);
+ }
+ } else if (type == TDBMSDIFF) {
+ int omax = qrys[0]->max;
+ int oskip = qrys[0]->skip;
+ qrys[0]->max = INT_MAX;
+ qrys[0]->skip = 0;
+ TCLIST *res = tctdbqrysearch(qrys[0]);
+ qrys[0]->max = omax;
+ qrys[0]->skip = oskip;
+ int rnum = TCLISTNUM(res);
+ for (int i = 0; i < rnum; i++) {
+ const char *pkbuf;
+ int pksiz;
+ TCLISTVAL(pkbuf, res, i, pksiz);
+ tcmapputkeep(uset, pkbuf, pksiz, "", 0);
+ }
+ tclistdel(res);
+ for (int i = 1; i < num; i++) {
+ TDBQRY *qry = qrys[i];
+ if (TCMAPRNUM(uset) < 1) {
+ tcxstrclear(qry->hint);
+ tcxstrprintf(qry->hint, "omitted\n");
+ continue;
+ }
+ omax = qry->max;
+ oskip = qry->skip;
+ qry->max = INT_MAX;
+ qry->skip = 0;
+ res = tctdbqrysearch(qry);
+ qry->max = omax;
+ qry->skip = oskip;
+ rnum = TCLISTNUM(res);
+ for (int j = 0; j < rnum; j++) {
+ const char *pkbuf;
+ int pksiz;
+ TCLISTVAL(pkbuf, res, j, pksiz);
+ tcmapout(uset, pkbuf, pksiz);
+ }
+ tclistdel(res);
+ }
+ }
+ int max = qrys[0]->max;
+ int skip = qrys[0]->skip;
+ TCLIST *res;
+ if (oname && type == TDBMSUNION) {
+ int rnum = TCMAPRNUM(uset);
+ TDBSORTREC *keys;
+ TCMALLOC(keys, sizeof (*keys) * rnum + 1);
+ tcmapiterinit(uset);
const char *pkbuf;
int pksiz;
- TCLISTVAL(pkbuf, res, j, pksiz);
- if(oname){
- int csiz;
- char *cbuf = tctdbget4(tdb, pkbuf, pksiz, oname, onsiz, &csiz);
- if(cbuf){
- tcmapput4(uset, pkbuf, pksiz, "=", 1, cbuf, csiz);
- TCFREE(cbuf);
- } else {
- tcmapput(uset, pkbuf, pksiz, "*", 1);
- }
- } else {
- tcmapputkeep(uset, pkbuf, pksiz, "", 0);
- }
- }
- tclistdel(res);
- }
- } else if(type == TDBMSISECT){
- int omax = qrys[0]->max;
- int oskip = qrys[0]->skip;
- qrys[0]->max = INT_MAX;
- qrys[0]->skip = 0;
- TCLIST *res = tctdbqrysearch(qrys[0]);
- qrys[0]->max = omax;
- qrys[0]->skip = oskip;
- int rnum = TCLISTNUM(res);
- for(int i = 0; i < rnum; i++){
- const char *pkbuf;
- int pksiz;
- TCLISTVAL(pkbuf, res, i, pksiz);
- tcmapputkeep(uset, pkbuf, pksiz, "", 0);
- }
- tclistdel(res);
- for(int i = 1; i < num; i++){
- TDBQRY *qry = qrys[i];
- if(TCMAPRNUM(uset) < 1){
- tcxstrclear(qry->hint);
- tcxstrprintf(qry->hint, "omitted\n");
- continue;
- }
- omax = qry->max;
- oskip = qry->skip;
- qry->max = INT_MAX;
- qry->skip = 0;
- res = tctdbqrysearch(qry);
- qry->max = omax;
- qry->skip = oskip;
- rnum = TCLISTNUM(res);
- TCMAP *nset = tcmapnew2(tclmin(TCMAPRNUM(uset), rnum) + 1);
- for(int j = 0; j < rnum; j++){
+ TDBSORTREC *key = keys;
+ while ((pkbuf = tcmapiternext(uset, &pksiz)) != NULL) {
+ int vsiz;
+ const char *vbuf = tcmapiterval(pkbuf, &vsiz);
+ key->kbuf = pkbuf;
+ key->ksiz = pksiz;
+ if (*vbuf == '=') {
+ key->vbuf = (char *) vbuf + 1;
+ key->vsiz = vsiz - 1;
+ } else {
+ key->vbuf = NULL;
+ key->vsiz = 0;
+ }
+ key++;
+ }
+ int (*compar)(const TDBSORTREC *a, const TDBSORTREC * b) = NULL;
+ switch (otype) {
+ case TDBQOSTRASC:
+ compar = tdbcmpsortrecstrasc;
+ break;
+ case TDBQOSTRDESC:
+ compar = tdbcmpsortrecstrdesc;
+ break;
+ case TDBQONUMASC:
+ compar = tdbcmpsortrecnumasc;
+ break;
+ case TDBQONUMDESC:
+ compar = tdbcmpsortrecnumdesc;
+ break;
+ }
+ if (compar) qsort(keys, rnum, sizeof (*keys), (int (*)(const void *, const void *))compar);
+ res = tclistnew2(tclmin(rnum, max));
+ for (int i = skip; max > 0 && i < rnum; i++) {
+ key = keys + i;
+ TCLISTPUSH(res, key->kbuf, key->ksiz);
+ max--;
+ }
+ TCFREE(keys);
+ } else {
+ res = tclistnew2(tclmin(tcmaprnum(uset), max));
+ tcmapiterinit(uset);
const char *pkbuf;
int pksiz;
- TCLISTVAL(pkbuf, res, j, pksiz);
- int vsiz;
- if(tcmapget(uset, pkbuf, pksiz, &vsiz)) tcmapputkeep(nset, pkbuf, pksiz, "", 0);
- }
- tcmapdel(uset);
- uset = nset;
- tclistdel(res);
- }
- } else if(type == TDBMSDIFF){
- int omax = qrys[0]->max;
- int oskip = qrys[0]->skip;
- qrys[0]->max = INT_MAX;
- qrys[0]->skip = 0;
- TCLIST *res = tctdbqrysearch(qrys[0]);
- qrys[0]->max = omax;
- qrys[0]->skip = oskip;
- int rnum = TCLISTNUM(res);
- for(int i = 0; i < rnum; i++){
- const char *pkbuf;
- int pksiz;
- TCLISTVAL(pkbuf, res, i, pksiz);
- tcmapputkeep(uset, pkbuf, pksiz, "", 0);
+ while (max > 0 && (pkbuf = tcmapiternext(uset, &pksiz)) != NULL) {
+ if (skip > 0) {
+ skip--;
+ } else {
+ TCLISTPUSH(res, pkbuf, pksiz);
+ max--;
+ }
+ }
}
- tclistdel(res);
- for(int i = 1; i < num; i++){
- TDBQRY *qry = qrys[i];
- if(TCMAPRNUM(uset) < 1){
+ tcmapdel(uset);
+ TCXSTR *hint = tcxstrnew();
+ for (int i = 0; i < num; i++) {
+ TDBQRY *qry = qrys[i];
+ TCLIST *lines = tcstrsplit(tctdbqryhint(qry), "\n");
+ int lnum = TCLISTNUM(lines);
+ for (int j = 0; j < lnum; j++) {
+ const char *line = TCLISTVALPTR(lines, j);
+ if (*line != 0) tcxstrprintf(hint, "[%d] %s\n", i, line);
+ }
+ tclistdel(lines);
tcxstrclear(qry->hint);
- tcxstrprintf(qry->hint, "omitted\n");
- continue;
- }
- omax = qry->max;
- oskip = qry->skip;
- qry->max = INT_MAX;
- qry->skip = 0;
- res = tctdbqrysearch(qry);
- qry->max = omax;
- qry->skip = oskip;
- rnum = TCLISTNUM(res);
- for(int j = 0; j < rnum; j++){
- const char *pkbuf;
- int pksiz;
- TCLISTVAL(pkbuf, res, j, pksiz);
- tcmapout(uset, pkbuf, pksiz);
- }
- tclistdel(res);
- }
- }
- int max = qrys[0]->max;
- int skip = qrys[0]->skip;
- TCLIST *res;
- if(oname && type == TDBMSUNION){
- int rnum = TCMAPRNUM(uset);
- TDBSORTREC *keys;
- TCMALLOC(keys, sizeof(*keys) * rnum + 1);
- tcmapiterinit(uset);
- const char *pkbuf;
- int pksiz;
- TDBSORTREC *key = keys;
- while((pkbuf = tcmapiternext(uset, &pksiz)) != NULL){
- int vsiz;
- const char *vbuf = tcmapiterval(pkbuf, &vsiz);
- key->kbuf = pkbuf;
- key->ksiz = pksiz;
- if(*vbuf == '='){
- key->vbuf = (char *)vbuf + 1;
- key->vsiz = vsiz - 1;
- } else {
- key->vbuf = NULL;
- key->vsiz = 0;
- }
- key++;
- }
- int (*compar)(const TDBSORTREC *a, const TDBSORTREC *b) = NULL;
- switch(otype){
- case TDBQOSTRASC:
- compar = tdbcmpsortrecstrasc;
- break;
- case TDBQOSTRDESC:
- compar = tdbcmpsortrecstrdesc;
- break;
- case TDBQONUMASC:
- compar = tdbcmpsortrecnumasc;
- break;
- case TDBQONUMDESC:
- compar = tdbcmpsortrecnumdesc;
- break;
- }
- if(compar) qsort(keys, rnum, sizeof(*keys), (int (*)(const void *, const void *))compar);
- res = tclistnew2(tclmin(rnum, max));
- for(int i = skip; max > 0 && i < rnum; i++){
- key = keys + i;
- TCLISTPUSH(res, key->kbuf, key->ksiz);
- max--;
+ qry->count = 0;
}
- TCFREE(keys);
- } else {
- res = tclistnew2(tclmin(tcmaprnum(uset), max));
- tcmapiterinit(uset);
- const char *pkbuf;
- int pksiz;
- while(max > 0 && (pkbuf = tcmapiternext(uset, &pksiz)) != NULL){
- if(skip > 0){
- skip--;
- } else {
- TCLISTPUSH(res, pkbuf, pksiz);
- max--;
- }
- }
- }
- tcmapdel(uset);
- TCXSTR *hint = tcxstrnew();
- for(int i = 0; i < num; i++){
- TDBQRY *qry = qrys[i];
- TCLIST *lines = tcstrsplit(tctdbqryhint(qry), "\n");
- int lnum = TCLISTNUM(lines);
- for(int j = 0; j < lnum; j++){
- const char *line = TCLISTVALPTR(lines, j);
- if(*line != 0) tcxstrprintf(hint, "[%d] %s\n", i, line);
- }
- tclistdel(lines);
- tcxstrclear(qry->hint);
- qry->count = 0;
- }
- TCXSTRCAT(qrys[0]->hint, TCXSTRPTR(hint), TCXSTRSIZE(hint));
- qrys[0]->count = TCLISTNUM(res);
- tcxstrdel(hint);
- return res;
+ TCXSTRCAT(qrys[0]->hint, TCXSTRPTR(hint), TCXSTRSIZE(hint));
+ qrys[0]->count = TCLISTNUM(res);
+ tcxstrdel(hint);
+ return res;
}
* features for experts
*************************************************************************************************/
-
/* Set the error code of a table database object. */
-void tctdbsetecode(TCTDB *tdb, int ecode, const char *filename, int line, const char *func){
- assert(tdb && filename && line >= 1 && func);
- tchdbsetecode(tdb->hdb, ecode, filename, line, func);
+void tctdbsetecode(TCTDB *tdb, int ecode, const char *filename, int line, const char *func) {
+ assert(tdb && filename && line >= 1 && func);
+ tchdbsetecode(tdb->hdb, ecode, filename, line, func);
}
-
/* Set the file descriptor for debugging output. */
-void tctdbsetdbgfd(TCTDB *tdb, HANDLE fd){
- assert(tdb);
- tchdbsetdbgfd(tdb->hdb, fd);
+void tctdbsetdbgfd(TCTDB *tdb, HANDLE fd) {
+ assert(tdb);
+ tchdbsetdbgfd(tdb->hdb, fd);
}
-
/* Get the file descriptor for debugging output. */
-HANDLE tctdbdbgfd(TCTDB *tdb){
- assert(tdb);
- return tchdbdbgfd(tdb->hdb);
+HANDLE tctdbdbgfd(TCTDB *tdb) {
+ assert(tdb);
+ return tchdbdbgfd(tdb->hdb);
}
-
/* Check whether mutual exclusion control is set to a table database object. */
-bool tctdbhasmutex(TCTDB *tdb){
- assert(tdb);
- return tdb->mmtx != NULL;
+bool tctdbhasmutex(TCTDB *tdb) {
+ assert(tdb);
+ return tdb->mmtx != NULL;
}
-
/* Synchronize updating contents on memory of a table database object. */
-bool tctdbmemsync(TCTDB *tdb, bool phys){
- assert(tdb);
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- bool err = false;
- if(!tchdbmemsync(tdb->hdb, phys)) err = true;
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tctdbidxsyncicc(tdb, idx, true)) err = true;
- break;
- }
- }
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tcbdbmemsync(idx->db, phys)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- }
- }
- return !err;
-}
-
-
-/* Get the number of elements of the bucket array of a table database object. */
-uint64_t tctdbbnum(TCTDB *tdb){
- assert(tdb);
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbbnum(tdb->hdb);
+bool tctdbmemsync(TCTDB *tdb, bool phys) {
+ assert(tdb);
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ bool err = false;
+ if (!tchdbmemsync(tdb->hdb, phys)) err = true;
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tctdbidxsyncicc(tdb, idx, true)) err = true;
+ break;
+ }
+ }
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tcbdbmemsync(idx->db, phys)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ }
+ }
+ return !err;
}
+/* Get the number of elements of the bucket array of a table database object. */
+uint64_t tctdbbnum(TCTDB *tdb) {
+ assert(tdb);
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return 0;
+ }
+ return tchdbbnum(tdb->hdb);
+}
/* Get the record alignment of a table database object. */
-uint32_t tctdbalign(TCTDB *tdb){
- assert(tdb);
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbalign(tdb->hdb);
+uint32_t tctdbalign(TCTDB *tdb) {
+ assert(tdb);
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return 0;
+ }
+ return tchdbalign(tdb->hdb);
}
-
/* Get the maximum number of the free block pool of a table database object. */
-uint32_t tctdbfbpmax(TCTDB *tdb){
- assert(tdb);
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbfbpmax(tdb->hdb);
+uint32_t tctdbfbpmax(TCTDB *tdb) {
+ assert(tdb);
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return 0;
+ }
+ return tchdbfbpmax(tdb->hdb);
}
-
/* Get the inode number of the database file of a table database object. */
-uint64_t tctdbinode(TCTDB *tdb){
- assert(tdb);
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbinode(tdb->hdb);
+uint64_t tctdbinode(TCTDB *tdb) {
+ assert(tdb);
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return 0;
+ }
+ return tchdbinode(tdb->hdb);
}
-
/* Get the modification time of the database file of a table database object. */
-time_t tctdbmtime(TCTDB *tdb){
- assert(tdb);
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbmtime(tdb->hdb);
+time_t tctdbmtime(TCTDB *tdb) {
+ assert(tdb);
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return 0;
+ }
+ return tchdbmtime(tdb->hdb);
}
-
/* Get the additional flags of a table database object. */
-uint8_t tctdbflags(TCTDB *tdb){
- assert(tdb);
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbflags(tdb->hdb);
+uint8_t tctdbflags(TCTDB *tdb) {
+ assert(tdb);
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return 0;
+ }
+ return tchdbflags(tdb->hdb);
}
-
/* Get the options of a table database object. */
-uint8_t tctdbopts(TCTDB *tdb){
- assert(tdb);
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tdb->opts;
+uint8_t tctdbopts(TCTDB *tdb) {
+ assert(tdb);
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return 0;
+ }
+ return tdb->opts;
}
-
/* Get the number of used elements of the bucket array of a table database object. */
-uint64_t tctdbbnumused(TCTDB *tdb){
- assert(tdb);
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbbnumused(tdb->hdb);
+uint64_t tctdbbnumused(TCTDB *tdb) {
+ assert(tdb);
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return 0;
+ }
+ return tchdbbnumused(tdb->hdb);
}
-
/* Get the number of column indices of a table database object. */
-int tctdbinum(TCTDB *tdb){
- assert(tdb);
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tdb->inum;
+int tctdbinum(TCTDB *tdb) {
+ assert(tdb);
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return 0;
+ }
+ return tdb->inum;
}
-
/* Get the seed of unique ID unumbers of a table database object. */
-int64_t tctdbuidseed(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, false)) return -1;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+int64_t tctdbuidseed(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, false)) return -1;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return -1;
+ }
+ int64_t rv = tctdbgenuidimpl(tdb, 0);
TDBUNLOCKMETHOD(tdb);
- return -1;
- }
- int64_t rv = tctdbgenuidimpl(tdb, 0);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Set the parameters of the inverted cache of a table database object. */
-bool tctdbsetinvcache(TCTDB *tdb, int64_t iccmax, double iccsync){
- assert(tdb);
- if(tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- tdb->iccmax = (iccmax > 0) ? iccmax : TDBIDXICCMAX;
- tdb->iccsync = (iccsync > 0) ? iccsync : TDBIDXICCSYNC;
- return true;
+bool tctdbsetinvcache(TCTDB *tdb, int64_t iccmax, double iccsync) {
+ assert(tdb);
+ if (tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ tdb->iccmax = (iccmax > 0) ? iccmax : TDBIDXICCMAX;
+ tdb->iccsync = (iccsync > 0) ? iccsync : TDBIDXICCSYNC;
+ return true;
}
-
/* Set the seed of unique ID unumbers of a table database object. */
-bool tctdbsetuidseed(TCTDB *tdb, int64_t seed){
- assert(tdb && seed >= 0);
- if(!TDBLOCKMETHOD(tdb, true)) return -1;
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbsetuidseed(TCTDB *tdb, int64_t seed) {
+ assert(tdb && seed >= 0);
+ if (!TDBLOCKMETHOD(tdb, true)) return -1;
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ tctdbgenuidimpl(tdb, -seed - 1);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- tctdbgenuidimpl(tdb, -seed - 1);
- TDBUNLOCKMETHOD(tdb);
- return true;
+ return true;
}
-
/* Set the custom codec functions of a table database object. */
-bool tctdbsetcodecfunc(TCTDB *tdb, TCCODEC enc, void *encop, TCCODEC dec, void *decop){
- assert(tdb && enc && dec);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbsetcodecfunc(TCTDB *tdb, TCCODEC enc, void *encop, TCCODEC dec, void *decop) {
+ assert(tdb && enc && dec);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tchdbsetcodecfunc(tdb->hdb, enc, encop, dec, decop);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tchdbsetcodecfunc(tdb->hdb, enc, encop, dec, decop);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Get the unit step number of auto defragmentation of a table database object. */
-uint32_t tctdbdfunit(TCTDB *tdb){
- assert(tdb);
- return tchdbdfunit(tdb->hdb);
+uint32_t tctdbdfunit(TCTDB *tdb) {
+ assert(tdb);
+ return tchdbdfunit(tdb->hdb);
}
-
/* Perform dynamic defragmentation of a table database object. */
-bool tctdbdefrag(TCTDB *tdb, int64_t step){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, false)) return false;
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbdefrag(TCTDB *tdb, int64_t step) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, false)) return false;
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tctdbdefragimpl(tdb, step);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tctdbdefragimpl(tdb, step);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Clear the cache of a table tree database object. */
-bool tctdbcacheclear(TCTDB *tdb){
- assert(tdb);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbcacheclear(TCTDB *tdb) {
+ assert(tdb);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tctdbcacheclearimpl(tdb);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tctdbcacheclearimpl(tdb);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Store a record into a table database object with a duplication handler. */
bool tctdbputproc(TCTDB *tdb, const void *pkbuf, int pksiz, const void *cbuf, int csiz,
- TCPDPROC proc, void *op){
- assert(tdb && pkbuf && pksiz >= 0 && proc);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool err = false;
- TCMAP *cols = tctdbgetimpl(tdb, pkbuf, pksiz);
- if(cols){
- int zsiz;
- char *zbuf = tcstrjoin4(cols, &zsiz);
- int ncsiz;
- void *ncbuf = proc(zbuf, zsiz, &ncsiz, op);
- if(ncbuf == (void *)-1){
- if(!tctdboutimpl(tdb, pkbuf, pksiz)) err = true;
- } else if(ncbuf){
- TCMAP *ncols = tcstrsplit4(ncbuf, ncsiz);
- if(!tctdbputimpl(tdb, pkbuf, pksiz, ncols, TDBPDOVER)) err = true;
- tcmapdel(ncols);
- TCFREE(ncbuf);
- } else {
- tctdbsetecode(tdb, TCEKEEP, __FILE__, __LINE__, __func__);
- err = true;
+ TCPDPROC proc, void *op) {
+ assert(tdb && pkbuf && pksiz >= 0 && proc);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
}
- TCFREE(zbuf);
- tcmapdel(cols);
- } else {
- if(cbuf){
- cols = tcstrsplit4(cbuf, csiz);
- if(!tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDOVER)) err = true;
- tcmapdel(cols);
+ bool err = false;
+ TCMAP *cols = tctdbgetimpl(tdb, pkbuf, pksiz);
+ if (cols) {
+ int zsiz;
+ char *zbuf = tcstrjoin4(cols, &zsiz);
+ int ncsiz;
+ void *ncbuf = proc(zbuf, zsiz, &ncsiz, op);
+ if (ncbuf == (void *) - 1) {
+ if (!tctdboutimpl(tdb, pkbuf, pksiz)) err = true;
+ } else if (ncbuf) {
+ TCMAP *ncols = tcstrsplit4(ncbuf, ncsiz);
+ if (!tctdbputimpl(tdb, pkbuf, pksiz, ncols, TDBPDOVER)) err = true;
+ tcmapdel(ncols);
+ TCFREE(ncbuf);
+ } else {
+ tctdbsetecode(tdb, TCEKEEP, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ TCFREE(zbuf);
+ tcmapdel(cols);
} else {
- tctdbsetecode(tdb, TCENOREC, __FILE__, __LINE__, __func__);
- err = true;
+ if (cbuf) {
+ cols = tcstrsplit4(cbuf, csiz);
+ if (!tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDOVER)) err = true;
+ tcmapdel(cols);
+ } else {
+ tctdbsetecode(tdb, TCENOREC, __FILE__, __LINE__, __func__);
+ err = true;
+ }
}
- }
- TDBUNLOCKMETHOD(tdb);
- return !err;
+ TDBUNLOCKMETHOD(tdb);
+ return !err;
}
-
/* Retrieve the value of a column of a record in a table database object. */
-char *tctdbget4(TCTDB *tdb, const void *pkbuf, int pksiz, const void *nbuf, int nsiz, int *sp){
- assert(tdb && pkbuf && pksiz >= 0 && nbuf && nsiz >= 0 && sp);
- if(!TDBLOCKMETHOD(tdb, false)) return NULL;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+char *tctdbget4(TCTDB *tdb, const void *pkbuf, int pksiz, const void *nbuf, int nsiz, int *sp) {
+ assert(tdb && pkbuf && pksiz >= 0 && nbuf && nsiz >= 0 && sp);
+ if (!TDBLOCKMETHOD(tdb, false)) return NULL;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return NULL;
+ }
+ char *rv = tctdbgetonecol(tdb, pkbuf, pksiz, nbuf, nsiz, sp);
TDBUNLOCKMETHOD(tdb);
- return NULL;
- }
- char *rv = tctdbgetonecol(tdb, pkbuf, pksiz, nbuf, nsiz, sp);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Move the iterator to the record corresponding a key of a table database object. */
-bool tctdbiterinit2(TCTDB *tdb, const void *pkbuf, int pksiz){
- assert(tdb && pkbuf && pksiz >= 0);
- if(!TDBLOCKMETHOD(tdb, true)) return false;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbiterinit2(TCTDB *tdb, const void *pkbuf, int pksiz) {
+ assert(tdb && pkbuf && pksiz >= 0);
+ if (!TDBLOCKMETHOD(tdb, true)) return false;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ bool rv = tchdbiterinit2(tdb->hdb, pkbuf, pksiz);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- bool rv = tchdbiterinit2(tdb->hdb, pkbuf, pksiz);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Move the iterator to the record corresponding a key string of a table database object. */
-bool tctdbiterinit3(TCTDB *tdb, const char *kstr){
- assert(tdb && kstr);
- return tctdbiterinit2(tdb, kstr, strlen(kstr));
+bool tctdbiterinit3(TCTDB *tdb, const char *kstr) {
+ assert(tdb && kstr);
+ return tctdbiterinit2(tdb, kstr, strlen(kstr));
}
-
/* Process each record atomically of a table database object. */
-bool tctdbforeach(TCTDB *tdb, TCITER iter, void *op){
- assert(tdb && iter);
- if(!TDBLOCKMETHOD(tdb, false)) return false;
- if(!tdb->open){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+bool tctdbforeach(TCTDB *tdb, TCITER iter, void *op) {
+ assert(tdb && iter);
+ if (!TDBLOCKMETHOD(tdb, false)) return false;
+ if (!tdb->open) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
+ return false;
+ }
+ TDBTHREADYIELD(tdb);
+ bool rv = tctdbforeachimpl(tdb, iter, op);
TDBUNLOCKMETHOD(tdb);
- return false;
- }
- TDBTHREADYIELD(tdb);
- bool rv = tctdbforeachimpl(tdb, iter, op);
- TDBUNLOCKMETHOD(tdb);
- return rv;
+ return rv;
}
-
/* Process each record corresponding to a query object with non-atomic fashion. */
-bool tctdbqryproc2(TDBQRY *qry, TDBQRYPROC proc, void *op){
- assert(qry && proc);
- TCTDB *tdb = qry->tdb;
- TDBCOND *conds = qry->conds;
- int cnum = qry->cnum;
- bool err = false;
- int64_t getnum = 0;
- int64_t putnum = 0;
- int64_t outnum = 0;
- TCLIST *res = tctdbqrysearch(qry);
- int rnum = TCLISTNUM(res);
- for(int i = 0; i < rnum; i++){
- if(!TDBLOCKMETHOD(tdb, true)){
- err = true;
- break;
- }
- if(!tdb->open || !tdb->wmode){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- TDBUNLOCKMETHOD(tdb);
- err = true;
- break;
- }
- int pksiz;
- const char *pkbuf;
- TCLISTVAL(pkbuf, res, i, pksiz);
- TCMAP *cols = tctdbgetimpl(tdb, pkbuf, pksiz);
- if(cols){
- getnum++;
- bool ok = true;
- for(int j = 0; j < cnum; j++){
- TDBCOND *cond = conds + j;
- if(cond->nsiz < 1){
- if(tctdbqrycondmatch(cond, pkbuf, pksiz) != cond->sign){
- ok = false;
+bool tctdbqryproc2(TDBQRY *qry, TDBQRYPROC proc, void *op) {
+ assert(qry && proc);
+ TCTDB *tdb = qry->tdb;
+ TDBCOND *conds = qry->conds;
+ int cnum = qry->cnum;
+ bool err = false;
+ int64_t getnum = 0;
+ int64_t putnum = 0;
+ int64_t outnum = 0;
+ TCLIST *res = tctdbqrysearch(qry);
+ int rnum = TCLISTNUM(res);
+ for (int i = 0; i < rnum; i++) {
+ if (!TDBLOCKMETHOD(tdb, true)) {
+ err = true;
break;
- }
- } else {
- int vsiz;
- const char *vbuf = tcmapget(cols, cond->name, cond->nsiz, &vsiz);
- if(vbuf){
- if(tctdbqrycondmatch(cond, vbuf, vsiz) != cond->sign){
- ok = false;
- break;
- }
- } else {
- if(cond->sign){
- ok = false;
- break;
- }
- }
}
- }
- if(ok){
- int flags = proc(pkbuf, pksiz, cols, op);
- if(flags & TDBQPPUT){
- if(tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDOVER)){
- putnum++;
- } else {
- err = true;
- }
- } else if(flags & TDBQPOUT){
- if(tctdboutimpl(tdb, pkbuf, pksiz)){
- outnum++;
- } else {
+ if (!tdb->open || !tdb->wmode) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ TDBUNLOCKMETHOD(tdb);
err = true;
- }
+ break;
+ }
+ int pksiz;
+ const char *pkbuf;
+ TCLISTVAL(pkbuf, res, i, pksiz);
+ TCMAP *cols = tctdbgetimpl(tdb, pkbuf, pksiz);
+ if (cols) {
+ getnum++;
+ bool ok = true;
+ for (int j = 0; j < cnum; j++) {
+ TDBCOND *cond = conds + j;
+ if (cond->nsiz < 1) {
+ if (tctdbqrycondmatch(cond, pkbuf, pksiz) != cond->sign) {
+ ok = false;
+ break;
+ }
+ } else {
+ int vsiz;
+ const char *vbuf = tcmapget(cols, cond->name, cond->nsiz, &vsiz);
+ if (vbuf) {
+ if (tctdbqrycondmatch(cond, vbuf, vsiz) != cond->sign) {
+ ok = false;
+ break;
+ }
+ } else {
+ if (cond->sign) {
+ ok = false;
+ break;
+ }
+ }
+ }
+ }
+ if (ok) {
+ int flags = proc(pkbuf, pksiz, cols, op);
+ if (flags & TDBQPPUT) {
+ if (tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDOVER)) {
+ putnum++;
+ } else {
+ err = true;
+ }
+ } else if (flags & TDBQPOUT) {
+ if (tctdboutimpl(tdb, pkbuf, pksiz)) {
+ outnum++;
+ } else {
+ err = true;
+ }
+ }
+ if (flags & TDBQPSTOP) i = rnum;
+ }
+ tcmapdel(cols);
}
- if(flags & TDBQPSTOP) i = rnum;
- }
- tcmapdel(cols);
+ TDBUNLOCKMETHOD(tdb);
}
- TDBUNLOCKMETHOD(tdb);
- }
- tclistdel(res);
- tcxstrprintf(qry->hint, "post treatment: get=%" PRIdMAX ", put=%" PRIdMAX ", out=%" PRIdMAX "\n",
- (long long)getnum, (long long)putnum, (long long)outnum);
- return !err;
+ tclistdel(res);
+ tcxstrprintf(qry->hint, "post treatment: get=%" PRIdMAX ", put=%" PRIdMAX ", out=%" PRIdMAX "\n",
+ (long long) getnum, (long long) putnum, (long long) outnum);
+ return !err;
}
-
/* Remove each record corresponding to a query object with non-atomic fashion. */
-bool tctdbqrysearchout2(TDBQRY *qry){
- assert(qry);
- return tctdbqryproc2(qry, tctdbqryprocoutcb, NULL);
+bool tctdbqrysearchout2(TDBQRY *qry) {
+ assert(qry);
+ return tctdbqryproc2(qry, tctdbqryprocoutcb, NULL);
}
-
/* Convert a string into the index type number. */
-int tctdbstrtoindextype(const char *str){
- assert(str);
- int type = -1;
- int flags = 0;
- if(*str == '+'){
- flags |= TDBITKEEP;
- str++;
- }
- if(!tcstricmp(str, "LEX") || !tcstricmp(str, "LEXICAL") || !tcstricmp(str, "STR")){
- type = TDBITLEXICAL;
- } else if(!tcstricmp(str, "DEC") || !tcstricmp(str, "DECIMAL") || !tcstricmp(str, "NUM")){
- type = TDBITDECIMAL;
- } else if(!tcstricmp(str, "TOK") || !tcstricmp(str, "TOKEN")){
- type = TDBITTOKEN;
- } else if(!tcstricmp(str, "QGR") || !tcstricmp(str, "QGRAM") || !tcstricmp(str, "FTS")){
- type = TDBITQGRAM;
- } else if(!tcstricmp(str, "OPT") || !tcstricmp(str, "OPTIMIZE")){
- type = TDBITOPT;
- } else if(!tcstricmp(str, "VOID") || !tcstricmp(str, "NULL")){
- type = TDBITVOID;
- } else if(tcstrisnum(str)){
- type = tcatoi(str);
- }
- return type | flags;
+int tctdbstrtoindextype(const char *str) {
+ assert(str);
+ int type = -1;
+ int flags = 0;
+ if (*str == '+') {
+ flags |= TDBITKEEP;
+ str++;
+ }
+ if (!tcstricmp(str, "LEX") || !tcstricmp(str, "LEXICAL") || !tcstricmp(str, "STR")) {
+ type = TDBITLEXICAL;
+ } else if (!tcstricmp(str, "DEC") || !tcstricmp(str, "DECIMAL") || !tcstricmp(str, "NUM")) {
+ type = TDBITDECIMAL;
+ } else if (!tcstricmp(str, "TOK") || !tcstricmp(str, "TOKEN")) {
+ type = TDBITTOKEN;
+ } else if (!tcstricmp(str, "QGR") || !tcstricmp(str, "QGRAM") || !tcstricmp(str, "FTS")) {
+ type = TDBITQGRAM;
+ } else if (!tcstricmp(str, "OPT") || !tcstricmp(str, "OPTIMIZE")) {
+ type = TDBITOPT;
+ } else if (!tcstricmp(str, "VOID") || !tcstricmp(str, "NULL")) {
+ type = TDBITVOID;
+ } else if (tcstrisnum(str)) {
+ type = tcatoi(str);
+ }
+ return type | flags;
}
-
/* Convert a string into the meta search type number. */
-int tctdbstrtometasearcytype(const char *str){
- assert(str);
- int type = -1;
- if(!tcstricmp(str, "UNION") || !tcstricmp(str, "OR")){
- type = TDBMSUNION;
- } else if(!tcstricmp(str, "ISECT") || !tcstricmp(str, "INTERSECTION") ||
- !tcstricmp(str, "AND")){
- type = TDBMSISECT;
- } else if(!tcstricmp(str, "DIFF") || !tcstricmp(str, "DIFFERENCE") ||
- !tcstricmp(str, "ANDNOT") || !tcstricmp(str, "NOT")){
- type = TDBMSDIFF;
- } else if(tcstrisnum(str)){
- type = tcatoi(str);
- }
- return type;
+int tctdbstrtometasearcytype(const char *str) {
+ assert(str);
+ int type = -1;
+ if (!tcstricmp(str, "UNION") || !tcstricmp(str, "OR")) {
+ type = TDBMSUNION;
+ } else if (!tcstricmp(str, "ISECT") || !tcstricmp(str, "INTERSECTION") ||
+ !tcstricmp(str, "AND")) {
+ type = TDBMSISECT;
+ } else if (!tcstricmp(str, "DIFF") || !tcstricmp(str, "DIFFERENCE") ||
+ !tcstricmp(str, "ANDNOT") || !tcstricmp(str, "NOT")) {
+ type = TDBMSDIFF;
+ } else if (tcstrisnum(str)) {
+ type = tcatoi(str);
+ }
+ return type;
}
-
/* Get the count of corresponding records of a query object. */
-int tctdbqrycount(TDBQRY *qry){
- assert(qry);
- return qry->count;
+int tctdbqrycount(TDBQRY *qry) {
+ assert(qry);
+ return qry->count;
}
-
/* Generate keyword-in-context strings from a query object. */
-TCLIST *tctdbqrykwic(TDBQRY *qry, TCMAP *cols, const char *name, int width, int opts){
- assert(qry && cols && width >= 0);
- TDBCOND *conds = qry->conds;
- int cnum = qry->cnum;
- TDBCOND *cond = NULL;
- if(name){
- for(int i = 0; i < cnum; i++){
- if(!strcmp(conds[i].name, name)){
- cond = conds + i;
- break;
- }
- }
- } else if(cnum > 0){
- cond = conds;
- name = cond->name;
- }
- if(!cond) return tclistnew2(1);
- const char *str = tcmapget2(cols, name);
- if(!str) return tclistnew2(1);
- TCLIST *words;
- if(cond->op == TDBQCSTRAND || cond->op == TDBQCSTROR ||
- cond->op == TDBQCSTROREQ || cond->op == TDBQCNUMOREQ){
- words = tcstrsplit(cond->expr, " ,");
- } else if(cond->op == TDBQCFTSPH){
- TDBFTSUNIT *ftsunits = cond->ftsunits;
- int ftsnum = cond->ftsnum;
- if(ftsnum > 0){
- words = tclistnew2(ftsnum * 2 + 1);
- for(int i = 0; i < ftsnum; i++){
- if(!ftsunits[i].sign) continue;
- TCLIST *tokens = ftsunits[i].tokens;
- int tnum = TCLISTNUM(tokens);
- for(int j = 0; j < tnum; j++){
- const char *token;
- int tsiz;
- TCLISTVAL(token, tokens, j, tsiz);
- TCLISTPUSH(words, token, tsiz);
+TCLIST *tctdbqrykwic(TDBQRY *qry, TCMAP *cols, const char *name, int width, int opts) {
+ assert(qry && cols && width >= 0);
+ TDBCOND *conds = qry->conds;
+ int cnum = qry->cnum;
+ TDBCOND *cond = NULL;
+ if (name) {
+ for (int i = 0; i < cnum; i++) {
+ if (!strcmp(conds[i].name, name)) {
+ cond = conds + i;
+ break;
+ }
+ }
+ } else if (cnum > 0) {
+ cond = conds;
+ name = cond->name;
+ }
+ if (!cond) return tclistnew2(1);
+ const char *str = tcmapget2(cols, name);
+ if (!str) return tclistnew2(1);
+ TCLIST *words;
+ if (cond->op == TDBQCSTRAND || cond->op == TDBQCSTROR ||
+ cond->op == TDBQCSTROREQ || cond->op == TDBQCNUMOREQ) {
+ words = tcstrsplit(cond->expr, " ,");
+ } else if (cond->op == TDBQCFTSPH) {
+ TDBFTSUNIT *ftsunits = cond->ftsunits;
+ int ftsnum = cond->ftsnum;
+ if (ftsnum > 0) {
+ words = tclistnew2(ftsnum * 2 + 1);
+ for (int i = 0; i < ftsnum; i++) {
+ if (!ftsunits[i].sign) continue;
+ TCLIST *tokens = ftsunits[i].tokens;
+ int tnum = TCLISTNUM(tokens);
+ for (int j = 0; j < tnum; j++) {
+ const char *token;
+ int tsiz;
+ TCLISTVAL(token, tokens, j, tsiz);
+ TCLISTPUSH(words, token, tsiz);
+ }
+ }
+ } else {
+ words = tclistnew2(1);
}
- }
} else {
- words = tclistnew2(1);
+ words = tclistnew3(cond->expr, NULL);
}
- } else {
- words = tclistnew3(cond->expr, NULL);
- }
- TCLIST *texts = tcstrkwic(str, words, width, opts);
- tclistdel(words);
- return texts;
+ TCLIST *texts = tcstrkwic(str, words, width, opts);
+ tclistdel(words);
+ return texts;
}
-
/* Convert a string into the query operation number. */
-int tctdbqrystrtocondop(const char *str){
- assert(str);
- int op = -1;
- int flags = 0;
- if(*str == '~' || *str == '!'){
- flags |= TDBQCNEGATE;
- str++;
- }
- if(*str == '+'){
- flags |= TDBQCNOIDX;
- str++;
- }
- if(!tcstricmp(str, "STREQ") || !tcstricmp(str, "STR") || !tcstricmp(str, "EQ")){
- op = TDBQCSTREQ;
- } else if(!tcstricmp(str, "STRINC") || !tcstricmp(str, "INC")){
- op = TDBQCSTRINC;
- } else if(!tcstricmp(str, "STRBW") || !tcstricmp(str, "BW")){
- op = TDBQCSTRBW;
- } else if(!tcstricmp(str, "STREW") || !tcstricmp(str, "EW")){
- op = TDBQCSTREW;
- } else if(!tcstricmp(str, "STRAND") || !tcstricmp(str, "AND")){
- op = TDBQCSTRAND;
- } else if(!tcstricmp(str, "STROR") || !tcstricmp(str, "OR")){
- op = TDBQCSTROR;
- } else if(!tcstricmp(str, "STROREQ") || !tcstricmp(str, "OREQ")){
- op = TDBQCSTROREQ;
- } else if(!tcstricmp(str, "STRRX") || !tcstricmp(str, "RX")){
- op = TDBQCSTRRX;
- } else if(!tcstricmp(str, "NUMEQ") || !tcstricmp(str, "NUM") ||
- !tcstricmp(str, "=") || !tcstricmp(str, "==")){
- op = TDBQCNUMEQ;
- } else if(!tcstricmp(str, "NUMGT") || !tcstricmp(str, ">")){
- op = TDBQCNUMGT;
- } else if(!tcstricmp(str, "NUMGE") || !tcstricmp(str, ">=")){
- op = TDBQCNUMGE;
- } else if(!tcstricmp(str, "NUMLT") || !tcstricmp(str, "<")){
- op = TDBQCNUMLT;
- } else if(!tcstricmp(str, "NUMLE") || !tcstricmp(str, "<=")){
- op = TDBQCNUMLE;
- } else if(!tcstricmp(str, "NUMBT")){
- op = TDBQCNUMBT;
- } else if(!tcstricmp(str, "NUMOREQ")){
- op = TDBQCNUMOREQ;
- } else if(!tcstricmp(str, "FTSPH") || !tcstricmp(str, "FTS")){
- op = TDBQCFTSPH;
- } else if(!tcstricmp(str, "FTSAND")){
- op = TDBQCFTSAND;
- } else if(!tcstricmp(str, "FTSOR")){
- op = TDBQCFTSOR;
- } else if(!tcstricmp(str, "FTSEX")){
- op = TDBQCFTSEX;
- } else if(tcstrisnum(str)){
- op = tcatoi(str);
- }
- return op | flags;
+int tctdbqrystrtocondop(const char *str) {
+ assert(str);
+ int op = -1;
+ int flags = 0;
+ if (*str == '~' || *str == '!') {
+ flags |= TDBQCNEGATE;
+ str++;
+ }
+ if (*str == '+') {
+ flags |= TDBQCNOIDX;
+ str++;
+ }
+ if (!tcstricmp(str, "STREQ") || !tcstricmp(str, "STR") || !tcstricmp(str, "EQ")) {
+ op = TDBQCSTREQ;
+ } else if (!tcstricmp(str, "STRINC") || !tcstricmp(str, "INC")) {
+ op = TDBQCSTRINC;
+ } else if (!tcstricmp(str, "STRBW") || !tcstricmp(str, "BW")) {
+ op = TDBQCSTRBW;
+ } else if (!tcstricmp(str, "STREW") || !tcstricmp(str, "EW")) {
+ op = TDBQCSTREW;
+ } else if (!tcstricmp(str, "STRAND") || !tcstricmp(str, "AND")) {
+ op = TDBQCSTRAND;
+ } else if (!tcstricmp(str, "STROR") || !tcstricmp(str, "OR")) {
+ op = TDBQCSTROR;
+ } else if (!tcstricmp(str, "STROREQ") || !tcstricmp(str, "OREQ")) {
+ op = TDBQCSTROREQ;
+ } else if (!tcstricmp(str, "STRRX") || !tcstricmp(str, "RX")) {
+ op = TDBQCSTRRX;
+ } else if (!tcstricmp(str, "NUMEQ") || !tcstricmp(str, "NUM") ||
+ !tcstricmp(str, "=") || !tcstricmp(str, "==")) {
+ op = TDBQCNUMEQ;
+ } else if (!tcstricmp(str, "NUMGT") || !tcstricmp(str, ">")) {
+ op = TDBQCNUMGT;
+ } else if (!tcstricmp(str, "NUMGE") || !tcstricmp(str, ">=")) {
+ op = TDBQCNUMGE;
+ } else if (!tcstricmp(str, "NUMLT") || !tcstricmp(str, "<")) {
+ op = TDBQCNUMLT;
+ } else if (!tcstricmp(str, "NUMLE") || !tcstricmp(str, "<=")) {
+ op = TDBQCNUMLE;
+ } else if (!tcstricmp(str, "NUMBT")) {
+ op = TDBQCNUMBT;
+ } else if (!tcstricmp(str, "NUMOREQ")) {
+ op = TDBQCNUMOREQ;
+ } else if (!tcstricmp(str, "FTSPH") || !tcstricmp(str, "FTS")) {
+ op = TDBQCFTSPH;
+ } else if (!tcstricmp(str, "FTSAND")) {
+ op = TDBQCFTSAND;
+ } else if (!tcstricmp(str, "FTSOR")) {
+ op = TDBQCFTSOR;
+ } else if (!tcstricmp(str, "FTSEX")) {
+ op = TDBQCFTSEX;
+ } else if (tcstrisnum(str)) {
+ op = tcatoi(str);
+ }
+ return op | flags;
}
-
/* Convert a string into the query order type number. */
-int tctdbqrystrtoordertype(const char *str){
- assert(str);
- int type = -1;
- if(!tcstricmp(str, "STRASC") || !tcstricmp(str, "STR") || !tcstricmp(str, "ASC")){
- type = TDBQOSTRASC;
- } else if(!tcstricmp(str, "STRDESC") || !tcstricmp(str, "DESC")){
- type = TDBQOSTRDESC;
- } else if(!tcstricmp(str, "NUMASC") || !tcstricmp(str, "NUM")){
- type = TDBQONUMASC;
- } else if(!tcstricmp(str, "NUMDESC")){
- type = TDBQONUMDESC;
- } else if(tcstrisnum(str)){
- type = tcatoi(str);
- }
- return type;
+int tctdbqrystrtoordertype(const char *str) {
+ assert(str);
+ int type = -1;
+ if (!tcstricmp(str, "STRASC") || !tcstricmp(str, "STR") || !tcstricmp(str, "ASC")) {
+ type = TDBQOSTRASC;
+ } else if (!tcstricmp(str, "STRDESC") || !tcstricmp(str, "DESC")) {
+ type = TDBQOSTRDESC;
+ } else if (!tcstricmp(str, "NUMASC") || !tcstricmp(str, "NUM")) {
+ type = TDBQONUMASC;
+ } else if (!tcstricmp(str, "NUMDESC")) {
+ type = TDBQONUMDESC;
+ } else if (tcstrisnum(str)) {
+ type = tcatoi(str);
+ }
+ return type;
}
-
/* Convert a string into the set operation type number. */
-int tctdbmetastrtosettype(const char *str){
- assert(str);
- int type = -1;
- if(!tcstricmp(str, "UNION") || !tcstricmp(str, "CUP") || !tcstricmp(str, "+")){
- type = TDBMSUNION;
- } else if(!tcstricmp(str, "ISECT") || !tcstricmp(str, "INTERSECTION") ||
- !tcstricmp(str, "CAP") || !tcstricmp(str, "*")){
- type = TDBMSISECT;
- } else if(!tcstricmp(str, "DIFF") || !tcstricmp(str, "DIFFERENCE") ||
- !tcstricmp(str, "MINUS") || !tcstricmp(str, "-")){
- type = TDBMSDIFF;
- } else if(tcstrisnum(str)){
- type = tcatoi(str);
- }
- return type;
+int tctdbmetastrtosettype(const char *str) {
+ assert(str);
+ int type = -1;
+ if (!tcstricmp(str, "UNION") || !tcstricmp(str, "CUP") || !tcstricmp(str, "+")) {
+ type = TDBMSUNION;
+ } else if (!tcstricmp(str, "ISECT") || !tcstricmp(str, "INTERSECTION") ||
+ !tcstricmp(str, "CAP") || !tcstricmp(str, "*")) {
+ type = TDBMSISECT;
+ } else if (!tcstricmp(str, "DIFF") || !tcstricmp(str, "DIFFERENCE") ||
+ !tcstricmp(str, "MINUS") || !tcstricmp(str, "-")) {
+ type = TDBMSDIFF;
+ } else if (tcstrisnum(str)) {
+ type = tcatoi(str);
+ }
+ return type;
}
* private features
*************************************************************************************************/
-
/* Clear all members.
`tdb' specifies the table database object. */
-static void tctdbclear(TCTDB *tdb){
- assert(tdb);
- tdb->mmtx = NULL;
- tdb->hdb = NULL;
- tdb->open = false;
- tdb->wmode = false;
- tdb->opts = 0;
- tdb->lcnum = TDBDEFLCNUM;
- tdb->ncnum = TDBDEFNCNUM;
- tdb->iccmax = TDBIDXICCMAX;
- tdb->iccsync = TDBIDXICCSYNC;
- tdb->idxs = NULL;
- tdb->inum = 0;
- tdb->tran = false;
+static void tctdbclear(TCTDB *tdb) {
+ assert(tdb);
+ tdb->mmtx = NULL;
+ tdb->hdb = NULL;
+ tdb->open = false;
+ tdb->wmode = false;
+ tdb->opts = 0;
+ tdb->lcnum = TDBDEFLCNUM;
+ tdb->ncnum = TDBDEFNCNUM;
+ tdb->iccmax = TDBIDXICCMAX;
+ tdb->iccsync = TDBIDXICCSYNC;
+ tdb->idxs = NULL;
+ tdb->inum = 0;
+ tdb->tran = false;
}
-
/* Open a database file and connect a table database object.
`tdb' specifies the table database object.
`path' specifies the path of the internal database file.
`omode' specifies the connection mode.
If successful, the return value is true, else, it is false. */
-static bool tctdbopenimpl(TCTDB *tdb, const char *path, int omode){
- assert(tdb && path);
- HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
- TCCODEC enc, dec;
- void *encop, *decop;
- tchdbcodecfunc(tdb->hdb, &enc, &encop, &dec, &decop);
- int homode = HDBOREADER;
- int bomode = BDBOREADER;
- if(omode & TDBOWRITER){
- homode = HDBOWRITER;
- bomode = BDBOWRITER;
- if(omode & TDBOCREAT){
- homode |= HDBOCREAT;
- bomode |= BDBOCREAT;
- }
- if(omode & TDBOTRUNC){
- homode |= HDBOTRUNC;
- bomode |= BDBOTRUNC;
- }
- tdb->wmode = true;
- } else {
- tdb->wmode = false;
- }
- if(omode & TDBONOLCK){
- homode |= HDBONOLCK;
- bomode |= BDBONOLCK;
- }
- if(omode & TDBOLCKNB){
- homode |= HDBOLCKNB;
- bomode |= BDBOLCKNB;
- }
- if(omode & TDBOTSYNC){
- homode |= HDBOTSYNC;
- bomode |= BDBOTSYNC;
- }
- tchdbsettype(tdb->hdb, TCDBTTABLE);
- if(!tchdbopen(tdb->hdb, path, homode)) return false;
- char *tpath = tcsprintf("%s%c%s%c*", path, MYEXTCHR, TDBIDXSUFFIX, MYEXTCHR);
- if((omode & TDBOWRITER) && (omode & TDBOTRUNC)){
+static bool tctdbopenimpl(TCTDB *tdb, const char *path, int omode) {
+ assert(tdb && path);
+ HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
+ TCCODEC enc, dec;
+ void *encop, *decop;
+ tchdbcodecfunc(tdb->hdb, &enc, &encop, &dec, &decop);
+ int homode = HDBOREADER;
+ int bomode = BDBOREADER;
+ if (omode & TDBOWRITER) {
+ homode = HDBOWRITER;
+ bomode = BDBOWRITER;
+ if (omode & TDBOCREAT) {
+ homode |= HDBOCREAT;
+ bomode |= BDBOCREAT;
+ }
+ if (omode & TDBOTRUNC) {
+ homode |= HDBOTRUNC;
+ bomode |= BDBOTRUNC;
+ }
+ tdb->wmode = true;
+ } else {
+ tdb->wmode = false;
+ }
+ if (omode & TDBONOLCK) {
+ homode |= HDBONOLCK;
+ bomode |= BDBONOLCK;
+ }
+ if (omode & TDBOLCKNB) {
+ homode |= HDBOLCKNB;
+ bomode |= BDBOLCKNB;
+ }
+ if (omode & TDBOTSYNC) {
+ homode |= HDBOTSYNC;
+ bomode |= BDBOTSYNC;
+ }
+ tchdbsettype(tdb->hdb, TCDBTTABLE);
+ if (!tchdbopen(tdb->hdb, path, homode)) return false;
+ char *tpath = tcsprintf("%s%c%s%c*", path, MYEXTCHR, TDBIDXSUFFIX, MYEXTCHR);
+ if ((omode & TDBOWRITER) && (omode & TDBOTRUNC)) {
+ TCLIST *paths = tcglobpat(tpath);
+ int pnum = TCLISTNUM(paths);
+ for (int i = 0; i < pnum; i++) {
+ tcunlinkfile(TCLISTVALPTR(paths, i));
+ }
+ tclistdel(paths);
+ }
TCLIST *paths = tcglobpat(tpath);
int pnum = TCLISTNUM(paths);
- for(int i = 0; i < pnum; i++){
- tcunlinkfile(TCLISTVALPTR(paths, i));
+ TCMALLOC(tdb->idxs, sizeof (tdb->idxs[0]) * pnum + 1);
+ TDBIDX *idxs = tdb->idxs;
+ int inum = 0;
+ for (int i = 0; i < pnum; i++) {
+ const char *ipath = TCLISTVALPTR(paths, i);
+ if (!tcstrfwm(ipath, path)) continue;
+ const char *rp = ipath + strlen(path);
+ if (*rp != MYEXTCHR) continue;
+ rp++;
+ if (!tcstrfwm(rp, TDBIDXSUFFIX)) continue;
+ rp += strlen(TDBIDXSUFFIX);
+ if (*rp != MYEXTCHR) continue;
+ rp++;
+ char *stem = tcstrdup(rp);
+ char *ep = strrchr(stem, MYEXTCHR);
+ if (!ep) continue;
+ *(ep++) = '\0';
+ int nsiz;
+ char *name = tcurldecode(stem, &nsiz);
+ if (!strcmp(ep, "lex") || !strcmp(ep, "dec") || !strcmp(ep, "tok") || !strcmp(ep, "qgr")) {
+ TCBDB *bdb = tcbdbnew();
+ if (!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(bdb, dbgfd);
+ if (tdb->mmtx) tcbdbsetmutex(bdb);
+ if (enc && dec) tcbdbsetcodecfunc(bdb, enc, encop, dec, decop);
+ tcbdbsetcache(bdb, tdb->lcnum, tdb->ncnum);
+ tcbdbsetxmsiz(bdb, tchdbxmsiz(tdb->hdb));
+ tcbdbsetdfunit(bdb, tchdbdfunit(tdb->hdb));
+ tcbdbsetlsmax(bdb, TDBIDXLSMAX);
+ if (tcbdbopen(bdb, ipath, bomode)) {
+ idxs[inum].name = tcstrdup(name);
+ idxs[inum].type = TDBITLEXICAL;
+ if (!strcmp(ep, "dec")) {
+ idxs[inum].type = TDBITDECIMAL;
+ } else if (!strcmp(ep, "tok")) {
+ idxs[inum].type = TDBITTOKEN;
+ } else if (!strcmp(ep, "qgr")) {
+ idxs[inum].type = TDBITQGRAM;
+ }
+ idxs[inum].db = bdb;
+ idxs[inum].cc = NULL;
+ if (idxs[inum].type == TDBITTOKEN) {
+ idxs[inum].cc = tcmapnew2(TDBIDXICCBNUM);
+ } else if (idxs[inum].type == TDBITQGRAM) {
+ idxs[inum].cc = tcmapnew2(TDBIDXICCBNUM);
+ }
+ inum++;
+ } else {
+ tcbdbdel(bdb);
+ }
+ }
+ TCFREE(name);
+ TCFREE(stem);
}
tclistdel(paths);
- }
- TCLIST *paths = tcglobpat(tpath);
- int pnum = TCLISTNUM(paths);
- TCMALLOC(tdb->idxs, sizeof(tdb->idxs[0]) * pnum + 1);
- TDBIDX *idxs = tdb->idxs;
- int inum = 0;
- for(int i = 0; i < pnum; i++){
- const char *ipath = TCLISTVALPTR(paths, i);
- if(!tcstrfwm(ipath, path)) continue;
- const char *rp = ipath + strlen(path);
- if(*rp != MYEXTCHR) continue;
- rp++;
- if(!tcstrfwm(rp, TDBIDXSUFFIX)) continue;
- rp += strlen(TDBIDXSUFFIX);
- if(*rp != MYEXTCHR) continue;
- rp++;
- char *stem = tcstrdup(rp);
- char *ep = strrchr(stem, MYEXTCHR);
- if(!ep) continue;
- *(ep++) = '\0';
- int nsiz;
- char *name = tcurldecode(stem, &nsiz);
- if(!strcmp(ep, "lex") || !strcmp(ep, "dec") || !strcmp(ep, "tok") || !strcmp(ep, "qgr")){
- TCBDB *bdb = tcbdbnew();
- if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(bdb, dbgfd);
- if(tdb->mmtx) tcbdbsetmutex(bdb);
- if(enc && dec) tcbdbsetcodecfunc(bdb, enc, encop, dec, decop);
- tcbdbsetcache(bdb, tdb->lcnum, tdb->ncnum);
- tcbdbsetxmsiz(bdb, tchdbxmsiz(tdb->hdb));
- tcbdbsetdfunit(bdb, tchdbdfunit(tdb->hdb));
- tcbdbsetlsmax(bdb, TDBIDXLSMAX);
- if(tcbdbopen(bdb, ipath, bomode)){
- idxs[inum].name = tcstrdup(name);
- idxs[inum].type = TDBITLEXICAL;
- if(!strcmp(ep, "dec")){
- idxs[inum].type = TDBITDECIMAL;
- } else if(!strcmp(ep, "tok")){
- idxs[inum].type = TDBITTOKEN;
- } else if(!strcmp(ep, "qgr")){
- idxs[inum].type = TDBITQGRAM;
- }
- idxs[inum].db = bdb;
- idxs[inum].cc = NULL;
- if(idxs[inum].type == TDBITTOKEN){
- idxs[inum].cc = tcmapnew2(TDBIDXICCBNUM);
- } else if(idxs[inum].type == TDBITQGRAM){
- idxs[inum].cc = tcmapnew2(TDBIDXICCBNUM);
- }
- inum++;
- } else {
- tcbdbdel(bdb);
- }
- }
- TCFREE(name);
- TCFREE(stem);
- }
- tclistdel(paths);
- TCFREE(tpath);
- tdb->inum = inum;
- tdb->open = true;
- uint8_t hopts = tchdbopts(tdb->hdb);
- uint8_t opts = 0;
- if(hopts & HDBTLARGE) opts |= TDBTLARGE;
- if(hopts & HDBTDEFLATE) opts |= TDBTDEFLATE;
- if(hopts & HDBTBZIP) opts |= TDBTBZIP;
- if(hopts & HDBTTCBS) opts |= TDBTTCBS;
- if(hopts & HDBTEXCODEC) opts |= TDBTEXCODEC;
- tdb->opts = opts;
- tdb->tran = false;
- return true;
+ TCFREE(tpath);
+ tdb->inum = inum;
+ tdb->open = true;
+ uint8_t hopts = tchdbopts(tdb->hdb);
+ uint8_t opts = 0;
+ if (hopts & HDBTLARGE) opts |= TDBTLARGE;
+ if (hopts & HDBTDEFLATE) opts |= TDBTDEFLATE;
+ if (hopts & HDBTBZIP) opts |= TDBTBZIP;
+ if (hopts & HDBTTCBS) opts |= TDBTTCBS;
+ if (hopts & HDBTEXCODEC) opts |= TDBTEXCODEC;
+ tdb->opts = opts;
+ tdb->tran = false;
+ return true;
}
-
/* Close a table database object.
`tdb' specifies the table database object.
If successful, the return value is true, else, it is false. */
-static bool tctdbcloseimpl(TCTDB *tdb){
- assert(tdb);
- bool err = false;
- if(tdb->tran && !tctdbtranabortimpl(tdb)) err = true;
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tctdbidxsyncicc(tdb, idx, true)) err = true;
- tcmapdel(idx->cc);
- break;
- }
- }
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tcbdbclose(idx->db)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- tcbdbdel(idx->db);
- break;
- }
- TCFREE(idx->name);
- }
- TCFREE(idxs);
- if(!tchdbclose(tdb->hdb)) err = true;
- tdb->open = false;
- return !err;
+static bool tctdbcloseimpl(TCTDB *tdb) {
+ assert(tdb);
+ bool err = false;
+ if (tdb->tran && !tctdbtranabortimpl(tdb)) err = true;
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tctdbidxsyncicc(tdb, idx, true)) err = true;
+ tcmapdel(idx->cc);
+ break;
+ }
+ }
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tcbdbclose(idx->db)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ tcbdbdel(idx->db);
+ break;
+ }
+ TCFREE(idx->name);
+ }
+ TCFREE(idxs);
+ if (!tchdbclose(tdb->hdb)) err = true;
+ tdb->open = false;
+ return !err;
}
-
/* Store a record into a table database object.
`tdb' specifies the table database object.
`pkbuf' specifies the pointer to the region of the primary key.
`cols' specifies a map object containing columns.
`dmode' specifies behavior when the key overlaps.
If successful, the return value is true, else, it is false. */
-static bool tctdbputimpl(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols, int dmode){
- assert(tdb && pkbuf && pksiz >= 0 && cols);
- bool err = false;
- int osiz;
- char *obuf = tdb->hdb->rnum > 0 ? tchdbget(tdb->hdb, pkbuf, pksiz, &osiz) : NULL;
- if(obuf){
- if(dmode == TDBPDKEEP){
- tctdbsetecode(tdb, TCEKEEP, __FILE__, __LINE__, __func__);
- TCFREE(obuf);
- return false;
- }
- TCMAP *ocols = tcmapload(obuf, osiz);
- if(dmode == TDBPDCAT){
- TCMAP *ncols = tcmapnew2(TCMAPRNUM(cols) + 1);
- tcmapiterinit(cols);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){
- int vsiz;
- const char *vbuf = tcmapiterval(kbuf, &vsiz);
- if(tcmapputkeep(ocols, kbuf, ksiz, vbuf, vsiz)) tcmapput(ncols, kbuf, ksiz, vbuf, vsiz);
- }
- if(!tctdbidxput(tdb, pkbuf, pksiz, ncols)) err = true;
- tcmapdel(ncols);
- int csiz;
- char *cbuf = tcmapdump(ocols, &csiz);
- if(!tchdbput(tdb->hdb, pkbuf, pksiz, cbuf, csiz)) err = true;
- TCFREE(cbuf);
- } else {
- TCMAP *ncols = tcmapnew2(TCMAPRNUM(cols) + 1);
- tcmapiterinit(cols);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){
- int vsiz;
- const char *vbuf = tcmapiterval(kbuf, &vsiz);
- int osiz;
- const char *obuf = tcmapget(ocols, kbuf, ksiz, &osiz);
- if(obuf && osiz == vsiz && !memcmp(obuf, vbuf, osiz)){
- tcmapout(ocols, kbuf, ksiz);
+static bool tctdbputimpl(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols, int dmode) {
+ assert(tdb && pkbuf && pksiz >= 0 && cols);
+ bool err = false;
+ int osiz;
+ char *obuf = tdb->hdb->rnum > 0 ? tchdbget(tdb->hdb, pkbuf, pksiz, &osiz) : NULL;
+ if (obuf) {
+ if (dmode == TDBPDKEEP) {
+ tctdbsetecode(tdb, TCEKEEP, __FILE__, __LINE__, __func__);
+ TCFREE(obuf);
+ return false;
+ }
+ TCMAP *ocols = tcmapload(obuf, osiz);
+ if (dmode == TDBPDCAT) {
+ TCMAP *ncols = tcmapnew2(TCMAPRNUM(cols) + 1);
+ tcmapiterinit(cols);
+ const char *kbuf;
+ int ksiz;
+ while ((kbuf = tcmapiternext(cols, &ksiz)) != NULL) {
+ int vsiz;
+ const char *vbuf = tcmapiterval(kbuf, &vsiz);
+ if (tcmapputkeep(ocols, kbuf, ksiz, vbuf, vsiz)) tcmapput(ncols, kbuf, ksiz, vbuf, vsiz);
+ }
+ if (!tctdbidxput(tdb, pkbuf, pksiz, ncols)) err = true;
+ tcmapdel(ncols);
+ int csiz;
+ char *cbuf = tcmapdump(ocols, &csiz);
+ if (!tchdbput(tdb->hdb, pkbuf, pksiz, cbuf, csiz)) err = true;
+ TCFREE(cbuf);
} else {
- tcmapput(ncols, kbuf, ksiz, vbuf, vsiz);
- }
- }
- if(!tctdbidxout(tdb, pkbuf, pksiz, ocols)) err = true;
- if(!tctdbidxput(tdb, pkbuf, pksiz, ncols)) err = true;
- tcmapdel(ncols);
- int csiz;
- char *cbuf = tcmapdump(cols, &csiz);
- if(!tchdbput(tdb->hdb, pkbuf, pksiz, cbuf, csiz)) err = true;
- TCFREE(cbuf);
- }
- tcmapdel(ocols);
- TCFREE(obuf);
- } else {
- if(!tctdbidxput(tdb, pkbuf, pksiz, cols)) err = true;
- int csiz;
- char *cbuf = tcmapdump(cols, &csiz);
- if(!tchdbput(tdb->hdb, pkbuf, pksiz, cbuf, csiz)) err = true;
- TCFREE(cbuf);
- }
- return !err;
+ TCMAP *ncols = tcmapnew2(TCMAPRNUM(cols) + 1);
+ tcmapiterinit(cols);
+ const char *kbuf;
+ int ksiz;
+ while ((kbuf = tcmapiternext(cols, &ksiz)) != NULL) {
+ int vsiz;
+ const char *vbuf = tcmapiterval(kbuf, &vsiz);
+ int osiz;
+ const char *obuf = tcmapget(ocols, kbuf, ksiz, &osiz);
+ if (obuf && osiz == vsiz && !memcmp(obuf, vbuf, osiz)) {
+ tcmapout(ocols, kbuf, ksiz);
+ } else {
+ tcmapput(ncols, kbuf, ksiz, vbuf, vsiz);
+ }
+ }
+ if (!tctdbidxout(tdb, pkbuf, pksiz, ocols)) err = true;
+ if (!tctdbidxput(tdb, pkbuf, pksiz, ncols)) err = true;
+ tcmapdel(ncols);
+ int csiz;
+ char *cbuf = tcmapdump(cols, &csiz);
+ if (!tchdbput(tdb->hdb, pkbuf, pksiz, cbuf, csiz)) err = true;
+ TCFREE(cbuf);
+ }
+ tcmapdel(ocols);
+ TCFREE(obuf);
+ } else {
+ if (!tctdbidxput(tdb, pkbuf, pksiz, cols)) err = true;
+ int csiz;
+ char *cbuf = tcmapdump(cols, &csiz);
+ if (!tchdbput(tdb->hdb, pkbuf, pksiz, cbuf, csiz)) err = true;
+ TCFREE(cbuf);
+ }
+ return !err;
}
-
/* Remove a record of a table database object.
`tdb' specifies the table database object.
`pkbuf' specifies the pointer to the region of the primary key.
`pksiz' specifies the size of the region of the primary key.
If successful, the return value is true, else, it is false. */
-static bool tctdboutimpl(TCTDB *tdb, const char *pkbuf, int pksiz){
- assert(tdb && pkbuf && pksiz >= 0);
- int csiz;
- char *cbuf = tchdbget(tdb->hdb, pkbuf, pksiz, &csiz);
- if(!cbuf) return false;
- bool err = false;
- TCMAP *cols = tcmapload(cbuf, csiz);
- if(!tctdbidxout(tdb, pkbuf, pksiz, cols)) err = true;
- if(!tchdbout(tdb->hdb, pkbuf, pksiz)) err = true;
- tcmapdel(cols);
- TCFREE(cbuf);
- return !err;
+static bool tctdboutimpl(TCTDB *tdb, const char *pkbuf, int pksiz) {
+ assert(tdb && pkbuf && pksiz >= 0);
+ int csiz;
+ char *cbuf = tchdbget(tdb->hdb, pkbuf, pksiz, &csiz);
+ if (!cbuf) return false;
+ bool err = false;
+ TCMAP *cols = tcmapload(cbuf, csiz);
+ if (!tctdbidxout(tdb, pkbuf, pksiz, cols)) err = true;
+ if (!tchdbout(tdb->hdb, pkbuf, pksiz)) err = true;
+ tcmapdel(cols);
+ TCFREE(cbuf);
+ return !err;
}
-
/* Retrieve a record in a table database object.
`tdb' specifies the table database object.
`pkbuf' specifies the pointer to the region of the primary key.
`pksiz' specifies the size of the region of the primary key.
If successful, the return value is a map object of the columns of the corresponding record. */
-static TCMAP *tctdbgetimpl(TCTDB *tdb, const void *pkbuf, int pksiz){
- assert(tdb && pkbuf && pksiz >= 0);
- int csiz;
- char *cbuf = tchdbget(tdb->hdb, pkbuf, pksiz, &csiz);
- if(!cbuf) return NULL;
- TCMAP *cols = tcmapload(cbuf, csiz);
- TCFREE(cbuf);
- return cols;
+static TCMAP *tctdbgetimpl(TCTDB *tdb, const void *pkbuf, int pksiz) {
+ assert(tdb && pkbuf && pksiz >= 0);
+ int csiz;
+ char *cbuf = tchdbget(tdb->hdb, pkbuf, pksiz, &csiz);
+ if (!cbuf) return NULL;
+ TCMAP *cols = tcmapload(cbuf, csiz);
+ TCFREE(cbuf);
+ return cols;
}
-
/* Retrieve the value of a column of a record in a table database object.
`tdb' specifies the table database object.
`pkbuf' specifies the pointer to the region of the primary key.
If successful, the return value is the pointer to the region of the value of the column of the
corresponding record. */
static char *tctdbgetonecol(TCTDB *tdb, const void *pkbuf, int pksiz,
- const void *nbuf, int nsiz, int *sp){
- assert(tdb && pkbuf && pksiz >= 0 && nbuf && nsiz >= 0 && sp);
- int csiz;
- char *cbuf = tchdbget(tdb->hdb, pkbuf, pksiz, &csiz);
- if(!cbuf) return NULL;
- void *rv = tcmaploadone(cbuf, csiz, nbuf, nsiz, sp);
- TCFREE(cbuf);
- return rv;
+ const void *nbuf, int nsiz, int *sp) {
+ assert(tdb && pkbuf && pksiz >= 0 && nbuf && nsiz >= 0 && sp);
+ int csiz;
+ char *cbuf = tchdbget(tdb->hdb, pkbuf, pksiz, &csiz);
+ if (!cbuf) return NULL;
+ void *rv = tcmaploadone(cbuf, csiz, nbuf, nsiz, sp);
+ TCFREE(cbuf);
+ return rv;
}
-
/* Add a real number to a column of a record in a table database object.
`tdb' specifies the table database object.
`pkbuf' specifies the pointer to the region of the primary key.
`pksiz' specifies the size of the region of the primary key.
`num' specifies the additional value.
If successful, the return value is the summation value, else, it is Not-a-Number. */
-static double tctdbaddnumber(TCTDB *tdb, const void *pkbuf, int pksiz, double num){
- assert(tdb && pkbuf && pksiz >= 0);
- int csiz;
- char *cbuf = tchdbget(tdb->hdb, pkbuf, pksiz, &csiz);
- TCMAP *cols = cbuf ? tcmapload(cbuf, csiz) : tcmapnew2(1);
- if(cbuf){
- const char *vbuf = tcmapget2(cols, TDBNUMCNTCOL);
- if(vbuf) num += tctdbatof(vbuf);
- TCFREE(cbuf);
- }
- char numbuf[TDBCOLBUFSIZ];
- int len = tcftoa(num, numbuf, TDBCOLBUFSIZ, 6);
- if(len >= TDBCOLBUFSIZ){ //truncation
- tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
- num = nan("");
- } else {
- while(--len > 0){
- if(numbuf[len] != '0') break;
- numbuf[len] = '\0';
+static double tctdbaddnumber(TCTDB *tdb, const void *pkbuf, int pksiz, double num) {
+ assert(tdb && pkbuf && pksiz >= 0);
+ int csiz;
+ char *cbuf = tchdbget(tdb->hdb, pkbuf, pksiz, &csiz);
+ TCMAP *cols = cbuf ? tcmapload(cbuf, csiz) : tcmapnew2(1);
+ if (cbuf) {
+ const char *vbuf = tcmapget2(cols, TDBNUMCNTCOL);
+ if (vbuf) num += tctdbatof(vbuf);
+ TCFREE(cbuf);
+ }
+ char numbuf[TDBCOLBUFSIZ];
+ int len = tcftoa(num, numbuf, TDBCOLBUFSIZ, 6);
+ if (len >= TDBCOLBUFSIZ) { //truncation
+ tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
+ num = nan("");
+ } else {
+ while (--len > 0) {
+ if (numbuf[len] != '0') break;
+ numbuf[len] = '\0';
+ }
+ if (numbuf[len] == '.') numbuf[len] = '\0';
+ tcmapput2(cols, TDBNUMCNTCOL, numbuf);
+ if (!tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDOVER)) num = nan("");
}
- if(numbuf[len] == '.') numbuf[len] = '\0';
- tcmapput2(cols, TDBNUMCNTCOL, numbuf);
- if(!tctdbputimpl(tdb, pkbuf, pksiz, cols, TDBPDOVER)) num = nan("");
- }
- tcmapdel(cols);
+ tcmapdel(cols);
- return num;
+ return num;
}
-
/* Optimize the file of a table database object.
`tdb' specifies the table database object.
`bnum' specifies the number of elements of the bucket array.
`fpow' specifies the maximum number of elements of the free block pool by power of 2.
`opts' specifies options by bitwise-or.
If successful, the return value is true, else, it is false. */
-static bool tctdboptimizeimpl(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
- assert(tdb);
- bool err = false;
- TCHDB *hdb = tdb->hdb;
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITTOKEN:
- case TDBITQGRAM:
- tcmapclear(idx->cc);
- break;
- }
- }
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tcbdbvanish(idx->db)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- }
- }
- const char *path = tchdbpath(tdb->hdb);
- char *tpath = tcsprintf("%s%ctmp%c%" PRIuMAX "", path, MYEXTCHR, MYEXTCHR, tchdbinode(tdb->hdb));
- TCHDB *thdb = tchdbnew();
- tchdbsettype(thdb, TCDBTTABLE);
- HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
- if(!INVALIDHANDLE(dbgfd)) tchdbsetdbgfd(thdb, dbgfd);
- TCCODEC enc, dec;
- void *encop, *decop;
- tchdbcodecfunc(hdb, &enc, &encop, &dec, &decop);
- if(enc && dec) tchdbsetcodecfunc(thdb, enc, encop, dec, decop);
- if(bnum < 1) bnum = tchdbrnum(hdb) * 2 + 1;
- if(apow < 0) apow = tclog2l(tchdbalign(hdb));
- if(fpow < 0) fpow = tclog2l(tchdbfbpmax(hdb));
- if(opts == UINT8_MAX) opts = tdb->opts;
- uint8_t hopts = 0;
- if(opts & TDBTLARGE) hopts |= HDBTLARGE;
- if(opts & TDBTDEFLATE) hopts |= HDBTDEFLATE;
- if(opts & TDBTBZIP) hopts |= HDBTBZIP;
- if(opts & TDBTTCBS) hopts |= HDBTTCBS;
- if(opts & TDBTEXCODEC) hopts |= HDBTEXCODEC;
- tchdbtune(thdb, bnum, apow, fpow, hopts);
- if(tchdbopen(thdb, tpath, HDBOWRITER | HDBOCREAT | HDBOTRUNC) && tchdbcopyopaque(thdb, hdb, 0, -1)) {
- if(!tchdbiterinit(hdb)) err = true;
- TCXSTR *kxstr = tcxstrnew();
- TCXSTR *vxstr = tcxstrnew();
- while(tchdbiternext3(hdb, kxstr, vxstr)){
- TCMAP *cols = tcmapload(TCXSTRPTR(vxstr), TCXSTRSIZE(vxstr));
- if(!tctdbidxput(tdb, TCXSTRPTR(kxstr), TCXSTRSIZE(kxstr), cols)) err = true;
- tcmapdel(cols);
- if(!tchdbput(thdb, TCXSTRPTR(kxstr), TCXSTRSIZE(kxstr),
- TCXSTRPTR(vxstr), TCXSTRSIZE(vxstr))){
+static bool tctdboptimizeimpl(TCTDB *tdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts) {
+ assert(tdb);
+ bool err = false;
+ TCHDB *hdb = tdb->hdb;
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ tcmapclear(idx->cc);
+ break;
+ }
+ }
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tcbdbvanish(idx->db)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ }
+ }
+ const char *path = tchdbpath(tdb->hdb);
+ char *tpath = tcsprintf("%s%ctmp%c%" PRIuMAX "", path, MYEXTCHR, MYEXTCHR, tchdbinode(tdb->hdb));
+ TCHDB *thdb = tchdbnew();
+ tchdbsettype(thdb, TCDBTTABLE);
+ HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
+ if (!INVALIDHANDLE(dbgfd)) tchdbsetdbgfd(thdb, dbgfd);
+ TCCODEC enc, dec;
+ void *encop, *decop;
+ tchdbcodecfunc(hdb, &enc, &encop, &dec, &decop);
+ if (enc && dec) tchdbsetcodecfunc(thdb, enc, encop, dec, decop);
+ if (bnum < 1) bnum = tchdbrnum(hdb) * 2 + 1;
+ if (apow < 0) apow = tclog2l(tchdbalign(hdb));
+ if (fpow < 0) fpow = tclog2l(tchdbfbpmax(hdb));
+ if (opts == UINT8_MAX) opts = tdb->opts;
+ uint8_t hopts = 0;
+ if (opts & TDBTLARGE) hopts |= HDBTLARGE;
+ if (opts & TDBTDEFLATE) hopts |= HDBTDEFLATE;
+ if (opts & TDBTBZIP) hopts |= HDBTBZIP;
+ if (opts & TDBTTCBS) hopts |= HDBTTCBS;
+ if (opts & TDBTEXCODEC) hopts |= HDBTEXCODEC;
+ tchdbtune(thdb, bnum, apow, fpow, hopts);
+ if (tchdbopen(thdb, tpath, HDBOWRITER | HDBOCREAT | HDBOTRUNC) && tchdbcopyopaque(thdb, hdb, 0, -1)) {
+ if (!tchdbiterinit(hdb)) err = true;
+ TCXSTR *kxstr = tcxstrnew();
+ TCXSTR *vxstr = tcxstrnew();
+ while (tchdbiternext3(hdb, kxstr, vxstr)) {
+ TCMAP *cols = tcmapload(TCXSTRPTR(vxstr), TCXSTRSIZE(vxstr));
+ if (!tctdbidxput(tdb, TCXSTRPTR(kxstr), TCXSTRSIZE(kxstr), cols)) err = true;
+ tcmapdel(cols);
+ if (!tchdbput(thdb, TCXSTRPTR(kxstr), TCXSTRSIZE(kxstr),
+ TCXSTRPTR(vxstr), TCXSTRSIZE(vxstr))) {
+ tctdbsetecode(tdb, tchdbecode(thdb), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ }
+ tcxstrdel(vxstr);
+ tcxstrdel(kxstr);
+ if (!tchdbclose(thdb)) {
+ tctdbsetecode(tdb, tchdbecode(thdb), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ if (!err) {
+ char *npath = tcstrdup(path);
+ int omode = (tchdbomode(hdb) & ~HDBOCREAT) & ~HDBOTRUNC;
+ if (!tchdbclose(hdb)) err = true;
+ if (!tcunlinkfile(npath)) {
+ tctdbsetecode(tdb, TCEUNLINK, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ if (!tcrenamefile(tpath, npath)) {
+ tctdbsetecode(tdb, TCERENAME, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ if (!tchdbopen(hdb, npath, omode)) err = true;
+ TCFREE(npath);
+ }
+ } else {
tctdbsetecode(tdb, tchdbecode(thdb), __FILE__, __LINE__, __func__);
err = true;
- }
- }
- tcxstrdel(vxstr);
- tcxstrdel(kxstr);
- if(!tchdbclose(thdb)){
- tctdbsetecode(tdb, tchdbecode(thdb), __FILE__, __LINE__, __func__);
- err = true;
- }
- if(!err){
- char *npath = tcstrdup(path);
- int omode = (tchdbomode(hdb) & ~HDBOCREAT) & ~HDBOTRUNC;
- if(!tchdbclose(hdb)) err = true;
- if(!tcunlinkfile(npath)){
- tctdbsetecode(tdb, TCEUNLINK, __FILE__, __LINE__, __func__);
- err = true;
- }
- if(!tcrenamefile(tpath, npath)){
- tctdbsetecode(tdb, TCERENAME, __FILE__, __LINE__, __func__);
- err = true;
- }
- if(!tchdbopen(hdb, npath, omode)) err = true;
- TCFREE(npath);
- }
- } else {
- tctdbsetecode(tdb, tchdbecode(thdb), __FILE__, __LINE__, __func__);
- err = true;
- }
- tchdbdel(thdb);
- TCFREE(tpath);
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tctdbidxsyncicc(tdb, idx, true)) err = true;
- break;
- }
- }
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tcbdboptimize(idx->db, -1, -1, -1, -1, -1, UINT8_MAX)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- }
- }
- return !err;
+ }
+ tchdbdel(thdb);
+ TCFREE(tpath);
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tctdbidxsyncicc(tdb, idx, true)) err = true;
+ break;
+ }
+ }
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tcbdboptimize(idx->db, -1, -1, -1, -1, -1, UINT8_MAX)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ }
+ }
+ return !err;
}
-
/* Remove all records of a table database object.
`tdb' specifies the table database object.
If successful, the return value is true, else, it is false. */
-static bool tctdbvanishimpl(TCTDB *tdb){
- assert(tdb);
- bool err = false;
- if(!tchdbvanish(tdb->hdb)) err = true;
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITTOKEN:
- case TDBITQGRAM:
- tcmapclear(idx->cc);
- break;
- }
- }
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tcbdbvanish(idx->db)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- }
- }
- return !err;
+static bool tctdbvanishimpl(TCTDB *tdb) {
+ assert(tdb);
+ bool err = false;
+ if (!tchdbvanish(tdb->hdb)) err = true;
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ tcmapclear(idx->cc);
+ break;
+ }
+ }
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tcbdbvanish(idx->db)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ }
+ }
+ return !err;
}
-
/* Copy the database file of a table database object.
`tdb' specifies the table database object.
`path' specifies the path of the destination file.
If successful, the return value is true, else, it is false. */
-static bool tctdbcopyimpl(TCTDB *tdb, const char *path){
- assert(tdb);
- bool err = false;
- if(!tchdbcopy(tdb->hdb, path)) err = true;
- const char *opath = tchdbpath(tdb->hdb);
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tctdbidxsyncicc(tdb, idx, true)) err = true;
- break;
- }
- }
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- const char *ipath;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(*path == '@'){
- if(!tcbdbcopy(idx->db, path)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- } else {
- ipath = tcbdbpath(idx->db);
- if(tcstrfwm(ipath, opath)){
- char *tpath = tcsprintf("%s%s", path, ipath + strlen(opath));
- if(!tcbdbcopy(idx->db, tpath)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- TCFREE(tpath);
- } else {
- tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
- err = true;
- }
+static bool tctdbcopyimpl(TCTDB *tdb, const char *path) {
+ assert(tdb);
+ bool err = false;
+ if (!tchdbcopy(tdb->hdb, path)) err = true;
+ const char *opath = tchdbpath(tdb->hdb);
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tctdbidxsyncicc(tdb, idx, true)) err = true;
+ break;
+ }
+ }
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ const char *ipath;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (*path == '@') {
+ if (!tcbdbcopy(idx->db, path)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ } else {
+ ipath = tcbdbpath(idx->db);
+ if (tcstrfwm(ipath, opath)) {
+ char *tpath = tcsprintf("%s%s", path, ipath + strlen(opath));
+ if (!tcbdbcopy(idx->db, tpath)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ TCFREE(tpath);
+ } else {
+ tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ }
+ break;
}
- break;
}
- }
- return !err;
+ return !err;
}
-
/* Begin the transaction of a table database object.
`tdb' specifies the table database object.
If successful, the return value is true, else, it is false. */
-bool tctdbtranbeginimpl(TCTDB *tdb){
- assert(tdb);
- if(!tctdbmemsync(tdb, false)) return false;
- if(!tchdbtranbegin(tdb->hdb)) return false;
- bool err = false;
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tctdbidxsyncicc(tdb, idx, true)) err = true;
- break;
- }
- }
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tcbdbtranbegin(idx->db)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- }
- }
- return !err;
+bool tctdbtranbeginimpl(TCTDB *tdb) {
+ assert(tdb);
+ if (!tctdbmemsync(tdb, false)) return false;
+ if (!tchdbtranbegin(tdb->hdb)) return false;
+ bool err = false;
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tctdbidxsyncicc(tdb, idx, true)) err = true;
+ break;
+ }
+ }
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tcbdbtranbegin(idx->db)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ }
+ }
+ return !err;
}
-
/* Commit the transaction of a table database object.
`tdb' specifies the table database object.
If successful, the return value is true, else, it is false. */
-bool tctdbtrancommitimpl(TCTDB *tdb){
- assert(tdb);
- bool err = false;
- if(!tctdbmemsync(tdb, false)) err = true;
- if(!tchdbtrancommit(tdb->hdb)) err = true;
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tctdbidxsyncicc(tdb, idx, true)) err = true;
- break;
- }
- }
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tcbdbtrancommit(idx->db)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- }
- }
- return !err;
-}
-
+bool tctdbtrancommitimpl(TCTDB *tdb) {
+ assert(tdb);
+ bool err = false;
+ if (!tctdbmemsync(tdb, false)) err = true;
+ if (!tchdbtrancommit(tdb->hdb)) err = true;
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tctdbidxsyncicc(tdb, idx, true)) err = true;
+ break;
+ }
+ }
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tcbdbtrancommit(idx->db)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ }
+ }
+ return !err;
+}
/* Abort the transaction of a table database object.
`tdb' specifies the table database object.
If successful, the return value is true, else, it is false. */
-bool tctdbtranabortimpl(TCTDB *tdb){
- assert(tdb);
- bool err = false;
- if(!tchdbtranabort(tdb->hdb)) err = true;
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITTOKEN:
- case TDBITQGRAM:
- tcmapclear(idx->cc);
- break;
- }
- }
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tcbdbtranabort(idx->db)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- }
- }
- return !err;
+bool tctdbtranabortimpl(TCTDB *tdb) {
+ assert(tdb);
+ bool err = false;
+ if (!tchdbtranabort(tdb->hdb)) err = true;
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ tcmapclear(idx->cc);
+ break;
+ }
+ }
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tcbdbtranabort(idx->db)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ }
+ }
+ return !err;
}
static char* tctdbmaprowldr(TCLIST *tokens,
- const char *pkbuf, int pksz,
- const char *rowdata, int rowdatasz,
- const char *cname, int cnamesz,
- void *op, int *vsz) {
+ const char *pkbuf, int pksz,
+ const char *rowdata, int rowdatasz,
+ const char *cname, int cnamesz,
+ void *op, int *vsz) {
char* res = NULL;
if (cname && *cname == '\0') {
TCMEMDUP(res, pkbuf, pksz);
`name' specifies the name of a column.
`type' specifies the index type.
If successful, the return value is true, else, it is false. */
-static bool tctdbsetindeximpl(TCTDB *tdb, const char *name, int type, TDBRVALOADER rvldr, void* rvldrop){
- assert(tdb && name);
- bool err = false;
- bool keep = false;
- if(type & TDBITKEEP){
- type &= ~TDBITKEEP;
- keep = true;
- }
- bool done = false;
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- char *path;
- if(!strcmp(idx->name, name)){
- if(keep){
- tctdbsetecode(tdb, TCEKEEP, __FILE__, __LINE__, __func__);
- return false;
- }
- if(type == TDBITOPT){
- switch(idx->type){
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tctdbidxsyncicc(tdb, idx, true)) err = true;
- break;
- }
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tcbdboptimize(idx->db, -1, -1, -1, -1, -1, UINT8_MAX)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
+static bool tctdbsetindeximpl(TCTDB *tdb, const char *name, int type, TDBRVALOADER rvldr, void* rvldrop) {
+ assert(tdb && name);
+ bool err = false;
+ bool keep = false;
+ if (type & TDBITKEEP) {
+ type &= ~TDBITKEEP;
+ keep = true;
+ }
+ bool done = false;
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ char *path;
+ if (!strcmp(idx->name, name)) {
+ if (keep) {
+ tctdbsetecode(tdb, TCEKEEP, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ if (type == TDBITOPT) {
+ switch (idx->type) {
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tctdbidxsyncicc(tdb, idx, true)) err = true;
+ break;
+ }
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tcbdboptimize(idx->db, -1, -1, -1, -1, -1, UINT8_MAX)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ }
+ done = true;
+ break;
}
+ switch (idx->type) {
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ tcmapdel(idx->cc);
+ break;
+ }
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ path = tcstrdup(tcbdbpath(idx->db));
+ tcbdbdel(idx->db);
+ if (path && !tcunlinkfile(path)) {
+ tctdbsetecode(tdb, TCEUNLINK, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ TCFREE(path);
+ break;
+ }
+ TCFREE(idx->name);
+ tdb->inum--;
+ inum = tdb->inum;
+ memmove(idxs + i, idxs + i + 1, sizeof (*idxs) * (inum - i));
+ done = true;
break;
}
- done = true;
- break;
- }
- switch(idx->type){
- case TDBITTOKEN:
- case TDBITQGRAM:
- tcmapdel(idx->cc);
- break;
- }
- switch(idx->type){
+ }
+ if (type == TDBITOPT || type == TDBITVOID) {
+ if (!done) {
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ return !err;
+ }
+ TCXSTR *pbuf = tcxstrnew();
+ tcxstrprintf(pbuf, "%s%c%s%c%?", tchdbpath(tdb->hdb), MYEXTCHR, TDBIDXSUFFIX, MYEXTCHR, name);
+ TCREALLOC(tdb->idxs, tdb->idxs, sizeof (tdb->idxs[0]) * (inum + 1));
+ TDBIDX *idx = tdb->idxs + inum;
+ int homode = tchdbomode(tdb->hdb);
+ int bomode = BDBOWRITER | BDBOCREAT | BDBOTRUNC;
+ if (homode & HDBONOLCK) bomode |= BDBONOLCK;
+ if (homode & HDBOLCKNB) bomode |= BDBOLCKNB;
+ if (homode & HDBOTSYNC) bomode |= BDBOTSYNC;
+ HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
+ TCCODEC enc, dec;
+ void *encop, *decop;
+ tchdbcodecfunc(tdb->hdb, &enc, &encop, &dec, &decop);
+ int64_t bbnum = (tchdbbnum(tdb->hdb) / TDBIDXLMEMB) * 4 + TDBIDXLMEMB;
+ int64_t bxmsiz = tchdbxmsiz(tdb->hdb);
+ uint8_t opts = tdb->opts;
+ uint8_t bopts = 0;
+ if (opts & TDBTLARGE) bopts |= BDBTLARGE;
+ if (opts & TDBTDEFLATE) bopts |= BDBTDEFLATE;
+ if (opts & TDBTBZIP) bopts |= BDBTBZIP;
+ if (opts & TDBTTCBS) bopts |= BDBTTCBS;
+ if (opts & TDBTEXCODEC) bopts |= BDBTEXCODEC;
+ switch (type) {
case TDBITLEXICAL:
+ idx->db = tcbdbnew();
+ idx->name = tcstrdup(name);
+ tcxstrprintf(pbuf, "%clex", MYEXTCHR);
+ if (!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
+ if (tdb->mmtx) tcbdbsetmutex(idx->db);
+ if (enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
+ tcbdbtune(idx->db, TDBIDXLMEMB, TDBIDXNMEMB, bbnum, -1, -1, bopts);
+ tcbdbsetcache(idx->db, tdb->lcnum, tdb->ncnum);
+ tcbdbsetxmsiz(idx->db, bxmsiz);
+ tcbdbsetdfunit(idx->db, tchdbdfunit(tdb->hdb));
+ tcbdbsetlsmax(idx->db, TDBIDXLSMAX);
+ if (!tcbdbopen(idx->db, TCXSTRPTR(pbuf), bomode)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ tdb->inum++;
+ break;
case TDBITDECIMAL:
+ idx->db = tcbdbnew();
+ idx->name = tcstrdup(name);
+ tcxstrprintf(pbuf, "%cdec", MYEXTCHR);
+ if (!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
+ if (tdb->mmtx) tcbdbsetmutex(idx->db);
+ tcbdbsetcmpfunc(idx->db, tccmpdecimal, NULL);
+ if (enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
+ tcbdbtune(idx->db, TDBIDXLMEMB, TDBIDXNMEMB, bbnum, -1, -1, bopts);
+ tcbdbsetcache(idx->db, tdb->lcnum, tdb->ncnum);
+ tcbdbsetxmsiz(idx->db, bxmsiz);
+ tcbdbsetdfunit(idx->db, tchdbdfunit(tdb->hdb));
+ tcbdbsetlsmax(idx->db, TDBIDXLSMAX);
+ if (!tcbdbopen(idx->db, TCXSTRPTR(pbuf), bomode)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ tdb->inum++;
+ break;
case TDBITTOKEN:
+ idx->db = tcbdbnew();
+ idx->cc = tcmapnew2(TDBIDXICCBNUM);
+ idx->name = tcstrdup(name);
+ tcxstrprintf(pbuf, "%ctok", MYEXTCHR);
+ if (!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
+ if (tdb->mmtx) tcbdbsetmutex(idx->db);
+ if (enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
+ tcbdbtune(idx->db, TDBIDXLMEMB, TDBIDXNMEMB, bbnum, -1, -1, bopts);
+ tcbdbsetcache(idx->db, tdb->lcnum, tdb->ncnum);
+ tcbdbsetxmsiz(idx->db, bxmsiz);
+ tcbdbsetdfunit(idx->db, tchdbdfunit(tdb->hdb));
+ tcbdbsetlsmax(idx->db, TDBIDXLSMAX);
+ if (!tcbdbopen(idx->db, TCXSTRPTR(pbuf), bomode)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ tdb->inum++;
+ break;
case TDBITQGRAM:
- path = tcstrdup(tcbdbpath(idx->db));
- tcbdbdel(idx->db);
- if(path && !tcunlinkfile(path)){
- tctdbsetecode(tdb, TCEUNLINK, __FILE__, __LINE__, __func__);
+ idx->db = tcbdbnew();
+ idx->cc = tcmapnew2(TDBIDXICCBNUM);
+ idx->name = tcstrdup(name);
+ tcxstrprintf(pbuf, "%cqgr", MYEXTCHR);
+ if (!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
+ if (tdb->mmtx) tcbdbsetmutex(idx->db);
+ if (enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
+ tcbdbtune(idx->db, TDBIDXLMEMB, TDBIDXNMEMB, bbnum, -1, -1, bopts);
+ tcbdbsetcache(idx->db, tdb->lcnum, tdb->ncnum);
+ tcbdbsetxmsiz(idx->db, bxmsiz);
+ tcbdbsetdfunit(idx->db, tchdbdfunit(tdb->hdb));
+ tcbdbsetlsmax(idx->db, TDBIDXLSMAX);
+ if (!tcbdbopen(idx->db, TCXSTRPTR(pbuf), bomode)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ tdb->inum++;
+ break;
+ default:
+ tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
err = true;
- }
- TCFREE(path);
- break;
- }
- TCFREE(idx->name);
- tdb->inum--;
- inum = tdb->inum;
- memmove(idxs + i, idxs + i + 1, sizeof(*idxs) * (inum - i));
- done = true;
- break;
- }
- }
- if(type == TDBITOPT || type == TDBITVOID){
- if(!done){
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- err = true;
+ break;
}
- return !err;
- }
- TCXSTR *pbuf = tcxstrnew();
- tcxstrprintf(pbuf, "%s%c%s%c%?", tchdbpath(tdb->hdb), MYEXTCHR, TDBIDXSUFFIX, MYEXTCHR, name);
- TCREALLOC(tdb->idxs, tdb->idxs, sizeof(tdb->idxs[0]) * (inum + 1));
- TDBIDX *idx = tdb->idxs + inum;
- int homode = tchdbomode(tdb->hdb);
- int bomode = BDBOWRITER | BDBOCREAT | BDBOTRUNC;
- if(homode & HDBONOLCK) bomode |= BDBONOLCK;
- if(homode & HDBOLCKNB) bomode |= BDBOLCKNB;
- if(homode & HDBOTSYNC) bomode |= BDBOTSYNC;
- HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
- TCCODEC enc, dec;
- void *encop, *decop;
- tchdbcodecfunc(tdb->hdb, &enc, &encop, &dec, &decop);
- int64_t bbnum = (tchdbbnum(tdb->hdb) / TDBIDXLMEMB) * 4 + TDBIDXLMEMB;
- int64_t bxmsiz = tchdbxmsiz(tdb->hdb);
- uint8_t opts = tdb->opts;
- uint8_t bopts = 0;
- if(opts & TDBTLARGE) bopts |= BDBTLARGE;
- if(opts & TDBTDEFLATE) bopts |= BDBTDEFLATE;
- if(opts & TDBTBZIP) bopts |= BDBTBZIP;
- if(opts & TDBTTCBS) bopts |= BDBTTCBS;
- if(opts & TDBTEXCODEC) bopts |= BDBTEXCODEC;
- switch(type){
- case TDBITLEXICAL:
- idx->db = tcbdbnew();
- idx->name = tcstrdup(name);
- tcxstrprintf(pbuf, "%clex", MYEXTCHR);
- if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
- if(tdb->mmtx) tcbdbsetmutex(idx->db);
- if(enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
- tcbdbtune(idx->db, TDBIDXLMEMB, TDBIDXNMEMB, bbnum, -1, -1, bopts);
- tcbdbsetcache(idx->db, tdb->lcnum, tdb->ncnum);
- tcbdbsetxmsiz(idx->db, bxmsiz);
- tcbdbsetdfunit(idx->db, tchdbdfunit(tdb->hdb));
- tcbdbsetlsmax(idx->db, TDBIDXLSMAX);
- if(!tcbdbopen(idx->db, TCXSTRPTR(pbuf), bomode)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- tdb->inum++;
- break;
- case TDBITDECIMAL:
- idx->db = tcbdbnew();
- idx->name = tcstrdup(name);
- tcxstrprintf(pbuf, "%cdec", MYEXTCHR);
- if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
- if(tdb->mmtx) tcbdbsetmutex(idx->db);
- tcbdbsetcmpfunc(idx->db, tccmpdecimal, NULL);
- if(enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
- tcbdbtune(idx->db, TDBIDXLMEMB, TDBIDXNMEMB, bbnum, -1, -1, bopts);
- tcbdbsetcache(idx->db, tdb->lcnum, tdb->ncnum);
- tcbdbsetxmsiz(idx->db, bxmsiz);
- tcbdbsetdfunit(idx->db, tchdbdfunit(tdb->hdb));
- tcbdbsetlsmax(idx->db, TDBIDXLSMAX);
- if(!tcbdbopen(idx->db, TCXSTRPTR(pbuf), bomode)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- tdb->inum++;
- break;
- case TDBITTOKEN:
- idx->db = tcbdbnew();
- idx->cc = tcmapnew2(TDBIDXICCBNUM);
- idx->name = tcstrdup(name);
- tcxstrprintf(pbuf, "%ctok", MYEXTCHR);
- if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
- if(tdb->mmtx) tcbdbsetmutex(idx->db);
- if(enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
- tcbdbtune(idx->db, TDBIDXLMEMB, TDBIDXNMEMB, bbnum, -1, -1, bopts);
- tcbdbsetcache(idx->db, tdb->lcnum, tdb->ncnum);
- tcbdbsetxmsiz(idx->db, bxmsiz);
- tcbdbsetdfunit(idx->db, tchdbdfunit(tdb->hdb));
- tcbdbsetlsmax(idx->db, TDBIDXLSMAX);
- if(!tcbdbopen(idx->db, TCXSTRPTR(pbuf), bomode)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- tdb->inum++;
- break;
- case TDBITQGRAM:
- idx->db = tcbdbnew();
- idx->cc = tcmapnew2(TDBIDXICCBNUM);
- idx->name = tcstrdup(name);
- tcxstrprintf(pbuf, "%cqgr", MYEXTCHR);
- if(!INVALIDHANDLE(dbgfd)) tcbdbsetdbgfd(idx->db, dbgfd);
- if(tdb->mmtx) tcbdbsetmutex(idx->db);
- if(enc && dec) tcbdbsetcodecfunc(idx->db, enc, encop, dec, decop);
- tcbdbtune(idx->db, TDBIDXLMEMB, TDBIDXNMEMB, bbnum, -1, -1, bopts);
- tcbdbsetcache(idx->db, tdb->lcnum, tdb->ncnum);
- tcbdbsetxmsiz(idx->db, bxmsiz);
- tcbdbsetdfunit(idx->db, tchdbdfunit(tdb->hdb));
- tcbdbsetlsmax(idx->db, TDBIDXLSMAX);
- if(!tcbdbopen(idx->db, TCXSTRPTR(pbuf), bomode)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- tdb->inum++;
- break;
- default:
- tctdbsetecode(tdb, TCEINVALID, __FILE__, __LINE__, __func__);
- err = true;
- break;
- }
- idx->type = type;
- if(!err){
- TCHDB *hdb = tdb->hdb;
- if(!tchdbiterinit(hdb)) err = true;
- void *db = idx->db;
- TCXSTR *kxstr = tcxstrnew();
- TCXSTR *vxstr = tcxstrnew();
- int nsiz = strlen(name);
- while(tchdbiternext3(hdb, kxstr, vxstr)){
- TCLIST *tokens = (type == TDBITTOKEN) ? tclistnew() : NULL;
- int vsiz;
- const char *pkbuf = TCXSTRPTR(kxstr);
- int pksiz = TCXSTRSIZE(kxstr);
- char *vbuf = rvldr(tokens, pkbuf, pksiz, TCXSTRPTR(vxstr), TCXSTRSIZE(vxstr), name, nsiz, rvldrop, &vsiz);
- if(nsiz < 1){
- switch(type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- assert(vbuf);
- if(!tcbdbput(db, pkbuf, pksiz, vbuf, vsiz)){
- tctdbsetecode(tdb, tcbdbecode(db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- case TDBITTOKEN:
- if(!tctdbidxputtoken2(tdb, idx, pkbuf, pksiz, tokens)) err = true;
- break;
- case TDBITQGRAM:
- assert(vbuf);
- if(!tctdbidxputqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
- break;
- }
- } else {
- switch(type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- if(vbuf && !tctdbidxputone(tdb, idx, pkbuf, pksiz, tctdbidxhash(pkbuf, pksiz), vbuf, vsiz)) err = true;
- break;
- case TDBITTOKEN:
- if(tokens && !tctdbidxputtoken2(tdb, idx, pkbuf, pksiz, tokens)) err = true;
- break;
- case TDBITQGRAM:
- if(vbuf && !tctdbidxputqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
- break;
+ idx->type = type;
+ if (!err) {
+ TCHDB *hdb = tdb->hdb;
+ if (!tchdbiterinit(hdb)) err = true;
+ void *db = idx->db;
+ TCXSTR *kxstr = tcxstrnew();
+ TCXSTR *vxstr = tcxstrnew();
+ int nsiz = strlen(name);
+ while (tchdbiternext3(hdb, kxstr, vxstr)) {
+ TCLIST *tokens = (type == TDBITTOKEN) ? tclistnew() : NULL;
+ int vsiz;
+ const char *pkbuf = TCXSTRPTR(kxstr);
+ int pksiz = TCXSTRSIZE(kxstr);
+ char *vbuf = rvldr(tokens, pkbuf, pksiz, TCXSTRPTR(vxstr), TCXSTRSIZE(vxstr), name, nsiz, rvldrop, &vsiz);
+ if (nsiz < 1) {
+ switch (type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ assert(vbuf);
+ if (!tcbdbput(db, pkbuf, pksiz, vbuf, vsiz)) {
+ tctdbsetecode(tdb, tcbdbecode(db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ case TDBITTOKEN:
+ if (!tctdbidxputtoken2(tdb, idx, pkbuf, pksiz, tokens)) err = true;
+ break;
+ case TDBITQGRAM:
+ assert(vbuf);
+ if (!tctdbidxputqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
+ break;
+ }
+ } else {
+ switch (type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ if (vbuf && !tctdbidxputone(tdb, idx, pkbuf, pksiz, tctdbidxhash(pkbuf, pksiz), vbuf, vsiz)) err = true;
+ break;
+ case TDBITTOKEN:
+ if (tokens && !tctdbidxputtoken2(tdb, idx, pkbuf, pksiz, tokens)) err = true;
+ break;
+ case TDBITQGRAM:
+ if (vbuf && !tctdbidxputqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
+ break;
+ }
}
- }
- if (vbuf) TCFREE(vbuf);
- if (tokens) tclistdel(tokens);
+ if (vbuf) TCFREE(vbuf);
+ if (tokens) tclistdel(tokens);
+ }
+ tcxstrdel(vxstr);
+ tcxstrdel(kxstr);
}
- tcxstrdel(vxstr);
- tcxstrdel(kxstr);
- }
- tcxstrdel(pbuf);
- return !err;
+ tcxstrdel(pbuf);
+ return !err;
}
-
/* Generate a unique ID number.
`tdb' specifies the table database object.
`inc' specifies the increment of the seed.
The return value is the new unique ID number or -1 on failure. */
-static int64_t tctdbgenuidimpl(TCTDB *tdb, int64_t inc){
- assert(tdb);
- uint64_t llnum, uid;
- if(inc < 0){
- uid = -inc - 1;
- } else {
- tchdbreadopaque(tdb->hdb, &llnum, 0, sizeof(llnum));
- if(inc == 0) return TCITOHLL(llnum);
- uid = TCITOHLL(llnum) + inc;
- }
- llnum = TCITOHLL(uid);
- tchdbwriteopaque(tdb->hdb, &llnum, 0, sizeof(llnum));
- return uid;
+static int64_t tctdbgenuidimpl(TCTDB *tdb, int64_t inc) {
+ assert(tdb);
+ uint64_t llnum, uid;
+ if (inc < 0) {
+ uid = -inc - 1;
+ } else {
+ tchdbreadopaque(tdb->hdb, &llnum, 0, sizeof (llnum));
+ if (inc == 0) return TCITOHLL(llnum);
+ uid = TCITOHLL(llnum) + inc;
+ }
+ llnum = TCITOHLL(uid);
+ tchdbwriteopaque(tdb->hdb, &llnum, 0, sizeof (llnum));
+ return uid;
}
-
/* Execute the search of a query object.
`qry' specifies the query object.
The return value is a list object of the primary keys of the corresponding records. */
-static TCLIST *tctdbqrysearchimpl(TDBQRY *qry){
- assert(qry);
- TCTDB *tdb = qry->tdb;
- TCHDB *hdb = tdb->hdb;
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- TDBCOND *conds = qry->conds;
- int cnum = qry->cnum;
- int acnum = cnum;
- int max = qry->max;
- if(max < INT_MAX - qry->skip) max += qry->skip;
- const char *oname = qry->oname;
- int otype = qry->otype;
- TCXSTR *hint = qry->hint;
- TCLIST *res = NULL;
- for(int i = 0; i < cnum; i++){
- TDBCOND *cond = conds + i;
- cond->alive = true;
- }
- tcxstrclear(hint);
- bool isord = oname != NULL;
- TDBCOND *mcond = NULL;
- TDBIDX *midx = NULL;
- TDBCOND *ncond = NULL;
- TDBIDX *nidx = NULL;
- TDBCOND *scond = NULL;
- TDBIDX *sidx = NULL;
- for(int i = 0; i < cnum; i++){
- TDBCOND *cond = conds + i;
- if(!cond->sign || cond->noidx) continue;
- for(int j = 0; j < inum; j++){
- TDBIDX *idx = idxs + j;
- if(!strcmp(cond->name, idx->name)){
- switch(idx->type){
- case TDBITLEXICAL:
- switch(cond->op){
- case TDBQCSTREQ:
- case TDBQCSTRBW:
- case TDBQCSTROREQ:
- if(!mcond){
- mcond = cond;
- midx = idx;
- } else if(!ncond){
- ncond = cond;
- nidx = idx;
+static TCLIST *tctdbqrysearchimpl(TDBQRY *qry) {
+ assert(qry);
+ TCTDB *tdb = qry->tdb;
+ TCHDB *hdb = tdb->hdb;
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ TDBCOND *conds = qry->conds;
+ int cnum = qry->cnum;
+ int acnum = cnum;
+ int max = qry->max;
+ if (max < INT_MAX - qry->skip) max += qry->skip;
+ const char *oname = qry->oname;
+ int otype = qry->otype;
+ TCXSTR *hint = qry->hint;
+ TCLIST *res = NULL;
+ for (int i = 0; i < cnum; i++) {
+ TDBCOND *cond = conds + i;
+ cond->alive = true;
+ }
+ tcxstrclear(hint);
+ bool isord = oname != NULL;
+ TDBCOND *mcond = NULL;
+ TDBIDX *midx = NULL;
+ TDBCOND *ncond = NULL;
+ TDBIDX *nidx = NULL;
+ TDBCOND *scond = NULL;
+ TDBIDX *sidx = NULL;
+ for (int i = 0; i < cnum; i++) {
+ TDBCOND *cond = conds + i;
+ if (!cond->sign || cond->noidx) continue;
+ for (int j = 0; j < inum; j++) {
+ TDBIDX *idx = idxs + j;
+ if (!strcmp(cond->name, idx->name)) {
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ switch (cond->op) {
+ case TDBQCSTREQ:
+ case TDBQCSTRBW:
+ case TDBQCSTROREQ:
+ if (!mcond) {
+ mcond = cond;
+ midx = idx;
+ } else if (!ncond) {
+ ncond = cond;
+ nidx = idx;
+ }
+ break;
+ default:
+ if (!scond) {
+ scond = cond;
+ sidx = idx;
+ }
+ break;
+ }
+ break;
+ case TDBITDECIMAL:
+ switch (cond->op) {
+ case TDBQCNUMEQ:
+ case TDBQCNUMGT:
+ case TDBQCNUMGE:
+ case TDBQCNUMLT:
+ case TDBQCNUMLE:
+ case TDBQCNUMBT:
+ case TDBQCNUMOREQ:
+ if (!mcond) {
+ mcond = cond;
+ midx = idx;
+ } else if (!ncond) {
+ ncond = cond;
+ nidx = idx;
+ }
+ break;
+ default:
+ if (!scond) {
+ scond = cond;
+ sidx = idx;
+ }
+ break;
+ }
+ break;
+ case TDBITTOKEN:
+ switch (cond->op) {
+ case TDBQCSTRAND:
+ case TDBQCSTROR:
+ if (!mcond) {
+ mcond = cond;
+ midx = idx;
+ } else if (!ncond) {
+ ncond = cond;
+ nidx = idx;
+ }
+ break;
+ }
+ break;
+ case TDBITQGRAM:
+ switch (cond->op) {
+ case TDBQCFTSPH:
+ if (!mcond) {
+ mcond = cond;
+ midx = idx;
+ } else if (!ncond) {
+ ncond = cond;
+ nidx = idx;
+ }
+ break;
+ }
+ break;
}
+ }
+ }
+ }
+ if (mcond) {
+ res = tclistnew();
+ mcond->alive = false;
+ acnum--;
+ TCMAP *nmap = NULL;
+ if (ncond) {
+ ncond->alive = false;
+ acnum--;
+ nmap = tctdbqryidxfetch(qry, ncond, nidx);
+ max = tclmin(max, TCMAPRNUM(nmap));
+ }
+ const char *expr = mcond->expr;
+ int esiz = mcond->esiz;
+ TDBCOND *ucond = NULL;
+ for (int i = 0; i < cnum; i++) {
+ TDBCOND *cond = conds + i;
+ if (!cond->alive) continue;
+ if (ucond) {
+ ucond = NULL;
break;
- default:
- if(!scond){
- scond = cond;
- sidx = idx;
+ }
+ ucond = cond;
+ }
+ bool trim = *midx->name != '\0';
+ if (mcond->op == TDBQCSTREQ) {
+ tcxstrprintf(hint, "using an index: \"%s\" asc (STREQ)\n", mcond->name);
+ BDBCUR *cur = tcbdbcurnew(midx->db);
+ tcbdbcurjump(cur, expr, esiz + trim);
+ if (oname && !strcmp(oname, mcond->name)) oname = NULL;
+ bool all = oname != NULL;
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ trim = *midx->name != '\0';
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (trim) ksiz -= 3;
+ if (ksiz == esiz && !memcmp(kbuf, expr, esiz)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ int nsiz;
+ if (!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ } else {
+ break;
}
- break;
+ tcbdbcurnext(cur);
}
- break;
- case TDBITDECIMAL:
- switch(cond->op){
- case TDBQCNUMEQ:
- case TDBQCNUMGT:
- case TDBQCNUMGE:
- case TDBQCNUMLT:
- case TDBQCNUMLE:
- case TDBQCNUMBT:
- case TDBQCNUMOREQ:
- if(!mcond){
- mcond = cond;
- midx = idx;
- } else if(!ncond){
- ncond = cond;
- nidx = idx;
+ tcbdbcurdel(cur);
+ } else if (mcond->op == TDBQCSTRBW) {
+ tcxstrprintf(hint, "using an index: \"%s\" asc (STRBW)\n", mcond->name);
+ BDBCUR *cur = tcbdbcurnew(midx->db);
+ tcbdbcurjump(cur, expr, esiz + trim);
+ bool all = oname && (strcmp(oname, mcond->name) || otype != TDBQOSTRASC);
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (trim) ksiz -= 3;
+ if (ksiz >= esiz && !memcmp(kbuf, expr, esiz)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ int nsiz;
+ if (!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ } else {
+ break;
}
- break;
- default:
- if(!scond){
- scond = cond;
- sidx = idx;
+ tcbdbcurnext(cur);
+ }
+ tcbdbcurdel(cur);
+ if (oname && !strcmp(oname, mcond->name)) {
+ if (otype == TDBQOSTRASC) {
+ oname = NULL;
+ } else if (otype == TDBQOSTRDESC) {
+ tclistinvert(res);
+ oname = NULL;
}
- break;
}
- break;
- case TDBITTOKEN:
- switch(cond->op){
- case TDBQCSTRAND:
- case TDBQCSTROR:
- if(!mcond){
- mcond = cond;
- midx = idx;
- } else if(!ncond){
- ncond = cond;
- nidx = idx;
+ } else if (mcond->op == TDBQCSTROREQ) {
+ tcxstrprintf(hint, "using an index: \"%s\" skip (STROREQ)\n", mcond->name);
+ BDBCUR *cur = tcbdbcurnew(midx->db);
+ TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
+ tclistsort(tokens);
+ for (int i = 1; i < TCLISTNUM(tokens); i++) {
+ if (!strcmp(TCLISTVALPTR(tokens, i), TCLISTVALPTR(tokens, i - 1))) {
+ TCFREE(tclistremove2(tokens, i));
+ i--;
}
- break;
}
- break;
- case TDBITQGRAM:
- switch(cond->op){
- case TDBQCFTSPH:
- if(!mcond){
- mcond = cond;
- midx = idx;
- } else if(!ncond){
- ncond = cond;
- nidx = idx;
+ if (oname && !strcmp(oname, mcond->name)) {
+ if (otype == TDBQOSTRASC) {
+ oname = NULL;
+ } else if (otype == TDBQOSTRDESC) {
+ tclistinvert(tokens);
+ oname = NULL;
+ }
+ }
+ int tnum = TCLISTNUM(tokens);
+ bool all = oname != NULL;
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ for (int i = 0; (all || TCLISTNUM(res) < max) && i < tnum; i++) {
+ const char *token;
+ int tsiz;
+ TCLISTVAL(token, tokens, i, tsiz);
+ if (tsiz < 1) continue;
+ tcbdbcurjump(cur, token, tsiz + trim);
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (trim) ksiz -= 3;
+ if (ksiz == tsiz && !memcmp(kbuf, token, tsiz)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ int nsiz;
+ if (!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ } else {
+ break;
+ }
+ tcbdbcurnext(cur);
+ }
+ }
+ tclistdel(tokens);
+ tcbdbcurdel(cur);
+ } else if (mcond->op == TDBQCNUMEQ) {
+ tcxstrprintf(hint, "using an index: \"%s\" asc (NUMEQ)\n", mcond->name);
+ BDBCUR *cur = tcbdbcurnew(midx->db);
+ if (oname && !strcmp(oname, mcond->name)) oname = NULL;
+ long double xnum = tctdbatof(expr);
+ tctdbqryidxcurjumpnum(cur, expr, esiz, true);
+ bool all = oname != NULL;
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (tctdbatof(kbuf) == xnum) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ int nsiz;
+ if (!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ } else {
+ break;
+ }
+ tcbdbcurnext(cur);
+ }
+ tcbdbcurdel(cur);
+ } else if (mcond->op == TDBQCNUMGT || mcond->op == TDBQCNUMGE) {
+ if (oname && !strcmp(oname, mcond->name) && otype == TDBQONUMDESC) {
+ tcxstrprintf(hint, "using an index: \"%s\" desc (NUMGT/NUMGE)\n", mcond->name);
+ long double xnum = tctdbatof(expr);
+ BDBCUR *cur = tcbdbcurnew(midx->db);
+ tcbdbcurlast(cur);
+ if (max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ const char *kbuf;
+ int ksiz;
+ while (TCLISTNUM(res) < max && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ long double knum = tctdbatof(kbuf);
+ if (knum < xnum) break;
+ if (knum > xnum || (knum >= xnum && mcond->op == TDBQCNUMGE)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ int nsiz;
+ if (!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ }
+ tcbdbcurprev(cur);
+ }
+ tcbdbcurdel(cur);
+ oname = NULL;
+ } else {
+ tcxstrprintf(hint, "using an index: \"%s\" asc (NUMGT/NUMGE)\n", mcond->name);
+ long double xnum = tctdbatof(expr);
+ BDBCUR *cur = tcbdbcurnew(midx->db);
+ tctdbqryidxcurjumpnum(cur, expr, esiz, true);
+ bool all = oname && (strcmp(oname, mcond->name) || otype != TDBQONUMASC);
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ long double knum = tctdbatof(kbuf);
+ if (knum > xnum || (knum >= xnum && mcond->op == TDBQCNUMGE)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ int nsiz;
+ if (!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ }
+ tcbdbcurnext(cur);
+ }
+ tcbdbcurdel(cur);
+ if (!all) oname = NULL;
+ }
+ } else if (mcond->op == TDBQCNUMLT || mcond->op == TDBQCNUMLE) {
+ if (oname && !strcmp(oname, mcond->name) && otype == TDBQONUMASC) {
+ tcxstrprintf(hint, "using an index: \"%s\" asc (NUMLT/NUMLE)\n", mcond->name);
+ long double xnum = tctdbatof(expr);
+ BDBCUR *cur = tcbdbcurnew(midx->db);
+ tcbdbcurfirst(cur);
+ if (max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ const char *kbuf;
+ int ksiz;
+ while (TCLISTNUM(res) < max && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ long double knum = tctdbatof(kbuf);
+ if (knum > xnum) break;
+ if (knum < xnum || (knum <= xnum && mcond->op == TDBQCNUMLE)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ int nsiz;
+ if (!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ }
+ tcbdbcurnext(cur);
+ }
+ tcbdbcurdel(cur);
+ oname = NULL;
+ } else {
+ tcxstrprintf(hint, "using an index: \"%s\" desc (NUMLT/NUMLE)\n", mcond->name);
+ long double xnum = tctdbatof(expr);
+ BDBCUR *cur = tcbdbcurnew(midx->db);
+ tctdbqryidxcurjumpnum(cur, expr, esiz, false);
+ bool all = oname && (strcmp(oname, mcond->name) || otype != TDBQONUMDESC);
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ long double knum = tctdbatof(kbuf);
+ if (knum < xnum || (knum <= xnum && mcond->op == TDBQCNUMLE)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ int nsiz;
+ if (!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ }
+ tcbdbcurprev(cur);
+ }
+ tcbdbcurdel(cur);
+ if (!all) oname = NULL;
+ }
+ } else if (mcond->op == TDBQCNUMBT) {
+ tcxstrprintf(hint, "using an index: \"%s\" asc (NUMBT)\n", mcond->name);
+ while (*expr == ' ' || *expr == ',') {
+ expr++;
+ }
+ const char *pv = expr;
+ while (*pv != '\0' && *pv != ' ' && *pv != ',') {
+ pv++;
+ }
+ esiz = pv - expr;
+ if (*pv != ' ' && *pv != ',') pv = " ";
+ pv++;
+ while (*pv == ' ' || *pv == ',') {
+ pv++;
+ }
+ long double lower = tctdbatof(expr);
+ long double upper = tctdbatof(pv);
+ if (lower > upper) {
+ expr = pv;
+ esiz = strlen(expr);
+ long double swap = lower;
+ lower = upper;
+ upper = swap;
+ }
+ BDBCUR *cur = tcbdbcurnew(midx->db);
+ tctdbqryidxcurjumpnum(cur, expr, esiz, true);
+ bool all = oname && (strcmp(oname, mcond->name) || otype != TDBQONUMASC);
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (tctdbatof(kbuf) > upper) break;
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ int nsiz;
+ if (!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ tcbdbcurnext(cur);
+ }
+ tcbdbcurdel(cur);
+ if (oname && !strcmp(oname, mcond->name)) {
+ if (otype == TDBQONUMASC) {
+ oname = NULL;
+ } else if (otype == TDBQONUMDESC) {
+ tclistinvert(res);
+ oname = NULL;
+ }
+ }
+ } else if (mcond->op == TDBQCNUMOREQ) {
+ tcxstrprintf(hint, "using an index: \"%s\" skip (NUMOREQ)\n", mcond->name);
+ BDBCUR *cur = tcbdbcurnew(midx->db);
+ TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
+ tclistsortex(tokens, tdbcmppkeynumasc);
+ for (int i = 1; i < TCLISTNUM(tokens); i++) {
+ if (tctdbatof(TCLISTVALPTR(tokens, i)) == tctdbatof(TCLISTVALPTR(tokens, i - 1))) {
+ TCFREE(tclistremove2(tokens, i));
+ i--;
+ }
+ }
+ if (oname && !strcmp(oname, mcond->name)) {
+ if (otype == TDBQONUMASC) {
+ oname = NULL;
+ } else if (otype == TDBQONUMDESC) {
+ tclistinvert(tokens);
+ oname = NULL;
+ }
+ }
+ int tnum = TCLISTNUM(tokens);
+ bool all = oname != NULL;
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ for (int i = 0; (all || TCLISTNUM(res) < max) && i < tnum; i++) {
+ const char *token;
+ int tsiz;
+ TCLISTVAL(token, tokens, i, tsiz);
+ if (tsiz < 1) continue;
+ long double xnum = tctdbatof(token);
+ tctdbqryidxcurjumpnum(cur, token, tsiz, true);
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (tctdbatof(kbuf) == xnum) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ int nsiz;
+ if (!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ } else {
+ break;
+ }
+ tcbdbcurnext(cur);
}
+ }
+ tclistdel(tokens);
+ tcbdbcurdel(cur);
+ } else if (mcond->op == TDBQCSTRAND || mcond->op == TDBQCSTROR) {
+ tcxstrprintf(hint, "using an index: \"%s\" inverted (%s)\n",
+ mcond->name, mcond->op == TDBQCSTRAND ? "STRAND" : "STROR");
+ bool all = oname != NULL;
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
+ tclistsort(tokens);
+ for (int i = 1; i < TCLISTNUM(tokens); i++) {
+ if (!strcmp(TCLISTVALPTR(tokens, i), TCLISTVALPTR(tokens, i - 1))) {
+ TCFREE(tclistremove2(tokens, i));
+ i--;
+ }
+ }
+ TCMAP *tres = tctdbidxgetbytokens(tdb, midx, tokens, mcond->op, hint);
+ tcmapiterinit(tres);
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcmapiternext(tres, &ksiz)) != NULL) {
+ int nsiz;
+ if (!nmap || tcmapget(nmap, kbuf, ksiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, kbuf, ksiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, kbuf, ksiz)) TCLISTPUSH(res, kbuf, ksiz);
+ } else if (tctdbqryallcondmatch(qry, kbuf, ksiz)) {
+ TCLISTPUSH(res, kbuf, ksiz);
+ }
+ }
+ }
+ tcmapdel(tres);
+ tclistdel(tokens);
+ } else if (mcond->op == TDBQCFTSPH) {
+ tcxstrprintf(hint, "using an index: \"%s\" inverted (FTS)\n", mcond->name);
+ TCMAP *tres = tctdbidxgetbyfts(tdb, midx, mcond, hint);
+ bool all = oname != NULL;
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ tcmapiterinit(tres);
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcmapiternext(tres, &ksiz)) != NULL) {
+ int nsiz;
+ if (!nmap || tcmapget(nmap, kbuf, ksiz, &nsiz)) {
+ if (acnum < 1) {
+ TCLISTPUSH(res, kbuf, ksiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, kbuf, ksiz)) TCLISTPUSH(res, kbuf, ksiz);
+ } else if (tctdbqryallcondmatch(qry, kbuf, ksiz)) {
+ TCLISTPUSH(res, kbuf, ksiz);
+ }
+ }
+ }
+ tcmapdel(tres);
+ }
+ if (nmap) tcmapdel(nmap);
+ }
+ if (!res && scond) {
+ res = tclistnew();
+ scond->alive = false;
+ acnum--;
+ TDBCOND *ucond = NULL;
+ for (int i = 0; i < cnum; i++) {
+ TDBCOND *cond = conds + i;
+ if (!cond->alive) continue;
+ if (ucond) {
+ ucond = NULL;
break;
}
- break;
+ ucond = cond;
}
- }
- }
- }
- if(mcond){
- res = tclistnew();
- mcond->alive = false;
- acnum--;
- TCMAP *nmap = NULL;
- if(ncond){
- ncond->alive = false;
- acnum--;
- nmap = tctdbqryidxfetch(qry, ncond, nidx);
- max = tclmin(max, TCMAPRNUM(nmap));
- }
- const char *expr = mcond->expr;
- int esiz = mcond->esiz;
- TDBCOND *ucond = NULL;
- for(int i = 0; i < cnum; i++){
- TDBCOND *cond = conds + i;
- if(!cond->alive) continue;
- if(ucond){
- ucond = NULL;
- break;
- }
- ucond = cond;
- }
- bool trim = *midx->name != '\0';
- if(mcond->op == TDBQCSTREQ){
- tcxstrprintf(hint, "using an index: \"%s\" asc (STREQ)\n", mcond->name);
- BDBCUR *cur = tcbdbcurnew(midx->db);
- tcbdbcurjump(cur, expr, esiz + trim);
- if(oname && !strcmp(oname, mcond->name)) oname = NULL;
- bool all = oname != NULL;
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
- trim = *midx->name != '\0';
- const char *kbuf;
- int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(trim) ksiz -= 3;
- if(ksiz == esiz && !memcmp(kbuf, expr, esiz)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- int nsiz;
- if(!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
+ bool trim = *sidx->name != '\0';
+ bool asc = true;
+ bool all = true;
+ if (!oname) {
+ all = false;
+ } else if (!strcmp(oname, scond->name)) {
+ switch (sidx->type) {
+ case TDBITLEXICAL:
+ switch (otype) {
+ case TDBQOSTRASC:
+ asc = true;
+ all = false;
+ break;
+ case TDBQOSTRDESC:
+ asc = false;
+ all = false;
+ break;
+ }
+ break;
+ case TDBITDECIMAL:
+ switch (otype) {
+ case TDBQONUMASC:
+ asc = true;
+ all = false;
+ break;
+ case TDBQONUMDESC:
+ asc = false;
+ all = false;
+ break;
+ }
+ break;
}
- }
+ }
+ if (asc) {
+ tcxstrprintf(hint, "using an index: \"%s\" asc (all)\n", scond->name);
+ BDBCUR *cur = tcbdbcurnew(sidx->db);
+ tcbdbcurfirst(cur);
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (trim) ksiz -= 3;
+ if (ksiz < 0) break;
+ if (tctdbqrycondmatch(scond, kbuf, ksiz)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ tcbdbcurnext(cur);
+ }
+ tcbdbcurdel(cur);
} else {
- break;
- }
- tcbdbcurnext(cur);
- }
- tcbdbcurdel(cur);
- } else if(mcond->op == TDBQCSTRBW){
- tcxstrprintf(hint, "using an index: \"%s\" asc (STRBW)\n", mcond->name);
- BDBCUR *cur = tcbdbcurnew(midx->db);
- tcbdbcurjump(cur, expr, esiz + trim);
- bool all = oname && (strcmp(oname, mcond->name) || otype != TDBQOSTRASC);
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
- const char *kbuf;
- int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(trim) ksiz -= 3;
- if(ksiz >= esiz && !memcmp(kbuf, expr, esiz)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- int nsiz;
- if(!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
+ tcxstrprintf(hint, "using an index: \"%s\" desc (all)\n", scond->name);
+ BDBCUR *cur = tcbdbcurnew(sidx->db);
+ tcbdbcurlast(cur);
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ const char *kbuf;
+ int ksiz;
+ while ((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (trim) ksiz -= 3;
+ if (ksiz < 0) break;
+ if (tctdbqrycondmatch(scond, kbuf, ksiz)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ }
+ tcbdbcurprev(cur);
+ }
+ tcbdbcurdel(cur);
+ }
+ if (!all) oname = NULL;
+ }
+ if (!res && oname && max < tchdbrnum(hdb) * TDBORDRATIO) {
+ TDBIDX *oidx = NULL;
+ bool asc = true;
+ for (int i = 0; !oidx && i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ if (strcmp(idx->name, oname)) continue;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ switch (otype) {
+ case TDBQOSTRASC:
+ oidx = idx;
+ asc = true;
+ break;
+ case TDBQOSTRDESC:
+ oidx = idx;
+ asc = false;
+ break;
+ }
+ break;
+ case TDBITDECIMAL:
+ switch (otype) {
+ case TDBQONUMASC:
+ oidx = idx;
+ asc = true;
+ break;
+ case TDBQONUMDESC:
+ oidx = idx;
+ asc = false;
+ break;
+ }
+ break;
+ }
+ }
+ if (oidx) {
+ res = tclistnew();
+ TDBCOND *ucond = NULL;
+ for (int i = 0; i < cnum; i++) {
+ TDBCOND *cond = conds + i;
+ if (!cond->alive) continue;
+ if (ucond) {
+ ucond = NULL;
+ break;
+ }
+ ucond = cond;
+ }
+ bool trim = *oidx->name != '\0';
+ if (asc) {
+ tcxstrprintf(hint, "using an index: \"%s\" asc (order)\n", oname);
+ BDBCUR *cur = tcbdbcurnew(oidx->db);
+ tcbdbcurfirst(cur);
+ tcxstrprintf(hint, "limited matching: %d\n", max);
+ const char *kbuf;
+ int ksiz;
+ while (TCLISTNUM(res) < max && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (trim) ksiz -= 3;
+ if (ksiz < 0) break;
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ tcbdbcurnext(cur);
+ }
+ tcbdbcurdel(cur);
+ } else {
+ tcxstrprintf(hint, "using an index: \"%s\" desc (order)\n", oname);
+ BDBCUR *cur = tcbdbcurnew(oidx->db);
+ tcbdbcurlast(cur);
+ tcxstrprintf(hint, "limited matching: %d\n", max);
+ const char *kbuf;
+ int ksiz;
+ while (TCLISTNUM(res) < max && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (trim) ksiz -= 3;
+ if (ksiz < 0) break;
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ if (acnum < 1) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ } else if (ucond) {
+ if (tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
+ } else if (tctdbqryallcondmatch(qry, vbuf, vsiz)) {
+ TCLISTPUSH(res, vbuf, vsiz);
+ }
+ tcbdbcurprev(cur);
+ }
+ tcbdbcurdel(cur);
+ }
+ int rnum = TCLISTNUM(res);
+ if (rnum >= max || tcbdbrnum(oidx->db) >= tchdbrnum(hdb)) {
+ oname = NULL;
+ } else {
+ tcxstrprintf(hint, "abort the result: %d\n", rnum);
+ tclistdel(res);
+ res = NULL;
+ }
+ }
+ }
+ if (!res) {
+ tcxstrprintf(hint, "scanning the whole table\n");
+ res = tclistnew();
+ TDBCOND *ucond = NULL;
+ for (int i = 0; i < cnum; i++) {
+ TDBCOND *cond = conds + i;
+ if (!cond->alive) continue;
+ if (ucond) {
+ ucond = NULL;
+ break;
+ }
+ ucond = cond;
+ }
+ char *lkbuf = NULL;
+ int lksiz = 0;
+ char *pkbuf;
+ int pksiz;
+ const char *cbuf;
+ int csiz;
+ bool all = oname != NULL;
+ if (!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ while ((all || TCLISTNUM(res) < max) &&
+ (pkbuf = tchdbgetnext3(hdb, lkbuf, lksiz, &pksiz, &cbuf, &csiz)) != NULL) {
+ if (ucond) {
+ if (ucond->nsiz < 1) {
+ char *tkbuf;
+ TCMEMDUP(tkbuf, pkbuf, pksiz);
+ if (tctdbqrycondmatch(ucond, tkbuf, pksiz) == ucond->sign)
+ TCLISTPUSH(res, pkbuf, pksiz);
+ TCFREE(tkbuf);
+ } else {
+ int vsiz;
+ char *vbuf = tcmaploadone(cbuf, csiz, ucond->name, ucond->nsiz, &vsiz);
+ if (vbuf) {
+ if (tctdbqrycondmatch(ucond, vbuf, vsiz) == ucond->sign)
+ TCLISTPUSH(res, pkbuf, pksiz);
+ TCFREE(vbuf);
+ } else {
+ if (!ucond->sign) TCLISTPUSH(res, pkbuf, pksiz);
+ }
+ }
+ } else {
+ TCMAP *cols = tcmapload(cbuf, csiz);
+ bool ok = true;
+ for (int i = 0; i < cnum; i++) {
+ TDBCOND *cond = conds + i;
+ if (cond->nsiz < 1) {
+ char *tkbuf;
+ TCMEMDUP(tkbuf, pkbuf, pksiz);
+ if (tctdbqrycondmatch(cond, tkbuf, pksiz) != cond->sign) {
+ TCFREE(tkbuf);
+ ok = false;
+ break;
+ }
+ TCFREE(tkbuf);
+ } else {
+ int vsiz;
+ const char *vbuf = tcmapget(cols, cond->name, cond->nsiz, &vsiz);
+ if (vbuf) {
+ if (tctdbqrycondmatch(cond, vbuf, vsiz) != cond->sign) {
+ ok = false;
+ break;
+ }
+ } else {
+ if (cond->sign) {
+ ok = false;
+ break;
+ }
+ }
+ }
+ }
+ if (ok) TCLISTPUSH(res, pkbuf, pksiz);
+ tcmapdel(cols);
+ }
+ TCFREE(lkbuf);
+ lkbuf = pkbuf;
+ lksiz = pksiz;
+ }
+ TCFREE(lkbuf);
+ }
+ int rnum = TCLISTNUM(res);
+ tcxstrprintf(hint, "result set size: %d\n", rnum);
+ if (oname) {
+ if (*oname == '\0') {
+ tcxstrprintf(hint, "sorting the result set: \"%s\"\n", oname);
+ switch (otype) {
+ case TDBQOSTRASC:
+ tclistsort(res);
+ break;
+ case TDBQOSTRDESC:
+ tclistsort(res);
+ tclistinvert(res);
+ break;
+ case TDBQONUMASC:
+ tclistsortex(res, tdbcmppkeynumasc);
+ break;
+ case TDBQONUMDESC:
+ tclistsortex(res, tdbcmppkeynumdesc);
+ break;
}
- }
} else {
- break;
- }
- tcbdbcurnext(cur);
- }
- tcbdbcurdel(cur);
- if(oname && !strcmp(oname, mcond->name)){
- if(otype == TDBQOSTRASC){
- oname = NULL;
- } else if(otype == TDBQOSTRDESC){
- tclistinvert(res);
- oname = NULL;
- }
- }
- } else if(mcond->op == TDBQCSTROREQ){
- tcxstrprintf(hint, "using an index: \"%s\" skip (STROREQ)\n", mcond->name);
- BDBCUR *cur = tcbdbcurnew(midx->db);
- TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
- tclistsort(tokens);
- for(int i = 1; i < TCLISTNUM(tokens); i++){
- if(!strcmp(TCLISTVALPTR(tokens, i), TCLISTVALPTR(tokens, i - 1))){
- TCFREE(tclistremove2(tokens, i));
- i--;
- }
- }
- if(oname && !strcmp(oname, mcond->name)){
- if(otype == TDBQOSTRASC){
- oname = NULL;
- } else if(otype == TDBQOSTRDESC){
- tclistinvert(tokens);
- oname = NULL;
- }
- }
- int tnum = TCLISTNUM(tokens);
- bool all = oname != NULL;
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
- for(int i = 0; (all || TCLISTNUM(res) < max) && i < tnum; i++){
- const char *token;
- int tsiz;
- TCLISTVAL(token, tokens, i, tsiz);
- if(tsiz < 1) continue;
- tcbdbcurjump(cur, token, tsiz + trim);
+ tcxstrprintf(hint, "sorting the result set: \"%s\"\n", oname);
+ TDBSORTREC *keys;
+ TCMALLOC(keys, sizeof (*keys) * rnum + 1);
+ int onsiz = strlen(oname);
+ for (int i = 0; i < rnum; i++) {
+ TDBSORTREC *key = keys + i;
+ const char *kbuf;
+ int ksiz;
+ TCLISTVAL(kbuf, res, i, ksiz);
+ char *vbuf = NULL;
+ int vsiz = 0;
+ int csiz;
+ char *cbuf = tchdbget(hdb, kbuf, ksiz, &csiz);
+ if (cbuf) {
+ vbuf = tcmaploadone(cbuf, csiz, oname, onsiz, &vsiz);
+ TCFREE(cbuf);
+ }
+ key->kbuf = kbuf;
+ key->ksiz = ksiz;
+ key->vbuf = vbuf;
+ key->vsiz = vsiz;
+ }
+ int (*compar)(const TDBSORTREC *a, const TDBSORTREC * b) = NULL;
+ switch (otype) {
+ case TDBQOSTRASC:
+ compar = tdbcmpsortrecstrasc;
+ break;
+ case TDBQOSTRDESC:
+ compar = tdbcmpsortrecstrdesc;
+ break;
+ case TDBQONUMASC:
+ compar = tdbcmpsortrecnumasc;
+ break;
+ case TDBQONUMDESC:
+ compar = tdbcmpsortrecnumdesc;
+ break;
+ }
+ if (compar) {
+ if (max <= rnum / 16) {
+ tctopsort(keys, rnum, sizeof (*keys), max, (int (*)(const void *, const void *))compar);
+ } else {
+ qsort(keys, rnum, sizeof (*keys), (int (*)(const void *, const void *))compar);
+ }
+ }
+ TCLIST *nres = tclistnew2(rnum);
+ for (int i = 0; i < rnum; i++) {
+ TDBSORTREC *key = keys + i;
+ TCLISTPUSH(nres, key->kbuf, key->ksiz);
+ TCFREE(key->vbuf);
+ }
+ tclistdel(res);
+ res = nres;
+ TCFREE(keys);
+ }
+ } else if (isord) {
+ tcxstrprintf(hint, "leaving the index order\n");
+ } else {
+ tcxstrprintf(hint, "leaving the natural order\n");
+ }
+ if (qry->skip > 0) {
+ int left = tclmin(TCLISTNUM(res), qry->skip);
+ while (left-- > 0) {
+ int rsiz;
+ TCFREE(tclistshift(res, &rsiz));
+ }
+ max -= qry->skip;
+ }
+ if (TCLISTNUM(res) > max) {
+ int left = TCLISTNUM(res) - max;
+ while (left-- > 0) {
+ int rsiz;
+ TCFREE(tclistpop(res, &rsiz));
+ }
+ }
+ qry->count = TCLISTNUM(res);
+ return res;
+}
+
+/* Fetch record keys from an index matching to a condition.
+ `qry' specifies the query object.
+ `cond' specifies the condition object.
+ `idx' specifies an index object.
+ The return value is a map object containing primary keys of the corresponding records. */
+static TCMAP *tctdbqryidxfetch(TDBQRY *qry, TDBCOND *cond, TDBIDX *idx) {
+ assert(qry && cond && idx);
+ TCTDB *tdb = qry->tdb;
+ TCHDB *hdb = tdb->hdb;
+ TCXSTR *hint = qry->hint;
+ const char *expr = cond->expr;
+ int esiz = cond->esiz;
+ bool trim = *idx->name != '\0';
+ TCMAP *nmap = tcmapnew2(tclmin(TDBDEFBNUM, tchdbrnum(hdb)) / 4 + 1);
+ if (cond->op == TDBQCSTREQ) {
+ tcxstrprintf(hint, "using an auxiliary index: \"%s\" one (STREQ)\n", cond->name);
+ BDBCUR *cur = tcbdbcurnew(idx->db);
+ tcbdbcurjump(cur, expr, esiz + trim);
const char *kbuf;
int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(trim) ksiz -= 3;
- if(ksiz == tsiz && !memcmp(kbuf, token, tsiz)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- int nsiz;
- if(!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
- }
- }
- } else {
- break;
- }
- tcbdbcurnext(cur);
- }
- }
- tclistdel(tokens);
- tcbdbcurdel(cur);
- } else if(mcond->op == TDBQCNUMEQ){
- tcxstrprintf(hint, "using an index: \"%s\" asc (NUMEQ)\n", mcond->name);
- BDBCUR *cur = tcbdbcurnew(midx->db);
- if(oname && !strcmp(oname, mcond->name)) oname = NULL;
- long double xnum = tctdbatof(expr);
- tctdbqryidxcurjumpnum(cur, expr, esiz, true);
- bool all = oname != NULL;
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
- const char *kbuf;
- int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(tctdbatof(kbuf) == xnum){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- int nsiz;
- if(!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
+ while ((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (trim) ksiz -= 3;
+ if (ksiz == esiz && !memcmp(kbuf, expr, esiz)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ tcmapputkeep(nmap, vbuf, vsiz, "", 0);
+ } else {
+ break;
}
- }
- } else {
- break;
- }
- tcbdbcurnext(cur);
- }
- tcbdbcurdel(cur);
- } else if(mcond->op == TDBQCNUMGT || mcond->op == TDBQCNUMGE){
- if(oname && !strcmp(oname, mcond->name) && otype == TDBQONUMDESC){
- tcxstrprintf(hint, "using an index: \"%s\" desc (NUMGT/NUMGE)\n", mcond->name);
- long double xnum = tctdbatof(expr);
- BDBCUR *cur = tcbdbcurnew(midx->db);
- tcbdbcurlast(cur);
- if(max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ tcbdbcurnext(cur);
+ }
+ tcbdbcurdel(cur);
+ } else if (cond->op == TDBQCSTRBW) {
+ tcxstrprintf(hint, "using an auxiliary index: \"%s\" asc (STRBW)\n", cond->name);
+ BDBCUR *cur = tcbdbcurnew(idx->db);
+ tcbdbcurjump(cur, expr, esiz + trim);
const char *kbuf;
int ksiz;
- while(TCLISTNUM(res) < max && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- long double knum = tctdbatof(kbuf);
- if(knum < xnum) break;
- if(knum > xnum || (knum >= xnum && mcond->op == TDBQCNUMGE)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- int nsiz;
- if(!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
- }
+ while ((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (trim) ksiz -= 3;
+ if (ksiz >= esiz && !memcmp(kbuf, expr, esiz)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ tcmapputkeep(nmap, vbuf, vsiz, "", 0);
+ } else {
+ break;
}
- }
- tcbdbcurprev(cur);
+ tcbdbcurnext(cur);
}
tcbdbcurdel(cur);
- oname = NULL;
- } else {
- tcxstrprintf(hint, "using an index: \"%s\" asc (NUMGT/NUMGE)\n", mcond->name);
+ } else if (cond->op == TDBQCSTROREQ) {
+ tcxstrprintf(hint, "using an auxiliary index: \"%s\" skip (STROREQ)\n", cond->name);
+ TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
+ tclistsort(tokens);
+ for (int i = 1; i < TCLISTNUM(tokens); i++) {
+ if (!strcmp(TCLISTVALPTR(tokens, i), TCLISTVALPTR(tokens, i - 1))) {
+ TCFREE(tclistremove2(tokens, i));
+ i--;
+ }
+ }
+ int tnum = TCLISTNUM(tokens);
+ for (int i = 0; i < tnum; i++) {
+ const char *token;
+ int tsiz;
+ TCLISTVAL(token, tokens, i, tsiz);
+ if (tsiz < 1) continue;
+ BDBCUR *cur = tcbdbcurnew(idx->db);
+ tcbdbcurjump(cur, token, tsiz + trim);
+ const char *kbuf;
+ int ksiz;
+ while ((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (trim) ksiz -= 3;
+ if (ksiz == tsiz && !memcmp(kbuf, token, tsiz)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ tcmapputkeep(nmap, vbuf, vsiz, "", 0);
+ } else {
+ break;
+ }
+ tcbdbcurnext(cur);
+ }
+ tcbdbcurdel(cur);
+ }
+ tclistdel(tokens);
+ } else if (cond->op == TDBQCNUMEQ) {
+ tcxstrprintf(hint, "using an auxiliary index: \"%s\" asc (NUMEQ)\n", cond->name);
long double xnum = tctdbatof(expr);
- BDBCUR *cur = tcbdbcurnew(midx->db);
+ BDBCUR *cur = tcbdbcurnew(idx->db);
tctdbqryidxcurjumpnum(cur, expr, esiz, true);
- bool all = oname && (strcmp(oname, mcond->name) || otype != TDBQONUMASC);
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
const char *kbuf;
int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- long double knum = tctdbatof(kbuf);
- if(knum > xnum || (knum >= xnum && mcond->op == TDBQCNUMGE)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- int nsiz;
- if(!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
- }
+ while ((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (tctdbatof(kbuf) == xnum) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ tcmapputkeep(nmap, vbuf, vsiz, "", 0);
+ } else {
+ break;
}
- }
- tcbdbcurnext(cur);
+ tcbdbcurnext(cur);
}
tcbdbcurdel(cur);
- if(!all) oname = NULL;
- }
- } else if(mcond->op == TDBQCNUMLT || mcond->op == TDBQCNUMLE){
- if(oname && !strcmp(oname, mcond->name) && otype == TDBQONUMASC){
- tcxstrprintf(hint, "using an index: \"%s\" asc (NUMLT/NUMLE)\n", mcond->name);
+ } else if (cond->op == TDBQCNUMGT || cond->op == TDBQCNUMGE) {
+ tcxstrprintf(hint, "using an auxiliary index: \"%s\" asc (NUMGT/NUMGE)\n", cond->name);
long double xnum = tctdbatof(expr);
- BDBCUR *cur = tcbdbcurnew(midx->db);
- tcbdbcurfirst(cur);
- if(max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
+ BDBCUR *cur = tcbdbcurnew(idx->db);
+ tctdbqryidxcurjumpnum(cur, expr, esiz, true);
const char *kbuf;
int ksiz;
- while(TCLISTNUM(res) < max && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- long double knum = tctdbatof(kbuf);
- if(knum > xnum) break;
- if(knum < xnum || (knum <= xnum && mcond->op == TDBQCNUMLE)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- int nsiz;
- if(!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
- }
+ while ((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ long double knum = tctdbatof(kbuf);
+ if (knum > xnum || (knum >= xnum && cond->op == TDBQCNUMGE)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ tcmapputkeep(nmap, vbuf, vsiz, "", 0);
}
- }
- tcbdbcurnext(cur);
+ tcbdbcurnext(cur);
}
tcbdbcurdel(cur);
- oname = NULL;
- } else {
- tcxstrprintf(hint, "using an index: \"%s\" desc (NUMLT/NUMLE)\n", mcond->name);
+ } else if (cond->op == TDBQCNUMLT || cond->op == TDBQCNUMLE) {
+ tcxstrprintf(hint, "using an auxiliary index: \"%s\" desc (NUMLT/NUMLE)\n", cond->name);
long double xnum = tctdbatof(expr);
- BDBCUR *cur = tcbdbcurnew(midx->db);
+ BDBCUR *cur = tcbdbcurnew(idx->db);
tctdbqryidxcurjumpnum(cur, expr, esiz, false);
- bool all = oname && (strcmp(oname, mcond->name) || otype != TDBQONUMDESC);
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
const char *kbuf;
int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- long double knum = tctdbatof(kbuf);
- if(knum < xnum || (knum <= xnum && mcond->op == TDBQCNUMLE)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- int nsiz;
- if(!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
- }
+ while ((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ long double knum = tctdbatof(kbuf);
+ if (knum < xnum || (knum <= xnum && cond->op == TDBQCNUMLE)) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ tcmapputkeep(nmap, vbuf, vsiz, "", 0);
}
- }
- tcbdbcurprev(cur);
+ tcbdbcurprev(cur);
}
tcbdbcurdel(cur);
- if(!all) oname = NULL;
- }
- } else if(mcond->op == TDBQCNUMBT){
- tcxstrprintf(hint, "using an index: \"%s\" asc (NUMBT)\n", mcond->name);
- while(*expr == ' ' || *expr == ','){
- expr++;
- }
- const char *pv = expr;
- while(*pv != '\0' && *pv != ' ' && *pv != ','){
- pv++;
- }
- esiz = pv - expr;
- if(*pv != ' ' && *pv != ',') pv = " ";
- pv++;
- while(*pv == ' ' || *pv == ','){
+ } else if (cond->op == TDBQCNUMBT) {
+ tcxstrprintf(hint, "using an auxiliary index: \"%s\" asc (NUMBT)\n", cond->name);
+ while (*expr == ' ' || *expr == ',') {
+ expr++;
+ }
+ const char *pv = expr;
+ while (*pv != '\0' && *pv != ' ' && *pv != ',') {
+ pv++;
+ }
+ esiz = pv - expr;
+ if (*pv != ' ' && *pv != ',') pv = " ";
pv++;
- }
- long double lower = tctdbatof(expr);
- long double upper = tctdbatof(pv);
- if(lower > upper){
- expr = pv;
- esiz = strlen(expr);
- long double swap = lower;
- lower = upper;
- upper = swap;
- }
- BDBCUR *cur = tcbdbcurnew(midx->db);
- tctdbqryidxcurjumpnum(cur, expr, esiz, true);
- bool all = oname && (strcmp(oname, mcond->name) || otype != TDBQONUMASC);
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
- const char *kbuf;
- int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(tctdbatof(kbuf) > upper) break;
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- int nsiz;
- if(!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
- }
- }
- tcbdbcurnext(cur);
- }
- tcbdbcurdel(cur);
- if(oname && !strcmp(oname, mcond->name)){
- if(otype == TDBQONUMASC){
- oname = NULL;
- } else if(otype == TDBQONUMDESC){
- tclistinvert(res);
- oname = NULL;
- }
- }
- } else if(mcond->op == TDBQCNUMOREQ){
- tcxstrprintf(hint, "using an index: \"%s\" skip (NUMOREQ)\n", mcond->name);
- BDBCUR *cur = tcbdbcurnew(midx->db);
- TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
- tclistsortex(tokens, tdbcmppkeynumasc);
- for(int i = 1; i < TCLISTNUM(tokens); i++){
- if(tctdbatof(TCLISTVALPTR(tokens, i)) == tctdbatof(TCLISTVALPTR(tokens, i - 1))){
- TCFREE(tclistremove2(tokens, i));
- i--;
- }
- }
- if(oname && !strcmp(oname, mcond->name)){
- if(otype == TDBQONUMASC){
- oname = NULL;
- } else if(otype == TDBQONUMDESC){
- tclistinvert(tokens);
- oname = NULL;
- }
- }
- int tnum = TCLISTNUM(tokens);
- bool all = oname != NULL;
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
- for(int i = 0; (all || TCLISTNUM(res) < max) && i < tnum; i++){
- const char *token;
- int tsiz;
- TCLISTVAL(token, tokens, i, tsiz);
- if(tsiz < 1) continue;
- long double xnum = tctdbatof(token);
- tctdbqryidxcurjumpnum(cur, token, tsiz, true);
+ while (*pv == ' ' || *pv == ',') {
+ pv++;
+ }
+ long double lower = tctdbatof(expr);
+ long double upper = tctdbatof(pv);
+ if (lower > upper) {
+ expr = pv;
+ esiz = strlen(expr);
+ long double swap = lower;
+ lower = upper;
+ upper = swap;
+ }
+ BDBCUR *cur = tcbdbcurnew(idx->db);
+ tctdbqryidxcurjumpnum(cur, expr, esiz, true);
const char *kbuf;
int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(tctdbatof(kbuf) == xnum){
+ while ((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (tctdbatof(kbuf) > upper) break;
int vsiz;
const char *vbuf = tcbdbcurval3(cur, &vsiz);
- int nsiz;
- if(!nmap || tcmapget(nmap, vbuf, vsiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
- }
- }
- } else {
- break;
- }
- tcbdbcurnext(cur);
- }
- }
- tclistdel(tokens);
- tcbdbcurdel(cur);
- } else if(mcond->op == TDBQCSTRAND || mcond->op == TDBQCSTROR){
- tcxstrprintf(hint, "using an index: \"%s\" inverted (%s)\n",
- mcond->name, mcond->op == TDBQCSTRAND ? "STRAND" : "STROR");
- bool all = oname != NULL;
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
- TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
- tclistsort(tokens);
- for(int i = 1; i < TCLISTNUM(tokens); i++){
- if(!strcmp(TCLISTVALPTR(tokens, i), TCLISTVALPTR(tokens, i - 1))){
- TCFREE(tclistremove2(tokens, i));
- i--;
- }
- }
- TCMAP *tres = tctdbidxgetbytokens(tdb, midx, tokens, mcond->op, hint);
- tcmapiterinit(tres);
- const char *kbuf;
- int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcmapiternext(tres, &ksiz)) != NULL){
- int nsiz;
- if(!nmap || tcmapget(nmap, kbuf, ksiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, kbuf, ksiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, kbuf, ksiz)) TCLISTPUSH(res, kbuf, ksiz);
- } else if(tctdbqryallcondmatch(qry, kbuf, ksiz)){
- TCLISTPUSH(res, kbuf, ksiz);
- }
- }
- }
- tcmapdel(tres);
- tclistdel(tokens);
- } else if(mcond->op == TDBQCFTSPH){
- tcxstrprintf(hint, "using an index: \"%s\" inverted (FTS)\n", mcond->name);
- TCMAP *tres = tctdbidxgetbyfts(tdb, midx, mcond, hint);
- bool all = oname != NULL;
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
- tcmapiterinit(tres);
- const char *kbuf;
- int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcmapiternext(tres, &ksiz)) != NULL){
- int nsiz;
- if(!nmap || tcmapget(nmap, kbuf, ksiz, &nsiz)){
- if(acnum < 1){
- TCLISTPUSH(res, kbuf, ksiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, kbuf, ksiz)) TCLISTPUSH(res, kbuf, ksiz);
- } else if(tctdbqryallcondmatch(qry, kbuf, ksiz)){
- TCLISTPUSH(res, kbuf, ksiz);
- }
- }
- }
- tcmapdel(tres);
- }
- if(nmap) tcmapdel(nmap);
- }
- if(!res && scond){
- res = tclistnew();
- scond->alive = false;
- acnum--;
- TDBCOND *ucond = NULL;
- for(int i = 0; i < cnum; i++){
- TDBCOND *cond = conds + i;
- if(!cond->alive) continue;
- if(ucond){
- ucond = NULL;
- break;
- }
- ucond = cond;
- }
- bool trim = *sidx->name != '\0';
- bool asc = true;
- bool all = true;
- if(!oname){
- all = false;
- } else if(!strcmp(oname, scond->name)){
- switch(sidx->type){
- case TDBITLEXICAL:
- switch(otype){
- case TDBQOSTRASC:
- asc = true;
- all = false;
- break;
- case TDBQOSTRDESC:
- asc = false;
- all = false;
- break;
- }
- break;
- case TDBITDECIMAL:
- switch(otype){
- case TDBQONUMASC:
- asc = true;
- all = false;
- break;
- case TDBQONUMDESC:
- asc = false;
- all = false;
- break;
- }
- break;
- }
- }
- if(asc){
- tcxstrprintf(hint, "using an index: \"%s\" asc (all)\n", scond->name);
- BDBCUR *cur = tcbdbcurnew(sidx->db);
- tcbdbcurfirst(cur);
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
- const char *kbuf;
- int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(trim) ksiz -= 3;
- if(ksiz < 0) break;
- if(tctdbqrycondmatch(scond, kbuf, ksiz)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
- }
- }
- tcbdbcurnext(cur);
- }
- tcbdbcurdel(cur);
- } else {
- tcxstrprintf(hint, "using an index: \"%s\" desc (all)\n", scond->name);
- BDBCUR *cur = tcbdbcurnew(sidx->db);
- tcbdbcurlast(cur);
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
- const char *kbuf;
- int ksiz;
- while((all || TCLISTNUM(res) < max) && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(trim) ksiz -= 3;
- if(ksiz < 0) break;
- if(tctdbqrycondmatch(scond, kbuf, ksiz)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
- }
- }
- tcbdbcurprev(cur);
- }
- tcbdbcurdel(cur);
- }
- if(!all) oname = NULL;
- }
- if(!res && oname && max < tchdbrnum(hdb) * TDBORDRATIO){
- TDBIDX *oidx = NULL;
- bool asc = true;
- for(int i = 0; !oidx && i < inum; i++){
- TDBIDX *idx = idxs + i;
- if(strcmp(idx->name, oname)) continue;
- switch(idx->type){
- case TDBITLEXICAL:
- switch(otype){
- case TDBQOSTRASC:
- oidx = idx;
- asc = true;
- break;
- case TDBQOSTRDESC:
- oidx = idx;
- asc = false;
- break;
- }
- break;
- case TDBITDECIMAL:
- switch(otype){
- case TDBQONUMASC:
- oidx = idx;
- asc = true;
- break;
- case TDBQONUMDESC:
- oidx = idx;
- asc = false;
- break;
- }
- break;
- }
- }
- if(oidx){
- res = tclistnew();
- TDBCOND *ucond = NULL;
- for(int i = 0; i < cnum; i++){
- TDBCOND *cond = conds + i;
- if(!cond->alive) continue;
- if(ucond){
- ucond = NULL;
- break;
- }
- ucond = cond;
- }
- bool trim = *oidx->name != '\0';
- if(asc){
- tcxstrprintf(hint, "using an index: \"%s\" asc (order)\n", oname);
- BDBCUR *cur = tcbdbcurnew(oidx->db);
- tcbdbcurfirst(cur);
- tcxstrprintf(hint, "limited matching: %d\n", max);
- const char *kbuf;
- int ksiz;
- while(TCLISTNUM(res) < max && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(trim) ksiz -= 3;
- if(ksiz < 0) break;
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
- }
- tcbdbcurnext(cur);
+ tcmapputkeep(nmap, vbuf, vsiz, "", 0);
+ tcbdbcurnext(cur);
}
tcbdbcurdel(cur);
- } else {
- tcxstrprintf(hint, "using an index: \"%s\" desc (order)\n", oname);
- BDBCUR *cur = tcbdbcurnew(oidx->db);
- tcbdbcurlast(cur);
- tcxstrprintf(hint, "limited matching: %d\n", max);
- const char *kbuf;
- int ksiz;
- while(TCLISTNUM(res) < max && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(trim) ksiz -= 3;
- if(ksiz < 0) break;
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- if(acnum < 1){
- TCLISTPUSH(res, vbuf, vsiz);
- } else if(ucond){
- if(tctdbqryonecondmatch(qry, ucond, vbuf, vsiz)) TCLISTPUSH(res, vbuf, vsiz);
- } else if(tctdbqryallcondmatch(qry, vbuf, vsiz)){
- TCLISTPUSH(res, vbuf, vsiz);
- }
- tcbdbcurprev(cur);
+ } else if (cond->op == TDBQCNUMOREQ) {
+ tcxstrprintf(hint, "using an auxiliary index: \"%s\" skip (NUMOREQ)\n", cond->name);
+ BDBCUR *cur = tcbdbcurnew(idx->db);
+ TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
+ tclistsortex(tokens, tdbcmppkeynumasc);
+ for (int i = 1; i < TCLISTNUM(tokens); i++) {
+ if (tctdbatof(TCLISTVALPTR(tokens, i)) == tctdbatof(TCLISTVALPTR(tokens, i - 1))) {
+ TCFREE(tclistremove2(tokens, i));
+ i--;
+ }
}
- tcbdbcurdel(cur);
- }
- int rnum = TCLISTNUM(res);
- if(rnum >= max || tcbdbrnum(oidx->db) >= tchdbrnum(hdb)){
- oname = NULL;
- } else {
- tcxstrprintf(hint, "abort the result: %d\n", rnum);
- tclistdel(res);
- res = NULL;
- }
- }
- }
- if(!res){
- tcxstrprintf(hint, "scanning the whole table\n");
- res = tclistnew();
- TDBCOND *ucond = NULL;
- for(int i = 0; i < cnum; i++){
- TDBCOND *cond = conds + i;
- if(!cond->alive) continue;
- if(ucond){
- ucond = NULL;
- break;
- }
- ucond = cond;
- }
- char *lkbuf = NULL;
- int lksiz = 0;
- char *pkbuf;
- int pksiz;
- const char *cbuf;
- int csiz;
- bool all = oname != NULL;
- if(!all && max < INT_MAX) tcxstrprintf(hint, "limited matching: %d\n", max);
- while((all || TCLISTNUM(res) < max) &&
- (pkbuf = tchdbgetnext3(hdb, lkbuf, lksiz, &pksiz, &cbuf, &csiz)) != NULL){
- if(ucond){
- if(ucond->nsiz < 1){
- char *tkbuf;
- TCMEMDUP(tkbuf, pkbuf, pksiz);
- if(tctdbqrycondmatch(ucond, tkbuf, pksiz) == ucond->sign)
- TCLISTPUSH(res, pkbuf, pksiz);
- TCFREE(tkbuf);
- } else {
- int vsiz;
- char *vbuf = tcmaploadone(cbuf, csiz, ucond->name, ucond->nsiz, &vsiz);
- if(vbuf){
- if(tctdbqrycondmatch(ucond, vbuf, vsiz) == ucond->sign)
- TCLISTPUSH(res, pkbuf, pksiz);
- TCFREE(vbuf);
- } else {
- if(!ucond->sign) TCLISTPUSH(res, pkbuf, pksiz);
- }
- }
- } else {
- TCMAP *cols = tcmapload(cbuf, csiz);
- bool ok = true;
- for(int i = 0; i < cnum; i++){
- TDBCOND *cond = conds + i;
- if(cond->nsiz < 1){
- char *tkbuf;
- TCMEMDUP(tkbuf, pkbuf, pksiz);
- if(tctdbqrycondmatch(cond, tkbuf, pksiz) != cond->sign){
- TCFREE(tkbuf);
- ok = false;
- break;
+ int tnum = TCLISTNUM(tokens);
+ for (int i = 0; i < tnum; i++) {
+ const char *token;
+ int tsiz;
+ TCLISTVAL(token, tokens, i, tsiz);
+ if (tsiz < 1) continue;
+ long double xnum = tctdbatof(token);
+ tctdbqryidxcurjumpnum(cur, token, tsiz, true);
+ const char *kbuf;
+ int ksiz;
+ while ((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL) {
+ if (tctdbatof(kbuf) == xnum) {
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ tcmapputkeep(nmap, vbuf, vsiz, "", 0);
+ } else {
+ break;
+ }
+ tcbdbcurnext(cur);
}
- TCFREE(tkbuf);
- } else {
- int vsiz;
- const char *vbuf = tcmapget(cols, cond->name, cond->nsiz, &vsiz);
- if(vbuf){
- if(tctdbqrycondmatch(cond, vbuf, vsiz) != cond->sign){
- ok = false;
- break;
- }
- } else {
- if(cond->sign){
- ok = false;
- break;
- }
+ }
+ tclistdel(tokens);
+ tcbdbcurdel(cur);
+ } else if (cond->op == TDBQCSTRAND || cond->op == TDBQCSTROR) {
+ tcxstrprintf(hint, "using an auxiliary index: \"%s\" inverted (%s)\n",
+ cond->name, cond->op == TDBQCSTRAND ? "STRAND" : "STROR");
+ TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
+ tclistsort(tokens);
+ for (int i = 1; i < TCLISTNUM(tokens); i++) {
+ if (!strcmp(TCLISTVALPTR(tokens, i), TCLISTVALPTR(tokens, i - 1))) {
+ TCFREE(tclistremove2(tokens, i));
+ i--;
}
- }
}
- if(ok) TCLISTPUSH(res, pkbuf, pksiz);
- tcmapdel(cols);
- }
- TCFREE(lkbuf);
- lkbuf = pkbuf;
- lksiz = pksiz;
- }
- TCFREE(lkbuf);
- }
- int rnum = TCLISTNUM(res);
- tcxstrprintf(hint, "result set size: %d\n", rnum);
- if(oname){
- if(*oname == '\0'){
- tcxstrprintf(hint, "sorting the result set: \"%s\"\n", oname);
- switch(otype){
- case TDBQOSTRASC:
- tclistsort(res);
- break;
- case TDBQOSTRDESC:
- tclistsort(res);
- tclistinvert(res);
- break;
- case TDBQONUMASC:
- tclistsortex(res, tdbcmppkeynumasc);
- break;
- case TDBQONUMDESC:
- tclistsortex(res, tdbcmppkeynumdesc);
- break;
- }
- } else {
- tcxstrprintf(hint, "sorting the result set: \"%s\"\n", oname);
- TDBSORTREC *keys;
- TCMALLOC(keys, sizeof(*keys) * rnum + 1);
- int onsiz = strlen(oname);
- for(int i = 0; i < rnum; i++){
- TDBSORTREC *key = keys + i;
- const char *kbuf;
- int ksiz;
- TCLISTVAL(kbuf, res, i, ksiz);
- char *vbuf = NULL;
- int vsiz = 0;
- int csiz;
- char *cbuf = tchdbget(hdb, kbuf, ksiz, &csiz);
- if(cbuf){
- vbuf = tcmaploadone(cbuf, csiz, oname, onsiz, &vsiz);
- TCFREE(cbuf);
- }
- key->kbuf = kbuf;
- key->ksiz = ksiz;
- key->vbuf = vbuf;
- key->vsiz = vsiz;
- }
- int (*compar)(const TDBSORTREC *a, const TDBSORTREC *b) = NULL;
- switch(otype){
- case TDBQOSTRASC:
- compar = tdbcmpsortrecstrasc;
- break;
- case TDBQOSTRDESC:
- compar = tdbcmpsortrecstrdesc;
- break;
- case TDBQONUMASC:
- compar = tdbcmpsortrecnumasc;
- break;
- case TDBQONUMDESC:
- compar = tdbcmpsortrecnumdesc;
- break;
- }
- if(compar){
- if(max <= rnum / 16){
- tctopsort(keys, rnum, sizeof(*keys), max, (int (*)(const void *, const void *))compar);
- } else {
- qsort(keys, rnum, sizeof(*keys), (int (*)(const void *, const void *))compar);
- }
- }
- TCLIST *nres = tclistnew2(rnum);
- for(int i = 0; i < rnum; i++){
- TDBSORTREC *key = keys + i;
- TCLISTPUSH(nres, key->kbuf, key->ksiz);
- TCFREE(key->vbuf);
- }
- tclistdel(res);
- res = nres;
- TCFREE(keys);
- }
- } else if(isord){
- tcxstrprintf(hint, "leaving the index order\n");
- } else {
- tcxstrprintf(hint, "leaving the natural order\n");
- }
- if(qry->skip > 0){
- int left = tclmin(TCLISTNUM(res), qry->skip);
- while(left-- > 0){
- int rsiz;
- TCFREE(tclistshift(res, &rsiz));
- }
- max -= qry->skip;
- }
- if(TCLISTNUM(res) > max){
- int left = TCLISTNUM(res) - max;
- while(left-- > 0){
- int rsiz;
- TCFREE(tclistpop(res, &rsiz));
- }
- }
- qry->count = TCLISTNUM(res);
- return res;
-}
-
-
-/* Fetch record keys from an index matching to a condition.
- `qry' specifies the query object.
- `cond' specifies the condition object.
- `idx' specifies an index object.
- The return value is a map object containing primary keys of the corresponding records. */
-static TCMAP *tctdbqryidxfetch(TDBQRY *qry, TDBCOND *cond, TDBIDX *idx){
- assert(qry && cond && idx);
- TCTDB *tdb = qry->tdb;
- TCHDB *hdb = tdb->hdb;
- TCXSTR *hint = qry->hint;
- const char *expr = cond->expr;
- int esiz = cond->esiz;
- bool trim = *idx->name != '\0';
- TCMAP *nmap = tcmapnew2(tclmin(TDBDEFBNUM, tchdbrnum(hdb)) / 4 + 1);
- if(cond->op == TDBQCSTREQ){
- tcxstrprintf(hint, "using an auxiliary index: \"%s\" one (STREQ)\n", cond->name);
- BDBCUR *cur = tcbdbcurnew(idx->db);
- tcbdbcurjump(cur, expr, esiz + trim);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(trim) ksiz -= 3;
- if(ksiz == esiz && !memcmp(kbuf, expr, esiz)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- tcmapputkeep(nmap, vbuf, vsiz, "", 0);
- } else {
- break;
- }
- tcbdbcurnext(cur);
- }
- tcbdbcurdel(cur);
- } else if(cond->op == TDBQCSTRBW){
- tcxstrprintf(hint, "using an auxiliary index: \"%s\" asc (STRBW)\n", cond->name);
- BDBCUR *cur = tcbdbcurnew(idx->db);
- tcbdbcurjump(cur, expr, esiz + trim);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(trim) ksiz -= 3;
- if(ksiz >= esiz && !memcmp(kbuf, expr, esiz)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- tcmapputkeep(nmap, vbuf, vsiz, "", 0);
- } else {
- break;
- }
- tcbdbcurnext(cur);
- }
- tcbdbcurdel(cur);
- } else if(cond->op == TDBQCSTROREQ){
- tcxstrprintf(hint, "using an auxiliary index: \"%s\" skip (STROREQ)\n", cond->name);
- TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
- tclistsort(tokens);
- for(int i = 1; i < TCLISTNUM(tokens); i++){
- if(!strcmp(TCLISTVALPTR(tokens, i), TCLISTVALPTR(tokens, i - 1))){
- TCFREE(tclistremove2(tokens, i));
- i--;
- }
+ tcmapdel(nmap);
+ nmap = tctdbidxgetbytokens(tdb, idx, tokens, cond->op, hint);
+ tclistdel(tokens);
+ } else if (cond->op == TDBQCFTSPH) {
+ tcxstrprintf(hint, "using an auxiliary index: \"%s\" inverted (FTS)\n", cond->name);
+ tcmapdel(nmap);
+ nmap = tctdbidxgetbyfts(tdb, idx, cond, hint);
}
- int tnum = TCLISTNUM(tokens);
- for(int i = 0; i < tnum; i++){
- const char *token;
- int tsiz;
- TCLISTVAL(token, tokens, i, tsiz);
- if(tsiz < 1) continue;
- BDBCUR *cur = tcbdbcurnew(idx->db);
- tcbdbcurjump(cur, token, tsiz + trim);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(trim) ksiz -= 3;
- if(ksiz == tsiz && !memcmp(kbuf, token, tsiz)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- tcmapputkeep(nmap, vbuf, vsiz, "", 0);
- } else {
- break;
- }
- tcbdbcurnext(cur);
- }
- tcbdbcurdel(cur);
- }
- tclistdel(tokens);
- } else if(cond->op == TDBQCNUMEQ){
- tcxstrprintf(hint, "using an auxiliary index: \"%s\" asc (NUMEQ)\n", cond->name);
- long double xnum = tctdbatof(expr);
- BDBCUR *cur = tcbdbcurnew(idx->db);
- tctdbqryidxcurjumpnum(cur, expr, esiz, true);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(tctdbatof(kbuf) == xnum){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- tcmapputkeep(nmap, vbuf, vsiz, "", 0);
- } else {
- break;
- }
- tcbdbcurnext(cur);
- }
- tcbdbcurdel(cur);
- } else if(cond->op == TDBQCNUMGT || cond->op == TDBQCNUMGE){
- tcxstrprintf(hint, "using an auxiliary index: \"%s\" asc (NUMGT/NUMGE)\n", cond->name);
- long double xnum = tctdbatof(expr);
- BDBCUR *cur = tcbdbcurnew(idx->db);
- tctdbqryidxcurjumpnum(cur, expr, esiz, true);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- long double knum = tctdbatof(kbuf);
- if(knum > xnum || (knum >= xnum && cond->op == TDBQCNUMGE)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- tcmapputkeep(nmap, vbuf, vsiz, "", 0);
- }
- tcbdbcurnext(cur);
- }
- tcbdbcurdel(cur);
- } else if(cond->op == TDBQCNUMLT || cond->op == TDBQCNUMLE){
- tcxstrprintf(hint, "using an auxiliary index: \"%s\" desc (NUMLT/NUMLE)\n", cond->name);
- long double xnum = tctdbatof(expr);
- BDBCUR *cur = tcbdbcurnew(idx->db);
- tctdbqryidxcurjumpnum(cur, expr, esiz, false);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- long double knum = tctdbatof(kbuf);
- if(knum < xnum || (knum <= xnum && cond->op == TDBQCNUMLE)){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- tcmapputkeep(nmap, vbuf, vsiz, "", 0);
- }
- tcbdbcurprev(cur);
- }
- tcbdbcurdel(cur);
- } else if(cond->op == TDBQCNUMBT){
- tcxstrprintf(hint, "using an auxiliary index: \"%s\" asc (NUMBT)\n", cond->name);
- while(*expr == ' ' || *expr == ','){
- expr++;
- }
- const char *pv = expr;
- while(*pv != '\0' && *pv != ' ' && *pv != ','){
- pv++;
- }
- esiz = pv - expr;
- if(*pv != ' ' && *pv != ',') pv = " ";
- pv++;
- while(*pv == ' ' || *pv == ','){
- pv++;
- }
- long double lower = tctdbatof(expr);
- long double upper = tctdbatof(pv);
- if(lower > upper){
- expr = pv;
- esiz = strlen(expr);
- long double swap = lower;
- lower = upper;
- upper = swap;
- }
- BDBCUR *cur = tcbdbcurnew(idx->db);
- tctdbqryidxcurjumpnum(cur, expr, esiz, true);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(tctdbatof(kbuf) > upper) break;
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- tcmapputkeep(nmap, vbuf, vsiz, "", 0);
- tcbdbcurnext(cur);
- }
- tcbdbcurdel(cur);
- } else if(cond->op == TDBQCNUMOREQ){
- tcxstrprintf(hint, "using an auxiliary index: \"%s\" skip (NUMOREQ)\n", cond->name);
- BDBCUR *cur = tcbdbcurnew(idx->db);
- TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
- tclistsortex(tokens, tdbcmppkeynumasc);
- for(int i = 1; i < TCLISTNUM(tokens); i++){
- if(tctdbatof(TCLISTVALPTR(tokens, i)) == tctdbatof(TCLISTVALPTR(tokens, i - 1))){
- TCFREE(tclistremove2(tokens, i));
- i--;
- }
- }
- int tnum = TCLISTNUM(tokens);
- for(int i = 0; i < tnum; i++){
- const char *token;
- int tsiz;
- TCLISTVAL(token, tokens, i, tsiz);
- if(tsiz < 1) continue;
- long double xnum = tctdbatof(token);
- tctdbqryidxcurjumpnum(cur, token, tsiz, true);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
- if(tctdbatof(kbuf) == xnum){
- int vsiz;
- const char *vbuf = tcbdbcurval3(cur, &vsiz);
- tcmapputkeep(nmap, vbuf, vsiz, "", 0);
- } else {
- break;
- }
- tcbdbcurnext(cur);
- }
- }
- tclistdel(tokens);
- tcbdbcurdel(cur);
- } else if(cond->op == TDBQCSTRAND || cond->op == TDBQCSTROR){
- tcxstrprintf(hint, "using an auxiliary index: \"%s\" inverted (%s)\n",
- cond->name, cond->op == TDBQCSTRAND ? "STRAND" : "STROR");
- TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
- tclistsort(tokens);
- for(int i = 1; i < TCLISTNUM(tokens); i++){
- if(!strcmp(TCLISTVALPTR(tokens, i), TCLISTVALPTR(tokens, i - 1))){
- TCFREE(tclistremove2(tokens, i));
- i--;
- }
- }
- tcmapdel(nmap);
- nmap = tctdbidxgetbytokens(tdb, idx, tokens, cond->op, hint);
- tclistdel(tokens);
- } else if(cond->op == TDBQCFTSPH){
- tcxstrprintf(hint, "using an auxiliary index: \"%s\" inverted (FTS)\n", cond->name);
- tcmapdel(nmap);
- nmap = tctdbidxgetbyfts(tdb, idx, cond, hint);
- }
- tcxstrprintf(hint, "auxiliary result set size: %" PRIdMAX "\n", (long long)TCMAPRNUM(nmap));
- return nmap;
+ tcxstrprintf(hint, "auxiliary result set size: %" PRIdMAX "\n", (long long) TCMAPRNUM(nmap));
+ return nmap;
}
-
/* Convert a string to a real number.
`str' specifies the string.
The return value is the real number. */
-long double tctdbatof(const char *str){
- assert(str);
- while(*str > '\0' && *str <= ' '){
- str++;
- }
- int sign = 1;
- if(*str == '-'){
- str++;
- sign = -1;
- } else if(*str == '+'){
- str++;
- }
- if(tcstrifwm(str, "inf")) return HUGE_VALL * sign;
- if(tcstrifwm(str, "nan")) return nanl("");
- long double num = 0;
- int col = 0;
- while(*str != '\0'){
- if(*str < '0' || *str > '9') break;
- num = num * 10 + *str - '0';
- str++;
- if(num > 0) col++;
- }
- if(*str == '.'){
- str++;
- long double fract = 0.0;
- long double base = 10;
- while(col < TDBNUMCOLMAX && *str != '\0'){
- if(*str < '0' || *str > '9') break;
- fract += (*str - '0') / base;
- str++;
- col++;
- base *= 10;
- }
- num += fract;
- }
- return num * sign;
-}
-
-
-double tctdbatof2(const char *str){
- assert(str);
- while(*str > '\0' && *str <= ' '){
- str++;
- }
- int sign = 1;
- if(*str == '-'){
- str++;
- sign = -1;
- } else if(*str == '+'){
- str++;
- }
- if(tcstrifwm(str, "inf")) return HUGE_VALL * sign;
- if(tcstrifwm(str, "nan")) return nan("");
- double num = 0;
- int col = 0;
- while(*str != '\0'){
- if(*str < '0' || *str > '9') break;
- num = num * 10 + *str - '0';
- str++;
- if(num > 0) col++;
- }
- if(*str == '.'){
- str++;
- double fract = 0.0;
- double base = 10;
- while(col < TDBNUMCOLMAX && *str != '\0'){
- if(*str < '0' || *str > '9') break;
- fract += (*str - '0') / base;
- str++;
- col++;
- base *= 10;
- }
- num += fract;
- }
- return num * sign;
-}
-
-int64_t tctdbatoi(const char *str){
- assert(str);
- while(*str > '\0' && *str <= ' '){
- str++;
- }
- int sign = 1;
- if(*str == '-'){
- str++;
- sign = -1;
- } else if(*str == '+'){
- str++;
- }
- if(tcstrifwm(str, "inf")) return (INT64_MAX * sign);
- if(tcstrifwm(str, "nan")) return 0;
- int64_t num = 0;
- int col = 0;
- while(*str != '\0'){
- if(*str < '0' || *str > '9') break;
- num = num * 10 + *str - '0';
- str++;
- if(num > 0) col++;
- }
- return num * sign;
+long double tctdbatof(const char *str) {
+ assert(str);
+ while (*str > '\0' && *str <= ' ') {
+ str++;
+ }
+ int sign = 1;
+ if (*str == '-') {
+ str++;
+ sign = -1;
+ } else if (*str == '+') {
+ str++;
+ }
+ if (tcstrifwm(str, "inf")) return HUGE_VALL * sign;
+ if (tcstrifwm(str, "nan")) return nanl("");
+ long double num = 0;
+ int col = 0;
+ while (*str != '\0') {
+ if (*str < '0' || *str > '9') break;
+ num = num * 10 + *str - '0';
+ str++;
+ if (num > 0) col++;
+ }
+ if (*str == '.') {
+ str++;
+ long double fract = 0.0;
+ long double base = 10;
+ while (col < TDBNUMCOLMAX && *str != '\0') {
+ if (*str < '0' || *str > '9') break;
+ fract += (*str - '0') / base;
+ str++;
+ col++;
+ base *= 10;
+ }
+ num += fract;
+ }
+ return num * sign;
+}
+
+double tctdbatof2(const char *str) {
+ assert(str);
+ while (*str > '\0' && *str <= ' ') {
+ str++;
+ }
+ int sign = 1;
+ if (*str == '-') {
+ str++;
+ sign = -1;
+ } else if (*str == '+') {
+ str++;
+ }
+ if (tcstrifwm(str, "inf")) return HUGE_VALL * sign;
+ if (tcstrifwm(str, "nan")) return nan("");
+ double num = 0;
+ int col = 0;
+ while (*str != '\0') {
+ if (*str < '0' || *str > '9') break;
+ num = num * 10 + *str - '0';
+ str++;
+ if (num > 0) col++;
+ }
+ if (*str == '.') {
+ str++;
+ double fract = 0.0;
+ double base = 10;
+ while (col < TDBNUMCOLMAX && *str != '\0') {
+ if (*str < '0' || *str > '9') break;
+ fract += (*str - '0') / base;
+ str++;
+ col++;
+ base *= 10;
+ }
+ num += fract;
+ }
+ return num * sign;
}
+int64_t tctdbatoi(const char *str) {
+ assert(str);
+ while (*str > '\0' && *str <= ' ') {
+ str++;
+ }
+ int sign = 1;
+ if (*str == '-') {
+ str++;
+ sign = -1;
+ } else if (*str == '+') {
+ str++;
+ }
+ if (tcstrifwm(str, "inf")) return (INT64_MAX * sign);
+ if (tcstrifwm(str, "nan")) return 0;
+ int64_t num = 0;
+ int col = 0;
+ while (*str != '\0') {
+ if (*str < '0' || *str > '9') break;
+ num = num * 10 + *str - '0';
+ str++;
+ if (num > 0) col++;
+ }
+ return num * sign;
+}
/* Jump a cursor to the record of a key.
`cur' specifies the cursor object.
`esiz' specifies the size of the expression.
`first' specifies whether to jump the first candidate.
If successful, the return value is true, else, it is false. */
-bool tctdbqryidxcurjumpnum(BDBCUR *cur, const char *expr, int esiz, bool first){
- assert(cur && expr && esiz >= 0);
- char stack[TCNUMBUFSIZ], *rbuf;
- if(esiz < sizeof(stack)){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, esiz + 1);
- }
- rbuf[0] = first ? 0x00 : 0x7f;
- memcpy(rbuf + 1, expr, esiz);
- bool err = false;
- if(first){
- if(!tcbdbcurjump(cur, rbuf, esiz + 1)) err = true;
- } else {
- if(!tcbdbcurjumpback(cur, rbuf, esiz + 1)) err = true;
- }
- if(rbuf != stack) TCFREE(rbuf);
- return !err;
+bool tctdbqryidxcurjumpnum(BDBCUR *cur, const char *expr, int esiz, bool first) {
+ assert(cur && expr && esiz >= 0);
+ char stack[TCNUMBUFSIZ], *rbuf;
+ if (esiz < sizeof (stack)) {
+ rbuf = stack;
+ } else {
+ TCMALLOC(rbuf, esiz + 1);
+ }
+ rbuf[0] = first ? 0x00 : 0x7f;
+ memcpy(rbuf + 1, expr, esiz);
+ bool err = false;
+ if (first) {
+ if (!tcbdbcurjump(cur, rbuf, esiz + 1)) err = true;
+ } else {
+ if (!tcbdbcurjumpback(cur, rbuf, esiz + 1)) err = true;
+ }
+ if (rbuf != stack) TCFREE(rbuf);
+ return !err;
}
-
/* Check matching of one condition and a record.
`qry' specifies the query object.
`cond' specifies the condition object.
`pkbuf' specifies the pointer to the region of the primary key.
`pksiz' specifies the size of the region of the primary key.
If they matches, the return value is true, else it is false. */
-static bool tctdbqryonecondmatch(TDBQRY *qry, TDBCOND *cond, const char *pkbuf, int pksiz){
- assert(qry && cond && pkbuf && pksiz >= 0);
- if(cond->nsiz < 1) return tctdbqrycondmatch(cond, pkbuf, pksiz) == cond->sign;
- int csiz;
- char *cbuf = tchdbget(qry->tdb->hdb, pkbuf, pksiz, &csiz);
- if(!cbuf) return false;
- bool rv;
- int vsiz;
- char *vbuf = tcmaploadone(cbuf, csiz, cond->name, cond->nsiz, &vsiz);
- if(vbuf){
- rv = tctdbqrycondmatch(cond, vbuf, vsiz) == cond->sign;
- TCFREE(vbuf);
- } else {
- rv = !cond->sign;
- }
- TCFREE(cbuf);
- return rv;
+static bool tctdbqryonecondmatch(TDBQRY *qry, TDBCOND *cond, const char *pkbuf, int pksiz) {
+ assert(qry && cond && pkbuf && pksiz >= 0);
+ if (cond->nsiz < 1) return tctdbqrycondmatch(cond, pkbuf, pksiz) == cond->sign;
+ int csiz;
+ char *cbuf = tchdbget(qry->tdb->hdb, pkbuf, pksiz, &csiz);
+ if (!cbuf) return false;
+ bool rv;
+ int vsiz;
+ char *vbuf = tcmaploadone(cbuf, csiz, cond->name, cond->nsiz, &vsiz);
+ if (vbuf) {
+ rv = tctdbqrycondmatch(cond, vbuf, vsiz) == cond->sign;
+ TCFREE(vbuf);
+ } else {
+ rv = !cond->sign;
+ }
+ TCFREE(cbuf);
+ return rv;
}
-
/* Check matching of all conditions and a record.
`qry' specifies the query object.
`pkbuf' specifies the pointer to the region of the primary key.
`pksiz' specifies the size of the region of the primary key.
If they matches, the return value is true, else it is false. */
-static bool tctdbqryallcondmatch(TDBQRY *qry, const char *pkbuf, int pksiz){
- assert(qry && pkbuf && pksiz >= 0);
- TCTDB *tdb = qry->tdb;
- TDBCOND *conds = qry->conds;
- int cnum = qry->cnum;
- int csiz;
- char *cbuf = tchdbget(tdb->hdb, pkbuf, pksiz, &csiz);
- if(!cbuf) return false;
- TCMAP *cols = tcmapload(cbuf, csiz);
- bool ok = true;
- for(int i = 0; i < cnum; i++){
- TDBCOND *cond = conds + i;
- if(!cond->alive) continue;
- if(cond->nsiz < 1){
- if(tctdbqrycondmatch(cond, pkbuf, pksiz) != cond->sign){
- ok = false;
- break;
- }
- } else {
- int vsiz;
- const char *vbuf = tcmapget(cols, cond->name, cond->nsiz, &vsiz);
- if(vbuf){
- if(tctdbqrycondmatch(cond, vbuf, vsiz) != cond->sign){
- ok = false;
- break;
- }
- } else {
- if(cond->sign){
- ok = false;
- break;
+static bool tctdbqryallcondmatch(TDBQRY *qry, const char *pkbuf, int pksiz) {
+ assert(qry && pkbuf && pksiz >= 0);
+ TCTDB *tdb = qry->tdb;
+ TDBCOND *conds = qry->conds;
+ int cnum = qry->cnum;
+ int csiz;
+ char *cbuf = tchdbget(tdb->hdb, pkbuf, pksiz, &csiz);
+ if (!cbuf) return false;
+ TCMAP *cols = tcmapload(cbuf, csiz);
+ bool ok = true;
+ for (int i = 0; i < cnum; i++) {
+ TDBCOND *cond = conds + i;
+ if (!cond->alive) continue;
+ if (cond->nsiz < 1) {
+ if (tctdbqrycondmatch(cond, pkbuf, pksiz) != cond->sign) {
+ ok = false;
+ break;
+ }
+ } else {
+ int vsiz;
+ const char *vbuf = tcmapget(cols, cond->name, cond->nsiz, &vsiz);
+ if (vbuf) {
+ if (tctdbqrycondmatch(cond, vbuf, vsiz) != cond->sign) {
+ ok = false;
+ break;
+ }
+ } else {
+ if (cond->sign) {
+ ok = false;
+ break;
+ }
+ }
}
- }
}
- }
- tcmapdel(cols);
- TCFREE(cbuf);
- return ok;
+ tcmapdel(cols);
+ TCFREE(cbuf);
+ return ok;
}
-
/* Check matching of a operand expression and a column value.
`cond' specifies the condition object.
`vbuf' specifies the column value.
`vsiz' specifies the size of the column value.
If they matches, the return value is true, else it is false. */
-static bool tctdbqrycondmatch(TDBCOND *cond, const char *vbuf, int vsiz){
- assert(cond && vbuf && vsiz >= 0);
- bool hit = false;
- switch(cond->op){
- case TDBQCSTREQ:
- hit = vsiz == cond->esiz && !memcmp(vbuf, cond->expr, cond->esiz);
- break;
- case TDBQCSTRINC:
- hit = strstr(vbuf, cond->expr) != NULL;
- break;
- case TDBQCSTRBW:
- hit = tcstrfwm(vbuf, cond->expr);
- break;
- case TDBQCSTREW:
- hit = tcstrbwm(vbuf, cond->expr);
- break;
- case TDBQCSTRAND:
- hit = tctdbqrycondcheckstrand(vbuf, cond->expr);
- break;
- case TDBQCSTROR:
- hit = tctdbqrycondcheckstror(vbuf, cond->expr);
- break;
- case TDBQCSTROREQ:
- hit = tctdbqrycondcheckstroreq(vbuf, cond->expr);
- break;
- case TDBQCSTRRX:
- hit = cond->regex && regexec(cond->regex, vbuf, 0, NULL, 0) == 0;
- break;
- case TDBQCNUMEQ:
- hit = tctdbatof(vbuf) == tctdbatof(cond->expr);
- break;
- case TDBQCNUMGT:
- hit = tctdbatof(vbuf) > tctdbatof(cond->expr);
- break;
- case TDBQCNUMGE:
- hit = tctdbatof(vbuf) >= tctdbatof(cond->expr);
- break;
- case TDBQCNUMLT:
- hit = tctdbatof(vbuf) < tctdbatof(cond->expr);
- break;
- case TDBQCNUMLE:
- hit = tctdbatof(vbuf) <= tctdbatof(cond->expr);
- break;
- case TDBQCNUMBT:
- hit = tctdbqrycondchecknumbt(vbuf, cond->expr);
- break;
- case TDBQCNUMOREQ:
- hit = tctdbqrycondchecknumoreq(vbuf, cond->expr);
- break;
- case TDBQCFTSPH:
- hit = tctdbqrycondcheckfts(vbuf, vsiz, cond);
- break;
- }
- return hit;
+static bool tctdbqrycondmatch(TDBCOND *cond, const char *vbuf, int vsiz) {
+ assert(cond && vbuf && vsiz >= 0);
+ bool hit = false;
+ switch (cond->op) {
+ case TDBQCSTREQ:
+ hit = vsiz == cond->esiz && !memcmp(vbuf, cond->expr, cond->esiz);
+ break;
+ case TDBQCSTRINC:
+ hit = strstr(vbuf, cond->expr) != NULL;
+ break;
+ case TDBQCSTRBW:
+ hit = tcstrfwm(vbuf, cond->expr);
+ break;
+ case TDBQCSTREW:
+ hit = tcstrbwm(vbuf, cond->expr);
+ break;
+ case TDBQCSTRAND:
+ hit = tctdbqrycondcheckstrand(vbuf, cond->expr);
+ break;
+ case TDBQCSTROR:
+ hit = tctdbqrycondcheckstror(vbuf, cond->expr);
+ break;
+ case TDBQCSTROREQ:
+ hit = tctdbqrycondcheckstroreq(vbuf, cond->expr);
+ break;
+ case TDBQCSTRRX:
+ hit = cond->regex && regexec(cond->regex, vbuf, 0, NULL, 0) == 0;
+ break;
+ case TDBQCNUMEQ:
+ hit = tctdbatof(vbuf) == tctdbatof(cond->expr);
+ break;
+ case TDBQCNUMGT:
+ hit = tctdbatof(vbuf) > tctdbatof(cond->expr);
+ break;
+ case TDBQCNUMGE:
+ hit = tctdbatof(vbuf) >= tctdbatof(cond->expr);
+ break;
+ case TDBQCNUMLT:
+ hit = tctdbatof(vbuf) < tctdbatof(cond->expr);
+ break;
+ case TDBQCNUMLE:
+ hit = tctdbatof(vbuf) <= tctdbatof(cond->expr);
+ break;
+ case TDBQCNUMBT:
+ hit = tctdbqrycondchecknumbt(vbuf, cond->expr);
+ break;
+ case TDBQCNUMOREQ:
+ hit = tctdbqrycondchecknumoreq(vbuf, cond->expr);
+ break;
+ case TDBQCFTSPH:
+ hit = tctdbqrycondcheckfts(vbuf, vsiz, cond);
+ break;
+ }
+ return hit;
}
-
/* Check whether a string includes all tokens in another string.
`vbuf' specifies the column value.
`expr' specifies the operand expression.
If they matches, the return value is true, else it is false. */
-static bool tctdbqrycondcheckstrand(const char *vbuf, const char *expr){
- assert(vbuf && expr);
- const unsigned char *sp = (unsigned char *)expr;
- while(*sp != '\0'){
- while((*sp != '\0' && *sp <= ' ') || *sp == ','){
- sp++;
- }
- const unsigned char *ep = sp;
- while(*ep > ' ' && *ep != ','){
- ep++;
- }
- if(ep > sp){
- bool hit = false;
- const unsigned char *rp = (unsigned char *)vbuf;
- while(*rp != '\0'){
- const unsigned char *pp;
- for(pp = sp; pp < ep; pp++, rp++){
- if(*pp != *rp) break;
- }
- if(pp == ep && (*rp <= ' ' || *rp == ',')){
- hit = true;
- break;
+static bool tctdbqrycondcheckstrand(const char *vbuf, const char *expr) {
+ assert(vbuf && expr);
+ const unsigned char *sp = (unsigned char *) expr;
+ while (*sp != '\0') {
+ while ((*sp != '\0' && *sp <= ' ') || *sp == ',') {
+ sp++;
}
- while(*rp > ' ' && *rp != ','){
- rp++;
+ const unsigned char *ep = sp;
+ while (*ep > ' ' && *ep != ',') {
+ ep++;
}
- while((*rp != '\0' && *rp <= ' ') || *rp == ','){
- rp++;
+ if (ep > sp) {
+ bool hit = false;
+ const unsigned char *rp = (unsigned char *) vbuf;
+ while (*rp != '\0') {
+ const unsigned char *pp;
+ for (pp = sp; pp < ep; pp++, rp++) {
+ if (*pp != *rp) break;
+ }
+ if (pp == ep && (*rp <= ' ' || *rp == ',')) {
+ hit = true;
+ break;
+ }
+ while (*rp > ' ' && *rp != ',') {
+ rp++;
+ }
+ while ((*rp != '\0' && *rp <= ' ') || *rp == ',') {
+ rp++;
+ }
+ }
+ if (!hit) return false;
}
- }
- if(!hit) return false;
+ sp = ep;
}
- sp = ep;
- }
- return true;
+ return true;
}
-
/* Check whether a string includes at least one token in another string.
`vbuf' specifies the target value.
`expr' specifies the operation value.
If they matches, the return value is true, else it is false. */
-static bool tctdbqrycondcheckstror(const char *vbuf, const char *expr){
- assert(vbuf && expr);
- const unsigned char *sp = (unsigned char *)expr;
- while(*sp != '\0'){
- while((*sp != '\0' && *sp <= ' ') || *sp == ','){
- sp++;
- }
- const unsigned char *ep = sp;
- while(*ep > ' ' && *ep != ','){
- ep++;
- }
- if(ep > sp){
- bool hit = false;
- const unsigned char *rp = (unsigned char *)vbuf;
- while(*rp != '\0'){
- const unsigned char *pp;
- for(pp = sp; pp < ep; pp++, rp++){
- if(*pp != *rp) break;
+static bool tctdbqrycondcheckstror(const char *vbuf, const char *expr) {
+ assert(vbuf && expr);
+ const unsigned char *sp = (unsigned char *) expr;
+ while (*sp != '\0') {
+ while ((*sp != '\0' && *sp <= ' ') || *sp == ',') {
+ sp++;
}
- if(pp == ep && (*rp <= ' ' || *rp == ',')){
- hit = true;
- break;
+ const unsigned char *ep = sp;
+ while (*ep > ' ' && *ep != ',') {
+ ep++;
}
- while(*rp > ' ' && *rp != ','){
- rp++;
- }
- while((*rp != '\0' && *rp <= ' ') || *rp == ','){
- rp++;
+ if (ep > sp) {
+ bool hit = false;
+ const unsigned char *rp = (unsigned char *) vbuf;
+ while (*rp != '\0') {
+ const unsigned char *pp;
+ for (pp = sp; pp < ep; pp++, rp++) {
+ if (*pp != *rp) break;
+ }
+ if (pp == ep && (*rp <= ' ' || *rp == ',')) {
+ hit = true;
+ break;
+ }
+ while (*rp > ' ' && *rp != ',') {
+ rp++;
+ }
+ while ((*rp != '\0' && *rp <= ' ') || *rp == ',') {
+ rp++;
+ }
+ }
+ if (hit) return true;
}
- }
- if(hit) return true;
+ sp = ep;
}
- sp = ep;
- }
- return false;
+ return false;
}
-
/* Check whether a string is equal to at least one token in another string.
`vbuf' specifies the target value.
`expr' specifies the operation value.
If they matches, the return value is true, else it is false. */
-static bool tctdbqrycondcheckstroreq(const char *vbuf, const char *expr){
- assert(vbuf && expr);
- const unsigned char *sp = (unsigned char *)expr;
- while(*sp != '\0'){
- while((*sp != '\0' && *sp <= ' ') || *sp == ','){
- sp++;
- }
- const unsigned char *ep = sp;
- while(*ep > ' ' && *ep != ','){
- ep++;
- }
- if(ep > sp){
- const unsigned char *rp;
- for(rp = (unsigned char *)vbuf; *rp != '\0'; rp++){
- if(*sp != *rp || sp >= ep) break;
- sp++;
- }
- if(*rp == '\0' && sp == ep) return true;
+static bool tctdbqrycondcheckstroreq(const char *vbuf, const char *expr) {
+ assert(vbuf && expr);
+ const unsigned char *sp = (unsigned char *) expr;
+ while (*sp != '\0') {
+ while ((*sp != '\0' && *sp <= ' ') || *sp == ',') {
+ sp++;
+ }
+ const unsigned char *ep = sp;
+ while (*ep > ' ' && *ep != ',') {
+ ep++;
+ }
+ if (ep > sp) {
+ const unsigned char *rp;
+ for (rp = (unsigned char *) vbuf; *rp != '\0'; rp++) {
+ if (*sp != *rp || sp >= ep) break;
+ sp++;
+ }
+ if (*rp == '\0' && sp == ep) return true;
+ }
+ sp = ep;
}
- sp = ep;
- }
- return false;
+ return false;
}
-
/* Check whether a decimal string is between two tokens in another string.
`vbuf' specifies the target value.
`expr' specifies the operation value.
If they matches, the return value is true, else it is false. */
-static bool tctdbqrycondchecknumbt(const char *vbuf, const char *expr){
- assert(vbuf && expr);
- while(*expr == ' ' || *expr == ','){
- expr++;
- }
- const char *pv = expr;
- while(*pv != '\0' && *pv != ' ' && *pv != ','){
- pv++;
- }
- if(*pv != ' ' && *pv != ',') pv = " ";
- pv++;
- while(*pv == ' ' || *pv == ','){
+static bool tctdbqrycondchecknumbt(const char *vbuf, const char *expr) {
+ assert(vbuf && expr);
+ while (*expr == ' ' || *expr == ',') {
+ expr++;
+ }
+ const char *pv = expr;
+ while (*pv != '\0' && *pv != ' ' && *pv != ',') {
+ pv++;
+ }
+ if (*pv != ' ' && *pv != ',') pv = " ";
pv++;
- }
- long double val = tctdbatof(vbuf);
- long double lower = tctdbatof(expr);
- long double upper = tctdbatof(pv);
- if(lower > upper){
- long double swap = lower;
- lower = upper;
- upper = swap;
- }
- return val >= lower && val <= upper;
+ while (*pv == ' ' || *pv == ',') {
+ pv++;
+ }
+ long double val = tctdbatof(vbuf);
+ long double lower = tctdbatof(expr);
+ long double upper = tctdbatof(pv);
+ if (lower > upper) {
+ long double swap = lower;
+ lower = upper;
+ upper = swap;
+ }
+ return val >= lower && val <= upper;
}
-
/* Check whether a number is equal to at least one token in another string.
`vbuf' specifies the target value.
`expr' specifies the operation value.
If they matches, the return value is true, else it is false. */
-static bool tctdbqrycondchecknumoreq(const char *vbuf, const char *expr){
- assert(vbuf && expr);
- long double vnum = tctdbatof(vbuf);
- const char *sp = expr;
- while(*sp != '\0'){
- while(*sp == ' ' || *sp == ','){
- sp++;
- }
- const char *ep = sp;
- while(*ep != '\0' && *ep != ' ' && *ep != ','){
- ep++;
+static bool tctdbqrycondchecknumoreq(const char *vbuf, const char *expr) {
+ assert(vbuf && expr);
+ long double vnum = tctdbatof(vbuf);
+ const char *sp = expr;
+ while (*sp != '\0') {
+ while (*sp == ' ' || *sp == ',') {
+ sp++;
+ }
+ const char *ep = sp;
+ while (*ep != '\0' && *ep != ' ' && *ep != ',') {
+ ep++;
+ }
+ if (ep > sp && vnum == tctdbatof(sp)) return true;
+ sp = ep;
}
- if(ep > sp && vnum == tctdbatof(sp)) return true;
- sp = ep;
- }
- return false;
+ return false;
}
-
/* Check whether a text matches a condition.
`vbuf' specifies the target value.
`vsiz' specifies the size of the target value.
`cond' specifies the condition object.
If they matches, the return value is true, else it is false. */
-static bool tctdbqrycondcheckfts(const char *vbuf, int vsiz, TDBCOND *cond){
- assert(vbuf && cond);
- TDBFTSUNIT *ftsunits = cond->ftsunits;
- int ftsnum = cond->ftsnum;
- if(ftsnum < 1) return false;
- if(!ftsunits[0].sign) return false;
- char astack[TDBCOLBUFSIZ];
- uint16_t *ary;
- int asiz = sizeof(*ary) * (vsiz + 1);
- if(asiz < sizeof(astack)){
- ary = (uint16_t *)astack;
- } else {
- TCMALLOC(ary, asiz + 1);
- }
- int anum;
- tcstrutftoucs(vbuf, ary, &anum);
- anum = tcstrucsnorm(ary, anum, TCUNSPACE | TCUNLOWER | TCUNNOACC | TCUNWIDTH);
- char sstack[TDBCOLBUFSIZ], *str;
- int ssiz = anum * 3 + 1;
- if(ssiz < sizeof(sstack)){
- str = sstack;
- } else {
- TCMALLOC(str, ssiz + 1);
- }
- tcstrucstoutf(ary, anum, str);
- bool ok = true;
- for(int i = 0; i < ftsnum; i++){
- TDBFTSUNIT *ftsunit = ftsunits + i;
- TCLIST *tokens = ftsunit->tokens;
- int tnum = TCLISTNUM(tokens);
- bool hit = false;
- for(int j = 0; j < tnum; j++){
- if(strstr(str, TCLISTVALPTR(tokens, j))){
- hit = true;
- break;
- }
+static bool tctdbqrycondcheckfts(const char *vbuf, int vsiz, TDBCOND *cond) {
+ assert(vbuf && cond);
+ TDBFTSUNIT *ftsunits = cond->ftsunits;
+ int ftsnum = cond->ftsnum;
+ if (ftsnum < 1) return false;
+ if (!ftsunits[0].sign) return false;
+ char astack[TDBCOLBUFSIZ];
+ uint16_t *ary;
+ int asiz = sizeof (*ary) * (vsiz + 1);
+ if (asiz < sizeof (astack)) {
+ ary = (uint16_t *) astack;
+ } else {
+ TCMALLOC(ary, asiz + 1);
+ }
+ int anum;
+ tcstrutftoucs(vbuf, ary, &anum);
+ anum = tcstrucsnorm(ary, anum, TCUNSPACE | TCUNLOWER | TCUNNOACC | TCUNWIDTH);
+ char sstack[TDBCOLBUFSIZ], *str;
+ int ssiz = anum * 3 + 1;
+ if (ssiz < sizeof (sstack)) {
+ str = sstack;
+ } else {
+ TCMALLOC(str, ssiz + 1);
}
- if(hit != ftsunit->sign) ok = false;
- }
- if(str != sstack) TCFREE(str);
- if(ary != (uint16_t *)astack) TCFREE(ary);
- return ok;
+ tcstrucstoutf(ary, anum, str);
+ bool ok = true;
+ for (int i = 0; i < ftsnum; i++) {
+ TDBFTSUNIT *ftsunit = ftsunits + i;
+ TCLIST *tokens = ftsunit->tokens;
+ int tnum = TCLISTNUM(tokens);
+ bool hit = false;
+ for (int j = 0; j < tnum; j++) {
+ if (strstr(str, TCLISTVALPTR(tokens, j))) {
+ hit = true;
+ break;
+ }
+ }
+ if (hit != ftsunit->sign) ok = false;
+ }
+ if (str != sstack) TCFREE(str);
+ if (ary != (uint16_t *) astack) TCFREE(ary);
+ return ok;
}
-
/* Compare two primary keys by number ascending.
`a' specifies a key.
`b' specifies of the other key.
The return value is positive if the former is big, negative if the latter is big, 0 if both
are equivalent. */
-int tdbcmppkeynumasc(const TCLISTDATUM *a, const TCLISTDATUM *b){
- assert(a && b);
- return tccmpdecimal(a->ptr, a->size, b->ptr, b->size, NULL);
+int tdbcmppkeynumasc(const TCLISTDATUM *a, const TCLISTDATUM *b) {
+ assert(a && b);
+ return tccmpdecimal(a->ptr, a->size, b->ptr, b->size, NULL);
}
-
/* Compare two primary keys by number descending.
`a' specifies a key.
`b' specifies of the other key.
The return value is positive if the former is big, negative if the latter is big, 0 if both
are equivalent. */
-int tdbcmppkeynumdesc(const TCLISTDATUM *a, const TCLISTDATUM *b){
- assert(a && b);
- return tccmpdecimal(b->ptr, b->size, a->ptr, a->size, NULL);
+int tdbcmppkeynumdesc(const TCLISTDATUM *a, const TCLISTDATUM *b) {
+ assert(a && b);
+ return tccmpdecimal(b->ptr, b->size, a->ptr, a->size, NULL);
}
-
/* Compare two sort records by string ascending.
`a' specifies a key.
`b' specifies of the other key.
The return value is positive if the former is big, negative if the latter is big, 0 if both
are equivalent. */
-static int tdbcmpsortrecstrasc(const TDBSORTREC *a, const TDBSORTREC *b){
- assert(a && b);
- if(!a->vbuf){
- if(!b->vbuf) return 0;
- return 1;
- }
- if(!b->vbuf){
- if(!a->vbuf) return 0;
- return -1;
- }
- int rv;
- TCCMPLEXICAL(rv, a->vbuf, a->vsiz, b->vbuf, b->vsiz);
- return rv;
+static int tdbcmpsortrecstrasc(const TDBSORTREC *a, const TDBSORTREC *b) {
+ assert(a && b);
+ if (!a->vbuf) {
+ if (!b->vbuf) return 0;
+ return 1;
+ }
+ if (!b->vbuf) {
+ if (!a->vbuf) return 0;
+ return -1;
+ }
+ int rv;
+ TCCMPLEXICAL(rv, a->vbuf, a->vsiz, b->vbuf, b->vsiz);
+ return rv;
}
-
/* Compare two sort records by string descending.
`a' specifies a key.
`b' specifies of the other key.
The return value is positive if the former is big, negative if the latter is big, 0 if both
are equivalent. */
-static int tdbcmpsortrecstrdesc(const TDBSORTREC *a, const TDBSORTREC *b){
- assert(a && b);
- if(!a->vbuf){
- if(!b->vbuf) return 0;
- return 1;
- }
- if(!b->vbuf){
- if(!a->vbuf) return 0;
- return -1;
- }
- int rv;
- TCCMPLEXICAL(rv, a->vbuf, a->vsiz, b->vbuf, b->vsiz);
- return -rv;
+static int tdbcmpsortrecstrdesc(const TDBSORTREC *a, const TDBSORTREC *b) {
+ assert(a && b);
+ if (!a->vbuf) {
+ if (!b->vbuf) return 0;
+ return 1;
+ }
+ if (!b->vbuf) {
+ if (!a->vbuf) return 0;
+ return -1;
+ }
+ int rv;
+ TCCMPLEXICAL(rv, a->vbuf, a->vsiz, b->vbuf, b->vsiz);
+ return -rv;
}
-
/* Compare two sort records by number ascending.
`a' specifies a key.
`b' specifies of the other key.
The return value is positive if the former is big, negative if the latter is big, 0 if both
are equivalent. */
-static int tdbcmpsortrecnumasc(const TDBSORTREC *a, const TDBSORTREC *b){
- assert(a && b);
- if(!a->vbuf){
- if(!b->vbuf) return 0;
- return 1;
- }
- if(!b->vbuf){
- if(!a->vbuf) return 0;
- return -1;
- }
- long double anum = tctdbatof(a->vbuf);
- long double bnum = tctdbatof(b->vbuf);
- if(anum < bnum) return -1;
- if(anum > bnum) return 1;
- return 0;
+static int tdbcmpsortrecnumasc(const TDBSORTREC *a, const TDBSORTREC *b) {
+ assert(a && b);
+ if (!a->vbuf) {
+ if (!b->vbuf) return 0;
+ return 1;
+ }
+ if (!b->vbuf) {
+ if (!a->vbuf) return 0;
+ return -1;
+ }
+ long double anum = tctdbatof(a->vbuf);
+ long double bnum = tctdbatof(b->vbuf);
+ if (anum < bnum) return -1;
+ if (anum > bnum) return 1;
+ return 0;
}
-
/* Compare two sort records by number descending.
`a' specifies a key.
`b' specifies of the other key.
The return value is positive if the former is big, negative if the latter is big, 0 if both
are equivalent. */
-static int tdbcmpsortrecnumdesc(const TDBSORTREC *a, const TDBSORTREC *b){
- assert(a && b);
- if(!a->vbuf){
- if(!b->vbuf) return 0;
- return 1;
- }
- if(!b->vbuf){
- if(!a->vbuf) return 0;
- return -1;
- }
- long double anum = tctdbatof(a->vbuf);
- long double bnum = tctdbatof(b->vbuf);
- if(anum < bnum) return 1;
- if(anum > bnum) return -1;
- return 0;
+static int tdbcmpsortrecnumdesc(const TDBSORTREC *a, const TDBSORTREC *b) {
+ assert(a && b);
+ if (!a->vbuf) {
+ if (!b->vbuf) return 0;
+ return 1;
+ }
+ if (!b->vbuf) {
+ if (!a->vbuf) return 0;
+ return -1;
+ }
+ long double anum = tctdbatof(a->vbuf);
+ long double bnum = tctdbatof(b->vbuf);
+ if (anum < bnum) return 1;
+ if (anum > bnum) return -1;
+ return 0;
}
-
/* Get the hash value of a record.
`pkbuf' specifies the pointer to the region of the primary key.
`pksiz' specifies the size of the region of the primary key.
The return value is the hash value. */
-static uint16_t tctdbidxhash(const char *pkbuf, int pksiz){
- assert(pkbuf && pksiz && pksiz >= 0);
- uint32_t hash = 19780211;
- while(pksiz--){
- hash = hash * 37 + *(uint8_t *)pkbuf++;
- }
- return hash;
+static uint16_t tctdbidxhash(const char *pkbuf, int pksiz) {
+ assert(pkbuf && pksiz && pksiz >= 0);
+ uint32_t hash = 19780211;
+ while (pksiz--) {
+ hash = hash * 37 + *(uint8_t *) pkbuf++;
+ }
+ return hash;
}
-
/* Add a record into indices of a table database object.
`tdb' specifies the table database object.
`pkbuf' specifies the pointer to the region of the primary key.
`pksiz' specifies the size of the region of the primary key.
`cols' specifies a map object containing columns.
If successful, the return value is true, else, it is false. */
-bool tctdbidxput(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols){
- assert(tdb && pkbuf && pksiz >= 0 && cols);
- bool err = false;
- uint16_t hash = tctdbidxhash(pkbuf, pksiz);
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- if(*(idx->name) != '\0') continue;
- char stack[TDBCOLBUFSIZ], *rbuf;
- if(pksiz < sizeof(stack)){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, pksiz + 1);
- }
- memcpy(rbuf, pkbuf, pksiz);
- rbuf[pksiz] = '\0';
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- if(!tcbdbput(idx->db, pkbuf, pksiz, rbuf, pksiz)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- case TDBITTOKEN:
- if(!tctdbidxputtoken(tdb, idx, pkbuf, pksiz, pkbuf, pksiz)) err = true;
- break;
- case TDBITQGRAM:
- if(!tctdbidxputqgram(tdb, idx, pkbuf, pksiz, pkbuf, pksiz)) err = true;
- break;
- }
- if(rbuf != stack) TCFREE(rbuf);
- }
- tcmapiterinit(cols);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){
- int vsiz;
- const char *vbuf = tcmapiterval(kbuf, &vsiz);
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- if(strcmp(idx->name, kbuf)) continue;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- if(!tctdbidxputone(tdb, idx, pkbuf, pksiz, hash, vbuf, vsiz)) err = true;
- break;
- case TDBITTOKEN:
- if(!tctdbidxputtoken(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
- break;
- case TDBITQGRAM:
- if(!tctdbidxputqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
- break;
- }
- }
- }
- return !err;
-}
-
-bool tctdbidxput2(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols){
- assert(tdb && pkbuf && pksiz >= 0 && cols);
- bool err = false;
- uint16_t hash = tctdbidxhash(pkbuf, pksiz);
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- if(*(idx->name) != '\0') continue;
- char stack[TDBCOLBUFSIZ], *rbuf;
- if(pksiz < sizeof(stack)){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, pksiz + 1);
- }
- memcpy(rbuf, pkbuf, pksiz);
- rbuf[pksiz] = '\0';
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- if(!tcbdbput(idx->db, pkbuf, pksiz, rbuf, pksiz)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- case TDBITTOKEN:
- if(!tctdbidxputtoken(tdb, idx, pkbuf, pksiz, pkbuf, pksiz)) err = true;
- break;
- case TDBITQGRAM:
- if(!tctdbidxputqgram(tdb, idx, pkbuf, pksiz, pkbuf, pksiz)) err = true;
- break;
- }
- if(rbuf != stack) TCFREE(rbuf);
- }
- tcmapiterinit(cols);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){
- int vsiz;
- const char *vbuf = tcmapiterval(kbuf, &vsiz);
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- if(strcmp(idx->name, kbuf)) continue;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- if(!tctdbidxputone(tdb, idx, pkbuf, pksiz, hash, vbuf, vsiz)) err = true;
- break;
- case TDBITTOKEN:
- {
- TCLIST *tokens = tclistload(vbuf, vsiz);
- if(!tctdbidxputtoken2(tdb, idx, pkbuf, pksiz, tokens)) err = true;
- tclistdel(tokens);
- break;
+bool tctdbidxput(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols) {
+ assert(tdb && pkbuf && pksiz >= 0 && cols);
+ bool err = false;
+ uint16_t hash = tctdbidxhash(pkbuf, pksiz);
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ if (*(idx->name) != '\0') continue;
+ char stack[TDBCOLBUFSIZ], *rbuf;
+ if (pksiz < sizeof (stack)) {
+ rbuf = stack;
+ } else {
+ TCMALLOC(rbuf, pksiz + 1);
}
- case TDBITQGRAM:
- if(!tctdbidxputqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
- break;
- }
+ memcpy(rbuf, pkbuf, pksiz);
+ rbuf[pksiz] = '\0';
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ if (!tcbdbput(idx->db, pkbuf, pksiz, rbuf, pksiz)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ case TDBITTOKEN:
+ if (!tctdbidxputtoken(tdb, idx, pkbuf, pksiz, pkbuf, pksiz)) err = true;
+ break;
+ case TDBITQGRAM:
+ if (!tctdbidxputqgram(tdb, idx, pkbuf, pksiz, pkbuf, pksiz)) err = true;
+ break;
+ }
+ if (rbuf != stack) TCFREE(rbuf);
+ }
+ tcmapiterinit(cols);
+ const char *kbuf;
+ int ksiz;
+ while ((kbuf = tcmapiternext(cols, &ksiz)) != NULL) {
+ int vsiz;
+ const char *vbuf = tcmapiterval(kbuf, &vsiz);
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ if (strcmp(idx->name, kbuf)) continue;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ if (!tctdbidxputone(tdb, idx, pkbuf, pksiz, hash, vbuf, vsiz)) err = true;
+ break;
+ case TDBITTOKEN:
+ if (!tctdbidxputtoken(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
+ break;
+ case TDBITQGRAM:
+ if (!tctdbidxputqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
+ break;
+ }
+ }
+ }
+ return !err;
+}
+
+bool tctdbidxput2(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols) {
+ assert(tdb && pkbuf && pksiz >= 0 && cols);
+ bool err = false;
+ uint16_t hash = tctdbidxhash(pkbuf, pksiz);
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ if (*(idx->name) != '\0') continue;
+ char stack[TDBCOLBUFSIZ], *rbuf;
+ if (pksiz < sizeof (stack)) {
+ rbuf = stack;
+ } else {
+ TCMALLOC(rbuf, pksiz + 1);
+ }
+ memcpy(rbuf, pkbuf, pksiz);
+ rbuf[pksiz] = '\0';
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ if (!tcbdbput(idx->db, pkbuf, pksiz, rbuf, pksiz)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ case TDBITTOKEN:
+ if (!tctdbidxputtoken(tdb, idx, pkbuf, pksiz, pkbuf, pksiz)) err = true;
+ break;
+ case TDBITQGRAM:
+ if (!tctdbidxputqgram(tdb, idx, pkbuf, pksiz, pkbuf, pksiz)) err = true;
+ break;
+ }
+ if (rbuf != stack) TCFREE(rbuf);
}
- }
- return !err;
+ tcmapiterinit(cols);
+ const char *kbuf;
+ int ksiz;
+ while ((kbuf = tcmapiternext(cols, &ksiz)) != NULL) {
+ int vsiz;
+ const char *vbuf = tcmapiterval(kbuf, &vsiz);
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ if (strcmp(idx->name, kbuf)) continue;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ if (!tctdbidxputone(tdb, idx, pkbuf, pksiz, hash, vbuf, vsiz)) err = true;
+ break;
+ case TDBITTOKEN:
+ {
+ TCLIST *tokens = tclistload(vbuf, vsiz);
+ if (!tctdbidxputtoken2(tdb, idx, pkbuf, pksiz, tokens)) err = true;
+ tclistdel(tokens);
+ break;
+ }
+ case TDBITQGRAM:
+ if (!tctdbidxputqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
+ break;
+ }
+ }
+ }
+ return !err;
}
/* Add a column of a record into an index of a table database object.
`vsiz' specifies the size of the region of the column value.
If successful, the return value is true, else, it is false. */
static bool tctdbidxputone(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz, uint16_t hash,
- const char *vbuf, int vsiz){
- assert(tdb && pkbuf && pksiz >= 0 && vbuf && vsiz);
- bool err = false;
- char stack[TDBCOLBUFSIZ], *rbuf;
- int rsiz = vsiz + 3;
- if(rsiz <= sizeof(stack)){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, rsiz);
- }
- memcpy(rbuf, vbuf, vsiz);
- rbuf[vsiz] = '\0';
- rbuf[vsiz+1] = hash >> 8;
- rbuf[vsiz+2] = hash & 0xff;
- if(!tcbdbputdup(idx->db, rbuf, rsiz, pkbuf, pksiz)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- if(rbuf != stack) TCFREE(rbuf);
- return !err;
+ const char *vbuf, int vsiz) {
+ assert(tdb && pkbuf && pksiz >= 0 && vbuf && vsiz);
+ bool err = false;
+ char stack[TDBCOLBUFSIZ], *rbuf;
+ int rsiz = vsiz + 3;
+ if (rsiz <= sizeof (stack)) {
+ rbuf = stack;
+ } else {
+ TCMALLOC(rbuf, rsiz);
+ }
+ memcpy(rbuf, vbuf, vsiz);
+ rbuf[vsiz] = '\0';
+ rbuf[vsiz + 1] = hash >> 8;
+ rbuf[vsiz + 2] = hash & 0xff;
+ if (!tcbdbputdup(idx->db, rbuf, rsiz, pkbuf, pksiz)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ if (rbuf != stack) TCFREE(rbuf);
+ return !err;
}
-
/* Add a column of a record into an token inverted index of a table database object.
`tdb' specifies the table database object.
`idx' specifies the index object.
`vsiz' specifies the size of the region of the column value.
If successful, the return value is true, else, it is false. */
static bool tctdbidxputtoken(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz,
- const char *vbuf, int vsiz){
- assert(tdb && idx && pkbuf && pksiz >= 0 && vbuf && vsiz >= 0);
- bool err = false;
- TCMAP *cc = idx->cc;
- char stack[TDBCOLBUFSIZ], *rbuf;
- int rsiz = pksiz + TCNUMBUFSIZ;
- if(rsiz < sizeof(stack)){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, rsiz);
- }
- uint64_t pkid = 0;
- for(int i = 0; i < pksiz; i++){
- int c = pkbuf[i];
- if(c >= '0' && c <= '9'){
- pkid = pkid * 10 + c - '0';
- if(pkid > INT64_MAX){
- pkid = 0;
- break;
- }
+ const char *vbuf, int vsiz) {
+ assert(tdb && idx && pkbuf && pksiz >= 0 && vbuf && vsiz >= 0);
+ bool err = false;
+ TCMAP *cc = idx->cc;
+ char stack[TDBCOLBUFSIZ], *rbuf;
+ int rsiz = pksiz + TCNUMBUFSIZ;
+ if (rsiz < sizeof (stack)) {
+ rbuf = stack;
+ } else {
+ TCMALLOC(rbuf, rsiz);
+ }
+ uint64_t pkid = 0;
+ for (int i = 0; i < pksiz; i++) {
+ int c = pkbuf[i];
+ if (c >= '0' && c <= '9') {
+ pkid = pkid * 10 + c - '0';
+ if (pkid > INT64_MAX) {
+ pkid = 0;
+ break;
+ }
+ } else {
+ pkid = 0;
+ break;
+ }
+ }
+ if (pksiz > 0 && *pkbuf == '0') pkid = 0;
+ if (pkid > 0) {
+ TCSETVNUMBUF64(rsiz, rbuf, pkid);
} else {
- pkid = 0;
- break;
- }
- }
- if(pksiz > 0 && *pkbuf == '0') pkid = 0;
- if(pkid > 0){
- TCSETVNUMBUF64(rsiz, rbuf, pkid);
- } else {
- char *wp = rbuf;
- *(wp++) = '\0';
- TCSETVNUMBUF(rsiz, wp, pksiz);
- wp += rsiz;
- memcpy(wp, pkbuf, pksiz);
- wp += pksiz;
- rsiz = wp - rbuf;
- }
- const unsigned char *sp = (unsigned char *)vbuf;
- while(*sp != '\0'){
- while((*sp != '\0' && *sp <= ' ') || *sp == ','){
- sp++;
- }
- const unsigned char *ep = sp;
- while(*ep > ' ' && *ep != ','){
- ep++;
-}
- if(ep > sp) tcmapputcat3(cc, sp, ep - sp, rbuf, rsiz);
- sp = ep;
- }
- if(rbuf != stack) TCFREE(rbuf);
- if(tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
- return !err;
+ char *wp = rbuf;
+ *(wp++) = '\0';
+ TCSETVNUMBUF(rsiz, wp, pksiz);
+ wp += rsiz;
+ memcpy(wp, pkbuf, pksiz);
+ wp += pksiz;
+ rsiz = wp - rbuf;
+ }
+ const unsigned char *sp = (unsigned char *) vbuf;
+ while (*sp != '\0') {
+ while ((*sp != '\0' && *sp <= ' ') || *sp == ',') {
+ sp++;
+ }
+ const unsigned char *ep = sp;
+ while (*ep > ' ' && *ep != ',') {
+ ep++;
+ }
+ if (ep > sp) tcmapputcat3(cc, sp, ep - sp, rbuf, rsiz);
+ sp = ep;
+ }
+ if (rbuf != stack) TCFREE(rbuf);
+ if (tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
+ return !err;
}
-
static bool tctdbidxputtoken2(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz,
- TCLIST *tokens){
- assert(tdb && idx && pkbuf && pksiz >= 0 && tokens);
- bool err = false;
- TCMAP *cc = idx->cc;
- char stack[TDBCOLBUFSIZ], *rbuf;
- int rsiz = pksiz + TCNUMBUFSIZ;
- if(rsiz < sizeof(stack)){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, rsiz);
- }
- uint64_t pkid = 0;
- for(int i = 0; i < pksiz; i++){
- int c = pkbuf[i];
- if(c >= '0' && c <= '9'){
- pkid = pkid * 10 + c - '0';
- if(pkid > INT64_MAX){
- pkid = 0;
- break;
- }
+ TCLIST *tokens) {
+ assert(tdb && idx && pkbuf && pksiz >= 0 && tokens);
+ bool err = false;
+ TCMAP *cc = idx->cc;
+ char stack[TDBCOLBUFSIZ], *rbuf;
+ int rsiz = pksiz + TCNUMBUFSIZ;
+ if (rsiz < sizeof (stack)) {
+ rbuf = stack;
+ } else {
+ TCMALLOC(rbuf, rsiz);
+ }
+ uint64_t pkid = 0;
+ for (int i = 0; i < pksiz; i++) {
+ int c = pkbuf[i];
+ if (c >= '0' && c <= '9') {
+ pkid = pkid * 10 + c - '0';
+ if (pkid > INT64_MAX) {
+ pkid = 0;
+ break;
+ }
+ } else {
+ pkid = 0;
+ break;
+ }
+ }
+ if (pksiz > 0 && *pkbuf == '0') pkid = 0;
+ if (pkid > 0) {
+ TCSETVNUMBUF64(rsiz, rbuf, pkid);
} else {
- pkid = 0;
- break;
+ char *wp = rbuf;
+ *(wp++) = '\0';
+ TCSETVNUMBUF(rsiz, wp, pksiz);
+ wp += rsiz;
+ memcpy(wp, pkbuf, pksiz);
+ wp += pksiz;
+ rsiz = wp - rbuf;
}
- }
- if(pksiz > 0 && *pkbuf == '0') pkid = 0;
- if(pkid > 0){
- TCSETVNUMBUF64(rsiz, rbuf, pkid);
- } else {
- char *wp = rbuf;
- *(wp++) = '\0';
- TCSETVNUMBUF(rsiz, wp, pksiz);
- wp += rsiz;
- memcpy(wp, pkbuf, pksiz);
- wp += pksiz;
- rsiz = wp - rbuf;
- }
- for (int i = 0; i < TCLISTNUM(tokens); ++i) {
- tcmapputcat3(cc, TCLISTVALPTR(tokens, i), TCLISTVALSIZ(tokens, i), rbuf, rsiz);
- }
+ for (int i = 0; i < TCLISTNUM(tokens); ++i) {
+ tcmapputcat3(cc, TCLISTVALPTR(tokens, i), TCLISTVALSIZ(tokens, i), rbuf, rsiz);
+ }
- if(rbuf != stack) TCFREE(rbuf);
- if(tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
- return !err;
+ if (rbuf != stack) TCFREE(rbuf);
+ if (tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
+ return !err;
}
-
-
/* Add a column of a record into an q-gram inverted index of a table database object.
`tdb' specifies the table database object.
`idx' specifies the index object.
`vsiz' specifies the size of the region of the column value.
If successful, the return value is true, else, it is false. */
static bool tctdbidxputqgram(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz,
- const char *vbuf, int vsiz){
- assert(tdb && idx && pkbuf && pksiz >= 0 && vbuf && vsiz >= 0);
- bool err = false;
- TCMAP *cc = idx->cc;
- char stack[TDBCOLBUFSIZ], *rbuf;
- int rsiz = pksiz + TCNUMBUFSIZ * 2;
- if(rsiz < sizeof(stack)){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, rsiz);
- }
- uint64_t pkid = 0;
- for(int i = 0; i < pksiz; i++){
- int c = pkbuf[i];
- if(c >= '0' && c <= '9'){
- pkid = pkid * 10 + c - '0';
- if(pkid > INT64_MAX){
- pkid = 0;
- break;
- }
+ const char *vbuf, int vsiz) {
+ assert(tdb && idx && pkbuf && pksiz >= 0 && vbuf && vsiz >= 0);
+ bool err = false;
+ TCMAP *cc = idx->cc;
+ char stack[TDBCOLBUFSIZ], *rbuf;
+ int rsiz = pksiz + TCNUMBUFSIZ * 2;
+ if (rsiz < sizeof (stack)) {
+ rbuf = stack;
+ } else {
+ TCMALLOC(rbuf, rsiz);
+ }
+ uint64_t pkid = 0;
+ for (int i = 0; i < pksiz; i++) {
+ int c = pkbuf[i];
+ if (c >= '0' && c <= '9') {
+ pkid = pkid * 10 + c - '0';
+ if (pkid > INT64_MAX) {
+ pkid = 0;
+ break;
+ }
+ } else {
+ pkid = 0;
+ break;
+ }
+ }
+ if (pksiz > 0 && *pkbuf == '0') pkid = 0;
+ if (pkid > 0) {
+ TCSETVNUMBUF64(rsiz, rbuf, pkid);
} else {
- pkid = 0;
- break;
- }
- }
- if(pksiz > 0 && *pkbuf == '0') pkid = 0;
- if(pkid > 0){
- TCSETVNUMBUF64(rsiz, rbuf, pkid);
- } else {
- char *wp = rbuf;
- *(wp++) = '\0';
- TCSETVNUMBUF(rsiz, wp, pksiz);
- wp += rsiz;
- memcpy(wp, pkbuf, pksiz);
- wp += pksiz;
- rsiz = wp - rbuf;
- }
- uint16_t *ary;
- TCMALLOC(ary, sizeof(*ary) * (vsiz + TDBIDXQGUNIT));
- int anum;
- tcstrutftoucs(vbuf, ary, &anum);
- anum = tcstrucsnorm(ary, anum, TCUNSPACE | TCUNLOWER | TCUNNOACC | TCUNWIDTH);
- for(int i = 0; i < TDBIDXQGUNIT; i++){
- ary[anum+i] = 0;
- }
- char *wp = rbuf + rsiz;
- char token[TDBIDXQGUNIT*3+1];
- for(int i = 0; i < anum; i++){
- tcstrucstoutf(ary + i, TDBIDXQGUNIT, token);
- int step;
- TCSETVNUMBUF(step, wp, i);
- tcmapputcat3(cc, token, strlen(token), rbuf, rsiz + step);
- }
- TCFREE(ary);
- if(rbuf != stack) TCFREE(rbuf);
- if(tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
- return !err;
+ char *wp = rbuf;
+ *(wp++) = '\0';
+ TCSETVNUMBUF(rsiz, wp, pksiz);
+ wp += rsiz;
+ memcpy(wp, pkbuf, pksiz);
+ wp += pksiz;
+ rsiz = wp - rbuf;
+ }
+ uint16_t *ary;
+ TCMALLOC(ary, sizeof (*ary) * (vsiz + TDBIDXQGUNIT));
+ int anum;
+ tcstrutftoucs(vbuf, ary, &anum);
+ anum = tcstrucsnorm(ary, anum, TCUNSPACE | TCUNLOWER | TCUNNOACC | TCUNWIDTH);
+ for (int i = 0; i < TDBIDXQGUNIT; i++) {
+ ary[anum + i] = 0;
+ }
+ char *wp = rbuf + rsiz;
+ char token[TDBIDXQGUNIT * 3 + 1];
+ for (int i = 0; i < anum; i++) {
+ tcstrucstoutf(ary + i, TDBIDXQGUNIT, token);
+ int step;
+ TCSETVNUMBUF(step, wp, i);
+ tcmapputcat3(cc, token, strlen(token), rbuf, rsiz + step);
+ }
+ TCFREE(ary);
+ if (rbuf != stack) TCFREE(rbuf);
+ if (tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
+ return !err;
}
-
/* Remove a record from indices of a table database object.
`tdb' specifies the table database object.
`pkbuf' specifies the pointer to the region of the primary key.
`pksiz' specifies the size of the region of the primary key.
`cols' specifies a map object containing columns.
If successful, the return value is true, else, it is false. */
-bool tctdbidxout(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols){
- assert(tdb && pkbuf && pksiz >= 0 && cols);
- bool err = false;
- uint16_t hash = tctdbidxhash(pkbuf, pksiz);
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- if(*(idx->name) != '\0') continue;
- char stack[TDBCOLBUFSIZ], *rbuf;
- if(pksiz < sizeof(stack)){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, pksiz + 1);
- }
- memcpy(rbuf, pkbuf, pksiz);
- rbuf[pksiz] = '\0';
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- if(!tcbdbout(idx->db, pkbuf, pksiz)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- case TDBITTOKEN:
- if(!tctdbidxouttoken(tdb, idx, pkbuf, pksiz, rbuf, pksiz)) err = true;
- break;
- case TDBITQGRAM:
- if(!tctdbidxoutqgram(tdb, idx, pkbuf, pksiz, rbuf, pksiz)) err = true;
- break;
- }
- if(rbuf != stack) TCFREE(rbuf);
- }
- tcmapiterinit(cols);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){
- int vsiz;
- const char *vbuf = tcmapiterval(kbuf, &vsiz);
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- if(strcmp(idx->name, kbuf)) continue;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- if(!tctdbidxoutone(tdb, idx, pkbuf, pksiz, hash, vbuf, vsiz)) err = true;
- break;
- case TDBITTOKEN:
- if(!tctdbidxouttoken(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
- break;
- case TDBITQGRAM:
- if(!tctdbidxoutqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
- break;
- }
- }
- }
- return !err;
-}
-
-bool tctdbidxout2(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols){
- assert(tdb && pkbuf && pksiz >= 0 && cols);
- bool err = false;
- uint16_t hash = tctdbidxhash(pkbuf, pksiz);
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- if(*(idx->name) != '\0') continue;
- char stack[TDBCOLBUFSIZ], *rbuf;
- if(pksiz < sizeof(stack)){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, pksiz + 1);
- }
- memcpy(rbuf, pkbuf, pksiz);
- rbuf[pksiz] = '\0';
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- if(!tcbdbout(idx->db, pkbuf, pksiz)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- case TDBITTOKEN:
- if(!tctdbidxouttoken(tdb, idx, pkbuf, pksiz, rbuf, pksiz)) err = true;
- break;
- case TDBITQGRAM:
- if(!tctdbidxoutqgram(tdb, idx, pkbuf, pksiz, rbuf, pksiz)) err = true;
- break;
- }
- if(rbuf != stack) TCFREE(rbuf);
- }
- tcmapiterinit(cols);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){
- int vsiz;
- const char *vbuf = tcmapiterval(kbuf, &vsiz);
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- if(strcmp(idx->name, kbuf)) continue;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- if(!tctdbidxoutone(tdb, idx, pkbuf, pksiz, hash, vbuf, vsiz)) err = true;
- break;
- case TDBITTOKEN:
- {
- TCLIST *tokens = tclistload(vbuf, vsiz);
- if(!tctdbidxouttoken2(tdb, idx, pkbuf, pksiz, tokens)) err = true;
- tclistdel(tokens);
- break;
+bool tctdbidxout(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols) {
+ assert(tdb && pkbuf && pksiz >= 0 && cols);
+ bool err = false;
+ uint16_t hash = tctdbidxhash(pkbuf, pksiz);
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ if (*(idx->name) != '\0') continue;
+ char stack[TDBCOLBUFSIZ], *rbuf;
+ if (pksiz < sizeof (stack)) {
+ rbuf = stack;
+ } else {
+ TCMALLOC(rbuf, pksiz + 1);
+ }
+ memcpy(rbuf, pkbuf, pksiz);
+ rbuf[pksiz] = '\0';
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ if (!tcbdbout(idx->db, pkbuf, pksiz)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ case TDBITTOKEN:
+ if (!tctdbidxouttoken(tdb, idx, pkbuf, pksiz, rbuf, pksiz)) err = true;
+ break;
+ case TDBITQGRAM:
+ if (!tctdbidxoutqgram(tdb, idx, pkbuf, pksiz, rbuf, pksiz)) err = true;
+ break;
+ }
+ if (rbuf != stack) TCFREE(rbuf);
+ }
+ tcmapiterinit(cols);
+ const char *kbuf;
+ int ksiz;
+ while ((kbuf = tcmapiternext(cols, &ksiz)) != NULL) {
+ int vsiz;
+ const char *vbuf = tcmapiterval(kbuf, &vsiz);
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ if (strcmp(idx->name, kbuf)) continue;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ if (!tctdbidxoutone(tdb, idx, pkbuf, pksiz, hash, vbuf, vsiz)) err = true;
+ break;
+ case TDBITTOKEN:
+ if (!tctdbidxouttoken(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
+ break;
+ case TDBITQGRAM:
+ if (!tctdbidxoutqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
+ break;
+ }
+ }
+ }
+ return !err;
+}
+
+bool tctdbidxout2(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols) {
+ assert(tdb && pkbuf && pksiz >= 0 && cols);
+ bool err = false;
+ uint16_t hash = tctdbidxhash(pkbuf, pksiz);
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ if (*(idx->name) != '\0') continue;
+ char stack[TDBCOLBUFSIZ], *rbuf;
+ if (pksiz < sizeof (stack)) {
+ rbuf = stack;
+ } else {
+ TCMALLOC(rbuf, pksiz + 1);
+ }
+ memcpy(rbuf, pkbuf, pksiz);
+ rbuf[pksiz] = '\0';
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ if (!tcbdbout(idx->db, pkbuf, pksiz)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ case TDBITTOKEN:
+ if (!tctdbidxouttoken(tdb, idx, pkbuf, pksiz, rbuf, pksiz)) err = true;
+ break;
+ case TDBITQGRAM:
+ if (!tctdbidxoutqgram(tdb, idx, pkbuf, pksiz, rbuf, pksiz)) err = true;
+ break;
+ }
+ if (rbuf != stack) TCFREE(rbuf);
+ }
+ tcmapiterinit(cols);
+ const char *kbuf;
+ int ksiz;
+ while ((kbuf = tcmapiternext(cols, &ksiz)) != NULL) {
+ int vsiz;
+ const char *vbuf = tcmapiterval(kbuf, &vsiz);
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ if (strcmp(idx->name, kbuf)) continue;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ if (!tctdbidxoutone(tdb, idx, pkbuf, pksiz, hash, vbuf, vsiz)) err = true;
+ break;
+ case TDBITTOKEN:
+ {
+ TCLIST *tokens = tclistload(vbuf, vsiz);
+ if (!tctdbidxouttoken2(tdb, idx, pkbuf, pksiz, tokens)) err = true;
+ tclistdel(tokens);
+ break;
+ }
+ case TDBITQGRAM:
+ if (!tctdbidxoutqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
+ break;
+ }
}
- case TDBITQGRAM:
- if(!tctdbidxoutqgram(tdb, idx, pkbuf, pksiz, vbuf, vsiz)) err = true;
- break;
- }
}
- }
- return !err;
+ return !err;
}
/* Remove a column of a record from an index of a table database object.
`vsiz' specifies the size of the region of the column value.
If successful, the return value is true, else, it is false. */
static bool tctdbidxoutone(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz, uint16_t hash,
- const char *vbuf, int vsiz){
- assert(tdb && idx && pkbuf && pksiz >= 0 && vbuf && vsiz >= 0);
- bool err = false;
- char stack[TDBCOLBUFSIZ], *rbuf;
- int rsiz = vsiz + 3;
- if(rsiz <= sizeof(stack)){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, rsiz);
- }
- memcpy(rbuf, vbuf, vsiz);
- rbuf[vsiz] = '\0';
- rbuf[vsiz+1] = hash >> 8;
- rbuf[vsiz+2] = hash & 0xff;
- int ovsiz;
- const char *ovbuf = tcbdbget3(idx->db, rbuf, rsiz, &ovsiz);
- if(ovbuf && ovsiz == pksiz && !memcmp(ovbuf, pkbuf, ovsiz)){
- if(!tcbdbout(idx->db, rbuf, rsiz)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- } else {
- BDBCUR *cur = tcbdbcurnew(idx->db);
- if(tcbdbcurjump(cur, rbuf, rsiz)){
- int oksiz;
- const char *okbuf;
- while((okbuf = tcbdbcurkey3(cur, &oksiz)) != NULL){
- if(oksiz != rsiz || memcmp(okbuf, rbuf, oksiz)) break;
- ovbuf = tcbdbcurval3(cur, &ovsiz);
- if(ovsiz == pksiz && !memcmp(ovbuf, pkbuf, ovsiz)){
- if(!tcbdbcurout(cur)){
+ const char *vbuf, int vsiz) {
+ assert(tdb && idx && pkbuf && pksiz >= 0 && vbuf && vsiz >= 0);
+ bool err = false;
+ char stack[TDBCOLBUFSIZ], *rbuf;
+ int rsiz = vsiz + 3;
+ if (rsiz <= sizeof (stack)) {
+ rbuf = stack;
+ } else {
+ TCMALLOC(rbuf, rsiz);
+ }
+ memcpy(rbuf, vbuf, vsiz);
+ rbuf[vsiz] = '\0';
+ rbuf[vsiz + 1] = hash >> 8;
+ rbuf[vsiz + 2] = hash & 0xff;
+ int ovsiz;
+ const char *ovbuf = tcbdbget3(idx->db, rbuf, rsiz, &ovsiz);
+ if (ovbuf && ovsiz == pksiz && !memcmp(ovbuf, pkbuf, ovsiz)) {
+ if (!tcbdbout(idx->db, rbuf, rsiz)) {
tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
err = true;
- }
- break;
}
- tcbdbcurnext(cur);
- }
} else {
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
+ BDBCUR *cur = tcbdbcurnew(idx->db);
+ if (tcbdbcurjump(cur, rbuf, rsiz)) {
+ int oksiz;
+ const char *okbuf;
+ while ((okbuf = tcbdbcurkey3(cur, &oksiz)) != NULL) {
+ if (oksiz != rsiz || memcmp(okbuf, rbuf, oksiz)) break;
+ ovbuf = tcbdbcurval3(cur, &ovsiz);
+ if (ovsiz == pksiz && !memcmp(ovbuf, pkbuf, ovsiz)) {
+ if (!tcbdbcurout(cur)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ }
+ tcbdbcurnext(cur);
+ }
+ } else {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ tcbdbcurdel(cur);
}
- tcbdbcurdel(cur);
- }
- if(rbuf != stack) TCFREE(rbuf);
- return !err;
+ if (rbuf != stack) TCFREE(rbuf);
+ return !err;
}
-
/* Remove a column of a record from a token inverted index of a table database object.
`tdb' specifies the table database object.
`idx' specifies the index object.
`vsiz' specifies the size of the region of the column value.
If successful, the return value is true, else, it is false. */
static bool tctdbidxouttoken(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz,
- const char *vbuf, int vsiz){
- assert(tdb && idx && pkbuf && pksiz >= 0 && vbuf && vsiz >= 0);
- bool err = false;
- TCBDB *db = idx->db;
- TCMAP *cc = idx->cc;
- uint64_t pkid = 0;
- for(int i = 0; i < pksiz; i++){
- int c = pkbuf[i];
- if(c >= '0' && c <= '9'){
- pkid = pkid * 10 + c - '0';
- if(pkid > INT64_MAX){
- pkid = 0;
- break;
- }
- } else {
- pkid = 0;
- break;
- }
- }
- TCXSTR *xstr = tcxstrnew();
- const unsigned char *sp = (unsigned char *)vbuf;
- while(*sp != '\0'){
- while((*sp != '\0' && *sp <= ' ') || *sp == ','){
- sp++;
- }
- const unsigned char *ep = sp;
- while(*ep > ' ' && *ep != ','){
- ep++;
- }
- if(ep > sp){
- tcxstrclear(xstr);
- int len = ep - sp;
- int csiz;
- const char *cbuf = tcmapget(cc, sp, len, &csiz);
- if(cbuf){
- while(csiz > 0){
- const char *pv = cbuf;
- bool ok = true;
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int tsiz, step;
- TCREADVNUMBUF(cbuf, tsiz, step);
- cbuf += step;
- csiz -= step;
- if(tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
- cbuf += tsiz;
- csiz -= tsiz;
- } else {
- int64_t tid;
- int step;
- TCREADVNUMBUF64(cbuf, tid, step);
- if(tid == pkid) ok = false;
- cbuf += step;
- csiz -= step;
- }
- if(ok) TCXSTRCAT(xstr, pv, cbuf - pv);
- }
- if(csiz != 0){
- tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
- err = true;
- }
- }
- cbuf = tcbdbget3(db, sp, len, &csiz);
- if(cbuf){
- while(csiz > 0){
- const char *pv = cbuf;
- bool ok = true;
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int tsiz, step;
- TCREADVNUMBUF(cbuf, tsiz, step);
- cbuf += step;
- csiz -= step;
- if(tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
- cbuf += tsiz;
- csiz -= tsiz;
- } else {
- int64_t tid;
- int step;
- TCREADVNUMBUF64(cbuf, tid, step);
- if(tid == pkid) ok = false;
- cbuf += step;
- csiz -= step;
- }
- if(ok) TCXSTRCAT(xstr, pv, cbuf - pv);
- }
- if(csiz != 0){
- tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
- err = true;
- }
- if(!tcbdbout(db, sp, len)){
- tctdbsetecode(tdb, tcbdbecode(db), __FILE__, __LINE__, __func__);
- err = true;
- }
- }
- tcmapput(cc, sp, len, TCXSTRPTR(xstr), TCXSTRSIZE(xstr));
- }
- sp = ep;
- }
- tcxstrdel(xstr);
- if(tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
- return !err;
+ const char *vbuf, int vsiz) {
+ assert(tdb && idx && pkbuf && pksiz >= 0 && vbuf && vsiz >= 0);
+ bool err = false;
+ TCBDB *db = idx->db;
+ TCMAP *cc = idx->cc;
+ uint64_t pkid = 0;
+ for (int i = 0; i < pksiz; i++) {
+ int c = pkbuf[i];
+ if (c >= '0' && c <= '9') {
+ pkid = pkid * 10 + c - '0';
+ if (pkid > INT64_MAX) {
+ pkid = 0;
+ break;
+ }
+ } else {
+ pkid = 0;
+ break;
+ }
+ }
+ TCXSTR *xstr = tcxstrnew();
+ const unsigned char *sp = (unsigned char *) vbuf;
+ while (*sp != '\0') {
+ while ((*sp != '\0' && *sp <= ' ') || *sp == ',') {
+ sp++;
+ }
+ const unsigned char *ep = sp;
+ while (*ep > ' ' && *ep != ',') {
+ ep++;
+ }
+ if (ep > sp) {
+ tcxstrclear(xstr);
+ int len = ep - sp;
+ int csiz;
+ const char *cbuf = tcmapget(cc, sp, len, &csiz);
+ if (cbuf) {
+ while (csiz > 0) {
+ const char *pv = cbuf;
+ bool ok = true;
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int tsiz, step;
+ TCREADVNUMBUF(cbuf, tsiz, step);
+ cbuf += step;
+ csiz -= step;
+ if (tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
+ cbuf += tsiz;
+ csiz -= tsiz;
+ } else {
+ int64_t tid;
+ int step;
+ TCREADVNUMBUF64(cbuf, tid, step);
+ if (tid == pkid) ok = false;
+ cbuf += step;
+ csiz -= step;
+ }
+ if (ok) TCXSTRCAT(xstr, pv, cbuf - pv);
+ }
+ if (csiz != 0) {
+ tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ }
+ cbuf = tcbdbget3(db, sp, len, &csiz);
+ if (cbuf) {
+ while (csiz > 0) {
+ const char *pv = cbuf;
+ bool ok = true;
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int tsiz, step;
+ TCREADVNUMBUF(cbuf, tsiz, step);
+ cbuf += step;
+ csiz -= step;
+ if (tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
+ cbuf += tsiz;
+ csiz -= tsiz;
+ } else {
+ int64_t tid;
+ int step;
+ TCREADVNUMBUF64(cbuf, tid, step);
+ if (tid == pkid) ok = false;
+ cbuf += step;
+ csiz -= step;
+ }
+ if (ok) TCXSTRCAT(xstr, pv, cbuf - pv);
+ }
+ if (csiz != 0) {
+ tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ if (!tcbdbout(db, sp, len)) {
+ tctdbsetecode(tdb, tcbdbecode(db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ }
+ tcmapput(cc, sp, len, TCXSTRPTR(xstr), TCXSTRSIZE(xstr));
+ }
+ sp = ep;
+ }
+ tcxstrdel(xstr);
+ if (tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
+ return !err;
}
static bool tctdbidxouttoken2(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz,
- TCLIST *tokens){
- assert(tdb && idx && pkbuf && pksiz >= 0 && tokens);
- bool err = false;
- TCBDB *db = idx->db;
- TCMAP *cc = idx->cc;
- uint64_t pkid = 0;
- for(int i = 0; i < pksiz; i++){
- int c = pkbuf[i];
- if(c >= '0' && c <= '9'){
- pkid = pkid * 10 + c - '0';
- if(pkid > INT64_MAX){
- pkid = 0;
- break;
- }
- } else {
- pkid = 0;
- break;
- }
- }
- TCXSTR *xstr = tcxstrnew();
- for (int i = 0; i < TCLISTNUM(tokens); ++i) {
- int csiz;
- const unsigned char *sp = TCLISTVALPTR(tokens, i);
- int len = TCLISTVALSIZ(tokens, i);
- tcxstrclear(xstr);
- const char *cbuf = tcmapget(cc, sp, len, &csiz);
- if(cbuf){
- while(csiz > 0){
- const char *pv = cbuf;
- bool ok = true;
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int tsiz, step;
- TCREADVNUMBUF(cbuf, tsiz, step);
- cbuf += step;
- csiz -= step;
- if(tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
- cbuf += tsiz;
- csiz -= tsiz;
- } else {
- int64_t tid;
- int step;
- TCREADVNUMBUF64(cbuf, tid, step);
- if(tid == pkid) ok = false;
- cbuf += step;
- csiz -= step;
- }
- if(ok) TCXSTRCAT(xstr, pv, cbuf - pv);
- }
- if(csiz != 0){
- tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
- err = true;
- }
- }
- cbuf = tcbdbget3(db, sp, len, &csiz);
- if(cbuf){
- while(csiz > 0){
- const char *pv = cbuf;
- bool ok = true;
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int tsiz, step;
- TCREADVNUMBUF(cbuf, tsiz, step);
- cbuf += step;
- csiz -= step;
- if(tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
- cbuf += tsiz;
- csiz -= tsiz;
- } else {
- int64_t tid;
- int step;
- TCREADVNUMBUF64(cbuf, tid, step);
- if(tid == pkid) ok = false;
- cbuf += step;
- csiz -= step;
- }
- if(ok) TCXSTRCAT(xstr, pv, cbuf - pv);
- }
- if(csiz != 0){
- tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
- err = true;
- }
- if(!tcbdbout(db, sp, len)){
- tctdbsetecode(tdb, tcbdbecode(db), __FILE__, __LINE__, __func__);
- err = true;
- }
- }
- tcmapput(cc, sp, len, TCXSTRPTR(xstr), TCXSTRSIZE(xstr));
- }
- tcxstrdel(xstr);
- if(tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
- return !err;
+ TCLIST *tokens) {
+ assert(tdb && idx && pkbuf && pksiz >= 0 && tokens);
+ bool err = false;
+ TCBDB *db = idx->db;
+ TCMAP *cc = idx->cc;
+ uint64_t pkid = 0;
+ for (int i = 0; i < pksiz; i++) {
+ int c = pkbuf[i];
+ if (c >= '0' && c <= '9') {
+ pkid = pkid * 10 + c - '0';
+ if (pkid > INT64_MAX) {
+ pkid = 0;
+ break;
+ }
+ } else {
+ pkid = 0;
+ break;
+ }
+ }
+ TCXSTR *xstr = tcxstrnew();
+ for (int i = 0; i < TCLISTNUM(tokens); ++i) {
+ int csiz;
+ const unsigned char *sp = TCLISTVALPTR(tokens, i);
+ int len = TCLISTVALSIZ(tokens, i);
+ tcxstrclear(xstr);
+ const char *cbuf = tcmapget(cc, sp, len, &csiz);
+ if (cbuf) {
+ while (csiz > 0) {
+ const char *pv = cbuf;
+ bool ok = true;
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int tsiz, step;
+ TCREADVNUMBUF(cbuf, tsiz, step);
+ cbuf += step;
+ csiz -= step;
+ if (tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
+ cbuf += tsiz;
+ csiz -= tsiz;
+ } else {
+ int64_t tid;
+ int step;
+ TCREADVNUMBUF64(cbuf, tid, step);
+ if (tid == pkid) ok = false;
+ cbuf += step;
+ csiz -= step;
+ }
+ if (ok) TCXSTRCAT(xstr, pv, cbuf - pv);
+ }
+ if (csiz != 0) {
+ tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ }
+ cbuf = tcbdbget3(db, sp, len, &csiz);
+ if (cbuf) {
+ while (csiz > 0) {
+ const char *pv = cbuf;
+ bool ok = true;
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int tsiz, step;
+ TCREADVNUMBUF(cbuf, tsiz, step);
+ cbuf += step;
+ csiz -= step;
+ if (tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
+ cbuf += tsiz;
+ csiz -= tsiz;
+ } else {
+ int64_t tid;
+ int step;
+ TCREADVNUMBUF64(cbuf, tid, step);
+ if (tid == pkid) ok = false;
+ cbuf += step;
+ csiz -= step;
+ }
+ if (ok) TCXSTRCAT(xstr, pv, cbuf - pv);
+ }
+ if (csiz != 0) {
+ tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ if (!tcbdbout(db, sp, len)) {
+ tctdbsetecode(tdb, tcbdbecode(db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ }
+ tcmapput(cc, sp, len, TCXSTRPTR(xstr), TCXSTRSIZE(xstr));
+ }
+ tcxstrdel(xstr);
+ if (tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
+ return !err;
}
/* Remove a column of a record from a q-gram inverted index of a table database object.
`vsiz' specifies the size of the region of the column value.
If successful, the return value is true, else, it is false. */
static bool tctdbidxoutqgram(TCTDB *tdb, TDBIDX *idx, const char *pkbuf, int pksiz,
- const char *vbuf, int vsiz){
- assert(tdb && idx && pkbuf && pksiz >= 0 && vbuf && vsiz >= 0);
- bool err = false;
- TCBDB *db = idx->db;
- TCMAP *cc = idx->cc;
- uint64_t pkid = 0;
- for(int i = 0; i < pksiz; i++){
- int c = pkbuf[i];
- if(c >= '0' && c <= '9'){
- pkid = pkid * 10 + c - '0';
- if(pkid > INT64_MAX){
- pkid = 0;
- break;
- }
- } else {
- pkid = 0;
- break;
- }
- }
- TCXSTR *xstr = tcxstrnew();
- uint16_t *ary;
- TCMALLOC(ary, sizeof(*ary) * (vsiz + TDBIDXQGUNIT));
- int anum;
- tcstrutftoucs(vbuf, ary, &anum);
- anum = tcstrucsnorm(ary, anum, TCUNSPACE | TCUNLOWER | TCUNNOACC | TCUNWIDTH);
- for(int i = 0; i < TDBIDXQGUNIT; i++){
- ary[anum+i] = 0;
- }
- char token[TDBIDXQGUNIT*3+1];
- for(int i = 0; i < anum; i++){
- tcstrucstoutf(ary + i, TDBIDXQGUNIT, token);
- int tsiz = strlen(token);
- tcxstrclear(xstr);
- int csiz;
- const char *cbuf = tcmapget(cc, token, tsiz, &csiz);
- if(cbuf){
- while(csiz > 0){
- const char *pv = cbuf;
- bool ok = true;
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int tsiz, step;
- TCREADVNUMBUF(cbuf, tsiz, step);
- cbuf += step;
- csiz -= step;
- if(tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
- cbuf += tsiz;
- csiz -= tsiz;
- } else {
- int64_t tid;
- int step;
- TCREADVNUMBUF64(cbuf, tid, step);
- if(tid == pkid) ok = false;
- cbuf += step;
- csiz -= step;
- }
- if(csiz > 0){
- int off, step;
- TCREADVNUMBUF(cbuf, off, step);
- cbuf += step;
- csiz -= step;
- if(ok) TCXSTRCAT(xstr, pv, cbuf - pv);
- }
- }
- if(csiz != 0){
- tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
- err = true;
- }
- }
- cbuf = tcbdbget3(db, token, tsiz, &csiz);
- if(cbuf){
- while(csiz > 0){
- const char *pv = cbuf;
- bool ok = true;
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int tsiz, step;
- TCREADVNUMBUF(cbuf, tsiz, step);
- cbuf += step;
- csiz -= step;
- if(tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
- cbuf += tsiz;
- csiz -= tsiz;
+ const char *vbuf, int vsiz) {
+ assert(tdb && idx && pkbuf && pksiz >= 0 && vbuf && vsiz >= 0);
+ bool err = false;
+ TCBDB *db = idx->db;
+ TCMAP *cc = idx->cc;
+ uint64_t pkid = 0;
+ for (int i = 0; i < pksiz; i++) {
+ int c = pkbuf[i];
+ if (c >= '0' && c <= '9') {
+ pkid = pkid * 10 + c - '0';
+ if (pkid > INT64_MAX) {
+ pkid = 0;
+ break;
+ }
} else {
- int64_t tid;
- int step;
- TCREADVNUMBUF64(cbuf, tid, step);
- if(tid == pkid) ok = false;
- cbuf += step;
- csiz -= step;
- }
- if(csiz > 0){
- int off, step;
- TCREADVNUMBUF(cbuf, off, step);
- cbuf += step;
- csiz -= step;
- if(ok) TCXSTRCAT(xstr, pv, cbuf - pv);
- }
- }
- if(csiz != 0){
- tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
- err = true;
- }
- if(!tcbdbout(db, token, tsiz)){
- tctdbsetecode(tdb, tcbdbecode(db), __FILE__, __LINE__, __func__);
- err = true;
- }
+ pkid = 0;
+ break;
+ }
+ }
+ TCXSTR *xstr = tcxstrnew();
+ uint16_t *ary;
+ TCMALLOC(ary, sizeof (*ary) * (vsiz + TDBIDXQGUNIT));
+ int anum;
+ tcstrutftoucs(vbuf, ary, &anum);
+ anum = tcstrucsnorm(ary, anum, TCUNSPACE | TCUNLOWER | TCUNNOACC | TCUNWIDTH);
+ for (int i = 0; i < TDBIDXQGUNIT; i++) {
+ ary[anum + i] = 0;
+ }
+ char token[TDBIDXQGUNIT * 3 + 1];
+ for (int i = 0; i < anum; i++) {
+ tcstrucstoutf(ary + i, TDBIDXQGUNIT, token);
+ int tsiz = strlen(token);
+ tcxstrclear(xstr);
+ int csiz;
+ const char *cbuf = tcmapget(cc, token, tsiz, &csiz);
+ if (cbuf) {
+ while (csiz > 0) {
+ const char *pv = cbuf;
+ bool ok = true;
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int tsiz, step;
+ TCREADVNUMBUF(cbuf, tsiz, step);
+ cbuf += step;
+ csiz -= step;
+ if (tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
+ cbuf += tsiz;
+ csiz -= tsiz;
+ } else {
+ int64_t tid;
+ int step;
+ TCREADVNUMBUF64(cbuf, tid, step);
+ if (tid == pkid) ok = false;
+ cbuf += step;
+ csiz -= step;
+ }
+ if (csiz > 0) {
+ int off, step;
+ TCREADVNUMBUF(cbuf, off, step);
+ cbuf += step;
+ csiz -= step;
+ if (ok) TCXSTRCAT(xstr, pv, cbuf - pv);
+ }
+ }
+ if (csiz != 0) {
+ tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ }
+ cbuf = tcbdbget3(db, token, tsiz, &csiz);
+ if (cbuf) {
+ while (csiz > 0) {
+ const char *pv = cbuf;
+ bool ok = true;
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int tsiz, step;
+ TCREADVNUMBUF(cbuf, tsiz, step);
+ cbuf += step;
+ csiz -= step;
+ if (tsiz == pksiz && !memcmp(cbuf, pkbuf, tsiz)) ok = false;
+ cbuf += tsiz;
+ csiz -= tsiz;
+ } else {
+ int64_t tid;
+ int step;
+ TCREADVNUMBUF64(cbuf, tid, step);
+ if (tid == pkid) ok = false;
+ cbuf += step;
+ csiz -= step;
+ }
+ if (csiz > 0) {
+ int off, step;
+ TCREADVNUMBUF(cbuf, off, step);
+ cbuf += step;
+ csiz -= step;
+ if (ok) TCXSTRCAT(xstr, pv, cbuf - pv);
+ }
+ }
+ if (csiz != 0) {
+ tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ if (!tcbdbout(db, token, tsiz)) {
+ tctdbsetecode(tdb, tcbdbecode(db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ }
+ tcmapput(cc, token, tsiz, TCXSTRPTR(xstr), TCXSTRSIZE(xstr));
}
- tcmapput(cc, token, tsiz, TCXSTRPTR(xstr), TCXSTRSIZE(xstr));
- }
- TCFREE(ary);
- tcxstrdel(xstr);
- if(tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
- return !err;
+ TCFREE(ary);
+ tcxstrdel(xstr);
+ if (tcmapmsiz(cc) > tdb->iccmax && !tctdbidxsyncicc(tdb, idx, false)) err = true;
+ return !err;
}
-
/* Synchronize updated contents of an inverted cache of a table database object.
`tdb' specifies the table database object.
`idx' specifies the index object.
`all' specifies whether to sync all tokens.
If successful, the return value is true, else, it is false. */
-static bool tctdbidxsyncicc(TCTDB *tdb, TDBIDX *idx, bool all){
- assert(tdb && idx);
- TCBDB *db = idx->db;
- TCMAP *cc = idx->cc;
- int rnum = TCMAPRNUM(cc);
- if(rnum < 1) return true;
- bool err = false;
- const char **keys;
- TCMALLOC(keys, sizeof(*keys) * rnum);
- int knum = 0;
- int64_t usiz = tcmapmsiz(cc) - sizeof(void *) * TDBIDXICCBNUM;
- int64_t max = all ? INT64_MAX : usiz * tdb->iccsync;
- int64_t sum = 0;
- const char *kbuf;
- int ksiz;
- tcmapiterinit(cc);
- while(sum < max && (kbuf = tcmapiternext(cc, &ksiz)) != NULL){
- int vsiz;
- tcmapiterval(kbuf, &vsiz);
- keys[knum++] = kbuf;
- sum += sizeof(TCMAPREC) + sizeof(void *) + ksiz + vsiz;
- }
- qsort(keys, knum, sizeof(*keys), (int(*)(const void *, const void *))tctdbidxcmpkey);
- for(int i = 0; i < knum; i++){
- const char *kbuf = keys[i];
- int ksiz = strlen(kbuf);
- int vsiz;
- const char *vbuf = tcmapget(cc, kbuf, ksiz, &vsiz);
- if(vsiz > 0 && !tcbdbputcat(db, kbuf, ksiz, vbuf, vsiz)){
- tctdbsetecode(tdb, tcbdbecode(db), __FILE__, __LINE__, __func__);
- err = true;
+static bool tctdbidxsyncicc(TCTDB *tdb, TDBIDX *idx, bool all) {
+ assert(tdb && idx);
+ TCBDB *db = idx->db;
+ TCMAP *cc = idx->cc;
+ int rnum = TCMAPRNUM(cc);
+ if (rnum < 1) return true;
+ bool err = false;
+ const char **keys;
+ TCMALLOC(keys, sizeof (*keys) * rnum);
+ int knum = 0;
+ int64_t usiz = tcmapmsiz(cc) - sizeof (void *) * TDBIDXICCBNUM;
+ int64_t max = all ? INT64_MAX : usiz * tdb->iccsync;
+ int64_t sum = 0;
+ const char *kbuf;
+ int ksiz;
+ tcmapiterinit(cc);
+ while (sum < max && (kbuf = tcmapiternext(cc, &ksiz)) != NULL) {
+ int vsiz;
+ tcmapiterval(kbuf, &vsiz);
+ keys[knum++] = kbuf;
+ sum += sizeof (TCMAPREC) + sizeof (void *) +ksiz + vsiz;
+ }
+ qsort(keys, knum, sizeof (*keys), (int(*)(const void *, const void *))tctdbidxcmpkey);
+ for (int i = 0; i < knum; i++) {
+ const char *kbuf = keys[i];
+ int ksiz = strlen(kbuf);
+ int vsiz;
+ const char *vbuf = tcmapget(cc, kbuf, ksiz, &vsiz);
+ if (vsiz > 0 && !tcbdbputcat(db, kbuf, ksiz, vbuf, vsiz)) {
+ tctdbsetecode(tdb, tcbdbecode(db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ tcmapout(cc, kbuf, ksiz);
}
- tcmapout(cc, kbuf, ksiz);
- }
- TCFREE(keys);
- return !err;
+ TCFREE(keys);
+ return !err;
}
-
/* Compare two index search keys in lexical order.
`a' specifies the pointer to one element.
`b' specifies the pointer to the other element.
The return value is positive if the former is big, negative if the latter is big, 0 if both
are equivalent. */
-static int tctdbidxcmpkey(const char **a, const char **b){
- assert(a && b);
- const unsigned char *ap = (unsigned char *)*a;
- const unsigned char *bp = (unsigned char *)*b;
- while(true){
- if(*ap == '\0') return *bp == '\0' ? 0 : -1;
- if(*bp == '\0') return *ap == '\0' ? 0 : 1;
- if(*ap != *bp) return *ap - *bp;
- ap++;
- bp++;
- }
- return 0;
+static int tctdbidxcmpkey(const char **a, const char **b) {
+ assert(a && b);
+ const unsigned char *ap = (unsigned char *) *a;
+ const unsigned char *bp = (unsigned char *) *b;
+ while (true) {
+ if (*ap == '\0') return *bp == '\0' ? 0 : -1;
+ if (*bp == '\0') return *ap == '\0' ? 0 : 1;
+ if (*ap != *bp) return *ap - *bp;
+ ap++;
+ bp++;
+ }
+ return 0;
}
-
/* Retrieve records by a token inverted index of a table database object.
`tdb' specifies the table database object.
`idx' specifies the index object.
`hint' specifies the hint object.
The return value is a map object of the primary keys of the corresponding records. */
TCMAP *tctdbidxgetbytokens(TCTDB *tdb, const TDBIDX *idx, const TCLIST *tokens, int op,
- TCXSTR *hint){
- assert(tdb && idx && tokens);
- TCBDB *db = idx->db;
- TCMAP *cc = idx->cc;
- int tnum = TCLISTNUM(tokens);
- TCMAP *res = tcmapnew();
- int cnt = 0;
- for(int i = 0; i < tnum; i++){
- const char *token;
- int tsiz;
- TCLISTVAL(token, tokens, i, tsiz);
- if(tsiz < 1) continue;
- int onum = 0;
- TCMAP *wring = (cnt > 0 && op == TDBQCSTRAND) ? tcmapnew() : NULL;
- int csiz;
- const char *cbuf = tcmapget(cc, token, tsiz, &csiz);
- if(cbuf){
- while(csiz > 0){
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int tsiz, step;
- TCREADVNUMBUF(cbuf, tsiz, step);
- cbuf += step;
- csiz -= step;
- if(cnt < 1){
- tcmapput(res, cbuf, tsiz, "", 0);
- } else if(wring){
- int rsiz;
- if(tcmapget(res, cbuf, tsiz, &rsiz)) tcmapput(wring, cbuf, tsiz, "", 0);
- } else {
- tcmapput(res, cbuf, tsiz, "", 0);
- }
- cbuf += tsiz;
- csiz -= tsiz;
- } else {
- int64_t tid;
- int step;
- TCREADVNUMBUF64(cbuf, tid, step);
- char pkbuf[TCNUMBUFSIZ];
- int pksiz = sprintf(pkbuf, "%" PRIdMAX "", (long long)tid);
- if(cnt < 1){
- tcmapput(res, pkbuf, pksiz, "", 0);
- } else if(wring){
- int rsiz;
- if(tcmapget(res, pkbuf, pksiz, &rsiz)) tcmapput(wring, pkbuf, pksiz, "", 0);
- } else {
- tcmapput(res, pkbuf, pksiz, "", 0);
- }
- cbuf += step;
- csiz -= step;
- }
- onum++;
- }
- }
- cbuf = tcbdbget3(db, token, tsiz, &csiz);
- if(cbuf){
- while(csiz > 0){
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int tsiz, step;
- TCREADVNUMBUF(cbuf, tsiz, step);
- cbuf += step;
- csiz -= step;
- if(cnt < 1){
- tcmapput(res, cbuf, tsiz, "", 0);
- } else if(wring){
- int rsiz;
- if(tcmapget(res, cbuf, tsiz, &rsiz)) tcmapput(wring, cbuf, tsiz, "", 0);
- } else {
- tcmapput(res, cbuf, tsiz, "", 0);
- }
- cbuf += tsiz;
- csiz -= tsiz;
- } else {
- int64_t tid;
- int step;
- TCREADVNUMBUF64(cbuf, tid, step);
- char pkbuf[TCNUMBUFSIZ];
- int pksiz = sprintf(pkbuf, "%" PRIdMAX "", (long long)tid);
- if(cnt < 1){
- tcmapput(res, pkbuf, pksiz, "", 0);
- } else if(wring){
- int rsiz;
- if(tcmapget(res, pkbuf, pksiz, &rsiz)) tcmapput(wring, pkbuf, pksiz, "", 0);
- } else {
- tcmapput(res, pkbuf, pksiz, "", 0);
- }
- cbuf += step;
- csiz -= step;
+ TCXSTR *hint) {
+ assert(tdb && idx && tokens);
+ TCBDB *db = idx->db;
+ TCMAP *cc = idx->cc;
+ int tnum = TCLISTNUM(tokens);
+ TCMAP *res = tcmapnew();
+ int cnt = 0;
+ for (int i = 0; i < tnum; i++) {
+ const char *token;
+ int tsiz;
+ TCLISTVAL(token, tokens, i, tsiz);
+ if (tsiz < 1) continue;
+ int onum = 0;
+ TCMAP *wring = (cnt > 0 && op == TDBQCSTRAND) ? tcmapnew() : NULL;
+ int csiz;
+ const char *cbuf = tcmapget(cc, token, tsiz, &csiz);
+ if (cbuf) {
+ while (csiz > 0) {
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int tsiz, step;
+ TCREADVNUMBUF(cbuf, tsiz, step);
+ cbuf += step;
+ csiz -= step;
+ if (cnt < 1) {
+ tcmapput(res, cbuf, tsiz, "", 0);
+ } else if (wring) {
+ int rsiz;
+ if (tcmapget(res, cbuf, tsiz, &rsiz)) tcmapput(wring, cbuf, tsiz, "", 0);
+ } else {
+ tcmapput(res, cbuf, tsiz, "", 0);
+ }
+ cbuf += tsiz;
+ csiz -= tsiz;
+ } else {
+ int64_t tid;
+ int step;
+ TCREADVNUMBUF64(cbuf, tid, step);
+ char pkbuf[TCNUMBUFSIZ];
+ int pksiz = sprintf(pkbuf, "%" PRIdMAX "", (long long) tid);
+ if (cnt < 1) {
+ tcmapput(res, pkbuf, pksiz, "", 0);
+ } else if (wring) {
+ int rsiz;
+ if (tcmapget(res, pkbuf, pksiz, &rsiz)) tcmapput(wring, pkbuf, pksiz, "", 0);
+ } else {
+ tcmapput(res, pkbuf, pksiz, "", 0);
+ }
+ cbuf += step;
+ csiz -= step;
+ }
+ onum++;
+ }
}
- onum++;
- }
- }
- if(wring){
- tcmapdel(res);
- res = wring;
- }
- if (hint) {
- tcxstrprintf(hint, "token occurrence: \"%s\" %d\n", token, onum);
+ cbuf = tcbdbget3(db, token, tsiz, &csiz);
+ if (cbuf) {
+ while (csiz > 0) {
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int tsiz, step;
+ TCREADVNUMBUF(cbuf, tsiz, step);
+ cbuf += step;
+ csiz -= step;
+ if (cnt < 1) {
+ tcmapput(res, cbuf, tsiz, "", 0);
+ } else if (wring) {
+ int rsiz;
+ if (tcmapget(res, cbuf, tsiz, &rsiz)) tcmapput(wring, cbuf, tsiz, "", 0);
+ } else {
+ tcmapput(res, cbuf, tsiz, "", 0);
+ }
+ cbuf += tsiz;
+ csiz -= tsiz;
+ } else {
+ int64_t tid;
+ int step;
+ TCREADVNUMBUF64(cbuf, tid, step);
+ char pkbuf[TCNUMBUFSIZ];
+ int pksiz = sprintf(pkbuf, "%" PRIdMAX "", (long long) tid);
+ if (cnt < 1) {
+ tcmapput(res, pkbuf, pksiz, "", 0);
+ } else if (wring) {
+ int rsiz;
+ if (tcmapget(res, pkbuf, pksiz, &rsiz)) tcmapput(wring, pkbuf, pksiz, "", 0);
+ } else {
+ tcmapput(res, pkbuf, pksiz, "", 0);
+ }
+ cbuf += step;
+ csiz -= step;
+ }
+ onum++;
+ }
+ }
+ if (wring) {
+ tcmapdel(res);
+ res = wring;
+ }
+ if (hint) {
+ tcxstrprintf(hint, "token occurrence: \"%s\" %d\n", token, onum);
+ }
+ cnt++;
}
- cnt++;
- }
- return res;
+ return res;
}
-
/* Retrieve records by a token inverted index of a table database object.
`tdb' specifies the table database object.
`idx' specifies the index object.
`cond' specifies the condition object.
`hint' specifies the hint object.
The return value is a map object of the primary keys of the corresponding records. */
-static TCMAP *tctdbidxgetbyfts(TCTDB *tdb, TDBIDX *idx, TDBCOND *cond, TCXSTR *hint){
- assert(tdb && idx && cond && hint);
- TDBFTSUNIT *ftsunits = cond->ftsunits;
- int ftsnum = cond->ftsnum;
- if(ftsnum < 1) return tcmapnew2(1);
- if(!ftsunits[0].sign) return tcmapnew2(1);
- TCMAP *res = tcmapnew();
- tctdbidxgetbyftsunion(idx, ftsunits->tokens, true, NULL, res, hint);
- for(int i = 1; i < ftsnum; i++){
- TDBFTSUNIT *ftsunit = ftsunits + i;
- if(ftsunit->sign){
- TCMAP *nres = tcmapnew2(TCMAPRNUM(res) + 1);
- tctdbidxgetbyftsunion(idx, ftsunit->tokens, true, res, nres, hint);
- tcmapdel(res);
- res = nres;
- } else {
- tctdbidxgetbyftsunion(idx, ftsunit->tokens, false, res, NULL, hint);
+static TCMAP *tctdbidxgetbyfts(TCTDB *tdb, TDBIDX *idx, TDBCOND *cond, TCXSTR *hint) {
+ assert(tdb && idx && cond && hint);
+ TDBFTSUNIT *ftsunits = cond->ftsunits;
+ int ftsnum = cond->ftsnum;
+ if (ftsnum < 1) return tcmapnew2(1);
+ if (!ftsunits[0].sign) return tcmapnew2(1);
+ TCMAP *res = tcmapnew();
+ tctdbidxgetbyftsunion(idx, ftsunits->tokens, true, NULL, res, hint);
+ for (int i = 1; i < ftsnum; i++) {
+ TDBFTSUNIT *ftsunit = ftsunits + i;
+ if (ftsunit->sign) {
+ TCMAP *nres = tcmapnew2(TCMAPRNUM(res) + 1);
+ tctdbidxgetbyftsunion(idx, ftsunit->tokens, true, res, nres, hint);
+ tcmapdel(res);
+ res = nres;
+ } else {
+ tctdbidxgetbyftsunion(idx, ftsunit->tokens, false, res, NULL, hint);
+ }
}
- }
- return res;
+ return res;
}
-
/* Retrieve union records by a token inverted index of a table database object.
`idx' specifies the index object.
`tokens' specifies a list object of the union tokens.
`nres' specifies a map object of new primary keys.
`hint' specifies the hint object. */
static void tctdbidxgetbyftsunion(TDBIDX *idx, const TCLIST *tokens, bool sign,
- TCMAP *ores, TCMAP *nres, TCXSTR *hint){
- assert(idx && tokens && hint);
- TCBDB *db = idx->db;
- TCMAP *cc = idx->cc;
- int tnum = TCLISTNUM(tokens);
- for(int i = 0; i < tnum; i++){
- const char *word;
- int wsiz;
- TCLISTVAL(word, tokens, i, wsiz);
- uint16_t *ary;
- TCMALLOC(ary, sizeof(*ary) * (wsiz + TDBIDXQGUNIT));
- int anum;
- tcstrutftoucs(word, ary, &anum);
- for(int j = 0; j < TDBIDXQGUNIT; j++){
- ary[anum+j] = 0;
- }
- if(anum >= TDBIDXQGUNIT){
- TDBFTSSTROCR *socrs;
- TCMALLOC(socrs, TDBFTSOCRUNIT * sizeof(*socrs));
- int sonum = 0;
- int soanum = TDBFTSOCRUNIT;
- int sobase = 0;
- TDBFTSNUMOCR *nocrs;
- TCMALLOC(nocrs, TDBFTSOCRUNIT * sizeof(*nocrs));
- int nonum = 0;
- int noanum = TDBFTSOCRUNIT;
- int nobase = 0;
- TCBITMAP *pkmap = TCBITMAPNEW(TDBFTSBMNUM);
- char token[TDBIDXQGUNIT*3+1];
- uint16_t seq = 0;
- for(int j = 0; j < anum; j += TDBIDXQGUNIT){
- sobase = sonum;
- nobase = nonum;
- int diff = anum - j - TDBIDXQGUNIT;
- if(diff < 0){
- j += diff;
- diff = -diff;
- } else {
- diff = 0;
+ TCMAP *ores, TCMAP *nres, TCXSTR *hint) {
+ assert(idx && tokens && hint);
+ TCBDB *db = idx->db;
+ TCMAP *cc = idx->cc;
+ int tnum = TCLISTNUM(tokens);
+ for (int i = 0; i < tnum; i++) {
+ const char *word;
+ int wsiz;
+ TCLISTVAL(word, tokens, i, wsiz);
+ uint16_t *ary;
+ TCMALLOC(ary, sizeof (*ary) * (wsiz + TDBIDXQGUNIT));
+ int anum;
+ tcstrutftoucs(word, ary, &anum);
+ for (int j = 0; j < TDBIDXQGUNIT; j++) {
+ ary[anum + j] = 0;
}
- tcstrucstoutf(ary + j, TDBIDXQGUNIT, token);
- int tsiz = strlen(token);
- int csiz;
- const char *cbuf = tcmapget(cc, token, tsiz, &csiz);
- if(cbuf){
- while(csiz > 0){
- const char *pkbuf = NULL;
- int32_t pksiz = 0;
- int64_t pkid = 0;
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int step;
- TCREADVNUMBUF(cbuf, pksiz, step);
- cbuf += step;
- csiz -= step;
- pkbuf = cbuf;
- cbuf += pksiz;
- csiz -= pksiz;
- } else {
- int step;
- TCREADVNUMBUF64(cbuf, pkid, step);
- cbuf += step;
- csiz -= step;
- }
- if(csiz > 0){
- int off, step;
- TCREADVNUMBUF(cbuf, off, step);
- cbuf += step;
- csiz -= step;
- off += diff;
- if(pkbuf){
- unsigned int hash = 19780211;
- for(int k = 0; k < pksiz; k++){
- hash = hash * 37 + ((unsigned char *)pkbuf)[k];
+ if (anum >= TDBIDXQGUNIT) {
+ TDBFTSSTROCR *socrs;
+ TCMALLOC(socrs, TDBFTSOCRUNIT * sizeof (*socrs));
+ int sonum = 0;
+ int soanum = TDBFTSOCRUNIT;
+ int sobase = 0;
+ TDBFTSNUMOCR *nocrs;
+ TCMALLOC(nocrs, TDBFTSOCRUNIT * sizeof (*nocrs));
+ int nonum = 0;
+ int noanum = TDBFTSOCRUNIT;
+ int nobase = 0;
+ TCBITMAP *pkmap = TCBITMAPNEW(TDBFTSBMNUM);
+ char token[TDBIDXQGUNIT * 3 + 1];
+ uint16_t seq = 0;
+ for (int j = 0; j < anum; j += TDBIDXQGUNIT) {
+ sobase = sonum;
+ nobase = nonum;
+ int diff = anum - j - TDBIDXQGUNIT;
+ if (diff < 0) {
+ j += diff;
+ diff = -diff;
+ } else {
+ diff = 0;
}
- hash = hash % TDBFTSBMNUM;
- if(j == 0 || TCBITMAPCHECK(pkmap, hash)){
- if(sonum >= soanum){
- soanum *= 2;
- TCREALLOC(socrs, socrs, soanum * sizeof(*socrs));
- }
- TDBFTSSTROCR *ocr = socrs + sonum;
- ocr->pkbuf = pkbuf;
- ocr->pksiz = pksiz;
- ocr->off = off;
- ocr->seq = seq;
- ocr->hash = hash;
- sonum++;
- if(j == 0) TCBITMAPON(pkmap, hash);
+ tcstrucstoutf(ary + j, TDBIDXQGUNIT, token);
+ int tsiz = strlen(token);
+ int csiz;
+ const char *cbuf = tcmapget(cc, token, tsiz, &csiz);
+ if (cbuf) {
+ while (csiz > 0) {
+ const char *pkbuf = NULL;
+ int32_t pksiz = 0;
+ int64_t pkid = 0;
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int step;
+ TCREADVNUMBUF(cbuf, pksiz, step);
+ cbuf += step;
+ csiz -= step;
+ pkbuf = cbuf;
+ cbuf += pksiz;
+ csiz -= pksiz;
+ } else {
+ int step;
+ TCREADVNUMBUF64(cbuf, pkid, step);
+ cbuf += step;
+ csiz -= step;
+ }
+ if (csiz > 0) {
+ int off, step;
+ TCREADVNUMBUF(cbuf, off, step);
+ cbuf += step;
+ csiz -= step;
+ off += diff;
+ if (pkbuf) {
+ unsigned int hash = 19780211;
+ for (int k = 0; k < pksiz; k++) {
+ hash = hash * 37 + ((unsigned char *) pkbuf)[k];
+ }
+ hash = hash % TDBFTSBMNUM;
+ if (j == 0 || TCBITMAPCHECK(pkmap, hash)) {
+ if (sonum >= soanum) {
+ soanum *= 2;
+ TCREALLOC(socrs, socrs, soanum * sizeof (*socrs));
+ }
+ TDBFTSSTROCR *ocr = socrs + sonum;
+ ocr->pkbuf = pkbuf;
+ ocr->pksiz = pksiz;
+ ocr->off = off;
+ ocr->seq = seq;
+ ocr->hash = hash;
+ sonum++;
+ if (j == 0) TCBITMAPON(pkmap, hash);
+ }
+ } else {
+ unsigned int hash = pkid % TDBFTSBMNUM;
+ if (j == 0 || TCBITMAPCHECK(pkmap, hash)) {
+ if (nonum >= noanum) {
+ noanum *= 2;
+ TCREALLOC(nocrs, nocrs, noanum * sizeof (*nocrs));
+ }
+ TDBFTSNUMOCR *ocr = nocrs + nonum;
+ ocr->pkid = pkid;
+ ocr->off = off;
+ ocr->seq = seq;
+ ocr->hash = hash;
+ nonum++;
+ if (j == 0) TCBITMAPON(pkmap, hash);
+ }
+ }
+ }
+ }
}
- } else {
- unsigned int hash = pkid % TDBFTSBMNUM;
- if(j == 0 || TCBITMAPCHECK(pkmap, hash)){
- if(nonum >= noanum){
- noanum *= 2;
- TCREALLOC(nocrs, nocrs, noanum * sizeof(*nocrs));
- }
- TDBFTSNUMOCR *ocr = nocrs + nonum;
- ocr->pkid = pkid;
- ocr->off = off;
- ocr->seq = seq;
- ocr->hash = hash;
- nonum++;
- if(j == 0) TCBITMAPON(pkmap, hash);
+ cbuf = tcbdbget3(db, token, tsiz, &csiz);
+ if (cbuf) {
+ while (csiz > 0) {
+ const char *pkbuf = NULL;
+ int32_t pksiz = 0;
+ int64_t pkid = 0;
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int step;
+ TCREADVNUMBUF(cbuf, pksiz, step);
+ cbuf += step;
+ csiz -= step;
+ pkbuf = cbuf;
+ cbuf += pksiz;
+ csiz -= pksiz;
+ } else {
+ int step;
+ TCREADVNUMBUF64(cbuf, pkid, step);
+ cbuf += step;
+ csiz -= step;
+ }
+ if (csiz > 0) {
+ int off, step;
+ TCREADVNUMBUF(cbuf, off, step);
+ cbuf += step;
+ csiz -= step;
+ off += diff;
+ if (pkbuf) {
+ unsigned int hash = 19780211;
+ for (int k = 0; k < pksiz; k++) {
+ hash = hash * 37 + ((unsigned char *) pkbuf)[k];
+ }
+ hash = hash % TDBFTSBMNUM;
+ if (j == 0 || TCBITMAPCHECK(pkmap, hash)) {
+ if (sonum >= soanum) {
+ soanum *= 2;
+ TCREALLOC(socrs, socrs, soanum * sizeof (*socrs));
+ }
+ TDBFTSSTROCR *ocr = socrs + sonum;
+ ocr->pkbuf = pkbuf;
+ ocr->pksiz = pksiz;
+ ocr->off = off;
+ ocr->seq = seq;
+ ocr->hash = hash;
+ sonum++;
+ if (j == 0) TCBITMAPON(pkmap, hash);
+ }
+ } else {
+ unsigned int hash = pkid % TDBFTSBMNUM;
+ if (j == 0 || TCBITMAPCHECK(pkmap, hash)) {
+ if (nonum >= noanum) {
+ noanum *= 2;
+ TCREALLOC(nocrs, nocrs, noanum * sizeof (*nocrs));
+ }
+ TDBFTSNUMOCR *ocr = nocrs + nonum;
+ ocr->pkid = pkid;
+ ocr->off = off;
+ ocr->seq = seq;
+ ocr->hash = hash;
+ nonum++;
+ if (j == 0) TCBITMAPON(pkmap, hash);
+ }
+ }
+ }
+ }
+ }
+ seq++;
+ if (sonum <= sobase && nonum <= nobase) {
+ sonum = 0;
+ nonum = 0;
+ break;
}
- }
- }
- }
- }
- cbuf = tcbdbget3(db, token, tsiz, &csiz);
- if(cbuf){
- while(csiz > 0){
- const char *pkbuf = NULL;
- int32_t pksiz = 0;
- int64_t pkid = 0;
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int step;
- TCREADVNUMBUF(cbuf, pksiz, step);
- cbuf += step;
- csiz -= step;
- pkbuf = cbuf;
- cbuf += pksiz;
- csiz -= pksiz;
- } else {
- int step;
- TCREADVNUMBUF64(cbuf, pkid, step);
- cbuf += step;
- csiz -= step;
}
- if(csiz > 0){
- int off, step;
- TCREADVNUMBUF(cbuf, off, step);
- cbuf += step;
- csiz -= step;
- off += diff;
- if(pkbuf){
- unsigned int hash = 19780211;
- for(int k = 0; k < pksiz; k++){
- hash = hash * 37 + ((unsigned char *)pkbuf)[k];
+ TCBITMAPDEL(pkmap);
+ if (seq > 1) {
+ if (sonum > UINT16_MAX) {
+ int flnum = sonum * 16 + 1;
+ TCBITMAP *flmap = TCBITMAPNEW(flnum);
+ for (int j = sobase; j < sonum; j++) {
+ TDBFTSSTROCR *ocr = socrs + j;
+ uint32_t hash = (((uint32_t) ocr->off << 16) | ocr->hash) % flnum;
+ TCBITMAPON(flmap, hash);
+ }
+ int wi = 0;
+ for (int j = 0; j < sobase; j++) {
+ TDBFTSSTROCR *ocr = socrs + j;
+ int rem = (seq - ocr->seq - 1) * TDBIDXQGUNIT;
+ uint32_t hash = (((uint32_t) (ocr->off + rem) << 16) | ocr->hash) % flnum;
+ if (TCBITMAPCHECK(flmap, hash)) socrs[wi++] = *ocr;
+ }
+ for (int j = sobase; j < sonum; j++) {
+ socrs[wi++] = socrs[j];
+ }
+ sonum = wi;
+ TCBITMAPDEL(flmap);
}
- hash = hash % TDBFTSBMNUM;
- if(j == 0 || TCBITMAPCHECK(pkmap, hash)){
- if(sonum >= soanum){
- soanum *= 2;
- TCREALLOC(socrs, socrs, soanum * sizeof(*socrs));
- }
- TDBFTSSTROCR *ocr = socrs + sonum;
- ocr->pkbuf = pkbuf;
- ocr->pksiz = pksiz;
- ocr->off = off;
- ocr->seq = seq;
- ocr->hash = hash;
- sonum++;
- if(j == 0) TCBITMAPON(pkmap, hash);
+ if (sonum > UINT16_MAX * 2) {
+ TDBFTSSTROCR *rocrs;
+ TCMALLOC(rocrs, sizeof (*rocrs) * sonum);
+ uint32_t *counts;
+ TCCALLOC(counts, sizeof (*counts), (UINT16_MAX + 1));
+ for (int j = 0; j < sonum; j++) {
+ counts[socrs[j].hash]++;
+ }
+ for (int j = 0; j < UINT16_MAX; j++) {
+ counts[j + 1] += counts[j];
+ }
+ for (int j = sonum - 1; j >= 0; j--) {
+ rocrs[--counts[socrs[j].hash]] = socrs[j];
+ }
+ for (int j = 0; j < UINT16_MAX; j++) {
+ int num = counts[j + 1] - counts[j];
+ if (num > 1) qsort(rocrs + counts[j], num, sizeof (*rocrs),
+ (int (*)(const void *, const void *))tctdbidxftscmpstrocr);
+ }
+ int num = sonum - counts[UINT16_MAX];
+ if (num > 1) qsort(rocrs + counts[UINT16_MAX], num, sizeof (*rocrs),
+ (int (*)(const void *, const void *))tctdbidxftscmpstrocr);
+ TCFREE(counts);
+ TCFREE(socrs);
+ socrs = rocrs;
+ } else if (sonum > 1) {
+ qsort(socrs, sonum, sizeof (*socrs),
+ (int (*)(const void *, const void *))tctdbidxftscmpstrocr);
}
- } else {
- unsigned int hash = pkid % TDBFTSBMNUM;
- if(j == 0 || TCBITMAPCHECK(pkmap, hash)){
- if(nonum >= noanum){
- noanum *= 2;
- TCREALLOC(nocrs, nocrs, noanum * sizeof(*nocrs));
- }
- TDBFTSNUMOCR *ocr = nocrs + nonum;
- ocr->pkid = pkid;
- ocr->off = off;
- ocr->seq = seq;
- ocr->hash = hash;
- nonum++;
- if(j == 0) TCBITMAPON(pkmap, hash);
+ if (nonum > UINT16_MAX) {
+ int flnum = nonum * 16 + 1;
+ TCBITMAP *flmap = TCBITMAPNEW(flnum);
+ for (int j = nobase; j < nonum; j++) {
+ TDBFTSNUMOCR *ocr = nocrs + j;
+ uint32_t hash = (((uint32_t) ocr->off << 16) | ocr->hash) % flnum;
+ TCBITMAPON(flmap, hash);
+ }
+ int wi = 0;
+ for (int j = 0; j < nobase; j++) {
+ TDBFTSNUMOCR *ocr = nocrs + j;
+ int rem = (seq - ocr->seq - 1) * TDBIDXQGUNIT;
+ uint32_t hash = (((uint32_t) (ocr->off + rem) << 16) | ocr->hash) % flnum;
+ if (TCBITMAPCHECK(flmap, hash)) nocrs[wi++] = *ocr;
+ }
+ for (int j = nobase; j < nonum; j++) {
+ nocrs[wi++] = nocrs[j];
+ }
+ nonum = wi;
+ TCBITMAPDEL(flmap);
}
- }
- }
- }
- }
- seq++;
- if(sonum <= sobase && nonum <= nobase){
- sonum = 0;
- nonum = 0;
- break;
- }
- }
- TCBITMAPDEL(pkmap);
- if(seq > 1){
- if(sonum > UINT16_MAX){
- int flnum = sonum * 16 + 1;
- TCBITMAP *flmap = TCBITMAPNEW(flnum);
- for(int j = sobase; j < sonum; j++){
- TDBFTSSTROCR *ocr = socrs + j;
- uint32_t hash = (((uint32_t)ocr->off << 16) | ocr->hash) % flnum;
- TCBITMAPON(flmap, hash);
- }
- int wi = 0;
- for(int j = 0; j < sobase; j++){
- TDBFTSSTROCR *ocr = socrs + j;
- int rem = (seq - ocr->seq - 1) * TDBIDXQGUNIT;
- uint32_t hash = (((uint32_t)(ocr->off + rem) << 16) | ocr->hash) % flnum;
- if(TCBITMAPCHECK(flmap, hash)) socrs[wi++] = *ocr;
- }
- for(int j = sobase; j < sonum; j++){
- socrs[wi++] = socrs[j];
- }
- sonum = wi;
- TCBITMAPDEL(flmap);
- }
- if(sonum > UINT16_MAX * 2){
- TDBFTSSTROCR *rocrs;
- TCMALLOC(rocrs, sizeof(*rocrs) * sonum);
- uint32_t *counts;
- TCCALLOC(counts, sizeof(*counts), (UINT16_MAX + 1));
- for(int j = 0; j < sonum; j++){
- counts[socrs[j].hash]++;
- }
- for(int j = 0; j < UINT16_MAX; j++){
- counts[j+1] += counts[j];
- }
- for(int j = sonum - 1; j >= 0; j--){
- rocrs[--counts[socrs[j].hash]] = socrs[j];
- }
- for(int j = 0; j < UINT16_MAX; j++){
- int num = counts[j+1] - counts[j];
- if(num > 1) qsort(rocrs + counts[j], num, sizeof(*rocrs),
- (int (*)(const void *, const void *))tctdbidxftscmpstrocr);
- }
- int num = sonum - counts[UINT16_MAX];
- if(num > 1) qsort(rocrs + counts[UINT16_MAX], num, sizeof(*rocrs),
- (int (*)(const void *, const void *))tctdbidxftscmpstrocr);
- TCFREE(counts);
- TCFREE(socrs);
- socrs = rocrs;
- } else if(sonum > 1){
- qsort(socrs, sonum, sizeof(*socrs),
- (int (*)(const void *, const void *))tctdbidxftscmpstrocr);
- }
- if(nonum > UINT16_MAX){
- int flnum = nonum * 16 + 1;
- TCBITMAP *flmap = TCBITMAPNEW(flnum);
- for(int j = nobase; j < nonum; j++){
- TDBFTSNUMOCR *ocr = nocrs + j;
- uint32_t hash = (((uint32_t)ocr->off << 16) | ocr->hash) % flnum;
- TCBITMAPON(flmap, hash);
- }
- int wi = 0;
- for(int j = 0; j < nobase; j++){
- TDBFTSNUMOCR *ocr = nocrs + j;
- int rem = (seq - ocr->seq - 1) * TDBIDXQGUNIT;
- uint32_t hash = (((uint32_t)(ocr->off + rem) << 16) | ocr->hash) % flnum;
- if(TCBITMAPCHECK(flmap, hash)) nocrs[wi++] = *ocr;
- }
- for(int j = nobase; j < nonum; j++){
- nocrs[wi++] = nocrs[j];
- }
- nonum = wi;
- TCBITMAPDEL(flmap);
- }
- if(nonum > UINT16_MAX * 2){
- TDBFTSNUMOCR *rocrs;
- TCMALLOC(rocrs, sizeof(*rocrs) * nonum);
- uint32_t *counts;
- TCCALLOC(counts, sizeof(*counts), (UINT16_MAX + 1));
- for(int j = 0; j < nonum; j++){
- counts[nocrs[j].hash]++;
- }
- for(int j = 0; j < UINT16_MAX; j++){
- counts[j+1] += counts[j];
- }
- for(int j = nonum - 1; j >= 0; j--){
- rocrs[--counts[nocrs[j].hash]] = nocrs[j];
- }
- for(int j = 0; j < UINT16_MAX; j++){
- int num = counts[j+1] - counts[j];
- if(num > 1) qsort(rocrs + counts[j], num, sizeof(*rocrs),
- (int (*)(const void *, const void *))tctdbidxftscmpnumocr);
- }
- int num = nonum - counts[UINT16_MAX];
- if(num > 1) qsort(rocrs + counts[UINT16_MAX], num, sizeof(*rocrs),
+ if (nonum > UINT16_MAX * 2) {
+ TDBFTSNUMOCR *rocrs;
+ TCMALLOC(rocrs, sizeof (*rocrs) * nonum);
+ uint32_t *counts;
+ TCCALLOC(counts, sizeof (*counts), (UINT16_MAX + 1));
+ for (int j = 0; j < nonum; j++) {
+ counts[nocrs[j].hash]++;
+ }
+ for (int j = 0; j < UINT16_MAX; j++) {
+ counts[j + 1] += counts[j];
+ }
+ for (int j = nonum - 1; j >= 0; j--) {
+ rocrs[--counts[nocrs[j].hash]] = nocrs[j];
+ }
+ for (int j = 0; j < UINT16_MAX; j++) {
+ int num = counts[j + 1] - counts[j];
+ if (num > 1) qsort(rocrs + counts[j], num, sizeof (*rocrs),
+ (int (*)(const void *, const void *))tctdbidxftscmpnumocr);
+ }
+ int num = nonum - counts[UINT16_MAX];
+ if (num > 1) qsort(rocrs + counts[UINT16_MAX], num, sizeof (*rocrs),
(int (*)(const void *, const void *))tctdbidxftscmpnumocr);
- TCFREE(counts);
- TCFREE(nocrs);
- nocrs = rocrs;
- } else if(nonum > 1){
- qsort(nocrs, nonum, sizeof(*nocrs),
- (int (*)(const void *, const void *))tctdbidxftscmpnumocr);
- }
- }
- int rem = (seq - 1) * TDBIDXQGUNIT;
- int onum = 0;
- int ri = 0;
- while(ri < sonum){
- TDBFTSSTROCR *ocr = socrs + ri;
- ri++;
- if(ocr->seq > 0) continue;
- const char *pkbuf = ocr->pkbuf;
- int32_t pksiz = ocr->pksiz;
- int32_t off = ocr->off;
- uint16_t seq = 1;
- for(int j = ri; j < sonum; j++){
- TDBFTSSTROCR *tocr = socrs + j;
- if(!tocr->pkbuf || tocr->pksiz != pksiz || memcmp(tocr->pkbuf, pkbuf, pksiz) ||
- tocr->off > off + TDBIDXQGUNIT) break;
- if(tocr->seq == seq && tocr->off == off + TDBIDXQGUNIT){
- off = tocr->off;
- seq++;
- }
- }
- if(off == ocr->off + rem){
- onum++;
- if(ores){
- int rsiz;
- if(tcmapget(ores, pkbuf, pksiz, &rsiz)){
- if(sign){
- tcmapputkeep(nres, pkbuf, pksiz, "", 0);
- } else {
- tcmapout(ores, pkbuf, pksiz);
- }
+ TCFREE(counts);
+ TCFREE(nocrs);
+ nocrs = rocrs;
+ } else if (nonum > 1) {
+ qsort(nocrs, nonum, sizeof (*nocrs),
+ (int (*)(const void *, const void *))tctdbidxftscmpnumocr);
+ }
}
- } else {
- tcmapputkeep(nres, pkbuf, pksiz, "", 0);
- }
- while(ri < sonum){
- ocr = socrs + ri;
- if(!ocr->pkbuf || ocr->pksiz != pksiz || memcmp(ocr->pkbuf, pkbuf, pksiz)) break;
- ri++;
- }
- }
- }
- ri = 0;
- while(ri < nonum){
- TDBFTSNUMOCR *ocr = nocrs + ri;
- ri++;
- if(ocr->seq > 0) continue;
- int64_t pkid = ocr->pkid;
- int32_t off = ocr->off;
- uint16_t seq = 1;
- for(int j = ri; j < nonum; j++){
- TDBFTSNUMOCR *tocr = nocrs + j;
- if(tocr->pkid != pkid || tocr->off > off + TDBIDXQGUNIT) break;
- if(tocr->seq == seq && tocr->off == off + TDBIDXQGUNIT){
- off = tocr->off;
- seq++;
- }
- }
- if(off == ocr->off + rem){
- onum++;
- char pkbuf[TCNUMBUFSIZ];
- int pksiz = sprintf(pkbuf, "%" PRIdMAX "", (long long)pkid);
- if(ores){
- int rsiz;
- if(tcmapget(ores, pkbuf, pksiz, &rsiz)){
- if(sign){
- tcmapputkeep(nres, pkbuf, pksiz, "", 0);
- } else {
- tcmapout(ores, pkbuf, pksiz);
- }
+ int rem = (seq - 1) * TDBIDXQGUNIT;
+ int onum = 0;
+ int ri = 0;
+ while (ri < sonum) {
+ TDBFTSSTROCR *ocr = socrs + ri;
+ ri++;
+ if (ocr->seq > 0) continue;
+ const char *pkbuf = ocr->pkbuf;
+ int32_t pksiz = ocr->pksiz;
+ int32_t off = ocr->off;
+ uint16_t seq = 1;
+ for (int j = ri; j < sonum; j++) {
+ TDBFTSSTROCR *tocr = socrs + j;
+ if (!tocr->pkbuf || tocr->pksiz != pksiz || memcmp(tocr->pkbuf, pkbuf, pksiz) ||
+ tocr->off > off + TDBIDXQGUNIT) break;
+ if (tocr->seq == seq && tocr->off == off + TDBIDXQGUNIT) {
+ off = tocr->off;
+ seq++;
+ }
+ }
+ if (off == ocr->off + rem) {
+ onum++;
+ if (ores) {
+ int rsiz;
+ if (tcmapget(ores, pkbuf, pksiz, &rsiz)) {
+ if (sign) {
+ tcmapputkeep(nres, pkbuf, pksiz, "", 0);
+ } else {
+ tcmapout(ores, pkbuf, pksiz);
+ }
+ }
+ } else {
+ tcmapputkeep(nres, pkbuf, pksiz, "", 0);
+ }
+ while (ri < sonum) {
+ ocr = socrs + ri;
+ if (!ocr->pkbuf || ocr->pksiz != pksiz || memcmp(ocr->pkbuf, pkbuf, pksiz)) break;
+ ri++;
+ }
+ }
}
- } else {
- tcmapputkeep(nres, pkbuf, pksiz, "", 0);
- }
- while(ri < nonum && nocrs[ri].pkid == pkid){
- ri++;
- }
- }
- }
- tcxstrprintf(hint, "token occurrence: \"%s\" %d\n", word, onum);
- TCFREE(nocrs);
- TCFREE(socrs);
- } else {
- int onum = 0;
- TCMAP *uniq = (i > 0 || ores) ? tcmapnew2(UINT16_MAX) : NULL;
- tcmapiterinit(cc);
- const char *kbuf;
- int ksiz;
- while((kbuf = tcmapiternext(cc, &ksiz)) != NULL){
- if(ksiz < wsiz || memcmp(kbuf, word, wsiz)) continue;
- int csiz;
- const char *cbuf = tcmapiterval(kbuf, &csiz);
- while(csiz > 0){
- const char *pkbuf = NULL;
- int32_t pksiz = 0;
- int64_t pkid = 0;
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int step;
- TCREADVNUMBUF(cbuf, pksiz, step);
- cbuf += step;
- csiz -= step;
- pkbuf = cbuf;
- cbuf += pksiz;
- csiz -= pksiz;
- } else {
- int step;
- TCREADVNUMBUF64(cbuf, pkid, step);
- cbuf += step;
- csiz -= step;
- }
- if(csiz > 0){
- int off, step;
- TCREADVNUMBUF(cbuf, off, step);
- cbuf += step;
- csiz -= step;
- if(pkbuf){
- if(ores){
- int rsiz;
- if(tcmapget(ores, pkbuf, pksiz, &rsiz)){
- if(sign){
- tcmapputkeep(nres, pkbuf, pksiz, "", 0);
- } else {
- tcmapout(ores, pkbuf, pksiz);
- }
+ ri = 0;
+ while (ri < nonum) {
+ TDBFTSNUMOCR *ocr = nocrs + ri;
+ ri++;
+ if (ocr->seq > 0) continue;
+ int64_t pkid = ocr->pkid;
+ int32_t off = ocr->off;
+ uint16_t seq = 1;
+ for (int j = ri; j < nonum; j++) {
+ TDBFTSNUMOCR *tocr = nocrs + j;
+ if (tocr->pkid != pkid || tocr->off > off + TDBIDXQGUNIT) break;
+ if (tocr->seq == seq && tocr->off == off + TDBIDXQGUNIT) {
+ off = tocr->off;
+ seq++;
+ }
}
- } else {
- if(tcmapputkeep(nres, pkbuf, pksiz, "", 0)) onum++;
- }
- if(uniq) tcmapputkeep(uniq, pkbuf, pksiz, "", 0);
- } else {
- char numbuf[TCNUMBUFSIZ];
- int pksiz = sprintf(numbuf, "%" PRIdMAX "", (long long)pkid);
- if(ores){
- int rsiz;
- if(tcmapget(ores, numbuf, pksiz, &rsiz)){
- if(sign){
- tcmapputkeep(nres, numbuf, pksiz, "", 0);
- } else {
- tcmapout(ores, numbuf, pksiz);
- }
+ if (off == ocr->off + rem) {
+ onum++;
+ char pkbuf[TCNUMBUFSIZ];
+ int pksiz = sprintf(pkbuf, "%" PRIdMAX "", (long long) pkid);
+ if (ores) {
+ int rsiz;
+ if (tcmapget(ores, pkbuf, pksiz, &rsiz)) {
+ if (sign) {
+ tcmapputkeep(nres, pkbuf, pksiz, "", 0);
+ } else {
+ tcmapout(ores, pkbuf, pksiz);
+ }
+ }
+ } else {
+ tcmapputkeep(nres, pkbuf, pksiz, "", 0);
+ }
+ while (ri < nonum && nocrs[ri].pkid == pkid) {
+ ri++;
+ }
}
- } else {
- if(tcmapputkeep(nres, numbuf, pksiz, "", 0)) onum++;
- }
- if(uniq) tcmapputkeep(uniq, numbuf, pksiz, "", 0);
}
- }
- }
- }
- BDBCUR *cur = tcbdbcurnew(db);
- tcbdbcurjump(cur, word, wsiz);
- TCXSTR *key = tcxstrnew();
- TCXSTR *val = tcxstrnew();
- while(tcbdbcurrec(cur, key, val)){
- const char *kbuf = TCXSTRPTR(key);
- int ksiz = TCXSTRSIZE(key);
- if(ksiz < wsiz || memcmp(kbuf, word, wsiz)) break;
- const char *cbuf = TCXSTRPTR(val);
- int csiz = TCXSTRSIZE(val);
- while(csiz > 0){
- const char *pkbuf = NULL;
- int32_t pksiz = 0;
- int64_t pkid = 0;
- if(*cbuf == '\0'){
- cbuf++;
- csiz--;
- int step;
- TCREADVNUMBUF(cbuf, pksiz, step);
- cbuf += step;
- csiz -= step;
- pkbuf = cbuf;
- cbuf += pksiz;
- csiz -= pksiz;
- } else {
- int step;
- TCREADVNUMBUF64(cbuf, pkid, step);
- cbuf += step;
- csiz -= step;
- }
- if(csiz > 0){
- int off, step;
- TCREADVNUMBUF(cbuf, off, step);
- cbuf += step;
- csiz -= step;
- if(pkbuf){
- if(ores){
- int rsiz;
- if(tcmapget(ores, pkbuf, pksiz, &rsiz)){
- if(sign){
- tcmapputkeep(nres, pkbuf, pksiz, "", 0);
- } else {
- tcmapout(ores, pkbuf, pksiz);
- }
+ tcxstrprintf(hint, "token occurrence: \"%s\" %d\n", word, onum);
+ TCFREE(nocrs);
+ TCFREE(socrs);
+ } else {
+ int onum = 0;
+ TCMAP *uniq = (i > 0 || ores) ? tcmapnew2(UINT16_MAX) : NULL;
+ tcmapiterinit(cc);
+ const char *kbuf;
+ int ksiz;
+ while ((kbuf = tcmapiternext(cc, &ksiz)) != NULL) {
+ if (ksiz < wsiz || memcmp(kbuf, word, wsiz)) continue;
+ int csiz;
+ const char *cbuf = tcmapiterval(kbuf, &csiz);
+ while (csiz > 0) {
+ const char *pkbuf = NULL;
+ int32_t pksiz = 0;
+ int64_t pkid = 0;
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int step;
+ TCREADVNUMBUF(cbuf, pksiz, step);
+ cbuf += step;
+ csiz -= step;
+ pkbuf = cbuf;
+ cbuf += pksiz;
+ csiz -= pksiz;
+ } else {
+ int step;
+ TCREADVNUMBUF64(cbuf, pkid, step);
+ cbuf += step;
+ csiz -= step;
+ }
+ if (csiz > 0) {
+ int off, step;
+ TCREADVNUMBUF(cbuf, off, step);
+ cbuf += step;
+ csiz -= step;
+ if (pkbuf) {
+ if (ores) {
+ int rsiz;
+ if (tcmapget(ores, pkbuf, pksiz, &rsiz)) {
+ if (sign) {
+ tcmapputkeep(nres, pkbuf, pksiz, "", 0);
+ } else {
+ tcmapout(ores, pkbuf, pksiz);
+ }
+ }
+ } else {
+ if (tcmapputkeep(nres, pkbuf, pksiz, "", 0)) onum++;
+ }
+ if (uniq) tcmapputkeep(uniq, pkbuf, pksiz, "", 0);
+ } else {
+ char numbuf[TCNUMBUFSIZ];
+ int pksiz = sprintf(numbuf, "%" PRIdMAX "", (long long) pkid);
+ if (ores) {
+ int rsiz;
+ if (tcmapget(ores, numbuf, pksiz, &rsiz)) {
+ if (sign) {
+ tcmapputkeep(nres, numbuf, pksiz, "", 0);
+ } else {
+ tcmapout(ores, numbuf, pksiz);
+ }
+ }
+ } else {
+ if (tcmapputkeep(nres, numbuf, pksiz, "", 0)) onum++;
+ }
+ if (uniq) tcmapputkeep(uniq, numbuf, pksiz, "", 0);
+ }
+ }
}
- } else {
- if(tcmapputkeep(nres, pkbuf, pksiz, "", 0)) onum++;
- }
- if(uniq) tcmapputkeep(uniq, pkbuf, pksiz, "", 0);
- } else {
- char numbuf[TCNUMBUFSIZ];
- int pksiz = sprintf(numbuf, "%" PRIdMAX "", (long long)pkid);
- if(ores){
- int rsiz;
- if(tcmapget(ores, numbuf, pksiz, &rsiz)){
- if(sign){
- tcmapputkeep(nres, numbuf, pksiz, "", 0);
- } else {
- tcmapout(ores, numbuf, pksiz);
- }
+ }
+ BDBCUR *cur = tcbdbcurnew(db);
+ tcbdbcurjump(cur, word, wsiz);
+ TCXSTR *key = tcxstrnew();
+ TCXSTR *val = tcxstrnew();
+ while (tcbdbcurrec(cur, key, val)) {
+ const char *kbuf = TCXSTRPTR(key);
+ int ksiz = TCXSTRSIZE(key);
+ if (ksiz < wsiz || memcmp(kbuf, word, wsiz)) break;
+ const char *cbuf = TCXSTRPTR(val);
+ int csiz = TCXSTRSIZE(val);
+ while (csiz > 0) {
+ const char *pkbuf = NULL;
+ int32_t pksiz = 0;
+ int64_t pkid = 0;
+ if (*cbuf == '\0') {
+ cbuf++;
+ csiz--;
+ int step;
+ TCREADVNUMBUF(cbuf, pksiz, step);
+ cbuf += step;
+ csiz -= step;
+ pkbuf = cbuf;
+ cbuf += pksiz;
+ csiz -= pksiz;
+ } else {
+ int step;
+ TCREADVNUMBUF64(cbuf, pkid, step);
+ cbuf += step;
+ csiz -= step;
+ }
+ if (csiz > 0) {
+ int off, step;
+ TCREADVNUMBUF(cbuf, off, step);
+ cbuf += step;
+ csiz -= step;
+ if (pkbuf) {
+ if (ores) {
+ int rsiz;
+ if (tcmapget(ores, pkbuf, pksiz, &rsiz)) {
+ if (sign) {
+ tcmapputkeep(nres, pkbuf, pksiz, "", 0);
+ } else {
+ tcmapout(ores, pkbuf, pksiz);
+ }
+ }
+ } else {
+ if (tcmapputkeep(nres, pkbuf, pksiz, "", 0)) onum++;
+ }
+ if (uniq) tcmapputkeep(uniq, pkbuf, pksiz, "", 0);
+ } else {
+ char numbuf[TCNUMBUFSIZ];
+ int pksiz = sprintf(numbuf, "%" PRIdMAX "", (long long) pkid);
+ if (ores) {
+ int rsiz;
+ if (tcmapget(ores, numbuf, pksiz, &rsiz)) {
+ if (sign) {
+ tcmapputkeep(nres, numbuf, pksiz, "", 0);
+ } else {
+ tcmapout(ores, numbuf, pksiz);
+ }
+ }
+ } else {
+ if (tcmapputkeep(nres, numbuf, pksiz, "", 0)) onum++;
+ }
+ if (uniq) tcmapputkeep(uniq, numbuf, pksiz, "", 0);
+ }
+ }
}
- } else {
- if(tcmapputkeep(nres, numbuf, pksiz, "", 0)) onum++;
- }
- if(uniq) tcmapputkeep(uniq, numbuf, pksiz, "", 0);
+ tcbdbcurnext(cur);
}
- }
+ tcxstrdel(val);
+ tcxstrdel(key);
+ tcbdbcurdel(cur);
+ tcxstrprintf(hint, "token occurrence: \"%s\" %d\n",
+ word, uniq ? (int) tcmaprnum(uniq) : onum);
+ if (uniq) tcmapdel(uniq);
}
- tcbdbcurnext(cur);
- }
- tcxstrdel(val);
- tcxstrdel(key);
- tcbdbcurdel(cur);
- tcxstrprintf(hint, "token occurrence: \"%s\" %d\n",
- word, uniq ? (int)tcmaprnum(uniq) : onum);
- if(uniq) tcmapdel(uniq);
+ TCFREE(ary);
}
- TCFREE(ary);
- }
}
-
/* Compare two string occurrences of full-text search in identical order.
`a' specifies the pointer to one occurrence.
`b' specifies the pointer to the other occurrence.
The return value is positive if the former is big, negative if the latter is big, 0 if both
are equivalent. */
-static int tctdbidxftscmpstrocr(TDBFTSSTROCR *a, TDBFTSSTROCR *b){
- assert(a && b);
- if(a->pksiz > b->pksiz) return 1;
- if(a->pksiz < b->pksiz) return -1;
- int diff = memcmp(a->pkbuf, b->pkbuf, a->pksiz);
- if(diff != 0) return diff;
- return a->off - b->off;
+static int tctdbidxftscmpstrocr(TDBFTSSTROCR *a, TDBFTSSTROCR *b) {
+ assert(a && b);
+ if (a->pksiz > b->pksiz) return 1;
+ if (a->pksiz < b->pksiz) return -1;
+ int diff = memcmp(a->pkbuf, b->pkbuf, a->pksiz);
+ if (diff != 0) return diff;
+ return a->off - b->off;
}
-
/* Compare two number occurrences of full-text search in identical order.
`a' specifies the pointer to one occurrence.
`b' specifies the pointer to the other occurrence.
The return value is positive if the former is big, negative if the latter is big, 0 if both
are equivalent. */
-static int tctdbidxftscmpnumocr(TDBFTSNUMOCR *a, TDBFTSNUMOCR *b){
- assert(a && b);
- if(a->pkid > b->pkid) return 1;
- if(a->pkid < b->pkid) return -1;
- return a->off - b->off;
+static int tctdbidxftscmpnumocr(TDBFTSNUMOCR *a, TDBFTSNUMOCR *b) {
+ assert(a && b);
+ if (a->pkid > b->pkid) return 1;
+ if (a->pkid < b->pkid) return -1;
+ return a->off - b->off;
}
-
/* Parse an expression of full-text search.
`expr' specifies the expression.
`esiz' specifies the size of the expression.
is assigned.
`op' specifies the operation type.
The return value is the pointer to the array of full-text search units. */
-static TDBFTSUNIT *tctdbftsparseexpr(const char *expr, int esiz, int op, int *np){
- assert(expr && esiz >= 0 && np);
- TDBFTSUNIT *ftsunits;
- TCMALLOC(ftsunits, TDBFTSUNITMAX * sizeof(*ftsunits));
- int ftsnum = 0;
- uint16_t *ary;
- TCMALLOC(ary, sizeof(*ary) * esiz + 1);
- int anum;
- tcstrutftoucs(expr, ary, &anum);
- anum = tcstrucsnorm(ary, anum, TCUNSPACE | TCUNLOWER | TCUNNOACC | TCUNWIDTH);
- char *str;
- TCMALLOC(str, esiz + 1);
- tcstrucstoutf(ary, anum, str);
- if(op == TDBQCFTSPH){
- TCLIST *tokens = tclistnew2(1);
- tclistpush2(tokens, str);
- ftsunits[ftsnum].tokens = tokens;
- ftsunits[ftsnum].sign = true;
- ftsnum++;
- } else if(op == TDBQCFTSAND){
- TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
- int tnum = TCLISTNUM(tokens);
- for(int i = 0; i < tnum && ftsnum < TDBFTSUNITMAX; i++){
- const char *token = TCLISTVALPTR(tokens, i);
- if(*token == '\0') continue;
- TCLIST *ttokens = tclistnew2(1);
- tclistpush2(ttokens, token);
- ftsunits[ftsnum].tokens = ttokens;
- ftsunits[ftsnum].sign = true;
- ftsnum++;
- }
- tclistdel(tokens);
- } else if(op == TDBQCFTSOR){
- TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
- int tnum = TCLISTNUM(tokens);
- TCLIST *ttokens = tclistnew2(tnum);
- for(int i = 0; i < tnum; i++){
- const char *token = TCLISTVALPTR(tokens, i);
- if(*token == '\0') continue;
- tclistpush2(ttokens, token);
- }
- ftsunits[ftsnum].tokens = ttokens;
- ftsunits[ftsnum].sign = true;
- ftsnum++;
- tclistdel(tokens);
- } else if(op == TDBQCFTSEX){
- TCLIST *tokens = tcstrtokenize(str);
- int op = 0;
- for(int i = 0; i < tclistnum(tokens); i++){
- const char *token = TCLISTVALPTR(tokens, i);
- if(!strcmp(token, "&&")){
- op = 0;
- } else if(!strcmp(token, "||")){
- op = 1;
- } else if(!strcmp(token, "!!")){
- op = 2;
- } else {
- if(op == 0 || op == 2){
- if(ftsnum >= TDBFTSUNITMAX) break;
- TCLIST *ttokens = tclistnew2(2);
- tclistpush2(ttokens, token);
- ftsunits[ftsnum].tokens = ttokens;
- ftsunits[ftsnum].sign = op == 0;
- ftsnum++;
- } else if(op == 1){
- if(ftsnum < 1){
- ftsunits[ftsnum].tokens = tclistnew2(2);
- ftsunits[ftsnum].sign = op == 0;
+static TDBFTSUNIT *tctdbftsparseexpr(const char *expr, int esiz, int op, int *np) {
+ assert(expr && esiz >= 0 && np);
+ TDBFTSUNIT *ftsunits;
+ TCMALLOC(ftsunits, TDBFTSUNITMAX * sizeof (*ftsunits));
+ int ftsnum = 0;
+ uint16_t *ary;
+ TCMALLOC(ary, sizeof (*ary) * esiz + 1);
+ int anum;
+ tcstrutftoucs(expr, ary, &anum);
+ anum = tcstrucsnorm(ary, anum, TCUNSPACE | TCUNLOWER | TCUNNOACC | TCUNWIDTH);
+ char *str;
+ TCMALLOC(str, esiz + 1);
+ tcstrucstoutf(ary, anum, str);
+ if (op == TDBQCFTSPH) {
+ TCLIST *tokens = tclistnew2(1);
+ tclistpush2(tokens, str);
+ ftsunits[ftsnum].tokens = tokens;
+ ftsunits[ftsnum].sign = true;
+ ftsnum++;
+ } else if (op == TDBQCFTSAND) {
+ TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
+ int tnum = TCLISTNUM(tokens);
+ for (int i = 0; i < tnum && ftsnum < TDBFTSUNITMAX; i++) {
+ const char *token = TCLISTVALPTR(tokens, i);
+ if (*token == '\0') continue;
+ TCLIST *ttokens = tclistnew2(1);
+ tclistpush2(ttokens, token);
+ ftsunits[ftsnum].tokens = ttokens;
+ ftsunits[ftsnum].sign = true;
ftsnum++;
- }
- TCLIST *ttokens = ftsunits[ftsnum-1].tokens;
- tclistpush2(ttokens, token);
}
- op = 0;
- }
+ tclistdel(tokens);
+ } else if (op == TDBQCFTSOR) {
+ TCLIST *tokens = tcstrsplit(expr, "\t\n\r ,");
+ int tnum = TCLISTNUM(tokens);
+ TCLIST *ttokens = tclistnew2(tnum);
+ for (int i = 0; i < tnum; i++) {
+ const char *token = TCLISTVALPTR(tokens, i);
+ if (*token == '\0') continue;
+ tclistpush2(ttokens, token);
+ }
+ ftsunits[ftsnum].tokens = ttokens;
+ ftsunits[ftsnum].sign = true;
+ ftsnum++;
+ tclistdel(tokens);
+ } else if (op == TDBQCFTSEX) {
+ TCLIST *tokens = tcstrtokenize(str);
+ int op = 0;
+ for (int i = 0; i < tclistnum(tokens); i++) {
+ const char *token = TCLISTVALPTR(tokens, i);
+ if (!strcmp(token, "&&")) {
+ op = 0;
+ } else if (!strcmp(token, "||")) {
+ op = 1;
+ } else if (!strcmp(token, "!!")) {
+ op = 2;
+ } else {
+ if (op == 0 || op == 2) {
+ if (ftsnum >= TDBFTSUNITMAX) break;
+ TCLIST *ttokens = tclistnew2(2);
+ tclistpush2(ttokens, token);
+ ftsunits[ftsnum].tokens = ttokens;
+ ftsunits[ftsnum].sign = op == 0;
+ ftsnum++;
+ } else if (op == 1) {
+ if (ftsnum < 1) {
+ ftsunits[ftsnum].tokens = tclistnew2(2);
+ ftsunits[ftsnum].sign = op == 0;
+ ftsnum++;
+ }
+ TCLIST *ttokens = ftsunits[ftsnum - 1].tokens;
+ tclistpush2(ttokens, token);
+ }
+ op = 0;
+ }
+ }
+ tclistdel(tokens);
}
- tclistdel(tokens);
- }
- TCFREE(str);
- TCFREE(ary);
- *np = ftsnum;
- return ftsunits;
+ TCFREE(str);
+ TCFREE(ary);
+ *np = ftsnum;
+ return ftsunits;
}
-
/* Perform dynamic defragmentation of a table database object.
`tdb' specifies the table database object.
`step' specifie the number of steps.
If successful, the return value is true, else, it is false. */
-static bool tctdbdefragimpl(TCTDB *tdb, int64_t step){
- assert(tdb);
- bool err = false;
- TCHDB *hdb = tdb->hdb;
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- if(!tchdbdefrag(hdb, step)) err = true;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tcbdbdefrag(idx->db, step)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- }
- }
- return !err;
+static bool tctdbdefragimpl(TCTDB *tdb, int64_t step) {
+ assert(tdb);
+ bool err = false;
+ TCHDB *hdb = tdb->hdb;
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ if (!tchdbdefrag(hdb, step)) err = true;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tcbdbdefrag(idx->db, step)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ }
+ }
+ return !err;
}
-
/* Clear the cache of a table tree database object.
`tdb' specifies the table tree database object.
If successful, the return value is true, else, it is false. */
-static bool tctdbcacheclearimpl(TCTDB *tdb){
- assert(tdb);
- bool err = false;
- TCHDB *hdb = tdb->hdb;
- TDBIDX *idxs = tdb->idxs;
- int inum = tdb->inum;
- if(!tchdbcacheclear(hdb)) err = true;
- for(int i = 0; i < inum; i++){
- TDBIDX *idx = idxs + i;
- switch(idx->type){
- case TDBITLEXICAL:
- case TDBITDECIMAL:
- case TDBITTOKEN:
- case TDBITQGRAM:
- if(!tcbdbcacheclear(idx->db)){
- tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
- err = true;
- }
- break;
- }
- }
- return !err;
+static bool tctdbcacheclearimpl(TCTDB *tdb) {
+ assert(tdb);
+ bool err = false;
+ TCHDB *hdb = tdb->hdb;
+ TDBIDX *idxs = tdb->idxs;
+ int inum = tdb->inum;
+ if (!tchdbcacheclear(hdb)) err = true;
+ for (int i = 0; i < inum; i++) {
+ TDBIDX *idx = idxs + i;
+ switch (idx->type) {
+ case TDBITLEXICAL:
+ case TDBITDECIMAL:
+ case TDBITTOKEN:
+ case TDBITQGRAM:
+ if (!tcbdbcacheclear(idx->db)) {
+ tctdbsetecode(tdb, tcbdbecode(idx->db), __FILE__, __LINE__, __func__);
+ err = true;
+ }
+ break;
+ }
+ }
+ return !err;
}
-
/* Process each record atomically of a table database object.
`tdb' specifies the table database object.
`func' specifies the pointer to the iterator function called for each record.
`op' specifies an arbitrary pointer to be given as a parameter of the iterator function.
If successful, the return value is true, else, it is false. */
-static bool tctdbforeachimpl(TCTDB *tdb, TCITER iter, void *op){
- assert(tdb && iter);
- TCHDB *hdb = tdb->hdb;
- char *lkbuf = NULL;
- int lksiz = 0;
- char *pkbuf, stack[TDBPAGEBUFSIZ], *rbuf;
- int pksiz;
- const char *cbuf;
- int csiz;
- while((pkbuf = tchdbgetnext3(hdb, lkbuf, lksiz, &pksiz, &cbuf, &csiz)) != NULL){
- if(pksiz < TDBPAGEBUFSIZ){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, pksiz + 1);
+static bool tctdbforeachimpl(TCTDB *tdb, TCITER iter, void *op) {
+ assert(tdb && iter);
+ TCHDB *hdb = tdb->hdb;
+ char *lkbuf = NULL;
+ int lksiz = 0;
+ char *pkbuf, stack[TDBPAGEBUFSIZ], *rbuf;
+ int pksiz;
+ const char *cbuf;
+ int csiz;
+ while ((pkbuf = tchdbgetnext3(hdb, lkbuf, lksiz, &pksiz, &cbuf, &csiz)) != NULL) {
+ if (pksiz < TDBPAGEBUFSIZ) {
+ rbuf = stack;
+ } else {
+ TCMALLOC(rbuf, pksiz + 1);
+ }
+ memcpy(rbuf, pkbuf, pksiz);
+ stack[pksiz] = '\0';
+ TCMAP *cols = tcmapload(cbuf, csiz);
+ int zsiz;
+ char *zbuf = tcstrjoin4(cols, &zsiz);
+ bool rv = iter(rbuf, pksiz, zbuf, zsiz, op);
+ TCFREE(zbuf);
+ if (rbuf != stack) TCFREE(rbuf);
+ tcmapdel(cols);
+ TCFREE(lkbuf);
+ lkbuf = pkbuf;
+ lksiz = pksiz;
+ if (!rv) break;
}
- memcpy(rbuf, pkbuf, pksiz);
- stack[pksiz] = '\0';
- TCMAP *cols = tcmapload(cbuf, csiz);
- int zsiz;
- char *zbuf = tcstrjoin4(cols, &zsiz);
- bool rv = iter(rbuf, pksiz, zbuf, zsiz, op);
- TCFREE(zbuf);
- if(rbuf != stack) TCFREE(rbuf);
- tcmapdel(cols);
TCFREE(lkbuf);
- lkbuf = pkbuf;
- lksiz = pksiz;
- if(!rv) break;
- }
- TCFREE(lkbuf);
- return true;
+ return true;
}
-
/* Answer to remove for each record of a query.
`pkbuf' is ignored.
`pksiz' is ignored.
`op' is ignored.
The return value is always `TDBQPOUT'. */
-static int tctdbqryprocoutcb(const void *pkbuf, int pksiz, TCMAP *cols, void *op){
- assert(pkbuf && pksiz >= 0 && cols);
- return TDBQPOUT;
+static int tctdbqryprocoutcb(const void *pkbuf, int pksiz, TCMAP *cols, void *op) {
+ assert(pkbuf && pksiz >= 0 && cols);
+ return TDBQPOUT;
}
-
/* Lock a method of the table database object.
`tdb' specifies the table database object.
`wr' specifies whether the lock is writer or not.
If successful, the return value is true, else, it is false. */
-static bool tctdblockmethod(TCTDB *tdb, bool wr){
- assert(tdb);
- if(wr ? pthread_rwlock_wrlock(tdb->mmtx) != 0 : pthread_rwlock_rdlock(tdb->mmtx) != 0){
- tctdbsetecode(tdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
+static bool tctdblockmethod(TCTDB *tdb, bool wr) {
+ assert(tdb);
+ if (wr ? pthread_rwlock_wrlock(tdb->mmtx) != 0 : pthread_rwlock_rdlock(tdb->mmtx) != 0) {
+ tctdbsetecode(tdb, TCETHREAD, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ TCTESTYIELD();
+ return true;
}
-
/* Unlock a method of the table database object.
`tdb' specifies the table database object.
If successful, the return value is true, else, it is false. */
-static bool tctdbunlockmethod(TCTDB *tdb){
- assert(tdb);
- if(pthread_rwlock_unlock(tdb->mmtx) != 0){
- tctdbsetecode(tdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
+static bool tctdbunlockmethod(TCTDB *tdb) {
+ assert(tdb);
+ if (pthread_rwlock_unlock(tdb->mmtx) != 0) {
+ tctdbsetecode(tdb, TCETHREAD, __FILE__, __LINE__, __func__);
+ return false;
+ }
+ TCTESTYIELD();
+ return true;
}
* debugging functions
*************************************************************************************************/
-
/* Print meta data of the header into the debugging output.
`tdb' specifies the table database object. */
-void tctdbprintmeta(TCTDB *tdb){
- assert(tdb);
- HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
- if(!INVALIDHANDLE(dbgfd)) {
- dbgfd = GET_STDOUT_HANDLE();
- }
- char buf[TDBPAGEBUFSIZ];
- char *wp = buf;
- wp += sprintf(wp, "META:");
- wp += sprintf(wp, " mmtx=%p", (void *)tdb->mmtx);
- wp += sprintf(wp, " hdb=%p", (void *)tdb->hdb);
- wp += sprintf(wp, " open=%d", tdb->open);
- wp += sprintf(wp, " wmode=%d", tdb->wmode);
- wp += sprintf(wp, " opts=%u", tdb->opts);
- wp += sprintf(wp, " lcnum=%d", tdb->lcnum);
- wp += sprintf(wp, " ncnum=%d", tdb->ncnum);
- wp += sprintf(wp, " iccmax=%" PRIdMAX "", (long long)tdb->iccmax);
- wp += sprintf(wp, " iccsync=%f", tdb->iccsync);
- wp += sprintf(wp, " idxs=%p", (void *)tdb->idxs);
- wp += sprintf(wp, " inum=%d", tdb->inum);
- wp += sprintf(wp, " tran=%d", tdb->tran);
- *(wp++) = '\n';
- tcwrite(dbgfd, buf, wp - buf);
+void tctdbprintmeta(TCTDB *tdb) {
+ assert(tdb);
+ HANDLE dbgfd = tchdbdbgfd(tdb->hdb);
+ if (!INVALIDHANDLE(dbgfd)) {
+ dbgfd = GET_STDOUT_HANDLE();
+ }
+ char buf[TDBPAGEBUFSIZ];
+ char *wp = buf;
+ wp += sprintf(wp, "META:");
+ wp += sprintf(wp, " mmtx=%p", (void *) tdb->mmtx);
+ wp += sprintf(wp, " hdb=%p", (void *) tdb->hdb);
+ wp += sprintf(wp, " open=%d", tdb->open);
+ wp += sprintf(wp, " wmode=%d", tdb->wmode);
+ wp += sprintf(wp, " opts=%u", tdb->opts);
+ wp += sprintf(wp, " lcnum=%d", tdb->lcnum);
+ wp += sprintf(wp, " ncnum=%d", tdb->ncnum);
+ wp += sprintf(wp, " iccmax=%" PRIdMAX "", (long long) tdb->iccmax);
+ wp += sprintf(wp, " iccsync=%f", tdb->iccsync);
+ wp += sprintf(wp, " idxs=%p", (void *) tdb->idxs);
+ wp += sprintf(wp, " inum=%d", tdb->inum);
+ wp += sprintf(wp, " tran=%d", tdb->tran);
+ *(wp++) = '\n';
+ tcwrite(dbgfd, buf, wp - buf);
}