varlena.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,310 行 · 第 1/4 页
C
2,310 行
PG_RETURN_BOOL(result > 0);}Datumtext_pattern_ne(PG_FUNCTION_ARGS){ text *arg1 = PG_GETARG_TEXT_P(0); text *arg2 = PG_GETARG_TEXT_P(1); int result; if (VARSIZE(arg1) != VARSIZE(arg2)) result = 1; else result = internal_text_pattern_compare(arg1, arg2); PG_FREE_IF_COPY(arg1, 0); PG_FREE_IF_COPY(arg2, 1); PG_RETURN_BOOL(result != 0);}Datumbttext_pattern_cmp(PG_FUNCTION_ARGS){ text *arg1 = PG_GETARG_TEXT_P(0); text *arg2 = PG_GETARG_TEXT_P(1); int result; result = internal_text_pattern_compare(arg1, arg2); PG_FREE_IF_COPY(arg1, 0); PG_FREE_IF_COPY(arg2, 1); PG_RETURN_INT32(result);}/*------------------------------------------------------------- * byteaoctetlen * * get the number of bytes contained in an instance of type 'bytea' *------------------------------------------------------------- */Datumbyteaoctetlen(PG_FUNCTION_ARGS){ PG_RETURN_INT32(toast_raw_datum_size(PG_GETARG_DATUM(0)) - VARHDRSZ);}/* * byteacat - * takes two bytea* and returns a bytea* that is the concatenation of * the two. * * Cloned from textcat and modified as required. */Datumbyteacat(PG_FUNCTION_ARGS){ bytea *t1 = PG_GETARG_BYTEA_P(0); bytea *t2 = PG_GETARG_BYTEA_P(1); int len1, len2, len; bytea *result; char *ptr; len1 = (VARSIZE(t1) - VARHDRSZ); if (len1 < 0) len1 = 0; len2 = (VARSIZE(t2) - VARHDRSZ); if (len2 < 0) len2 = 0; len = len1 + len2 + VARHDRSZ; result = (bytea *) palloc(len); /* Set size of result string... */ VARATT_SIZEP(result) = len; /* Fill data field of result string... */ ptr = VARDATA(result); if (len1 > 0) memcpy(ptr, VARDATA(t1), len1); if (len2 > 0) memcpy(ptr + len1, VARDATA(t2), len2); PG_RETURN_BYTEA_P(result);}#define PG_STR_GET_BYTEA(str_) \ DatumGetByteaP(DirectFunctionCall1(byteain, CStringGetDatum(str_)))/* * bytea_substr() * Return a substring starting at the specified position. * Cloned from text_substr and modified as required. * * Input: * - string * - starting position (is one-based) * - string length (optional) * * If the starting position is zero or less, then return from the start of the string * adjusting the length to be consistent with the "negative start" per SQL92. * If the length is less than zero, an ERROR is thrown. If no third argument * (length) is provided, the length to the end of the string is assumed. */Datumbytea_substr(PG_FUNCTION_ARGS){ int S = PG_GETARG_INT32(1); /* start position */ int S1; /* adjusted start position */ int L1; /* adjusted substring length */ S1 = Max(S, 1); if (fcinfo->nargs == 2) { /* * Not passed a length - PG_GETARG_BYTEA_P_SLICE() grabs * everything to the end of the string if we pass it a negative * value for length. */ L1 = -1; } else { /* end position */ int E = S + PG_GETARG_INT32(2); /* * A negative value for L is the only way for the end position to * be before the start. SQL99 says to throw an error. */ if (E < S) ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), errmsg("negative substring length not allowed"))); /* * A zero or negative value for the end position can happen if the * start was negative or one. SQL99 says to return a zero-length * string. */ if (E < 1) PG_RETURN_BYTEA_P(PG_STR_GET_BYTEA("")); L1 = E - S1; } /* * If the start position is past the end of the string, SQL99 says to * return a zero-length string -- PG_GETARG_TEXT_P_SLICE() will do * that for us. Convert to zero-based starting position */ PG_RETURN_BYTEA_P(PG_GETARG_BYTEA_P_SLICE(0, S1 - 1, L1));}/* * bytea_substr_no_len - * Wrapper to avoid opr_sanity failure due to * one function accepting a different number of args. */Datumbytea_substr_no_len(PG_FUNCTION_ARGS){ return bytea_substr(fcinfo);}/* * byteapos - * Return the position of the specified substring. * Implements the SQL92 POSITION() function. * Cloned from textpos and modified as required. */Datumbyteapos(PG_FUNCTION_ARGS){ bytea *t1 = PG_GETARG_BYTEA_P(0); bytea *t2 = PG_GETARG_BYTEA_P(1); int pos; int px, p; int len1, len2; char *p1, *p2; if (VARSIZE(t2) <= VARHDRSZ) PG_RETURN_INT32(1); /* result for empty pattern */ len1 = (VARSIZE(t1) - VARHDRSZ); len2 = (VARSIZE(t2) - VARHDRSZ); p1 = VARDATA(t1); p2 = VARDATA(t2); pos = 0; px = (len1 - len2); for (p = 0; p <= px; p++) { if ((*p2 == *p1) && (memcmp(p1, p2, len2) == 0)) { pos = p + 1; break; }; p1++; }; PG_RETURN_INT32(pos);}/*------------------------------------------------------------- * byteaGetByte * * this routine treats "bytea" as an array of bytes. * It returns the Nth byte (a number between 0 and 255). *------------------------------------------------------------- */DatumbyteaGetByte(PG_FUNCTION_ARGS){ bytea *v = PG_GETARG_BYTEA_P(0); int32 n = PG_GETARG_INT32(1); int len; int byte; len = VARSIZE(v) - VARHDRSZ; if (n < 0 || n >= len) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("index %d out of valid range, 0..%d", n, len - 1))); byte = ((unsigned char *) VARDATA(v))[n]; PG_RETURN_INT32(byte);}/*------------------------------------------------------------- * byteaGetBit * * This routine treats a "bytea" type like an array of bits. * It returns the value of the Nth bit (0 or 1). * *------------------------------------------------------------- */DatumbyteaGetBit(PG_FUNCTION_ARGS){ bytea *v = PG_GETARG_BYTEA_P(0); int32 n = PG_GETARG_INT32(1); int byteNo, bitNo; int len; int byte; len = VARSIZE(v) - VARHDRSZ; if (n < 0 || n >= len * 8) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("index %d out of valid range, 0..%d", n, len * 8 - 1))); byteNo = n / 8; bitNo = n % 8; byte = ((unsigned char *) VARDATA(v))[byteNo]; if (byte & (1 << bitNo)) PG_RETURN_INT32(1); else PG_RETURN_INT32(0);}/*------------------------------------------------------------- * byteaSetByte * * Given an instance of type 'bytea' creates a new one with * the Nth byte set to the given value. * *------------------------------------------------------------- */DatumbyteaSetByte(PG_FUNCTION_ARGS){ bytea *v = PG_GETARG_BYTEA_P(0); int32 n = PG_GETARG_INT32(1); int32 newByte = PG_GETARG_INT32(2); int len; bytea *res; len = VARSIZE(v) - VARHDRSZ; if (n < 0 || n >= len) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("index %d out of valid range, 0..%d", n, len - 1))); /* * Make a copy of the original varlena. */ res = (bytea *) palloc(VARSIZE(v)); memcpy((char *) res, (char *) v, VARSIZE(v)); /* * Now set the byte. */ ((unsigned char *) VARDATA(res))[n] = newByte; PG_RETURN_BYTEA_P(res);}/*------------------------------------------------------------- * byteaSetBit * * Given an instance of type 'bytea' creates a new one with * the Nth bit set to the given value. * *------------------------------------------------------------- */DatumbyteaSetBit(PG_FUNCTION_ARGS){ bytea *v = PG_GETARG_BYTEA_P(0); int32 n = PG_GETARG_INT32(1); int32 newBit = PG_GETARG_INT32(2); bytea *res; int len; int oldByte, newByte; int byteNo, bitNo; len = VARSIZE(v) - VARHDRSZ; if (n < 0 || n >= len * 8) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("index %d out of valid range, 0..%d", n, len * 8 - 1))); byteNo = n / 8; bitNo = n % 8; /* * sanity check! */ if (newBit != 0 && newBit != 1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("new bit must be 0 or 1"))); /* * Make a copy of the original varlena. */ res = (bytea *) palloc(VARSIZE(v)); memcpy((char *) res, (char *) v, VARSIZE(v)); /* * Update the byte. */ oldByte = ((unsigned char *) VARDATA(res))[byteNo]; if (newBit == 0) newByte = oldByte & (~(1 << bitNo)); else newByte = oldByte | (1 << bitNo); ((unsigned char *) VARDATA(res))[byteNo] = newByte; PG_RETURN_BYTEA_P(res);}/* text_name() * Converts a text type to a Name type. */Datumtext_name(PG_FUNCTION_ARGS){ text *s = PG_GETARG_TEXT_P(0); Name result; int len; len = VARSIZE(s) - VARHDRSZ; /* Truncate oversize input */ if (len >= NAMEDATALEN) len = NAMEDATALEN - 1;#ifdef STRINGDEBUG printf("text- convert string length %d (%d) ->%d\n", VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);#endif result = (Name) palloc(NAMEDATALEN); memcpy(NameStr(*result), VARDATA(s), len); /* now null pad to full length... */ while (len < NAMEDATALEN) { *(NameStr(*result) + len) = '\0'; len++; } PG_RETURN_NAME(result);}/* name_text() * Converts a Name type to a text type. */Datumname_text(PG_FUNCTION_ARGS){ Name s = PG_GETARG_NAME(0); text *result; int len; len = strlen(NameStr(*s));#ifdef STRINGDEBUG printf("text- convert string length %d (%d) ->%d\n", VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);#endif result = palloc(VARHDRSZ + len); VARATT_SIZEP(result) = VARHDRSZ + len; memcpy(VARDATA(result), NameStr(*s), len); PG_RETURN_TEXT_P(result);}/* * textToQualifiedNameList - convert a text object to list of names * * This implements the input parsing needed by nextval() and other * functions that take a text parameter representing a qualified name. * We split the name at dots, downcase if not double-quoted, and * truncate names if they're too long. */List *textToQualifiedNameList(text *textval, const char *caller){ char *rawname; List *result = NIL; List *namelist; List *l; /* Convert to C string (handles possible detoasting). */ /* Note we rely on being able to modify rawname below. */ rawname = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textval))); if (!SplitIdentifierString(rawname, '.', &namelist)) ereport(ERROR, (errcode(ERRCODE_INVALID_NAME), errmsg("invalid name syntax"))); if (namelist == NIL) ereport(ERROR, (errcode(ERRCODE_INVALID_NAME), errmsg("invalid name syntax"))); foreach(l, namelist) { char *curname = (char *) lfirst(l); result = lappend(result, makeString(pstrdup(curname))); } pfree(rawname); freeList(namelist); return result;}/* * SplitIdentifierString --- parse a string containing identifiers * * This is the guts of textToQualifiedNameList, and is exported for use in * other situations such as parsing GUC variables. In the GUC case, it's * important to avoid memory leaks, so the API is designed to minimize the * amount of stuff that needs to be allocated and freed. * * Inputs: * rawstring: the input string; must be overwritable! On return, it's * been modified to contain the separated identifiers. * separator: the separator punctuation expected between identifiers * (typically '.' or ','). Whitespace may also appear around * identifiers. * Outputs: * namelist: filled with a palloc'd list of pointers to identifiers within * rawstring. Caller should freeList() this even on error return. * * Returns TRUE if okay, FALSE if there is a syntax error in the string. * * Note that an empty string is considered okay here, though not in * textToQualifiedNameList. */boolSplitIdentifierString(char *rawstring, char separator, List **namelist){ char *nextp = rawstring; bool done = false; *namelist = NIL; while (isspace((unsigned char) *nextp)) nextp++; /* skip leading whitespace */ if (*nextp == '\0') return true; /* allow empty string */ /* At the top of the loop, we are at start of a new identifier. */ do { char *curname; char *endp; if (*nextp == '\"') { /* Quoted name --- collapse quote-quote pairs, no downcasing */ curname = nextp + 1; for (;;) { endp = strchr(nextp + 1, '\"'); if (endp == NULL) return false; /* mismatched quotes */ if (endp[1] != '\"') break; /* found end of quoted name */ /* Collapse adjacent quotes into one quote, and look again */ memmove(endp, endp + 1, strlen(endp)); nextp = endp; } /* endp now points at the terminating quote */ nextp = endp + 1; } else { /* Unquoted name --- extends to separator or whitespace */ char *downname; int len; curname = nextp; while (*nextp && *nextp != separator && !isspace((unsigned char) *nextp)) nextp++; endp = nextp; if (curname == nextp) return false; /* empty unquoted name not allowed */ /* * Downcase the identifier, using same code as main lexer does. * * XXX because we want to overwrite the input in-place, we cannot * support a downcasing transformation that increases the * string length. This is not a problem given the current * implementation of downcase_truncate_identifier, but we'll * probably have to do something about this someday. */ len = endp - curname; downname = downcase_truncate_identifier(curname, len, false); Assert(strlen(downname) <= len); strncpy(curname, downname, len); pfree(downname); } while (isspace((unsigned char) *nextp)) nextp++; /* skip trailing whitespace */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?