tsquery.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 980 行 · 第 1/2 页
C
980 行
*(state.curop) = '\0'; /* parse query & make polish notation (postfix, but in reverse order) */ makepol(&state, pushval, opaque); close_tsvector_parser(state.valstate); if (list_length(state.polstr) == 0) { ereport(NOTICE, (errmsg("text-search query doesn't contain lexemes: \"%s\"", state.buffer))); query = (TSQuery) palloc(HDRSIZETQ); SET_VARSIZE(query, HDRSIZETQ); query->size = 0; return query; } /* Pack the QueryItems in the final TSQuery struct to return to caller */ commonlen = COMPUTESIZE(list_length(state.polstr), state.sumlen); query = (TSQuery) palloc0(commonlen); SET_VARSIZE(query, commonlen); query->size = list_length(state.polstr); ptr = GETQUERY(query); /* Copy QueryItems to TSQuery */ i = 0; foreach(cell, state.polstr) { QueryItem *item = (QueryItem *) lfirst(cell); switch (item->type) { case QI_VAL: memcpy(&ptr[i], item, sizeof(QueryOperand)); break; case QI_VALSTOP: ptr[i].type = QI_VALSTOP; break; case QI_OPR: memcpy(&ptr[i], item, sizeof(QueryOperator)); break; default: elog(ERROR, "unrecognized QueryItem type: %d", item->type); } i++; } /* Copy all the operand strings to TSQuery */ memcpy((void *) GETOPERAND(query), (void *) state.op, state.sumlen); pfree(state.op); /* Set left operand pointers for every operator. */ findoprnd(ptr, query->size); return query;}static voidpushval_asis(Datum opaque, TSQueryParserState state, char *strval, int lenval, int16 weight){ pushValue(state, strval, lenval, weight);}/* * in without morphology */Datumtsqueryin(PG_FUNCTION_ARGS){ char *in = PG_GETARG_CSTRING(0); pg_verifymbstr(in, strlen(in), false); PG_RETURN_TSQUERY(parse_tsquery(in, pushval_asis, PointerGetDatum(NULL), false));}/* * out function */typedef struct{ QueryItem *curpol; char *buf; char *cur; char *op; int buflen;} INFIX;/* Makes sure inf->buf is large enough for adding 'addsize' bytes */#define RESIZEBUF(inf, addsize) \while( ( (inf)->cur - (inf)->buf ) + (addsize) + 1 >= (inf)->buflen ) \{ \ int len = (inf)->cur - (inf)->buf; \ (inf)->buflen *= 2; \ (inf)->buf = (char*) repalloc( (void*)(inf)->buf, (inf)->buflen ); \ (inf)->cur = (inf)->buf + len; \}/* * recursive walk on tree and print it in * infix (human-readable) view */static voidinfix(INFIX *in, bool first){ /* since this function recurses, it could be driven to stack overflow. */ check_stack_depth(); if (in->curpol->type == QI_VAL) { QueryOperand *curpol = &in->curpol->operand; char *op = in->op + curpol->distance; int clen; RESIZEBUF(in, curpol->length * (pg_database_encoding_max_length() + 1) + 2 + 5); *(in->cur) = '\''; in->cur++; while (*op) { if (t_iseq(op, '\'')) { *(in->cur) = '\''; in->cur++; } else if (t_iseq(op, '\\')) { *(in->cur) = '\\'; in->cur++; } COPYCHAR(in->cur, op); clen = pg_mblen(op); op += clen; in->cur += clen; } *(in->cur) = '\''; in->cur++; if (curpol->weight) { *(in->cur) = ':'; in->cur++; if (curpol->weight & (1 << 3)) { *(in->cur) = 'A'; in->cur++; } if (curpol->weight & (1 << 2)) { *(in->cur) = 'B'; in->cur++; } if (curpol->weight & (1 << 1)) { *(in->cur) = 'C'; in->cur++; } if (curpol->weight & 1) { *(in->cur) = 'D'; in->cur++; } } *(in->cur) = '\0'; in->curpol++; } else if (in->curpol->operator.oper == OP_NOT) { bool isopr = false; RESIZEBUF(in, 1); *(in->cur) = '!'; in->cur++; *(in->cur) = '\0'; in->curpol++; if (in->curpol->type == QI_OPR) { isopr = true; RESIZEBUF(in, 2); sprintf(in->cur, "( "); in->cur = strchr(in->cur, '\0'); } infix(in, isopr); if (isopr) { RESIZEBUF(in, 2); sprintf(in->cur, " )"); in->cur = strchr(in->cur, '\0'); } } else { int8 op = in->curpol->operator.oper; INFIX nrm; in->curpol++; if (op == OP_OR && !first) { RESIZEBUF(in, 2); sprintf(in->cur, "( "); in->cur = strchr(in->cur, '\0'); } nrm.curpol = in->curpol; nrm.op = in->op; nrm.buflen = 16; nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen); /* get right operand */ infix(&nrm, false); /* get & print left operand */ in->curpol = nrm.curpol; infix(in, false); /* print operator & right operand */ RESIZEBUF(in, 3 + (nrm.cur - nrm.buf)); switch (op) { case OP_OR: sprintf(in->cur, " | %s", nrm.buf); break; case OP_AND: sprintf(in->cur, " & %s", nrm.buf); break; default: /* OP_NOT is handled in above if-branch */ elog(ERROR, "unrecognized operator type: %d", op); } in->cur = strchr(in->cur, '\0'); pfree(nrm.buf); if (op == OP_OR && !first) { RESIZEBUF(in, 2); sprintf(in->cur, " )"); in->cur = strchr(in->cur, '\0'); } }}Datumtsqueryout(PG_FUNCTION_ARGS){ TSQuery query = PG_GETARG_TSQUERY(0); INFIX nrm; if (query->size == 0) { char *b = palloc(1); *b = '\0'; PG_RETURN_POINTER(b); } nrm.curpol = GETQUERY(query); nrm.buflen = 32; nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen); *(nrm.cur) = '\0'; nrm.op = GETOPERAND(query); infix(&nrm, true); PG_FREE_IF_COPY(query, 0); PG_RETURN_CSTRING(nrm.buf);}/* * Binary Input / Output functions. The binary format is as follows: * * uint32 number of operators/operands in the query * * Followed by the operators and operands, in prefix notation. For each * operand: * * uint8 type, QI_VAL * uint8 weight * operand text in client encoding, null-terminated * * For each operator: * uint8 type, QI_OPR * uint8 operator, one of OP_AND, OP_OR, OP_NOT. */Datumtsquerysend(PG_FUNCTION_ARGS){ TSQuery query = PG_GETARG_TSQUERY(0); StringInfoData buf; int i; QueryItem *item = GETQUERY(query); pq_begintypsend(&buf); pq_sendint(&buf, query->size, sizeof(uint32)); for (i = 0; i < query->size; i++) { pq_sendint(&buf, item->type, sizeof(item->type)); switch (item->type) { case QI_VAL: pq_sendint(&buf, item->operand.weight, sizeof(uint8)); pq_sendstring(&buf, GETOPERAND(query) + item->operand.distance); break; case QI_OPR: pq_sendint(&buf, item->operator.oper, sizeof(item->operator.oper)); break; default: elog(ERROR, "unrecognized tsquery node type: %d", item->type); } item++; } PG_FREE_IF_COPY(query, 0); PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}Datumtsqueryrecv(PG_FUNCTION_ARGS){ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); TSQuery query; int i, len; QueryItem *item; int datalen; char *ptr; uint32 size; const char **operands; size = pq_getmsgint(buf, sizeof(uint32)); if (size > (MaxAllocSize / sizeof(QueryItem))) elog(ERROR, "invalid size of tsquery"); /* Allocate space to temporarily hold operand strings */ operands = palloc(size * sizeof(char *)); /* Allocate space for all the QueryItems. */ len = HDRSIZETQ + sizeof(QueryItem) * size; query = (TSQuery) palloc0(len); query->size = size; item = GETQUERY(query); datalen = 0; for (i = 0; i < size; i++) { item->type = (int8) pq_getmsgint(buf, sizeof(int8)); if (item->type == QI_VAL) { size_t val_len; /* length after recoding to server encoding */ uint8 weight; const char *val; pg_crc32 valcrc; weight = (uint8) pq_getmsgint(buf, sizeof(uint8)); val = pq_getmsgstring(buf); val_len = strlen(val); /* Sanity checks */ if (weight > 0xF) elog(ERROR, "invalid tsquery: invalid weight bitmap"); if (val_len > MAXSTRLEN) elog(ERROR, "invalid tsquery: operand too long"); if (datalen > MAXSTRPOS) elog(ERROR, "invalid tsquery: total operand length exceeded"); /* Looks valid. */ INIT_CRC32(valcrc); COMP_CRC32(valcrc, val, val_len); FIN_CRC32(valcrc); item->operand.weight = weight; item->operand.valcrc = (int32) valcrc; item->operand.length = val_len; item->operand.distance = datalen; /* * Operand strings are copied to the final struct after this loop; * here we just collect them to an array */ operands[i] = val; datalen += val_len + 1; /* + 1 for the '\0' terminator */ } else if (item->type == QI_OPR) { int8 oper; oper = (int8) pq_getmsgint(buf, sizeof(int8)); if (oper != OP_NOT && oper != OP_OR && oper != OP_AND) elog(ERROR, "invalid tsquery: unrecognized operator type %d", (int) oper); if (i == size - 1) elog(ERROR, "invalid pointer to right operand"); item->operator.oper = oper; } else elog(ERROR, "unrecognized tsquery node type: %d", item->type); item++; } /* Enlarge buffer to make room for the operand values. */ query = (TSQuery) repalloc(query, len + datalen); item = GETQUERY(query); ptr = GETOPERAND(query); /* * Fill in the left-pointers. Checks that the tree is well-formed as a * side-effect. */ findoprnd(item, size); /* Copy operands to output struct */ for (i = 0; i < size; i++) { if (item->type == QI_VAL) { memcpy(ptr, operands[i], item->operand.length + 1); ptr += item->operand.length + 1; } item++; } pfree(operands); Assert(ptr - GETOPERAND(query) == datalen); SET_VARSIZE(query, len + datalen); PG_RETURN_TSVECTOR(query);}/* * debug function, used only for view query * which will be executed in non-leaf pages in index */Datumtsquerytree(PG_FUNCTION_ARGS){ TSQuery query = PG_GETARG_TSQUERY(0); INFIX nrm; text *res; QueryItem *q; int len; if (query->size == 0) { res = (text *) palloc(VARHDRSZ); SET_VARSIZE(res, VARHDRSZ); PG_RETURN_POINTER(res); } q = clean_NOT(GETQUERY(query), &len); if (!q) { res = (text *) palloc(1 + VARHDRSZ); SET_VARSIZE(res, 1 + VARHDRSZ); *((char *) VARDATA(res)) = 'T'; } else { nrm.curpol = q; nrm.buflen = 32; nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen); *(nrm.cur) = '\0'; nrm.op = GETOPERAND(query); infix(&nrm, true); res = (text *) palloc(nrm.cur - nrm.buf + VARHDRSZ); SET_VARSIZE(res, nrm.cur - nrm.buf + VARHDRSZ); strncpy(VARDATA(res), nrm.buf, nrm.cur - nrm.buf); pfree(q); } PG_FREE_IF_COPY(query, 0); PG_RETURN_POINTER(res);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?