📄 tcl_dbcursor.c
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1999-2001 * Sleepycat Software. All rights reserved. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: tcl_dbcursor.c,v 11.51 2002/08/06 06:20:59 bostic Exp $";#endif /* not lint */#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <stdlib.h>#include <string.h>#include <tcl.h>#endif#include "db_int.h"#include "dbinc/tcl_db.h"/* * Prototypes for procedures defined later in this file: */static int tcl_DbcDup __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *));static int tcl_DbcGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *, int));static int tcl_DbcPut __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBC *));/* * PUBLIC: int dbc_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*)); * * dbc_cmd -- * Implements the cursor command. */intdbc_Cmd(clientData, interp, objc, objv) ClientData clientData; /* Cursor handle */ Tcl_Interp *interp; /* Interpreter */ int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */{ static char *dbccmds[] = {#if CONFIG_TEST "pget",#endif "close", "del", "dup", "get", "put", NULL }; enum dbccmds {#if CONFIG_TEST DBCPGET,#endif DBCCLOSE, DBCDELETE, DBCDUP, DBCGET, DBCPUT }; DBC *dbc; DBTCL_INFO *dbip; int cmdindex, result, ret; Tcl_ResetResult(interp); dbc = (DBC *)clientData; dbip = _PtrToInfo((void *)dbc); result = TCL_OK; if (objc <= 1) { Tcl_WrongNumArgs(interp, 1, objv, "command cmdargs"); return (TCL_ERROR); } if (dbc == NULL) { Tcl_SetResult(interp, "NULL dbc pointer", TCL_STATIC); return (TCL_ERROR); } if (dbip == NULL) { Tcl_SetResult(interp, "NULL dbc info pointer", TCL_STATIC); return (TCL_ERROR); } /* * Get the command name index from the object based on the berkdbcmds * defined above. */ if (Tcl_GetIndexFromObj(interp, objv[1], dbccmds, "command", TCL_EXACT, &cmdindex) != TCL_OK) return (IS_HELP(objv[1])); switch ((enum dbccmds)cmdindex) {#if CONFIG_TEST case DBCPGET: result = tcl_DbcGet(interp, objc, objv, dbc, 1); break;#endif case DBCCLOSE: /* * No args for this. Error if there are some. */ if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return (TCL_ERROR); } _debug_check(); ret = dbc->c_close(dbc); result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "dbc close"); if (result == TCL_OK) { (void)Tcl_DeleteCommand(interp, dbip->i_name); _DeleteInfo(dbip); } break; case DBCDELETE: /* * No args for this. Error if there are some. */ if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return (TCL_ERROR); } _debug_check(); ret = dbc->c_del(dbc, 0); result = _ReturnSetup(interp, ret, DB_RETOK_DBCDEL(ret), "dbc delete"); break; case DBCDUP: result = tcl_DbcDup(interp, objc, objv, dbc); break; case DBCGET: result = tcl_DbcGet(interp, objc, objv, dbc, 0); break; case DBCPUT: result = tcl_DbcPut(interp, objc, objv, dbc); break; } return (result);}/* * tcl_DbcPut -- */static inttcl_DbcPut(interp, objc, objv, dbc) Tcl_Interp *interp; /* Interpreter */ int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */ DBC *dbc; /* Cursor pointer */{ static char *dbcutopts[] = {#if CONFIG_TEST "-nodupdata",#endif "-after", "-before", "-current", "-keyfirst", "-keylast", "-partial", NULL }; enum dbcutopts {#if CONFIG_TEST DBCPUT_NODUPDATA,#endif DBCPUT_AFTER, DBCPUT_BEFORE, DBCPUT_CURRENT, DBCPUT_KEYFIRST, DBCPUT_KEYLAST, DBCPUT_PART }; DB *thisdbp; DBT key, data; DBTCL_INFO *dbcip, *dbip; DBTYPE type; Tcl_Obj **elemv, *res; void *dtmp, *ktmp; db_recno_t recno; u_int32_t flag; int elemc, freekey, freedata, i, optindex, result, ret; result = TCL_OK; flag = 0; freekey = freedata = 0; if (objc < 2) { Tcl_WrongNumArgs(interp, 2, objv, "?-args? ?key?"); return (TCL_ERROR); } memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); /* * Get the command name index from the object based on the options * defined above. */ i = 2; while (i < (objc - 1)) { if (Tcl_GetIndexFromObj(interp, objv[i], dbcutopts, "option", TCL_EXACT, &optindex) != TCL_OK) { /* * Reset the result so we don't get * an errant error message if there is another error. */ if (IS_HELP(objv[i]) == TCL_OK) { result = TCL_OK; goto out; } Tcl_ResetResult(interp); break; } i++; switch ((enum dbcutopts)optindex) {#if CONFIG_TEST case DBCPUT_NODUPDATA: FLAG_CHECK(flag); flag = DB_NODUPDATA; break;#endif case DBCPUT_AFTER: FLAG_CHECK(flag); flag = DB_AFTER; break; case DBCPUT_BEFORE: FLAG_CHECK(flag); flag = DB_BEFORE; break; case DBCPUT_CURRENT: FLAG_CHECK(flag); flag = DB_CURRENT; break; case DBCPUT_KEYFIRST: FLAG_CHECK(flag); flag = DB_KEYFIRST; break; case DBCPUT_KEYLAST: FLAG_CHECK(flag); flag = DB_KEYLAST; break; case DBCPUT_PART: if (i > (objc - 2)) { Tcl_WrongNumArgs(interp, 2, objv, "?-partial {offset length}?"); result = TCL_ERROR; break; } /* * Get sublist as {offset length} */ result = Tcl_ListObjGetElements(interp, objv[i++], &elemc, &elemv); if (elemc != 2) { Tcl_SetResult(interp, "List must be {offset length}", TCL_STATIC); result = TCL_ERROR; break; } data.flags |= DB_DBT_PARTIAL; result = _GetUInt32(interp, elemv[0], &data.doff); if (result != TCL_OK) break; result = _GetUInt32(interp, elemv[1], &data.dlen); /* * NOTE: We don't check result here because all we'd * do is break anyway, and we are doing that. If you * add code here, you WILL need to add the check * for result. (See the check for save.doff, a few * lines above and copy that.) */ } if (result != TCL_OK) break; } if (result != TCL_OK) goto out; /* * We need to determine if we are a recno database or not. If we are, * then key.data is a recno, not a string. */ dbcip = _PtrToInfo(dbc); if (dbcip == NULL) type = DB_UNKNOWN; else { dbip = dbcip->i_parent; if (dbip == NULL) { Tcl_SetResult(interp, "Cursor without parent database", TCL_STATIC); result = TCL_ERROR; return (result); } thisdbp = dbip->i_dbp; (void)thisdbp->get_type(thisdbp, &type); } /* * When we get here, we better have: * 1 arg if -after, -before or -current * 2 args in all other cases */ if (flag == DB_AFTER || flag == DB_BEFORE || flag == DB_CURRENT) { if (i != (objc - 1)) { Tcl_WrongNumArgs(interp, 2, objv, "?-args? data"); result = TCL_ERROR; goto out; } /* * We want to get the key back, so we need to set * up the location to get it back in. */ if (type == DB_RECNO || type == DB_QUEUE) { recno = 0; key.data = &recno; key.size = sizeof(db_recno_t); } } else { if (i != (objc - 2)) { Tcl_WrongNumArgs(interp, 2, objv, "?-args? key data"); result = TCL_ERROR; goto out; } if (type == DB_RECNO || type == DB_QUEUE) { result = _GetUInt32(interp, objv[objc-2], &recno); if (result == TCL_OK) { key.data = &recno; key.size = sizeof(db_recno_t); } else return (result); } else { ret = _CopyObjBytes(interp, objv[objc-2], &ktmp, &key.size, &freekey); if (ret != 0) { result = _ReturnSetup(interp, ret, DB_RETOK_DBCPUT(ret), "dbc put"); return (result); } key.data = ktmp; } } ret = _CopyObjBytes(interp, objv[objc-1], &dtmp, &data.size, &freedata); data.data = dtmp; if (ret != 0) { result = _ReturnSetup(interp, ret, DB_RETOK_DBCPUT(ret), "dbc put"); goto out; } _debug_check(); ret = dbc->c_put(dbc, &key, &data, flag); result = _ReturnSetup(interp, ret, DB_RETOK_DBCPUT(ret), "dbc put"); if (ret == 0 && (flag == DB_AFTER || flag == DB_BEFORE) && type == DB_RECNO) { res = Tcl_NewLongObj((long)*(db_recno_t *)key.data); Tcl_SetObjResult(interp, res); }out: if (freedata) (void)__os_free(NULL, dtmp); if (freekey) (void)__os_free(NULL, ktmp); return (result);}/* * tcl_dbc_get -- */static inttcl_DbcGet(interp, objc, objv, dbc, ispget) Tcl_Interp *interp; /* Interpreter */ int objc; /* How many arguments? */ Tcl_Obj *CONST objv[]; /* The argument objects */ DBC *dbc; /* Cursor pointer */ int ispget; /* 1 for pget, 0 for get */{ static char *dbcgetopts[] = {#if CONFIG_TEST "-dirty", "-get_both_range", "-multi", "-multi_key",#endif "-current", "-first", "-get_both", "-get_recno", "-join_item", "-last", "-next", "-nextdup", "-nextnodup", "-partial", "-prev", "-prevnodup", "-rmw", "-set", "-set_range", "-set_recno", NULL }; enum dbcgetopts {#if CONFIG_TEST DBCGET_DIRTY, DBCGET_BOTH_RANGE, DBCGET_MULTI, DBCGET_MULTI_KEY,#endif DBCGET_CURRENT, DBCGET_FIRST, DBCGET_BOTH, DBCGET_RECNO, DBCGET_JOIN, DBCGET_LAST, DBCGET_NEXT, DBCGET_NEXTDUP, DBCGET_NEXTNODUP, DBCGET_PART, DBCGET_PREV, DBCGET_PREVNODUP, DBCGET_RMW, DBCGET_SET, DBCGET_SETRANGE, DBCGET_SETRECNO }; DB *thisdbp; DBT key, data, pdata; DBTCL_INFO *dbcip, *dbip; DBTYPE ptype, type; Tcl_Obj **elemv, *myobj, *retlist; void *dtmp, *ktmp; db_recno_t precno, recno; u_int32_t flag, op; int bufsize, elemc, freekey, freedata, i, optindex, result, ret; result = TCL_OK; flag = 0; freekey = freedata = 0; if (objc < 2) { Tcl_WrongNumArgs(interp, 2, objv, "?-args? ?key?"); return (TCL_ERROR); } memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); /* * Get the command name index from the object based on the options * defined above. */ i = 2; while (i < objc) { if (Tcl_GetIndexFromObj(interp, objv[i], dbcgetopts, "option", TCL_EXACT, &optindex) != TCL_OK) { /* * Reset the result so we don't get * an errant error message if there is another error.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -