📄 mapi.c
字号:
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; hdl->prev = NULL; hdl->next = NULL; hdl->mid = NULL; free(hdl); return MOK;}/* Allocate a new connection handle. */static Mapimapi_new(void){ Mapi mid; mid = malloc(sizeof(*mid)); if (mid == NULL) return NULL; assert(mid); /* initialize everything to 0 */ memset(mid, 0, sizeof(*mid)); /* then fill in some details */ mid->auto_commit = 1; mid->error = MOK; mid->hostname = strdup("localhost"); mid->server = NULL; mid->language = strdup("mil"); mid->languageId = LANG_MIL; mid->versionId = 4; mid->noexplain = NULL; mid->motd = NULL; mid->mapiversion = "mapi 1.0"; mid->username = NULL; mid->password = NULL; mid->cachelimit = 100; mid->redircnt = 0; mid->tracelog = NULL; mid->blk.eos = 0; mid->blk.buf = malloc(BLOCK + 1); mid->blk.buf[BLOCK] = 0; mid->blk.buf[0] = 0; mid->blk.nxt = 0; mid->blk.end = 0; mid->blk.lim = BLOCK; mid->first = NULL; return mid;}/* Allocate a new connection handle and fill in the information needed to connect to a server, but don't connect yet. */Mapimapi_mapi(const char *host, int port, const char *username, const char *password, const char *lang, const char *dbname){ Mapi mid; if (!mapi_initialized) { mapi_initialized = 1; if (stream_init() < 0) return NULL; } mid = mapi_new(); if (mid == NULL) return NULL; if (host) { free(mid->hostname); mid->hostname = strdup(host); } if (port == 0) { char *def; if ((def = getenv("MAPIPORT")) != NULL) port = atoi(def); } if (port == 0) port = 50000; /* hardwired default */ /* fill some defaults for user/pass, this should actually never happen */ if (username == NULL) username = "guest"; if (mid->username != NULL) free(mid->username); mid->username = strdup(username); if (password == NULL) password = "guest"; if (mid->password) free(mid->password); mid->password = strdup(password); mid->port = port;#ifdef HAVE_OPENSSL mid->secure = 0;#endif if (lang == NULL) lang = "mil"; free(mid->language); mid->language = strdup(lang); if (strcmp(lang, "mil") == 0) mid->languageId = LANG_MIL; else if (strcmp(lang, "mal") == 0) mid->languageId = LANG_MAL; else if (strcmp(lang, "sql") == 0) mid->languageId = LANG_SQL; else if (strcmp(lang, "xquery") == 0) mid->languageId = LANG_XQUERY; if (mid->database) free(mid->database); mid->database = dbname ? strdup(dbname) : NULL; return mid;}/* Close a connection and free all memory associated with the connection handle. */MapiMsgmapi_destroy(Mapi mid){ mapi_clrError(mid); while (mid->first) mapi_close_handle(mid->first); if (mid->connected) (void) mapi_disconnect(mid); if (mid->blk.buf) free(mid->blk.buf); if (mid->errorstr) free(mid->errorstr); if (mid->hostname) free(mid->hostname); if (mid->username) free(mid->username); if (mid->password) free(mid->password); if (mid->language) free(mid->language); if (mid->database) free(mid->database); if (mid->server) free(mid->server); free(mid); return MOK;}#line 1851 "/export/scratch0/monet/monet.GNU.64.64.d.14791/clients/src/mapilib/Mapi.mx"#ifdef HAVE_OPENSSLstatic char *ssl_error(int err, int ret){ char *errstr; char buf[120]; unsigned long e; switch (err) { case SSL_ERROR_ZERO_RETURN: errstr = "TLS/SSL connection has been closed"; break; case SSL_ERROR_WANT_READ: errstr = "The operation did not complete (read)"; break; case SSL_ERROR_WANT_WRITE: errstr = "The operation did not complete (write)"; break; case SSL_ERROR_WANT_X509_LOOKUP: errstr = "The operation did not complete (X509 lookup)"; break; case SSL_ERROR_WANT_CONNECT: errstr = "The operation did not complete (connect)"; break; case SSL_ERROR_SYSCALL: e = ERR_get_error(); if (e == 0) { if (ret == 0) { errstr = "EOF occurred in violation of protocol"; } else if (ret == -1) { /* the underlying BIO reported an I/O error */ errstr = "I/O error"; } else { /* possible? */ errstr = "Some I/O error occurred"; } } else { errstr = ERR_error_string(e, buf); } break; case SSL_ERROR_SSL: e = ERR_get_error(); if (e != 0) errstr = ERR_error_string(e, buf); else { /* possible? */ errstr = "A failure in the SSL library occurred"; } break; default: errstr = "Invalid error code";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -