static void luaP_pushtuptable (lua_State *L, Portal cursor) { luaP_Tuptable *t; luaP_getfield(L, PLLUA_TUPTABLE); t = (luaP_Tuptable *) lua_touserdata(L, -1); if (t == NULL) { /* not initialized? */ lua_pop(L, 1); t = (luaP_Tuptable *) lua_newuserdata(L, sizeof(luaP_Tuptable)); luaP_getfield(L, PLLUA_TUPTABLEMT); lua_setmetatable(L, -2); lua_pushlightuserdata(L, (void *) PLLUA_TUPTABLE); lua_pushvalue(L, -2); /* tuptable */ lua_rawset(L, LUA_REGISTRYINDEX); } t->size = SPI_processed; t->tuptable = SPI_tuptable; if (cursor == NULL || (cursor != NULL && t->cursor != cursor)) { lua_pushinteger(L, (int) InvalidOid); luaP_pushdesctable(L, t->tuptable->tupdesc); lua_rawset(L, LUA_REGISTRYINDEX); t->cursor = cursor; } /* reset tuptable env */ lua_newtable(L); /* env */ lua_setuservalue(L, -2); }
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MkStrXEQ (QString text, wnd *vp) // execute MicroMir command from its text { // presentation, several times if KbCount int repeat = KbRadix ? KbCount : 1; // was set (by MkMimXEQ function) KbRadix = 0; KbCount = 1; // <- must reset that counter here! int N, len = text.length(); for (int k = 0; k < repeat; k++) { for (int i = 0; i < len; i++) { int k = text.at(i).unicode(); if (k == 0x2446) { // ⑆ used to escape special characters (× and ‹) if (i == len-1) break; vipOnKeyCode(vp, text.at(++i).unicode()); } else if (k == 0x2039) { // ‹ if ((N = text.indexOf(Utf8("›"),i+1)) > 0) { luaP_getglobal("Mk"); luaP_getfield(-1,text.mid(i+1,N-i-1).cStr()); i=N; MkLuaXEQ("", vp); } } else if (k == 0xD7) { // × if ((N = text.indexOf(Utf8("⁝"),i+1)) > 0) { KbRadix = 1; // applied to next command KbCount = text.mid(i+1,N-i-1).toInt(); i=N; // (radix does not matter) } } else if (Mk_IsCHAR(k)) vipOnKeyCode(vp, k); if (qkbhin()) return; // } } } // KB interrupt (currently not used), or an error
void setHstoreFromDatum(lua_State *L, Datum datum) { Lua_Hstore * strg; BEGINLUA; strg = (Lua_Hstore *)lua_newuserdata(L, sizeof(Lua_Hstore)); MTOLUA(L); datum = datumCopy(datum, hs_type.byval, hs_type.len); MTOPG; strg->hstore = DatumGetHStoreP(datum); strg->datum = datum; strg->issync = 1; strg->havetodel = 1; lua_pushlightuserdata(L, strg); lua_newtable(L); lua_settable(L, LUA_REGISTRYINDEX); luaP_getfield(L, hstore_type_name); lua_setmetatable(L, -2); ENDLUAV(1); }
static int hs_delete(lua_State *L) { if (lua_gettop(L)!= 2){ return luaL_error(L, "wrong args length in hstore.delete(hstore, text)"); } if (hstore_oid >0){ bool isnull; Datum a; Datum b; if ((lua_type(L, 2) != LUA_TSTRING)|| (lua_type(L, 1) != LUA_TUSERDATA) ){ return luaL_error(L, "wrong args types for hstore.delete(hstore, text)"); } lua_getmetatable (L, 1); luaP_getfield(L, hstore_type_name); if (lua_equal (L, -1, -2)!= 1){ return luaL_error(L, "hstore.delete(hstore, text) first arg is not hstore"); } a = luaP_todatum(L, hstore_oid, 0, &isnull, 1); b = luaP_todatum(L, TEXTOID, 0, &isnull, 2); luaP_pushdatum(L, call_delete_hstore_text(a,b), hstore_oid); return 1; } return luaL_error(L, "hstore is not registered //hstore.delete"); }
void luaP_pushtuple (lua_State *L, TupleDesc desc, HeapTuple tuple, Oid relid, int readonly) { luaP_Tuple *t; int i, n = desc->natts; if (readonly) { t = lua_newuserdata(L, sizeof(luaP_Tuple)); t->changed = -1; t->value = NULL; t->null = NULL; } else { t = lua_newuserdata(L, sizeof(luaP_Tuple) + n * (sizeof(Datum) + sizeof(bool))); t->changed = 0; t->value = (Datum *) (t + 1); t->null = (bool *) (t->value + n); for (i = 0; i < n; i++) { bool isnull; t->value[i] = heap_getattr(tuple, desc->attrs[i]->attnum, desc, &isnull); t->null[i] = isnull; } } t->desc = desc; t->relid = relid; t->tuple = tuple; luaP_getfield(L, PLLUA_TUPLEMT); lua_setmetatable(L, -2); }
static void luaP_checkabort (lua_State *L) { luaP_getfield(L, PLLUA_TXNABORT); if (lua_isnil(L, -1)) { lua_pop(L, 1); return; } luaL_error(L, "transaction is aborted"); }
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ void MkMimXEQ (int kcode, int modMask, QString text, wnd *vp) { int digit = MkToDigit(kcode); if (KbRadix && !modMask && digit >= 0) { KbCount = KbRadix * KbCount + digit; Twnd->sctw->DisplayInfo( Utf8("×%1").arg(KbCount) ); return; } luaP_getglobal("Mk"); if (MkPrefix.isEmpty()) { last_MiCmd_key = MkToString(kcode|modMask); luaP_getfield(-1,last_MiCmd_key.uStr()); } else { if (MkPrefix == "Esc" && !modMask) { QString info; if (kcode == 'I') { KbCount = 2147483647; KbRadix = 1; info = "(inf)"; } else if (kcode == 'X') { KbRadix = 16; info = "(hex)"; KbCount = 0; } else if (digit == 0 ) { KbRadix = 8; info = "(oct)"; KbCount = 0; } else if (digit > 0 ) { KbRadix = 10; info.setNum( KbCount = digit ); } if (KbRadix) { Twnd->sctw->DisplayInfo( Utf8("×%1").arg(info) ); luaQn_pop(1); MkPrefix.clear(); return; } } QString MkStr = MkToString(kcode|modMask); last_MiCmd_key = MkPrefix + "," + MkStr; luaP_getfield(-1,last_MiCmd_key.uStr()); MkPrefix.clear(); if (lua_isnil(L,-1)) { luaQn_pop(1); last_MiCmd_key = MkStr; // Try finding CCD with prefix luaP_getfield(-1,last_MiCmd_key.uStr()); // 1st, ignore it if not found } } if (MiApp_debugKB) fprintf(stderr, ",‹%s›", last_MiCmd_key.uStr()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (MkRecording) { if (KbRadix) MkMacro.append(Utf8("×")+QString::number(KbCount)+Utf8("⁝")); if (text.isEmpty() || !text.at(0).isPrint()) MkMacro.append(MkQuoteCmd(last_MiCmd_key)); // no printable text exists else switch (text.at(0).unicode()) { case 0x00D7: // × ← these two characters have special meaning in macros case 0x2039: // ‹ (must escape them) MkMacro.append(Utf8("⑆")+text); break; default: MkMacro.append (text); break; } if (MkMacro.size() > MkMAX_MACRO_SIZE) { vipBell(); MkStopRecording(); } } MkLuaXEQ(text, vp); // Lua stack here: [-2] global "Mk" (not used below) } // [-1] Mk[kcode] value (may be nil)
static luaP_Tuple *luaP_checktuple (lua_State *L, int pos) { luaP_Tuple *t = (luaP_Tuple *) lua_touserdata(L, pos); if (t != NULL) { if (lua_getmetatable(L, pos)) { luaP_getfield(L, PLLUA_TUPLEMT); if (!lua_rawequal(L, -1, -2)) /* not tuple? */ t = NULL; lua_pop(L, 2); /* metatables */ } } return t; }
int luaP_clearabort (lua_State *L) { luaP_getfield(L, PLLUA_TXNABORT); if (lua_isnil(L, -1)) { lua_pop(L, 1); return 0; } elog(INFO, "clearing pllua abort state"); lua_pushlightuserdata(L, (void *)PLLUA_TXNABORT); lua_pushnil(L); lua_rawset(L, LUA_REGISTRYINDEX); return 1; }
void *luaP_toudata (lua_State *L, int ud, const char *tname) { void *p = lua_touserdata(L, ud); if (p != NULL) { /* value is userdata? */ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ luaP_getfield(L, tname); /* get metatable */ if (lua_rawequal(L, -1, -2)) { /* MTs match? */ lua_pop(L, 2); /* MTs */ return p; } } } return NULL; }
luaP_Buffer *luaP_getbuffer (lua_State *L, int n) { int i; luaP_Buffer *b; luaP_getfield(L, PLLUA_BUFFER); b = (luaP_Buffer *) lua_touserdata(L, -1); lua_pop(L, 1); if (b == NULL || n > b->size) { /* resize? */ lua_pushlightuserdata(L, (void *) PLLUA_BUFFER); b = (luaP_Buffer *) lua_newuserdata(L, sizeof(luaP_Buffer) + n * (sizeof(Datum) + sizeof(char))); b->size = n; b->value = (Datum *) (b + 1); b->null = (char *) (b->value + n); lua_rawset(L, LUA_REGISTRYINDEX); } for (i = 0; i < n; i++) { b->value[i] = 0; b->null[i] = 'n'; } return b; }
static void luaP_pushtuple_cmn (lua_State *L, HeapTuple tuple, int readonly, RTupDesc* rtupdesc) { luaP_Tuple *t; TupleDesc tupleDesc; int i, n; BEGINLUA; tupleDesc = rtupdesc->tupdesc; n = tupleDesc->natts; t = lua_newuserdata(L, sizeof(luaP_Tuple) + n * (sizeof(Datum) + sizeof(bool))); t->value = (Datum *) (t + 1); t->null = (bool *) (t->value + n); t->rtupdesc = rtupdesc_ref(rtupdesc); for (i = 0; i < n; i++) { bool isnull; t->value[i] = heap_getattr(tuple, tupleDesc->attrs[i]->attnum, tupleDesc, &isnull); t->null[i] = isnull; } if (readonly) { t->changed = -1; } else { t->changed = 0; } t->tupdesc = 0; t->relid = 0; t->tuple = tuple; luaP_getfield(L, PLLUA_TUPLEMT); lua_setmetatable(L, -2); ENDLUAV(1); }
void luaP_pushcursor (lua_State *L, Portal cursor) { luaP_Cursor *c = (luaP_Cursor *) lua_newuserdata(L, sizeof(luaP_Cursor)); c->cursor = cursor; luaP_getfield(L, PLLUA_CURSORMT); lua_setmetatable(L, -2); }
int get_pgfunc(lua_State *L) { Lua_pgfunc *lf; Pgfunc_options opt; MemoryContext m; const char* reg_name = NULL; HeapTuple proctup; Form_pg_proc proc; int luasrc = 0; Oid funcid = 0; BEGINLUA; opt.only_internal = true; opt.throwable = true; if (lua_gettop(L) == 2){ luaL_checktype(L, 2, LUA_TTABLE); parse_options(L, &opt); }else if (lua_gettop(L) != 1){ return luaL_error(L, "pgfunc(text): wrong arguments"); } if(lua_type(L, 1) == LUA_TSTRING){ reg_name = luaL_checkstring(L, 1); m = MemoryContextSwitchTo(tmpcontext); PG_TRY(); { funcid = DatumGetObjectId(DirectFunctionCall1(regprocedurein, CStringGetDatum(reg_name))); } PG_CATCH();{} PG_END_TRY(); MemoryContextSwitchTo(m); MemoryContextReset(tmpcontext); }else if (lua_type(L, 1) == LUA_TNUMBER){ funcid = luaL_checkinteger(L, 1); } if (!OidIsValid(funcid)){ if (reg_name) return luaL_error(L,"failed to register %s", reg_name); return luaL_error(L,"failed to register function with oid %d", funcid); } proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); if (!HeapTupleIsValid(proctup)){ return luaL_error(L,"cache lookup failed for function %d", funcid); } proc = (Form_pg_proc) GETSTRUCT(proctup); luasrc = ((proc->prolang == get_pllua_oid()) || (proc->prolang == get_plluau_oid())); if ( opt.only_internal &&(proc->prolang != INTERNALlanguageId) &&(!luasrc) ){ ReleaseSysCache(proctup); return luaL_error(L, "supported only SQL/internal functions"); } lf = (Lua_pgfunc *)lua_newuserdata(L, sizeof(Lua_pgfunc)); /*make it g/collected*/ luaP_getfield(L, pg_func_type_name); lua_setmetatable(L, -2); lf->prorettype = proc->prorettype; lf->funcid = funcid; lf->options = opt; { Oid *argtypes; char **argnames; char *argmodes; int argc; MemoryContext cur = CurrentMemoryContext; MemoryContextSwitchTo(tmpcontext); argc = get_func_arg_info(proctup, &argtypes, &argnames, &argmodes); MemoryContextSwitchTo(get_common_ctx()); lf->numargs = argc; lf->argtypes = (Oid*)palloc(argc * sizeof(Oid)); memcpy(lf->argtypes, argtypes, argc * sizeof(Oid)); MemoryContextSwitchTo(cur); MemoryContextReset(tmpcontext); } if (luasrc){ bool isnull; text *t; const char *s; luaL_Buffer b; int pcall_result; Datum prosrc; if((lf->numargs != 1) || (lf->argtypes[0] != INTERNALOID) || (lf->prorettype != INTERNALOID)){ luaL_error(L, "pgfunc accepts only 'internal' pllua/u functions with internal argument"); } prosrc = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull); if (isnull) elog(ERROR, "[pgfunc]: null lua prosrc"); luaL_buffinit(L, &b); luaL_addstring(&b,"do "); t = DatumGetTextP(prosrc); luaL_addlstring(&b, VARDATA(t), VARSIZE(t) - VARHDRSZ); luaL_addstring(&b, " end"); luaL_pushresult(&b); s = lua_tostring(L, -1); ReleaseSysCache(proctup); clean_pgfuncinfo(lf); if (luaL_loadbuffer(L, s, strlen(s), "pgfunc chunk")) luaL_error(L, "compile"); lua_remove(L, -2); /*delete source element*/ pcall_result = lua_pcall(L, 0, 1, 0); lua_remove(L, -2); /*delete chunk*/ if(pcall_result == 0){ ENDLUAV(1); return 1; } if( pcall_result == LUA_ERRRUN) luaL_error(L,"%s %s","Runtime error:",lua_tostring(L, -1)); else if(pcall_result == LUA_ERRMEM) luaL_error(L,"%s %s","Memory error:",lua_tostring(L, -1)); else if(pcall_result == LUA_ERRERR) luaL_error(L,"%s %s","Error:",lua_tostring(L, -1)); return luaL_error(L, "pgfunc unknown error"); } if(proc->proretset) { lua_pushcclosure(L, pgfunc_rows, 1); } else { fmgr_info(funcid, &lf->fi); lua_pushcclosure(L, pg_callable_func, 1); } ReleaseSysCache(proctup); ENDLUAV(1); return 1; }