int mqi_create_table_trigger(mqi_trigger_cb_t callback, void *user_data) { mqi_db_t *db; mqi_db_functbl_t *ftb; int i; MDB_CHECKARG(callback, -1); MDB_PREREQUISITE(dbs && ndb > 0, -1); for (i = 0; i < ndb; i++) { db = dbs + i; ftb = db->functbl; if (ftb->create_table_trigger(callback, user_data) < 0) { for (i--; i >= 0; i--) { db = dbs + i; ftb = db->functbl; ftb->drop_table_trigger(callback, user_data); } return -1; } } return 0; }
void *mdb_handle_get_data(mdb_handle_map_t *hmap, mdb_handle_t h) { uint32_t useid = HANDLE_USEID(h); int index = HANDLE_INDEX(h); indextbl_t *indextbl; indextbl_entry_t *entry; MDB_CHECKARG(hmap && h != MDB_HANDLE_INVALID, NULL); indextbl = &hmap->indextbl; if (index >= indextbl->nentry) { errno = EKEYREJECTED; return NULL; } entry = indextbl->entries + index; if (entry->useid != useid) { errno = ENOANO; return NULL; } if (!entry->data) errno = ENODATA; return entry->data; }
static void *index_realloc(indextbl_t *indextbl, uint32_t useid, int index, void *data) { indextbl_entry_t *entry; void *old_data; MDB_CHECKARG(indextbl, NULL); if (index < 0 || index >= indextbl->nentry) { errno = EKEYREJECTED; return NULL; } entry = indextbl->entries + index; if (entry->useid != useid) { errno = ENOKEY; return NULL; } if (!(old_data = entry->data)) { errno = ENOENT; return NULL; } entry->data = data; return old_data; }
double mql_result_rows_get_floating(mql_result_t *r, int colidx, int rowidx) { result_rows_t *rslt = (result_rows_t *)r; void *addr; double v = 0; MDB_CHECKARG(rslt && rslt->type == mql_result_rows && colidx >= 0 && colidx < rslt->ncol && rowidx >= 0 && rowidx < rslt->nrow, 0.0); if ((addr = get_column_address(rslt, colidx, rowidx))) { switch (get_column_type(rslt, colidx)) { case mqi_varchar: v = strtod(*(char **)addr, NULL); break; case mqi_integer: v = *(int32_t *)addr; break; case mqi_unsignd: v = *(uint32_t *)addr; break; case mqi_floating: v = *(double *)addr; break; default: v = 0; break; } } return v; }
static int db_register(const char *engine, uint32_t flags, mqi_db_functbl_t *functbl) { mqi_db_t *db; int i; MDB_CHECKARG(engine && engine[0] && functbl, -1); MDB_PREREQUISITE(dbs, -1); if (ndb + 1 >= MAX_DB) { errno = EOVERFLOW; return -1; } for (i = 0; i < ndb; i++) { if (!strcmp(engine, dbs[i].engine)) { errno = EEXIST; return -1; } } db = dbs + ndb++; db->engine = strdup(engine); db->flags = flags; db->functbl = functbl; return 0; }
int mdb_index_print(mdb_table_t *tbl, char *buf, int len) { #define PRINT(args...) if (e > p) p += snprintf(p, e-p, args) mdb_index_t *ix; const char *sep; char *p, *e; int i; MDB_CHECKARG(tbl && buf && len > 0, 0); ix = &tbl->index; MDB_PREREQUISITE(MDB_INDEX_DEFINED(ix), 0); e = (p = buf) + len; PRINT("index columns: "); for (i = 0, sep = ""; i < ix->ncolumn; i++, sep = ",") PRINT("%s%02d", sep, ix->columns[i]); PRINT("\n type offset length\n ---------------------" "\n %-7s %4d %4d\n", mqi_data_type_str(ix->type), ix->offset, ix->length); return p - buf; #undef PRINT }
int mdb_index_delete(mdb_table_t *tbl, mdb_row_t *row) { mdb_index_t *ix; int lgh; void *key; mdb_hash_t *hash; mdb_sequence_t *seq; MDB_CHECKARG(tbl && row, -1); ix = &tbl->index; if (!MDB_INDEX_DEFINED(ix)) return 0; hash = ix->hash; seq = ix->sequence; lgh = ix->length; key = (void *)row->data + ix->offset; if (mdb_hash_delete(hash, lgh,key) != row || mdb_sequence_delete(seq, lgh,key) != row) { errno = EIO; return -1; } return 0; }
int mqi_drop_table(mqi_handle_t h) { mqi_table_t *tbl; mqi_db_functbl_t *ftb; char *name; void *data; void *cursor; int sts; MDB_CHECKARG(h != MDB_HANDLE_INVALID, -1); MDB_PREREQUISITE(dbs && ndb > 0, -1); if (!(tbl = mdb_handle_delete(table_handle, h))) return -1; ftb = tbl->db->functbl; MDB_HASH_TABLE_FOR_EACH_WITH_KEY_SAFE(table_name_hash, data,name, cursor) { if ((mqi_handle_t)(data - NULL) == h) { mdb_hash_delete(table_name_hash, 0,name); sts = ftb->drop_table(tbl->handle); free(name); free(tbl); return sts; } } return -1; }
int mqi_rollback_transaction(mqi_handle_t h) { uint32_t depth = TX_DEPTH(h); uint32_t useid = TX_USEID(h); mqi_transaction_t *tx; mqi_db_t *db; mqi_db_functbl_t *ftb; int err; int i; MDB_CHECKARG(h != MQI_HANDLE_INVALID && depth < MQI_TXDEPTH_MAX, -1); MDB_PREREQUISITE(dbs && ndb > 0, -1); MDB_ASSERT(txdepth > 0 && depth == (uint32_t)txdepth - 1, EBADSLT, -1); tx = txstack + depth; MDB_ASSERT(tx->useid == useid, EBADSLT, -1); for (i = 0, err = 0; i < ndb; i++) { db = dbs + i; ftb = db->functbl; if (ftb->rollback_transaction(tx->txid[i]) < 0) err = -1; } txdepth--; return err; }
double mql_result_list_get_floating(mql_result_t *r, int idx) { result_list_t *rslt = (result_list_t *)r; double v = 0; MDB_CHECKARG(rslt && rslt->type == mql_result_list && idx >= 0 && idx < rslt->length, 0); switch (rslt->value.type) { case mqi_varchar: v = strtod(rslt->value.v.varchar[idx], NULL); break; case mqi_integer: v = rslt->value.v.integer[idx]; break; case mqi_unsignd: v = rslt->value.v.unsignd[idx]; break; case mqi_floating: v = rslt->value.v.floating[idx]; break; default: v = 0; break; } return v; }
mql_result_t *mql_result_string_create_table_change(mqi_event_type_t event, const char *table) { #define EVENT 0 #define TABLE 1 #define FLDS 2 static const char *hstr[FLDS] = {" event", "table"}; static int hlen[FLDS] = { 6 , 5 }; result_string_t *rslt; int len[FLDS]; const char *cstr[FLDS]; int cw[FLDS]; int linlen; char *p; int i; MDB_CHECKARG((event == mqi_table_created || event == mqi_table_dropped) && table, NULL); cstr[EVENT] = (event == mqi_table_created) ? "'table created'" : "'table dropped'"; cstr[TABLE] = table; for (i = 0; i < FLDS; i++) len[i] = strlen(cstr[i]); for (linlen = (FLDS-1) * 2 + 1, i = 0; i < FLDS; i++) linlen += (cw[i] = len[i] > hlen[i] ? len[i] : hlen[i]); if (!(rslt = calloc(1, sizeof(result_string_t) + (linlen*3 + 1)))) { errno = ENOMEM; return NULL; } p = rslt->string; for (i = 0; i < FLDS; i++) p += sprintf(p, "%-*s%s", cw[i], hstr[i], i == FLDS-1 ? "\n" : " "); memset(p, '-', linlen-1); p[linlen-1] = '\n'; p += linlen; for (i = 0; i < FLDS; i++) p += sprintf(p, "%-*s%s", cw[i], cstr[i], i == FLDS-1 ? "\n" : " "); rslt->type = mql_result_string; rslt->length = p - rslt->string; return (mql_result_t *)rslt; #undef FLDS #undef TABLE #undef EVENT }
int mdb_sequence_add(mdb_sequence_t *seq, int klen, void *key, void *data) { sequence_entry_t *entry; int nentry; size_t old_length; size_t length; int cmp; int min, max, i; MDB_CHECKARG(seq && key && data, -1); nentry = seq->nentry++; if ((nentry + 1) > seq->size) { old_length = sizeof(sequence_entry_t) * seq->size; seq->size += seq->alloc; length = sizeof(sequence_entry_t) * seq->size; if (!(seq->entries = realloc(seq->entries, length))) { seq->nentry = 0; errno = ENOMEM; return -1; } memset(seq->entries + old_length, 0, length - old_length); } for (min = 0, i = (max = nentry)/2; ; i = (min+max)/2) { if (!(cmp = seq->scomp(klen, key, seq->entries[i].key))) break; if (i == min) { if (cmp > 0) i = max; break; } if (cmp < 0) max = i; else min = i; } entry = seq->entries + i; if (i < nentry) { memmove(entry+1, entry, sizeof(sequence_entry_t) * (nentry - i)); } entry->key = key; entry->data = data; #ifdef SEQUENCE_STATISTICS if (seq->nentry > seq->max_entry) seq->max_entry = seq->nentry; #endif return 0; }
int mql_result_columns_get_column_count(mql_result_t *r) { result_columns_t *rslt = (result_columns_t *)r; MDB_CHECKARG(rslt && rslt->type == mql_result_columns, -1); return rslt->ncol; }
const char *mql_result_string_get(mql_result_t *r) { result_string_t *rslt = (result_string_t *)r; MDB_CHECKARG(rslt && rslt->type == mql_result_string, ""); return rslt->string; }
int mql_result_rows_get_row_count(mql_result_t *r) { result_rows_t *rslt = (result_rows_t *)r; MDB_CHECKARG(rslt && rslt->type == mql_result_rows, -1); return rslt->nrow; }
int mql_result_list_get_length(mql_result_t *r) { result_list_t *rslt = (result_list_t *)r; MDB_CHECKARG(rslt && rslt->type == mql_result_list, -1); return rslt->length; }
int mdb_sequence_table_destroy(mdb_sequence_t *seq) { MDB_CHECKARG(seq, -1); free(seq->entries); free(seq); return 0; }
mqi_data_type_t mql_result_rows_get_row_column_type(mql_result_t *r, int colidx) { result_rows_t *rslt = (result_rows_t *)r; MDB_CHECKARG(rslt && rslt->type == mql_result_rows && rslt->ncol > colidx, -1); return rslt->cols[colidx].type; }
int mql_result_rows_get_row_column_index(mql_result_t *r, int colidx) { result_rows_t *rslt = (result_rows_t *)r; MDB_CHECKARG(rslt && rslt->type == mql_result_rows && rslt->ncol > colidx, -1); return rslt->cols[colidx].cindex; }
uint32_t mql_result_columns_get_flags(mql_result_t *r, int colidx) { result_columns_t *rslt = (result_columns_t *)r; MDB_CHECKARG(rslt && rslt->type == mql_result_columns && colidx >= 0 && colidx < rslt->ncol, -1); return rslt->cols[colidx].flags; }
int mql_result_columns_get_length(mql_result_t *r, int colidx) { result_columns_t *rslt = (result_columns_t *)r; MDB_CHECKARG(rslt && rslt->type == mql_result_columns && colidx >= 0 && colidx < rslt->ncol, -1); return rslt->cols[colidx].length; }
mqi_data_type_t mql_result_columns_get_type(mql_result_t *r, int colidx) { result_columns_t *rslt = (result_columns_t *)r; MDB_CHECKARG(rslt && rslt->type == mql_result_columns && colidx >= 0 && colidx < rslt->ncol, -1); return rslt->cols[colidx].type; }
const char *mql_result_columns_get_name(mql_result_t *r, int colidx) { result_columns_t *rslt = (result_columns_t *)r; MDB_CHECKARG(rslt && rslt->type == mql_result_columns && colidx >= 0 && colidx < rslt->ncol, NULL); return rslt->cols[colidx].name; }
mdb_row_t *mdb_index_get_row(mdb_table_t *tbl, int idxlen, void *idxval) { mdb_index_t *ix; MDB_CHECKARG(tbl && idxlen >= 0 && idxval, NULL); ix = &tbl->index; return mdb_hash_get_data(ix->hash, idxlen, idxval); }
const char *mql_result_rows_get_string(mql_result_t *r, int colidx, int rowidx, char *buf, int len) { result_rows_t *rslt = (result_rows_t *)r; void *addr; char *v = NULL; MDB_CHECKARG(rslt && rslt->type == mql_result_rows && colidx >= 0 && colidx < rslt->ncol && rowidx >= 0 && rowidx < rslt->nrow && (!buf || (buf && len > 0)), NULL); if ((v = buf)) *v = '\0'; if ((addr = get_column_address(rslt, colidx, rowidx))) { switch (get_column_type(rslt, colidx)) { case mqi_varchar: if (!v) v = *(char **)addr; else { strncpy(v, *(char **)addr, len); v[len-1] = '\0'; } break; case mqi_integer: if (!v) v = ""; else snprintf(v, len, "%d", *(int32_t *)addr); break; case mqi_unsignd: if (!v) v = ""; else snprintf(v, len, "%u", *(uint32_t *)addr); break; case mqi_floating: if (!v) v = ""; else snprintf(v, len, "%lf", *(double *)addr); break; default: v = ""; break; } } return v; }
int mdb_handle_map_destroy(mdb_handle_map_t *hmap) { MDB_CHECKARG(hmap, -1); free(hmap->freemap.buckets); free(hmap->indextbl.entries); free(hmap); return 0; }
mql_result_t *mql_result_list_create(mqi_data_type_t type, int length, void *values) { result_list_t *rslt; size_t datalen; char **strs; int *slen = NULL; char *strpool; int poollen = 0; int i; MDB_CHECKARG(length > 0 && values, NULL); switch (type) { case mqi_varchar: slen = alloca(sizeof(int) * length); for (strs = (char **)values, i = 0; i < length; i++) poollen += (slen[i] = strlen(strs[i]) + 1); datalen = sizeof(char *) * length + poollen; break; case mqi_integer: datalen = sizeof(int32_t) * length; break; case mqi_unsignd: datalen = sizeof(uint32_t) * length; break; case mqi_floating: datalen = sizeof(double) * length; break; default: errno = EINVAL; return NULL; } if ((rslt = calloc(1, sizeof(result_list_t) + datalen))) { rslt->type = mql_result_list; rslt->length = length; rslt->value.type = type; if (type != mqi_varchar) memcpy(rslt->value.v.generic, values, datalen); else { strs = (char **)values; strpool = (char *)&rslt->value.v.varchar[length]; for (i = 0; i < length; i++) { rslt->value.v.varchar[i] = memcpy(strpool, strs[i], slen[i]); strpool += slen[i]; } } } return (mql_result_t *)rslt; }
int mqi_print_rows(mqi_handle_t h, char *buf, int len) { mqi_db_functbl_t *ftb; void *tbl; MDB_CHECKARG(h != MDB_HANDLE_INVALID && buf && len > 0, -1); MDB_PREREQUISITE(dbs && ndb > 0, -1); GET_TABLE(tbl, ftb, h, -1); return ftb->print_rows(tbl, buf, len); }
int mdb_sequence_table_reset(mdb_sequence_t *seq) { MDB_CHECKARG(seq, -1); free(seq->entries); seq->size = 0; seq->nentry = 0; seq->entries = NULL; return 0; }
mdb_handle_t mdb_handle_add(mdb_handle_map_t *hmap, void *data) { int index; MDB_CHECKARG(hmap && data, MDB_HANDLE_INVALID); if ((index = freemap_alloc(&hmap->freemap)) == HANDLE_INDEX_INVALID) { return MDB_HANDLE_INVALID; } return index_alloc(&hmap->indextbl, index, data); }