Datum check_get_opname(PG_FUNCTION_ARGS) { Oid opno = PG_GETARG_OID(0); char *result; StringInfoData buf; initStringInfo(&buf); result = get_opname(opno); if (result) appendStringInfo(&buf, "%s", result); PG_RETURN_TEXT_P(cstring_to_text(buf.data)); }
/** * @fn Datum reorg_get_index_keys(PG_FUNCTION_ARGS) * @brief Get key definition of the index. * * reorg_get_index_keys(index, table) * * @param index Oid of target index. * @param table Oid of table of the index. * @retval Create index DDL for temp table. * * FIXME: this function is named get_index_keys, but actually returns * an expression for ORDER BY clause. get_order_by() might be a better name. */ Datum reorg_get_index_keys(PG_FUNCTION_ARGS) { Oid index = PG_GETARG_OID(0); Oid table = PG_GETARG_OID(1); IndexDef stmt; char *token; char *next; StringInfoData str; Relation indexRel = NULL; int nattr; parse_indexdef(&stmt, index, table); elog(DEBUG2, "indexdef.create = %s", stmt.create); elog(DEBUG2, "indexdef.index = %s", stmt.index); elog(DEBUG2, "indexdef.table = %s", stmt.table); elog(DEBUG2, "indexdef.type = %s", stmt.type); elog(DEBUG2, "indexdef.columns = %s", stmt.columns); elog(DEBUG2, "indexdef.options = %s", stmt.options); /* * FIXME: this is very unreliable implementation but I don't want to * re-implement customized versions of pg_get_indexdef_string... * * TODO: Support ASC/DESC and NULL FIRST/LAST. */ initStringInfo(&str); for (nattr = 0, next = stmt.columns; next; nattr++) { char *opcname; token = next; while (isspace((unsigned char) *token)) token++; next = skip_until(index, next, ','); opcname = skip_until(index, token, ' '); if (opcname) { /* lookup default operator name from operator class */ Oid opclass; Oid oprid; int16 strategy = BTLessStrategyNumber; Oid opcintype; Oid opfamily; HeapTuple tp; Form_pg_opclass opclassTup; opclass = OpclassnameGetOpcid(BTREE_AM_OID, opcname); /* Retrieve operator information. */ tp = SearchSysCache(CLAOID, ObjectIdGetDatum(opclass), 0, 0, 0); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for opclass %u", opclass); opclassTup = (Form_pg_opclass) GETSTRUCT(tp); opfamily = opclassTup->opcfamily; opcintype = opclassTup->opcintype; ReleaseSysCache(tp); if (!OidIsValid(opcintype)) { if (indexRel == NULL) indexRel = index_open(index, NoLock); opcintype = RelationGetDescr(indexRel)->attrs[nattr]->atttypid; } oprid = get_opfamily_member(opfamily, opcintype, opcintype, strategy); if (!OidIsValid(oprid)) elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", strategy, opcintype, opcintype, opfamily); opcname[-1] = '\0'; appendStringInfo(&str, "%s USING %s", token, get_opname(oprid)); } else appendStringInfoString(&str, token); if (next) appendStringInfoString(&str, ", "); } if (indexRel != NULL) index_close(indexRel, NoLock); PG_RETURN_TEXT_P(cstring_to_text(str.data)); }
/* * ApplicableOpExpressionList walks over all filter clauses that relate to this * foreign table, and chooses applicable clauses that we know we can translate * into Mongo queries. Currently, these clauses include comparison expressions * that have a column and a constant as arguments. For example, "o_orderdate >= * date '1994-01-01' + interval '1' year" is an applicable expression. */ List * ApplicableOpExpressionList(RelOptInfo *baserel) { List *opExpressionList = NIL; List *restrictInfoList = baserel->baserestrictinfo; ListCell *restrictInfoCell = NULL; foreach(restrictInfoCell, restrictInfoList) { RestrictInfo *restrictInfo = (RestrictInfo *) lfirst(restrictInfoCell); Expr *expression = restrictInfo->clause; NodeTag expressionType = 0; OpExpr *opExpression = NULL; char *operatorName = NULL; char *mongoOperatorName = NULL; List *argumentList = NIL; Var *column = NULL; Const *constant = NULL; bool equalsOperator = false; bool constantIsArray = false; /* we only support operator expressions */ expressionType = nodeTag(expression); if (expressionType != T_OpExpr) { continue; } opExpression = (OpExpr *) expression; operatorName = get_opname(opExpression->opno); /* we only support =, <, >, <=, >=, and <> operators */ if (strncmp(operatorName, EQUALITY_OPERATOR_NAME, NAMEDATALEN) == 0) { equalsOperator = true; } mongoOperatorName = MongoOperatorName(operatorName); if (!equalsOperator && mongoOperatorName == NULL) { continue; } /* * We only support simple binary operators that compare a column against * a constant. If the expression is a tree, we don't recurse into it. */ argumentList = opExpression->args; column = (Var *) FindArgumentOfType(argumentList, T_Var); constant = (Const *) FindArgumentOfType(argumentList, T_Const); /* * We don't push down operators where the constant is an array, since * conditional operators for arrays in MongoDB aren't properly defined. * For example, {similar_products : [ "B0009S4IJW", "6301964144" ]} * finds results that are equal to the array, but {similar_products: * {$gte: [ "B0009S4IJW", "6301964144" ]}} returns an empty set. */ if (constant != NULL) { Oid constantArrayTypeId = get_element_type(constant->consttype); if (constantArrayTypeId != InvalidOid) { constantIsArray = true; } } if (column != NULL && constant != NULL && !constantIsArray) { opExpressionList = lappend(opExpressionList, opExpression); } }
void listline(char *var, statement *stmt, byte showline) { int x; outcount = 0; if (stmt->errorflag) { mysprintf(var, "*ERR "); for (x=0; x<tokenpos; x++) mysprintf(var, " "); mysprintf(var, "V\n"); } if (showline) mysprintf(var, "%.5d ", stmt->linenum); if (stmt->errorflag) { mysprintf(var, "%s", stmt->metalist[1].stringarg); return; } if (stmt->numlabels) { for (x=0; x<stmt->numlabels; x++) mysprintf(var, "%s: ", get_labelname(stmt->labelset[x]->labelnum)); } mysprintf(var, "%s ", get_opname(stmt->opcode)); switch(stmt->opcode) { case CMD_DEFFN: list_deffn(var, stmt); break; case CMD_REM: mysprintf(var, "%s", stmt->metalist[1].stringarg); break; case CMD_IF: list_if(var, stmt); break; case CMD_LET: list_let(var, stmt); break; case CMD_SETESC: case CMD_SETERR: case CMD_GOTO: case CMD_GOSUB: if (stmt->metalist[1].operation == LABELREF) mysprintf(var, "%s", get_labelname(stmt->metalist[1].shortarg)); else mysprintf(var, "%.5d", stmt->metalist[1].shortarg); break; case CMD_FOR: list_for(var, stmt); break; case CMD_NEXT: mysprintf(var, "%s", get_symname(stmt->metalist[1].shortarg)); break; case CMD_LIST: case CMD_DELETE: if (stmt->metapos == 1) mysprintf(var, "00001, 65534"); else if (stmt->metapos == 2) mysprintf(var, "%.5d", flt2int(stmt->metalist[1].floatarg)); else mysprintf(var, "%.5d, %.5d", flt2int(stmt->metalist[1].floatarg), flt2int(stmt->metalist[3].floatarg)); break; case CMD_RETURN: case CMD_WEND: case CMD_RETRY: case CMD_SETERRON: case CMD_SETERROFF: break; case CMD_ON: list_on(var, stmt); break; default: if (stmt->metapos == 1) break; simplifylist(var, stmt, 0, stmt->metapos); mysprintf(var, "%s", listpop()); break; } }
// main entry into parser void encode_rpn() { statement *stmt, *tempstmt = gprog->firststmt; struct labelset *label; unsigned int x = 0, y = 0; int channum = 0, lastfnc = 0, lastvar = 0, ifcount = 0; byte display = 0, watchchannel = 0, special = 0; char *cont; symbol *sym; begin: stmt = SafeMalloc(sizeof(statement)); stmtinit(stmt); for (x=0; x<MAX_STMT_METAS; x++) { stmt->metalist[x].operation = 0; stmt->metalist[x].floatarg.mantisa.i = 0; stmt->metalist[x].floatarg.exp = 0; stmt->metalist[x].shortarg = 0; for (y=0; y<MAX_STRING_LENGTH; y++) stmt->metalist[x].stringarg[y] = 0; } special = 0; foundequals = 0; firstvar = 1; numlabels = 0; envinfo.stmttype = 0; tokenpos = 0; token_type = 1; lastopcode = 0; for (x=0; x<32; x++) { numargs[x] = 0; parenstack[x] = 0; } do { get_token(); tokenpos += strlen(token); if(!checkoption(get_cmdindex(get_opname(stmt->opcode)), token, token_type)) lineerror(stmt, __FILE__, __LINE__); // hack to avoid using runtime system // using runtime system would change the last executed line info. // if ((!strcmp(token, "PBSTEP")) && (token_type == TOK_COMMAND)) // dbg_step(); switch (token_type) { case TOK_ERROR: lineerror(stmt, __FILE__, __LINE__); break; case TOK_COMMAND: lastopcode = get_opcode(token); if (cmdtable[get_cmdindex(token)].options & IO_CHANNEL) watchchannel = 1; else watchchannel = 0; stmt->opcode = get_opcode(token); if (stmt->opcode == CMD_LET) goto loop2; else goto loop; case TOK_NUMBER: stmt->opcode = 0; stmt->linenum = atoi(token); break; default: buffermeta(stmt, token_type, token); goto loop2; } buffermeta(stmt, token_type, token); loop: get_token(); if (checkerr == 2) checkerr = 1; else if (checkerr == 1) { if (token[0] == '=') { if (stmt->metalist[stmt->metapos-2].operation == 0xEC) stmt->metapos-=2; else stmt->metapos--; push("ERR", TOK_OPERATOR); } else if (token[0] == '(') { prog--; stmt->metapos--; strcpy(token, "ERR"); token_type = TOK_FUNCTION; } checkerr = 0; } if (lastopcode == CMD_SETERR) { if (!strcmp(token, "ON")) lastopcode = CMD_SETERRON; if (!strcmp(token, "OFF")) lastopcode = CMD_SETERROFF; } if (!strcmp(token, "RECORD")) { if (stmt->opcode == CMD_READ) lastopcode = CMD_READRECORD; if (stmt->opcode == CMD_WRITE) lastopcode = CMD_WRITERECORD; if (stmt->opcode == CMD_EXTRACT) lastopcode = CMD_EXTRACTRECORD; if (stmt->opcode == CMD_FIND) lastopcode = CMD_FINDRECORD; if (stmt->opcode == CMD_PRINT) lastopcode = CMD_PRINTRECORD; token_type = lasttype; goto loop; } if (lastopcode == CMD_REM) { stmt->metalist[1].operation = 0xF5; tokenpos -= 2; if (input[tokenpos] == '\"') x = tokenpos; else x = tokenpos+2; stmt->metalist[1].shortarg = strlen(input) - x; y = 0; for (x=x; x<strlen(input); x++) { stmt->metalist[1].stringarg[y] = input[x]; y++; } stmt->metalist[1].stringarg[y] = '\0'; stmt->metapos++; if (stmt->linenum) insertstmt(gprog, stmt); return; } tokenpos += strlen(token); if(!checkoption(get_cmdindex(get_opname(lastopcode)), token, token_type)) lineerror(stmt, __FILE__, __LINE__); loop2: switch (token_type) { case TOK_SEMICOLON: popstack(stmt, -1); if (!stmt->linenum) { execline(gprog, stmt); stmtinit(stmt); } break; case TOK_COLON: if ((stmt->metalist[stmt->metapos-1].operation == SETVAL_NUMERIC) || (stmt->metalist[stmt->metapos-1].operation == GETVAL_NUMERIC) || (stmt->metalist[stmt->metapos-1].operation == LABELREF)) { label = SafeMalloc(sizeof(struct labelset)); sym = idx2sym(gprog, stmt->metalist[stmt->metapos-1].shortarg); label->labelnum = addlabel(gprog, sym->name, stmt->linenum); for (x=0; x<MAX_STRING_LENGTH; x++) sym->name[x] = '\0'; x = 0; stmt->metapos--; stmt->metalist[stmt->metapos].shortarg = 0; stmt->opcode = 0; stmt->labelset[stmt->numlabels] = label; stmt->numlabels++; firstvar = 1; } else { do { if (stmt->linenum == tempstmt->linenum) { for (x=0; x<strlen(input); x++) if (input[x] == ':') break; y = x; for (x=0; x<=y; x++) input[x] = ' '; cont = SafeMalloc(1024*64); *cont = 0; listline(cont, tempstmt, 1); strcat(cont, input); *prog = 0; prog = cont; display = 1; goto begin; } tempstmt = tempstmt->nextstmt; } while (tempstmt != NULL); numlabels++; } goto loop; case TOK_COMMA: if (parencount > 0) { // comma being delimiter for system functions popstack(stmt, -2); push("(", TOK_OPERATOR); if (chaninfo == 1) { if (!channum) { channum = 1; stmt->metalist[stmt->metapos].operation = 0xE1; stmt->metapos++; } } else { if (special == 1) numargs[parencount-1]+=10; else numargs[parencount-1]++; envinfo.stmttype = 0; } } else { // comma being delimiter for verbs popstack(stmt, -1); buffermeta(stmt, TOK_COMMA, token); for (x=0; x<32; x++) numargs[x] = 0; envinfo.stmttype = 0; foundequals = 0; firstvar = 1; } goto loop; case TOK_ERROR: lineerror(stmt, __FILE__, __LINE__); return; case TOK_COMMAND: lastopcode = get_opcode(token); if (cmdtable[get_cmdindex(token)].options & IO_CHANNEL) watchchannel = 1; else watchchannel = 0; if (!strcmp(token, "IF")) ifcount++; if (!stmt->opcode) { stmt->opcode = get_opcode(token); envinfo.stmttype = 0; goto loop; } else { popstack(stmt, -1); envinfo.stmttype = 0; if (ifcount > 0) { stmt->metalist[stmt->metapos].operation = 0xE7; stmt->metalist[stmt->metapos].shortarg = 0; stmt->metalist[stmt->metapos].intarg = 0; stmt->metapos++; stmt->length++; // watchchannel = 0; chaninfo = 0; channum = 0; ifcount--; } if (lastopcode == CMD_ON) { special = 1; if (!strcmp(token, "GOTO")) stmt->metalist[stmt->metapos].operation = 0x00F4; else stmt->metalist[stmt->metapos].operation = 0x01F4; stmt->length += 2; stmt->metapos++; } else buffermeta(stmt, TOK_COMMAND, token); goto loop; } break; case TOK_RESERVED: popstack(stmt, -1); envinfo.stmttype = 0; lineref = 0; if (!strcmp(token, "ELSE")) { stmt->metalist[stmt->metapos].operation = 0xE7; stmt->metalist[stmt->metapos].intarg = 0; stmt->metalist[stmt->metapos].shortarg = 0; stmt->metapos++; stmt->metalist[stmt->metapos].operation = 0xE2; stmt->metalist[stmt->metapos].intarg = 0; stmt->metalist[stmt->metapos].shortarg = 0; stmt->metapos++; stmt->length+=2; envinfo.stmttype = 0; chaninfo = 0; channum = 0; } goto loop; case TOK_DONE: if ((stmt->linenum) && (!stmt->opcode)) deletestmt(gprog,stmt->linenum); else { popstack(stmt, -1); if (stmt->opcode == CMD_LET && foundequals == 0) lineerror(stmt, __FILE__, __LINE__); if (parencount > 0 || numlabels < 0) lineerror(stmt, __FILE__, __LINE__); if (stmt->linenum) { if (!stmt->errorflag) insertstmt(gprog, stmt); } else if (stmt->opcode) { if (!stmt->errorflag) { execline(gprog, stmt); } } } if (display) { GC_realloc(cont, strlen(cont)); listprog(gprog, stmt->linenum, stmt->linenum); } return; case TOK_USERFUNCTION: if (lastopcode == CMD_DEFFN) addfunction(gprog, token, stmt->linenum, 1); else addfunction(gprog, token, stmt->linenum, 0); if (token[strlen(token)-1] == '$') parenstack[parencount] = 8; else parenstack[parencount] = 7; buffermeta(stmt, TOK_USERFUNCTION, token); break; case TOK_FUNCTION: lastfnc = get_fnc(token); numlabels++; case TOK_OPERATOR: if (token[0] == '[') { special = 1; cont = get_symname(lastvar); if (cont[strlen(cont)-1] == '$') parenstack[parencount] = 2; else parenstack[parencount] = 1; numlabels++; goto openparen; } else if (token[0] == ']') { numargs[parencount-1] += 9; popstack(stmt, -2); envinfo.stmttype = parenstack[parencount]; token_type = TOK_ARRAY; special = 0; goto loop; } else if (token[0] == '-') { // placeholder if ((lasttype == TOK_OPERATOR) || (lasttype == TOK_RESERVED)) token[0] = '_'; evalstack(stmt); goto loop; } else if (token[0] == '(') { openparen: if (lasttype == TOK_COMMAND) { if (watchchannel == 1) chaninfo = 1; } else if (lasttype == TOK_ARRAY) { envinfo.stmttype = 0; numargs[parencount]++; push(token, token_type); goto loop; } else if (lasttype == TOK_SETVAL) { push(get_symname(lastvar), TOK_SETVAL); stmt->metapos--; stmt->metalist[stmt->metapos].shortarg = 0; numlabels++; cont = get_symname(lastvar); if (cont[strlen(cont)-1] == '$') parenstack[parencount] = 2; else parenstack[parencount] = 1; } else if (lasttype == TOK_VARIABLE) { push(get_symname(lastvar), TOK_VARIABLE); numlabels++; stmt->metapos--; stmt->metalist[stmt->metapos].shortarg = 0; cont = get_symname(lastvar); if (cont[strlen(cont)-1] == '$') parenstack[parencount] = 2; else parenstack[parencount] = 1; } else if (lasttype == TOK_USERFUNCTION) { stmt->metapos--; stmt->metalist[stmt->metapos].operation = 0xF5; stmt->metapos++; stmt->length++; } else if (lasttype == TOK_FUNCTION) { if ((envinfo.stmttype != fnctable[lastfnc].returntype) && (envinfo.stmttype != 0)) lineerror(stmt, __FILE__, __LINE__); else parenstack[parencount] = fnctable[lastfnc].returntype; } else parenstack[parencount] = 1; envinfo.stmttype = 0; numargs[parencount] = 1; push(token, token_type); goto loop; } else if (token[0] == ')') { if (parencount == 0) lineerror(stmt, __FILE__, __LINE__); popstack(stmt, -2); if (parenstack[parencount] == 7) { stmt->metalist[stmt->metapos].operation = 0xF8; stmt->metapos++; stmt->length++; envinfo.stmttype = 1; } else if (parenstack[parencount] == 8) { stmt->metalist[stmt->metapos].operation = 0xF8; stmt->metapos++; stmt->length++; envinfo.stmttype = 2; } else envinfo.stmttype = parenstack[parencount]; if (lastopcode == CMD_DEFFN && foundequals == 0) { stmt->metapos--; stmt->metalist[stmt->metapos].operation = 0xF8; stmt->metapos++; } if (chaninfo == 1) { chaninfo = 0; if (!channum) { stmt->metalist[stmt->metapos].operation = 0xE1; stmt->metapos++; } stmt->metalist[stmt->metapos].operation = 0xF4F1; stmt->metapos++; numargs[parencount] = 0; } goto loop; } else { evalstack(stmt); goto loop; } break; case TOK_VARIABLE: if (get_sysvar(token)) { buffermeta(stmt, TOK_SYSVAR, token); numlabels++; goto loop; } else { addsymbol(gprog, token); lastvar = get_symref(token); } case TOK_NUMBER: default: if(!stmt->opcode) { envinfo.stmttype = 0; lastopcode = stmt->opcode = CMD_LET; } if ((firstvar == 1) && (token_type == TOK_VARIABLE) && (lastopcode == CMD_LET || lastopcode == CMD_FOR || lastopcode == CMD_FOR || lastopcode == CMD_NEXT || lastopcode == CMD_DIM || lastopcode == CMD_INPUT)) { buffermeta(stmt, TOK_SETVAL, token); firstvar = 0; token_type = TOK_SETVAL; } else { numlabels++; buffermeta(stmt, token_type, token); } goto loop; } } while (1); }
NezVMInstruction *nez_LoadMachineCode(ParsingContext context, const char *fileName, const char *nonTerminalName) { NezVMInstruction *inst = NULL; NezVMInstruction *head = NULL; size_t len; char *buf = loadFile(fileName, &len); byteCodeInfo info; info.pos = 0; /* load bytecode header */ info.version0 = buf[info.pos++]; /* version info */ info.version1 = buf[info.pos++]; info.filename_length = read32(buf, &info); /* file name */ info.filename = malloc(sizeof(uint8_t) * info.filename_length + 1); for (uint32_t i = 0; i < info.filename_length; i++) { info.filename[i] = buf[info.pos++]; } info.filename[info.filename_length] = 0; /* call table size */ context->call_table_size = read32(buf, &info); context->call_table = (int *)malloc(sizeof(int) * (int)context->call_table_size); /* set table size */ context->set_table_size = read32(buf, &info); context->set_table = (bitset_ptr_t *)malloc(sizeof(bitset_t) * (int)context->set_table_size); /* str table size */ context->str_table_size = read32(buf, &info); context->str_table = (nezvm_string_ptr_t *)malloc(sizeof(nezvm_string_ptr_t) * (int)context->str_table_size); /* bytecode length */ info.bytecode_length = read64(buf, &info); free(info.filename); /* ** head is a tmporary variable that indecates the begining ** of the instruction sequence */ head = inst = malloc(sizeof(*inst) * info.bytecode_length); memset(inst, 0, sizeof(*inst) * info.bytecode_length); /* init bytecode loader */ ByteCodeLoader *loader = malloc(sizeof(ByteCodeLoader)); loader->input = buf; loader->info = &info; loader->head = head; /* f_convert[] is function pointer that emit instruction */ for (uint64_t i = 0; i < info.bytecode_length; i++) { if (i == 723) { fprintf(stderr, "debug\n"); } inst->op = buf[info.pos++]; fprintf(stderr, "[%llu]%s\n", i, get_opname(inst->op)); nez_EmitInstruction(inst, loader, context); inst++; } #if PEGVM_DEBUG dump_NezVMInstructions(inst, info.bytecode_length); #endif context->bytecode_length = info.bytecode_length; free(buf); return head; }