📄 pgtclcmds.c
字号:
char *arrVar; char nameBuffer[256]; const char *appendstr; if (argc < 3 || argc > 5) { Tcl_AppendResult(interp, "Wrong # of arguments\n", 0); goto Pg_result_errReturn; /* append help info */ } result = PgGetResultId(interp, argv[1]); if (result == (PGresult *) NULL) { Tcl_AppendResult(interp, argv[1], " is not a valid query result", 0); return TCL_ERROR; } opt = argv[2]; if (strcmp(opt, "-status") == 0) { Tcl_AppendResult(interp, PQresStatus(PQresultStatus(result)), 0); return TCL_OK; } else if (strcmp(opt, "-error") == 0) { Tcl_SetResult(interp, (char *) PQresultErrorMessage(result), TCL_STATIC); return TCL_OK; } else if (strcmp(opt, "-conn") == 0) return PgGetConnByResultId(interp, argv[1]); else if (strcmp(opt, "-oid") == 0) { Tcl_AppendResult(interp, PQoidStatus(result), 0); return TCL_OK; } else if (strcmp(opt, "-clear") == 0) { PgDelResultId(interp, argv[1]); PQclear(result); return TCL_OK; } else if (strcmp(opt, "-numTuples") == 0) { sprintf(interp->result, "%d", PQntuples(result)); return TCL_OK; } else if (strcmp(opt, "-numAttrs") == 0) { sprintf(interp->result, "%d", PQnfields(result)); return TCL_OK; } else if (strcmp(opt, "-assign") == 0) { if (argc != 4) { Tcl_AppendResult(interp, "-assign option must be followed by a variable name", 0); return TCL_ERROR; } arrVar = argv[3]; /* * this assignment assigns the table of result tuples into a giant * array with the name given in the argument. The indices of the * array are of the form (tupno,attrName). Note we expect field * names not to exceed a few dozen characters, so truncating to * prevent buffer overflow shouldn't be a problem. */ for (tupno = 0; tupno < PQntuples(result); tupno++) { for (i = 0; i < PQnfields(result); i++) { sprintf(nameBuffer, "%d,%.200s", tupno, PQfname(result, i)); if (Tcl_SetVar2(interp, arrVar, nameBuffer,#ifdef TCL_ARRAYS tcl_value(PQgetvalue(result, tupno, i)),#else PQgetvalue(result, tupno, i),#endif TCL_LEAVE_ERR_MSG) == NULL) return TCL_ERROR; } } Tcl_AppendResult(interp, arrVar, 0); return TCL_OK; } else if (strcmp(opt, "-assignbyidx") == 0) { if (argc != 4 && argc != 5) { Tcl_AppendResult(interp, "-assignbyidx option requires an array name and optionally an append string", 0); return TCL_ERROR; } arrVar = argv[3]; appendstr = (argc == 5) ? (const char *) argv[4] : ""; /* * this assignment assigns the table of result tuples into a giant * array with the name given in the argument. The indices of the * array are of the form (field0Value,attrNameappendstr). Here, we * still assume PQfname won't exceed 200 characters, but we dare * not make the same assumption about the data in field 0 nor the * append string. */ for (tupno = 0; tupno < PQntuples(result); tupno++) { const char *field0 =#ifdef TCL_ARRAYS tcl_value(PQgetvalue(result, tupno, 0));#else PQgetvalue(result, tupno, 0);#endif char *workspace = malloc(strlen(field0) + strlen(appendstr) + 210); for (i = 1; i < PQnfields(result); i++) { sprintf(workspace, "%s,%.200s%s", field0, PQfname(result, i), appendstr); if (Tcl_SetVar2(interp, arrVar, workspace,#ifdef TCL_ARRAYS tcl_value(PQgetvalue(result, tupno, i)),#else PQgetvalue(result, tupno, i),#endif TCL_LEAVE_ERR_MSG) == NULL) { free(workspace); return TCL_ERROR; } } free(workspace); } Tcl_AppendResult(interp, arrVar, 0); return TCL_OK; } else if (strcmp(opt, "-getTuple") == 0) { if (argc != 4) { Tcl_AppendResult(interp, "-getTuple option must be followed by a tuple number", 0); return TCL_ERROR; } tupno = atoi(argv[3]); if (tupno < 0 || tupno >= PQntuples(result)) { Tcl_AppendResult(interp, "argument to getTuple cannot exceed number of tuples - 1", 0); return TCL_ERROR; }#ifdef TCL_ARRAYS for (i = 0; i < PQnfields(result); i++) Tcl_AppendElement(interp, tcl_value(PQgetvalue(result, tupno, i)));#else for (i = 0; i < PQnfields(result); i++) Tcl_AppendElement(interp, PQgetvalue(result, tupno, i));#endif return TCL_OK; } else if (strcmp(opt, "-tupleArray") == 0) { if (argc != 5) { Tcl_AppendResult(interp, "-tupleArray option must be followed by a tuple number and array name", 0); return TCL_ERROR; } tupno = atoi(argv[3]); if (tupno < 0 || tupno >= PQntuples(result)) { Tcl_AppendResult(interp, "argument to tupleArray cannot exceed number of tuples - 1", 0); return TCL_ERROR; } for (i = 0; i < PQnfields(result); i++) { if (Tcl_SetVar2(interp, argv[4], PQfname(result, i),#ifdef TCL_ARRAYS tcl_value(PQgetvalue(result, tupno, i)),#else PQgetvalue(result, tupno, i),#endif TCL_LEAVE_ERR_MSG) == NULL) return TCL_ERROR; } return TCL_OK; } else if (strcmp(opt, "-attributes") == 0) { for (i = 0; i < PQnfields(result); i++) Tcl_AppendElement(interp, PQfname(result, i)); return TCL_OK; } else if (strcmp(opt, "-lAttributes") == 0) { for (i = 0; i < PQnfields(result); i++) { /* start a sublist */ if (i > 0) Tcl_AppendResult(interp, " {", 0); else Tcl_AppendResult(interp, "{", 0); Tcl_AppendElement(interp, PQfname(result, i)); sprintf(nameBuffer, "%ld", (long) PQftype(result, i)); Tcl_AppendElement(interp, nameBuffer); sprintf(nameBuffer, "%ld", (long) PQfsize(result, i)); Tcl_AppendElement(interp, nameBuffer); /* end the sublist */ Tcl_AppendResult(interp, "}", 0); } return TCL_OK; } else { Tcl_AppendResult(interp, "Invalid option\n", 0); goto Pg_result_errReturn; /* append help info */ }Pg_result_errReturn: Tcl_AppendResult(interp, "pg_result result ?option? where option is\n", "\t-status\n", "\t-error\n", "\t-conn\n", "\t-oid\n", "\t-numTuples\n", "\t-numAttrs\n" "\t-assign arrayVarName\n", "\t-assignbyidx arrayVarName ?appendstr?\n", "\t-getTuple tupleNumber\n", "\t-tupleArray tupleNumber arrayVarName\n", "\t-attributes\n" "\t-lAttributes\n" "\t-clear\n", (char *) 0); return TCL_ERROR;}/********************************** * pg_lo_open open a large object syntax: pg_lo_open conn objOid mode where mode can be either 'r', 'w', or 'rw'**********************/intPg_lo_open(ClientData cData, Tcl_Interp *interp, int argc, char *argv[]){ PGconn *conn; int lobjId; int mode; int fd; if (argc != 4) { Tcl_AppendResult(interp, "Wrong # of arguments\n", "pg_lo_open connection lobjOid mode", 0); return TCL_ERROR; } conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId **) NULL); if (conn == (PGconn *) NULL) return TCL_ERROR; lobjId = atoi(argv[2]); if (strlen(argv[3]) < 1 || strlen(argv[3]) > 2) { Tcl_AppendResult(interp, "mode argument must be 'r', 'w', or 'rw'", 0); return TCL_ERROR; } switch (argv[3][0]) { case 'r': case 'R': mode = INV_READ; break; case 'w': case 'W': mode = INV_WRITE; break; default: Tcl_AppendResult(interp, "mode argument must be 'r', 'w', or 'rw'", 0); return TCL_ERROR; } switch (argv[3][1]) { case '\0': break; case 'r': case 'R': mode = mode & INV_READ; break; case 'w': case 'W': mode = mode & INV_WRITE; break; default: Tcl_AppendResult(interp, "mode argument must be 'r', 'w', or 'rw'", 0); return TCL_ERROR; } fd = lo_open(conn, lobjId, mode); sprintf(interp->result, "%d", fd); return TCL_OK;}/********************************** * pg_lo_close close a large object syntax: pg_lo_close conn fd**********************/intPg_lo_close(ClientData cData, Tcl_Interp *interp, int argc, char *argv[]){ PGconn *conn; int fd; if (argc != 3) { Tcl_AppendResult(interp, "Wrong # of arguments\n", "pg_lo_close connection fd", 0); return TCL_ERROR; } conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId **) NULL); if (conn == (PGconn *) NULL) return TCL_ERROR; fd = atoi(argv[2]); sprintf(interp->result, "%d", lo_close(conn, fd)); return TCL_OK;}/********************************** * pg_lo_read reads at most len bytes from a large object into a variable named bufVar syntax: pg_lo_read conn fd bufVar len bufVar is the name of a variable in which to store the contents of the read**********************/intPg_lo_read(ClientData cData, Tcl_Interp *interp, int argc, char *argv[]){ PGconn *conn; int fd; int nbytes = 0; char *buf; char *bufVar; int len; if (argc != 5) { Tcl_AppendResult(interp, "Wrong # of arguments\n", " pg_lo_read conn fd bufVar len", 0); return TCL_ERROR; } conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId **) NULL); if (conn == (PGconn *) NULL) return TCL_ERROR; fd = atoi(argv[2]); bufVar = argv[3]; len = atoi(argv[4]); if (len <= 0) { sprintf(interp->result, "%d", nbytes); return TCL_OK; } buf = ckalloc(len + 1); nbytes = lo_read(conn, fd, buf, len); Tcl_SetVar(interp, bufVar, buf, TCL_LEAVE_ERR_MSG); sprintf(interp->result, "%d", nbytes); ckfree(buf); return TCL_OK;}/***********************************Pg_lo_write write at most len bytes to a large object syntax: pg_lo_write conn fd buf len***********************************/intPg_lo_write(ClientData cData, Tcl_Interp *interp, int argc, char *argv[]){ PGconn *conn; char *buf; int fd; int nbytes = 0; int len; if (argc != 5) { Tcl_AppendResult(interp, "Wrong # of arguments\n", "pg_lo_write conn fd buf len", 0); return TCL_ERROR; } conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId **) NULL); if (conn == (PGconn *) NULL) return TCL_ERROR; fd = atoi(argv[2]); buf = argv[3]; len = atoi(argv[4]); if (len <= 0) { sprintf(interp->result, "%d", nbytes); return TCL_OK; } nbytes = lo_write(conn, fd, buf, len); sprintf(interp->result, "%d", nbytes); return TCL_OK;}/***********************************Pg_lo_lseek seek to a certain position in a large objectsyntax pg_lo_lseek conn fd offset whencewhence can be either"SEEK_CUR", "SEEK_END", or "SEEK_SET"***********************************/intPg_lo_lseek(ClientData cData, Tcl_Interp *interp, int argc, char *argv[]){ PGconn *conn; int fd; char *whenceStr; int offset, whence; if (argc != 5) { Tcl_AppendResult(interp, "Wrong # of arguments\n", "pg_lo_lseek conn fd offset whence", 0); return TCL_ERROR; } conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId **) NULL); if (conn == (PGconn *) NULL) return TCL_ERROR; fd = atoi(argv[2]); offset = atoi(argv[3]); whenceStr = argv[4]; if (strcmp(whenceStr, "SEEK_SET") == 0) whence = SEEK_SET; else if (strcmp(whenceStr, "SEEK_CUR") == 0) whence = SEEK_CUR; else if (strcmp(whenceStr, "SEEK_END") == 0) whence = SEEK_END; else { Tcl_AppendResult(interp, "the whence argument to Pg_lo_lseek must be SEEK_SET, SEEK_CUR or SEEK_END", 0); return TCL_ERROR; } sprintf(interp->result, "%d", lo_lseek(conn, fd, offset, whence)); return TCL_OK;}/***********************************Pg_lo_creat create a new large object with mode syntax: pg_lo_creat conn modemode can be any OR'ing together of INV_READ, INV_WRITE,for now, we don't support any additional storage managers.***********************************/intPg_lo_creat(ClientData cData, Tcl_Interp *interp, int argc, char *argv[]){ PGconn *conn; char *modeStr; char *modeWord; int mode; if (argc != 3) { Tcl_AppendResult(interp, "Wrong # of arguments\n", "pg_lo_creat conn mode", 0); return TCL_ERROR; } conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId **) NULL); if (conn == (PGconn *) NULL) return TCL_ERROR; modeStr = argv[2]; modeWord = strtok(modeStr, "|"); if (strcmp(modeWord, "INV_READ") == 0) mode = INV_READ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -