oracle_compat.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 1,498 行 · 第 1/3 页
C
1,498 行
{ ptr2 = ptr2start; while (ptr2 <= end2) { if (*ptr == *ptr2) break; ++ptr2; } if (ptr2 > end2) break; ptr++; m--; } while (m > 0) { ptr2 = ptr2start; while (ptr2 <= end2) { if (*end == *ptr2) break; ++ptr2; } if (ptr2 > end2) break; end--; m--; } ret = (bytea *) palloc(VARHDRSZ + m); SET_VARSIZE(ret, VARHDRSZ + m); memcpy(VARDATA(ret), ptr, m); PG_RETURN_BYTEA_P(ret);}/******************************************************************** * * ltrim * * Syntax: * * text ltrim(text string, text set) * * Purpose: * * Returns string with initial characters removed up to the first * character not in set. * ********************************************************************/Datumltrim(PG_FUNCTION_ARGS){ text *string = PG_GETARG_TEXT_PP(0); text *set = PG_GETARG_TEXT_PP(1); text *ret; ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set), true, false); PG_RETURN_TEXT_P(ret);}/******************************************************************** * * ltrim1 --- ltrim with set fixed as ' ' * ********************************************************************/Datumltrim1(PG_FUNCTION_ARGS){ text *string = PG_GETARG_TEXT_PP(0); text *ret; ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), " ", 1, true, false); PG_RETURN_TEXT_P(ret);}/******************************************************************** * * rtrim * * Syntax: * * text rtrim(text string, text set) * * Purpose: * * Returns string with final characters removed after the last * character not in set. * ********************************************************************/Datumrtrim(PG_FUNCTION_ARGS){ text *string = PG_GETARG_TEXT_PP(0); text *set = PG_GETARG_TEXT_PP(1); text *ret; ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set), false, true); PG_RETURN_TEXT_P(ret);}/******************************************************************** * * rtrim1 --- rtrim with set fixed as ' ' * ********************************************************************/Datumrtrim1(PG_FUNCTION_ARGS){ text *string = PG_GETARG_TEXT_PP(0); text *ret; ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), " ", 1, false, true); PG_RETURN_TEXT_P(ret);}/******************************************************************** * * translate * * Syntax: * * text translate(text string, text from, text to) * * Purpose: * * Returns string after replacing all occurrences of characters in from * with the corresponding character in to. If from is longer than to, * occurrences of the extra characters in from are deleted. * Improved by Edwin Ramirez <ramirez@doc.mssm.edu>. * ********************************************************************/Datumtranslate(PG_FUNCTION_ARGS){ text *string = PG_GETARG_TEXT_PP(0); text *from = PG_GETARG_TEXT_PP(1); text *to = PG_GETARG_TEXT_PP(2); text *result; char *from_ptr, *to_ptr; char *source, *target; int m, fromlen, tolen, retlen, i; int worst_len; int len; int source_len; int from_index; m = VARSIZE_ANY_EXHDR(string); if (m <= 0) PG_RETURN_TEXT_P(string); source = VARDATA_ANY(string); fromlen = VARSIZE_ANY_EXHDR(from); from_ptr = VARDATA_ANY(from); tolen = VARSIZE_ANY_EXHDR(to); to_ptr = VARDATA_ANY(to); /* * The worst-case expansion is to substitute a max-length character for a * single-byte character at each position of the string. */ worst_len = pg_database_encoding_max_length() * m; /* check for integer overflow */ if (worst_len / pg_database_encoding_max_length() != m) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("requested length too large"))); result = (text *) palloc(worst_len + VARHDRSZ); target = VARDATA(result); retlen = 0; while (m > 0) { source_len = pg_mblen(source); from_index = 0; for (i = 0; i < fromlen; i += len) { len = pg_mblen(&from_ptr[i]); if (len == source_len && memcmp(source, &from_ptr[i], len) == 0) break; from_index++; } if (i < fromlen) { /* substitute */ char *p = to_ptr; for (i = 0; i < from_index; i++) { p += pg_mblen(p); if (p >= (to_ptr + tolen)) break; } if (p < (to_ptr + tolen)) { len = pg_mblen(p); memcpy(target, p, len); target += len; retlen += len; } } else { /* no match, so copy */ memcpy(target, source, source_len); target += source_len; retlen += source_len; } source += source_len; m -= source_len; } SET_VARSIZE(result, retlen + VARHDRSZ); /* * The function result is probably much bigger than needed, if we're using * a multibyte encoding, but it's not worth reallocating it; the result * probably won't live long anyway. */ PG_RETURN_TEXT_P(result);}/******************************************************************** * * ascii * * Syntax: * * int ascii(text string) * * Purpose: * * Returns the decimal representation of the first character from * string. * If the string is empty we return 0. * If the database encoding is UTF8, we return the Unicode codepoint. * If the database encoding is any other multi-byte encoding, we * return the value of the first byte if it is an ASCII character * (range 1 .. 127), or raise an error. * For all other encodings we return the value of the first byte, * (range 1..255). * ********************************************************************/Datumascii(PG_FUNCTION_ARGS){ text *string = PG_GETARG_TEXT_PP(0); int encoding = GetDatabaseEncoding(); unsigned char *data; if (VARSIZE_ANY_EXHDR(string) <= 0) PG_RETURN_INT32(0); data = (unsigned char *) VARDATA_ANY(string); if (encoding == PG_UTF8 && *data > 127) { /* return the code point for Unicode */ int result = 0, tbytes = 0, i; if (*data >= 0xF0) { result = *data & 0x07; tbytes = 3; } else if (*data >= 0xE0) { result = *data & 0x0F; tbytes = 2; } else { Assert(*data > 0xC0); result = *data & 0x1f; tbytes = 1; } Assert(tbytes > 0); for (i = 1; i <= tbytes; i++) { Assert((data[i] & 0xC0) == 0x80); result = (result << 6) + (data[i] & 0x3f); } PG_RETURN_INT32(result); } else { if (pg_encoding_max_length(encoding) > 1 && *data > 127) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("requested character too large"))); PG_RETURN_INT32((int32) *data); }}/******************************************************************** * * chr * * Syntax: * * text chr(int val) * * Purpose: * * Returns the character having the binary equivalent to val. * * For UTF8 we treat the argumwent as a Unicode code point. * For other multi-byte encodings we raise an error for arguments * outside the strict ASCII range (1..127). * * It's important that we don't ever return a value that is not valid * in the database encoding, so that this doesn't become a way for * invalid data to enter the database. * ********************************************************************/Datumchr (PG_FUNCTION_ARGS){ uint32 cvalue = PG_GETARG_UINT32(0); text *result; int encoding = GetDatabaseEncoding(); if (encoding == PG_UTF8 && cvalue > 127) { /* for Unicode we treat the argument as a code point */ int bytes; char *wch; /* We only allow valid Unicode code points */ if (cvalue > 0x001fffff) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("requested character too large for encoding: %d", cvalue))); if (cvalue > 0xffff) bytes = 4; else if (cvalue > 0x07ff) bytes = 3; else bytes = 2; result = (text *) palloc(VARHDRSZ + bytes); SET_VARSIZE(result, VARHDRSZ + bytes); wch = VARDATA(result); if (bytes == 2) { wch[0] = 0xC0 | ((cvalue >> 6) & 0x1F); wch[1] = 0x80 | (cvalue & 0x3F);; } else if (bytes == 3) { wch[0] = 0xE0 | ((cvalue >> 12) & 0x0F); wch[1] = 0x80 | ((cvalue >> 6) & 0x3F); wch[2] = 0x80 | (cvalue & 0x3F); } else { wch[0] = 0xF0 | ((cvalue >> 18) & 0x07); wch[1] = 0x80 | ((cvalue >> 12) & 0x3F); wch[2] = 0x80 | ((cvalue >> 6) & 0x3F); wch[3] = 0x80 | (cvalue & 0x3F); } } else { bool is_mb; /* * Error out on arguments that make no sense or that we can't validly * represent in the encoding. */ if (cvalue == 0) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("null character not permitted"))); is_mb = pg_encoding_max_length(encoding) > 1; if ((is_mb && (cvalue > 127)) || (!is_mb && (cvalue > 255))) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("requested character too large for encoding: %d", cvalue))); result = (text *) palloc(VARHDRSZ + 1); SET_VARSIZE(result, VARHDRSZ + 1); *VARDATA(result) = (char) cvalue; } PG_RETURN_TEXT_P(result);}/******************************************************************** * * repeat * * Syntax: * * text repeat(text string, int val) * * Purpose: * * Repeat string by val. * ********************************************************************/Datumrepeat(PG_FUNCTION_ARGS){ text *string = PG_GETARG_TEXT_PP(0); int32 count = PG_GETARG_INT32(1); text *result; int slen, tlen; int i; char *cp, *sp; if (count < 0) count = 0; slen = VARSIZE_ANY_EXHDR(string); tlen = VARHDRSZ + (count * slen); /* Check for integer overflow */ if (slen != 0 && count != 0) { int check = count * slen; int check2 = check + VARHDRSZ; if ((check / slen) != count || check2 <= check) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("requested length too large"))); } result = (text *) palloc(tlen); SET_VARSIZE(result, tlen); cp = VARDATA(result); sp = VARDATA_ANY(string); for (i = 0; i < count; i++) { memcpy(cp, sp, slen); cp += slen; } PG_RETURN_TEXT_P(result);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?