📄 mapi.mx
字号:
assert(hdl); mid = hdl->mid; assert(mid); if (mid->noexplain == NULL) { fprintf(fd, "MAPI = %s\@%s:%d\n", mid->username, mid->hostname, mid->port); if (mid->action) fprintf(fd, "ACTION= %s\n", mid->action); if (hdl->query) indented_print(hdl->query, "QUERY = ", fd); if (mid->errorstr) indented_print(mid->errorstr, "ERROR = ", fd); } else if (mid->errorstr) { clean_print(mid->errorstr, mid->noexplain, fd); } fflush(fd); mapi_clrError(mid); return MOK;}MapiMsgmapi_explain_result(MapiHdl hdl, FILE *fd){ Mapi mid; if (hdl == NULL || hdl->result == NULL || hdl->result->errorstr == NULL) return MOK; assert(hdl); assert(hdl->result); assert(hdl->result->errorstr); mid = hdl->mid; assert(mid); if (mid->noexplain == NULL) { fprintf(fd, "MAPI = %s\@%s:%d\n", mid->username, mid->hostname, mid->port); if (mid->action) fprintf(fd, "ACTION= %s\n", mid->action); if (hdl->query) indented_print(hdl->query, "QUERY = ", fd); indented_print(hdl->result->errorstr, "ERROR = ", fd); } else { clean_print(hdl->result->errorstr, mid->noexplain, fd); } fflush(fd); return MOK;}intmapi_get_trace(Mapi mid){ mapi_check0(mid, "mapi_get_trace"); return mid->trace;}MapiMsgmapi_trace_log(Mapi mid, const char *nme){ mapi_clrError(mid); mid->tracelog = open_wastream(nme); if (mid->tracelog == NULL || stream_errnr(mid->tracelog)) { if (mid->tracelog) stream_destroy(mid->tracelog); mid->tracelog = NULL; return mapi_setError(mid, "Could not create log file", "mapi_trace_log", MERROR); } return MOK;}/* send a dummy request to the server to see whether the connection is still alive */MapiMsgmapi_ping(Mapi mid){ MapiHdl hdl = NULL; mapi_check(mid, "mapi_ping"); switch (mid->languageId) { case LANG_SQL: hdl = mapi_query(mid, "select true;"); break; case LANG_MAL: hdl = mapi_query(mid, "io.print(1);"); break; case LANG_MIL: hdl = mapi_query(mid, "print(1);"); break; } if (hdl) mapi_close_handle(hdl); return mid->error;}/* allocate a new structure to represent a result set */static struct MapiResultSet *new_result(MapiHdl hdl){ struct MapiResultSet *result; assert((hdl->lastresult == NULL && hdl->result == NULL) || (hdl->result != NULL && hdl->lastresult != NULL && hdl->lastresult->next == NULL)); if (hdl->mid->trace == MAPI_TRACE) printf("allocating new result set\n"); /* append a newly allocated struct to the end of the linked list */ result = malloc(sizeof(*result)); result->next = NULL; if (hdl->lastresult == NULL) hdl->result = hdl->lastresult = result; else { hdl->lastresult->next = result; hdl->lastresult = result; } result->hdl = hdl; result->tableid = -1; result->querytype = -1; result->errorstr = NULL; result->row_count = 0; result->fieldcnt = 0; result->maxfields = 0; result->fields = NULL; result->cache.rowlimit = hdl->mid->cachelimit; result->cache.shuffle = 100; result->cache.limit = 0; result->cache.writer = 0; result->cache.reader = -1; result->cache.first = 0; result->cache.tuplecount = 0; result->cache.line = NULL; return result;}/* close a result set, discarding any unread results */static MapiMsgclose_result(MapiHdl hdl){ struct MapiResultSet *result; Mapi mid; int i; result = hdl->result; if (result == NULL) return MERROR; mid = hdl->mid; assert(mid != NULL); if (mid->trace == MAPI_TRACE) printf("closing result set\n"); if (result->tableid >= 0 && result->querytype != Q_PREPARE) { if (mid->active && !mid->active->needmore && read_into_cache(mid->active, 0) != MOK) return MERROR; assert(hdl->npending_close == 0 || (hdl->npending_close > 0 && hdl->pending_close != NULL)); if (mid->active && result->cache.tuplecount < result->row_count) { /* can't write "X" commands now, so save for later */ REALLOC(hdl->pending_close, hdl->npending_close + 1); hdl->pending_close[hdl->npending_close] = result->tableid; hdl->npending_close++; } else if (mid->to != NULL) { /* first close saved up to-be-closed tables */ for (i = 0; i < hdl->npending_close; i++) { mid->active = hdl; if (stream_printf(mid->to, "X" "close %d\n", hdl->pending_close[i]) < 0 || stream_flush(mid->to)) { close_connection(mid); mapi_setError(mid, stream_error(mid->to), "mapi_close_handle", MTIMEOUT); break; } read_into_cache(hdl, 0); } hdl->npending_close = 0; if (hdl->pending_close) free(hdl->pending_close); hdl->pending_close = NULL; if (mid->to != NULL && result->cache.tuplecount < result->row_count) { mid->active = hdl; if (stream_printf(mid->to, "X" "close %d\n", result->tableid) < 0 || stream_flush(mid->to)) { close_connection(mid); mapi_setError(mid, stream_error(mid->to), "mapi_close_handle", MTIMEOUT); } else read_into_cache(hdl, 0); } } result->tableid = -1; } if (mid->active == hdl && hdl->active == result && read_into_cache(hdl, -1) != MOK) return MERROR; assert(hdl->active != result); if (result->fields) { for (i = 0; i < result->maxfields; i++) { if (result->fields[i].tablename) free(result->fields[i].tablename); if (result->fields[i].columnname) free(result->fields[i].columnname); if (result->fields[i].columntype) free(result->fields[i].columntype); } free(result->fields); } result->fields = NULL; result->maxfields = result->fieldcnt = 0; if (result->cache.line) { for (i = 0; i < result->cache.writer; i++) { if (result->cache.line[i].rows) free(result->cache.line[i].rows); if (result->cache.line[i].anchors) free(result->cache.line[i].anchors); } free(result->cache.line); result->cache.line = NULL; result->cache.tuplecount = 0; } if (result->errorstr) free(result->errorstr); result->errorstr = NULL; result->hdl = NULL; hdl->result = result->next; if (hdl->result == NULL) hdl->lastresult = NULL; result->next = NULL; free(result); return MOK;}static voidadd_error(struct MapiResultSet *result, char *error){ /* concatenate the error messages */ size_t size = result->errorstr ? strlen(result->errorstr) : 0; REALLOC(result->errorstr, size + strlen(error) + 2); strcpy(result->errorstr + size, error); strcat(result->errorstr + size, "\n");}char *mapi_result_error(MapiHdl hdl){ return hdl && hdl->result ? hdl->result->errorstr : NULL;}/* Go to the next result set, if any, and close the current result set. This function returns 1 if there are more result sets after the one that was closed, otherwise, if more input is needed, return MMORE, else, return MOK */MapiMsgmapi_next_result(MapiHdl hdl){ mapi_hdl_check(hdl, "mapi_next_result"); while (hdl->result != NULL) { if (close_result(hdl) != MOK) return MERROR; if (hdl->result && (hdl->result->querytype == -1 || hdl->result->querytype == Q_TABLE || hdl->result->querytype == Q_UPDATE || hdl->result->errorstr != NULL)) return 1; } return hdl->needmore ? MMORE : MOK;}MapiMsgmapi_needmore(MapiHdl hdl){ return hdl->needmore ? MMORE : MOK;}intmapi_more_results(MapiHdl hdl){ struct MapiResultSet *result; mapi_hdl_check(hdl, "mapi_more_results"); if ((result = hdl->result) == 0) { /* there are no results at all */ return 0; } if (result->querytype == Q_TABLE && hdl->mid->active == hdl) { /* read until next result (if any) */ read_into_cache(hdl, -1); } if (hdl->needmore) { /* assume the application will provide more data and that we will then have a result */ return 1; } while (result->next) { result = result->next; if (result->querytype == -1 || result->querytype == Q_TABLE || result->querytype == Q_UPDATE || result->errorstr != NULL) return 1; } /* no more results */ return 0;}MapiHdlmapi_new_handle(Mapi mid){ MapiHdl hdl; mapi_check0(mid, "mapi_new_handle"); hdl = malloc(sizeof(*hdl)); assert(hdl); if (hdl == NULL) { mapi_setError(mid, "Memory allocation failure", "mapi_new_handle", MERROR); return NULL; } hdl->mid = mid; hdl->template = NULL; hdl->query = NULL; hdl->maxbindings = 0; hdl->bindings = NULL; hdl->maxparams = 0; hdl->params = NULL; hdl->result = NULL; hdl->lastresult = NULL; hdl->active = NULL; hdl->needmore = 0; hdl->pending_close = NULL; hdl->npending_close = 0; /* add to doubly-linked list */ hdl->prev = NULL; hdl->next = mid->first; mid->first = hdl; if (hdl->next) hdl->next->prev = hdl; return hdl;}/* close all result sets on the handle but don't close the handle itself */static MapiMsgfinish_handle(MapiHdl hdl){ Mapi mid; int i; if (hdl == NULL) return MERROR; mid = hdl->mid; if (mid->active == hdl && !hdl->needmore && read_into_cache(hdl, 0) != MOK) return MERROR; if (mid->to) { if (hdl->needmore) { assert(mid->active == NULL || mid->active == hdl); hdl->needmore = 0; mid->active = hdl; stream_flush(mid->to); check_stream(mid, mid->to, "write error on stream", "finish_handle", mid->error); read_into_cache(hdl, 0); } for (i = 0; i < hdl->npending_close; i++) { mid->active = hdl; if (stream_printf(mid->to, "X" "close %d\n", hdl->pending_close[i]) < 0 || stream_flush(mid->to)) { close_connection(mid); mapi_setError(mid, stream_error(mid->to), "finish_handle", MTIMEOUT); break; } read_into_cache(hdl, 0); } } hdl->npending_close = 0; if (hdl->pending_close) free(hdl->pending_close); hdl->pending_close = NULL; while (hdl->result) { if (close_result(hdl) != MOK) return MERROR; if (hdl->needmore) { assert(mid->active == NULL || mid->active == hdl); hdl->needmore = 0; mid->active = hdl; stream_flush(mid->to); check_stream(mid, mid->to, "write error on stream", "finish_handle", mid->error); read_into_cache(hdl, 0); } } return MOK;}/* Close a statement handle, discarding any unread output. */MapiMsgmapi_close_handle(MapiHdl hdl){ debugprint("entering %s\n", "mapi_close_handle"); /* don't use mapi_check_hdl: it's ok if we're not connected */ mapi_clrError(hdl->mid); if (finish_handle(hdl) != MOK) return MERROR; hdl->npending_close = 0; if (hdl->pending_close) free(hdl->pending_close); hdl->pending_close = NULL; if (hdl->bindings) free(hdl->bindings); hdl->bindings = NULL; hdl->maxbindings = 0; if (hdl->params) free(hdl->params); hdl->params = NULL; hdl->maxparams = 0; if (hdl->query) free(hdl->query); hdl->query = NULL; if (hdl->template) free(hdl->template); hdl->template = NULL; /* remove from doubly-linked list */ if (hdl->prev) hdl->prev->next = hdl->next; if (hdl->next) hdl->next->prev = hdl->prev; if (hdl->mid->first == hdl) hdl->mid->first = hdl->next;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -