📄 mapi.c
字号:
#line 654 "/export/scratch0/monet/monet.GNU.64.64.d.14791/clients/src/mapilib/Mapi.mx"#include "clients_config.h"#include <monet_utils.h>#include <stream.h> /* include before Mapi.h */#include "Mapi.h"#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#include <stdio.h>#ifdef HAVE_PWD_H#include <pwd.h>#endif#include <sys/types.h>#ifdef HAVE_SYS_SOCKET_H# include <sys/socket.h>#endif#ifdef NATIVE_WIN32# include <winsock.h>#endif#ifdef HAVE_SYS_UN_H#include <sys/un.h>#endif#include <signal.h>#include <string.h>#include <memory.h>#if TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# if HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#ifdef NATIVE_WIN32#define strdup _strdup#endif#ifdef HAVE_CRYPT_H# include <crypt.h>#else# if defined(HAVE_CRYPT) && defined(__MINGW32__)_CRTIMP char * __cdecl crypt(const char *key, const char *salt);# endif#endif#ifdef HAVE_OPENSSL# include <openssl/sha.h># include <openssl/md5.h>#endif#line 762 "/export/scratch0/monet/monet.GNU.64.64.d.14791/clients/src/mapilib/Mapi.mx"#define MAPIBLKSIZE 256 /* minimum buffer shipped *//* information about the columns in a result set */struct MapiColumn { char *tablename; char *columnname; char *columntype; int columnlength;};/* information about bound columns */struct MapiBinding { void *outparam; /* pointer to application variable */ int outtype; /* type of application variable */ int precision; int scale;};/* information about statement parameters */struct MapiParam { void *inparam; /* pointer to application variable */ int *sizeptr; /* if string, points to length of string or -1 */ int intype; /* type of application variable */ int outtype; /* type of value */ int precision; int scale;};#line 800 "/export/scratch0/monet/monet.GNU.64.64.d.14791/clients/src/mapilib/Mapi.mx"struct MapiRowBuf { int rowlimit; /* maximum number of rows to cache */ int shuffle; /* percentage of rows to shuffle upon overflow */ int limit; /* current storage space limit */ int writer; int reader; int first; /* row # of first tuple */ int tuplecount; /* number of tuples in the cache */ struct { int fldcnt; /* actual number of fields in each row */ char *rows; /* string representation of rows received */ int tupleindex; /* index of tuple rows */ int tuplerev; /* reverse map of tupleindex */ char **anchors; /* corresponding field pointers */ } *line;};struct BlockCache { char *buf; int lim; int nxt; int end; int eos; /* end of sequence */};/* A connection to a server is represented by a struct MapiStruct. An application can have any number of connections to any number of servers. Connections are completely independent of each other.*/#line 844 "/export/scratch0/monet/monet.GNU.64.64.d.14791/clients/src/mapilib/Mapi.mx"struct MapiStruct { char *server; /* server version */ char *mapiversion; /* mapi version */ char *hostname; int port;#ifdef HAVE_OPENSSL int secure;#endif char *username; char *password; char *language; char *database; /* to obtain from server */ int languageId; int versionId; /* Monet 4 or 5 */ char *motd; /* welcome message from server */ int profile; /* profile Mapi interaction */ int trace; /* Trace Mapi interaction */ int auto_commit; char *noexplain; /* on error, don't explain, only print result */ MapiMsg error; /* Error occurred */ char *errorstr; /* error from server */ const char *action; /* pointer to constant string */ struct BlockCache blk; int connected; MapiHdl first; /* start of doubly-linked list */ MapiHdl active; /* set when not all rows have been received */ int cachelimit; /* default maximum number of rows to cache */ int redircnt; /* redirection count */ stream *tracelog; /* keep a log for inspection */ stream *from, *to;};struct MapiResultSet { struct MapiResultSet *next; struct MapiStatement *hdl; int tableid; /* SQL id of current result set */ int querytype; /* type of SQL query */ int row_count; int fieldcnt; int maxfields; char *errorstr; /* error from server */ struct MapiColumn *fields; struct MapiRowBuf cache;};#line 897 "/export/scratch0/monet/monet.GNU.64.64.d.14791/clients/src/mapilib/Mapi.mx"struct MapiStatement { struct MapiStruct *mid; char *template; /* keep parameterized query text around */ char *query; int maxbindings; struct MapiBinding *bindings; int maxparams; struct MapiParam *params; struct MapiResultSet *result, *active, *lastresult; int needmore; /* need more input */ int *pending_close; int npending_close; MapiHdl prev, next;};#line 917 "/export/scratch0/monet/monet.GNU.64.64.d.14791/clients/src/mapilib/Mapi.mx"#ifdef DEBUG#define debugprint(fmt,arg) printf(fmt,arg)#else#define debugprint(fmt,arg) ((void) 0)#endif#define mapi_check(X,C) \ do { \ debugprint("entering %s\n", (C)); \ assert(X); \ if ((X)->connected == 0) { \ mapi_setError((X), "Connection lost", (C), MERROR); \ return (X)->error; \ } \ mapi_clrError(X); \ } while (0)#define mapi_check0(X,C) \ do { \ debugprint("entering %s\n", (C)); \ assert(X); \ if ((X)->connected == 0) { \ mapi_setError((X), "Connection lost", (C), MERROR); \ return 0; \ } \ mapi_clrError(X); \ } while (0)#define mapi_hdl_check(X,C) \ do { \ debugprint("entering %s\n", (C)); \ assert(X); \ assert((X)->mid); \ if ((X)->mid->connected == 0) { \ mapi_setError((X)->mid, "Connection lost", (C), MERROR); \ return (X)->mid->error; \ } \ mapi_clrError((X)->mid); \ } while (0)#define mapi_hdl_check0(X,C) \ do { \ debugprint("entering %s\n", (C)); \ assert(X); \ assert((X)->mid); \ if ((X)->mid->connected == 0) { \ mapi_setError((X)->mid, "Connection lost", (C), MERROR); \ return 0; \ } \ mapi_clrError((X)->mid); \ } while (0)#line 1110 "/export/scratch0/monet/monet.GNU.64.64.d.14791/clients/src/mapilib/Mapi.mx"static Mapi mapi_new(void);static int mapi_extend_bindings(MapiHdl hdl, int minbindings);static int mapi_extend_params(MapiHdl hdl, int minparams);static MapiMsg mapi_setError(Mapi mid, const char *msg, const char *action, MapiMsg error);static void close_connection(Mapi mid);static MapiMsg read_into_cache(MapiHdl hdl, int lookahead);static int unquote(const char *msg, char **start, const char **next, int endchar);static int mapi_slice_row(struct MapiResultSet *result, int cr);static void mapi_store_bind(struct MapiResultSet *result, int cr);#ifdef HAVE_OPENSSLstatic SSL_CTX *mapi_ssl_ctx = 0;#endifstatic int mapi_initialized = 0;#ifdef HAVE_LONG_LONGtypedef unsigned long long mapi_uint64;typedef long long mapi_int64;#else#ifdef HAVE___INT64typedef unsigned __int64 mapi_uint64;typedef __int64 mapi_int64;#endif#endif#define check_stream(mid,s,msg,f,e) \ do { \ if ((s) == NULL || stream_errnr(s)) { \ close_connection(mid); \ mapi_setError((mid), (msg), (f), MTIMEOUT); \ return (e); \ } \ } while (0)#define REALLOC(p,c) ((p) = ((p) ? realloc((p),(c)*sizeof(*(p))) : malloc((c)*sizeof(*(p)))))#line 1159 "/export/scratch0/monet/monet.GNU.64.64.d.14791/clients/src/mapilib/Mapi.mx"static voidmapi_clrError(Mapi mid){ assert(mid); if (mid->errorstr) free(mid->errorstr); mid->action = 0; /* contains references to constants */ mid->error = 0; mid->errorstr = 0;}static MapiMsgmapi_setError(Mapi mid, const char *msg, const char *action, MapiMsg error){ assert(msg); REALLOC(mid->errorstr, strlen(msg) + 1); strcpy(mid->errorstr, msg); mid->error = error; mid->action = action; return mid->error;}MapiMsgmapi_error(Mapi mid){ assert(mid); return mid->error;}char *mapi_error_str(Mapi mid){ assert(mid); return mid->errorstr;}static voidclean_print(char *msg, const char *prefix, FILE *fd){ int len = (int) strlen(prefix); while (msg && *msg) { /* cut by line */ char *p = strchr(msg, '\n'); if (p) *p++ = 0; /* skip over prefix */ if (strncmp(msg, prefix, len) == 0) msg += len; /* output line */ fputs(msg, fd); fputc('\n', fd); msg = p; }}static voidindented_print(const char *msg, const char *prefix, FILE *fd){ /* for multiline error messages, indent all subsequent lines with the space it takes to print "ERROR = " */ const char *s, *p, *q; s = prefix; p = msg; while (p && *p) { fprintf(fd, "%s", s); s = " "; q = strchr(p, '\n'); if (q) { q++; /* also print the newline */ fprintf(fd, "%.*s", (int) (q - p), p); } else { /* print bit after last newline, adding one ourselves */ fprintf(fd, "%s\n", p); break; /* nothing more to do */ } p = q; }}voidmapi_noexplain(Mapi mid, char *errorprefix){ assert(mid); mid->noexplain = errorprefix;}MapiMsgmapi_explain(Mapi mid, FILE *fd){ 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 (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_query(MapiHdl hdl, FILE *fd){ Mapi mid; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -