📄 varlena.c
字号:
{ /* * If escape char is not followed by any expected char, just treat * it as ordinary data to copy. (XXX would it be better to throw * an error?) */ appendStringInfoChar(str, '\\'); continue; } if (so != -1 && eo != -1) { /* * Copy the text that is back reference of regexp. Note so and eo * are counted in characters not bytes. */ char *chunk_start; int chunk_len; Assert(so >= data_pos); chunk_start = start_ptr; chunk_start += charlen_to_bytelen(chunk_start, so - data_pos); chunk_len = charlen_to_bytelen(chunk_start, eo - so); appendBinaryStringInfo(str, chunk_start, chunk_len); } }}#define REGEXP_REPLACE_BACKREF_CNT 10/* * replace_text_regexp * * replace text that matches to regexp in src_text to replace_text. * * Note: to avoid having to include regex.h in builtins.h, we declare * the regexp argument as void *, but really it's regex_t *. */text *replace_text_regexp(text *src_text, void *regexp, text *replace_text, bool glob){ text *ret_text; regex_t *re = (regex_t *) regexp; int src_text_len = VARSIZE_ANY_EXHDR(src_text); StringInfoData buf; regmatch_t pmatch[REGEXP_REPLACE_BACKREF_CNT]; pg_wchar *data; size_t data_len; int search_start; int data_pos; char *start_ptr; bool have_escape; initStringInfo(&buf); /* Convert data string to wide characters. */ data = (pg_wchar *) palloc((src_text_len + 1) * sizeof(pg_wchar)); data_len = pg_mb2wchar_with_len(VARDATA_ANY(src_text), data, src_text_len); /* Check whether replace_text has escape char. */ have_escape = check_replace_text_has_escape_char(replace_text); /* start_ptr points to the data_pos'th character of src_text */ start_ptr = (char *) VARDATA_ANY(src_text); data_pos = 0; search_start = 0; while (search_start <= data_len) { int regexec_result; CHECK_FOR_INTERRUPTS(); regexec_result = pg_regexec(re, data, data_len, search_start, NULL, /* no details */ REGEXP_REPLACE_BACKREF_CNT, pmatch, 0); if (regexec_result == REG_NOMATCH) break; if (regexec_result != REG_OKAY) { char errMsg[100]; pg_regerror(regexec_result, re, errMsg, sizeof(errMsg)); ereport(ERROR, (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION), errmsg("regular expression failed: %s", errMsg))); } /* * Copy the text to the left of the match position. Note we are given * character not byte indexes. */ if (pmatch[0].rm_so - data_pos > 0) { int chunk_len; chunk_len = charlen_to_bytelen(start_ptr, pmatch[0].rm_so - data_pos); appendBinaryStringInfo(&buf, start_ptr, chunk_len); /* * Advance start_ptr over that text, to avoid multiple rescans of * it if the replace_text contains multiple back-references. */ start_ptr += chunk_len; data_pos = pmatch[0].rm_so; } /* * Copy the replace_text. Process back references when the * replace_text has escape characters. */ if (have_escape) appendStringInfoRegexpSubstr(&buf, replace_text, pmatch, start_ptr, data_pos); else appendStringInfoText(&buf, replace_text); /* Advance start_ptr and data_pos over the matched text. */ start_ptr += charlen_to_bytelen(start_ptr, pmatch[0].rm_eo - data_pos); data_pos = pmatch[0].rm_eo; /* * When global option is off, replace the first instance only. */ if (!glob) break; /* * Search from next character when the matching text is zero width. */ search_start = data_pos; if (pmatch[0].rm_so == pmatch[0].rm_eo) search_start++; } /* * Copy the text to the right of the last match. */ if (data_pos < data_len) { int chunk_len; chunk_len = ((char *) src_text + VARSIZE_ANY(src_text)) - start_ptr; appendBinaryStringInfo(&buf, start_ptr, chunk_len); } ret_text = PG_STR_GET_TEXT(buf.data); pfree(buf.data); pfree(data); return ret_text;}/* * split_text * parse input string * return ord item (1 based) * based on provided field separator */Datumsplit_text(PG_FUNCTION_ARGS){ text *inputstring = PG_GETARG_TEXT_PP(0); text *fldsep = PG_GETARG_TEXT_PP(1); int fldnum = PG_GETARG_INT32(2); int inputstring_len; int fldsep_len; TextPositionState state; int start_posn; int end_posn; text *result_text; /* field number is 1 based */ if (fldnum < 1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("field position must be greater than zero"))); text_position_setup(inputstring, fldsep, &state); /* * Note: we check the converted string length, not the original, because * they could be different if the input contained invalid encoding. */ inputstring_len = state.len1; fldsep_len = state.len2; /* return empty string for empty input string */ if (inputstring_len < 1) { text_position_cleanup(&state); PG_RETURN_TEXT_P(PG_STR_GET_TEXT("")); } /* empty field separator */ if (fldsep_len < 1) { text_position_cleanup(&state); /* if first field, return input string, else empty string */ if (fldnum == 1) PG_RETURN_TEXT_P(inputstring); else PG_RETURN_TEXT_P(PG_STR_GET_TEXT("")); } /* identify bounds of first field */ start_posn = 1; end_posn = text_position_next(1, &state); /* special case if fldsep not found at all */ if (end_posn == 0) { text_position_cleanup(&state); /* if field 1 requested, return input string, else empty string */ if (fldnum == 1) PG_RETURN_TEXT_P(inputstring); else PG_RETURN_TEXT_P(PG_STR_GET_TEXT("")); } while (end_posn > 0 && --fldnum > 0) { /* identify bounds of next field */ start_posn = end_posn + fldsep_len; end_posn = text_position_next(start_posn, &state); } text_position_cleanup(&state); if (fldnum > 0) { /* N'th field separator not found */ /* if last field requested, return it, else empty string */ if (fldnum == 1) result_text = text_substring(PointerGetDatum(inputstring), start_posn, -1, true); else result_text = PG_STR_GET_TEXT(""); } else { /* non-last field requested */ result_text = text_substring(PointerGetDatum(inputstring), start_posn, end_posn - start_posn, false); } PG_RETURN_TEXT_P(result_text);}/* * text_to_array * parse input string * return text array of elements * based on provided field separator */Datumtext_to_array(PG_FUNCTION_ARGS){ text *inputstring = PG_GETARG_TEXT_PP(0); text *fldsep = PG_GETARG_TEXT_PP(1); int inputstring_len; int fldsep_len; TextPositionState state; int fldnum; int start_posn; int end_posn; int chunk_len; char *start_ptr; text *result_text; ArrayBuildState *astate = NULL; text_position_setup(inputstring, fldsep, &state); /* * Note: we check the converted string length, not the original, because * they could be different if the input contained invalid encoding. */ inputstring_len = state.len1; fldsep_len = state.len2; /* return NULL for empty input string */ if (inputstring_len < 1) { text_position_cleanup(&state); PG_RETURN_NULL(); } /* * empty field separator return one element, 1D, array using the input * string */ if (fldsep_len < 1) { text_position_cleanup(&state); PG_RETURN_ARRAYTYPE_P(create_singleton_array(fcinfo, TEXTOID, PointerGetDatum(inputstring), 1)); } start_posn = 1; /* start_ptr points to the start_posn'th character of inputstring */ start_ptr = VARDATA_ANY(inputstring); for (fldnum = 1;; fldnum++) /* field number is 1 based */ { CHECK_FOR_INTERRUPTS(); end_posn = text_position_next(start_posn, &state); if (end_posn == 0) { /* fetch last field */ chunk_len = ((char *) inputstring + VARSIZE_ANY(inputstring)) - start_ptr; } else { /* fetch non-last field */ chunk_len = charlen_to_bytelen(start_ptr, end_posn - start_posn); } /* must build a temp text datum to pass to accumArrayResult */ result_text = (text *) palloc(VARHDRSZ + chunk_len); SET_VARSIZE(result_text, VARHDRSZ + chunk_len); memcpy(VARDATA(result_text), start_ptr, chunk_len); /* stash away this field */ astate = accumArrayResult(astate, PointerGetDatum(result_text), false, TEXTOID, CurrentMemoryContext); pfree(result_text); if (end_posn == 0) break; start_posn = end_posn; start_ptr += chunk_len; start_posn += fldsep_len; start_ptr += charlen_to_bytelen(start_ptr, fldsep_len); } text_position_cleanup(&state); PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, CurrentMemoryContext));}/* * array_to_text * concatenate Cstring representation of input array elements * using provided field separator */Datumarray_to_text(PG_FUNCTION_ARGS){ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); char *fldsep = PG_TEXTARG_GET_STR(1); int nitems, *dims, ndims; Oid element_type; int typlen; bool typbyval; char typalign; StringInfoData buf; bool printed = false; char *p; bits8 *bitmap; int bitmask; int i; ArrayMetaState *my_extra; ndims = ARR_NDIM(v); dims = ARR_DIMS(v); nitems = ArrayGetNItems(ndims, dims); /* if there are no elements, return an empty string */ if (nitems == 0) PG_RETURN_TEXT_P(PG_STR_GET_TEXT("")); element_type = ARR_ELEMTYPE(v); initStringInfo(&buf); /* * We arrange to look up info about element type, including its output * conversion proc, only once per series of calls, assuming the element * type doesn't change underneath us. */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = ~element_type; } if (my_extra->element_type != element_type) { /* * Get info about element type, including its output conversion proc */ get_type_io_data(element_type, IOFunc_output, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign, &my_extra->typdelim, &my_extra->typioparam, &my_extra->typiofunc); fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc, fcinfo->flinfo->fn_mcxt); my_extra->element_type = element_type; } typlen = my_extra->typlen; typbyval = my_extra->typbyval; typalign = my_extra->typalign; p = ARR_DATA_PTR(v); bitmap = ARR_NULLBITMAP(v); bitmask = 1; for (i = 0; i < nitems; i++) { Datum itemvalue; char *value; /* Get source element, checking for NULL */ if (bitmap && (*bitmap & bitmask) == 0) { /* we ignore nulls */ } else { itemvalue = fetch_att(p, typbyval, typlen); value = OutputFunctionCall(&my_extra->proc, itemvalue); if (printed) appendStringInfo(&buf, "%s%s", fldsep, value); else appendStringInfoString(&buf, value); printed = true; p = att_addlength_pointer(p, typlen, p); p = (char *) att_align_nominal(p, typalign); } /* advance bitmap pointer if any */ if (bitmap) { bitmask <<= 1; if (bitmask == 0x100) { bitmap++; bitmask = 1; } } } PG_RETURN_TEXT_P(PG_STR_GET_TEXT(buf.data));}#define HEXBASE 16/* * Convert a int32 to a string containing a base 16 (hex) representation of * the number. */Datumto_hex32(PG_FUNCTION_ARGS){ uint32 value = (uint32) PG_GETARG_INT32(0); text *result_text; char *ptr; const char *digits = "0123456789abcdef"; char buf[32]; /* bigger than needed, but reasonable */ ptr = buf + sizeof(buf) - 1; *ptr = '\0'; do { *--ptr = digits[value % HEXBASE]; value /= HEXBASE; } while (ptr > buf && value); result_text = PG_STR_GET_TEXT(ptr); PG_RETURN_TEXT_P(result_text);}/* * Convert a int64 to a string containing a base 16 (hex) representation of * the number. */Datumto_hex64(PG_FUNCTION_ARGS){ uint64 value = (uint64) PG_GETARG_INT64(0); text *result_text; char *ptr; const char *digits = "0123456789abcdef"; char buf[32]; /* bigger than needed, but reasonable */ ptr = buf + sizeof(buf) - 1; *ptr = '\0'; do { *--ptr = digits[value % HEXBASE]; value /= HEXBASE; } while (ptr > buf && value); result_text = PG_STR_GET_TEXT(ptr); PG_RETURN_TEXT_P(result_text);}/* * Create an md5 hash of a text string and return it as hex * * md5 produces a 16 byte (128 bit) hash; double it for hex */#define MD5_HASH_LEN 32Datummd5_text(PG_FUNCTION_ARGS){ text *in_text = PG_GETARG_TEXT_PP(0); size_t len; char hexsum[MD5_HASH_LEN + 1]; text *result_text; /* Calculate the length of the buffer using varlena metadata */ len = VARSIZE_ANY_EXHDR(in_text); /* get the hash result */ if (pg_md5_hash(VARDATA_ANY(in_text), len, hexsum) == false) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); /* convert to text and return it */ result_text = PG_STR_GET_TEXT(hexsum); PG_RETURN_TEXT_P(result_text);}/* * Create an md5 hash of a bytea field and return it as a hex string: * 16-byte md5 digest is represented in 32 hex characters. */Datummd5_bytea(PG_FUNCTION_ARGS){ bytea *in = PG_GETARG_BYTEA_PP(0); size_t len; char hexsum[MD5_HASH_LEN + 1]; text *result_text; len = VARSIZE_ANY_EXHDR(in); if (pg_md5_hash(VARDATA_ANY(in), len, hexsum) == false) ereport(ERROR, (errcode(ER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -