jbe@0: /* jbe@0: * Copyright (c) 2006, FlexiGuided GmbH, Berlin, Germany jbe@0: * Author: Jan Behrens jbe@0: * All rights reserved. jbe@0: * jbe@0: * Redistribution and use in source and binary forms, with or without jbe@0: * modification, are permitted provided that the following conditions are jbe@0: * met: jbe@0: * jbe@0: * 1. Redistributions of source code must retain the above copyright jbe@0: * notice, this list of conditions and the following disclaimer. jbe@0: * 2. Redistributions in binary form must reproduce the above copyright jbe@0: * notice, this list of conditions and the following disclaimer in the jbe@0: * documentation and/or other materials provided with the distribution. jbe@0: * 3. Neither the name of the FlexiGuided GmbH nor the names of its jbe@0: * contributors may be used to endorse or promote products derived from jbe@0: * this software without specific prior written permission. jbe@0: * jbe@0: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS jbe@0: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT jbe@0: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A jbe@0: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER jbe@0: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, jbe@0: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, jbe@0: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR jbe@0: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF jbe@0: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING jbe@0: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS jbe@0: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. jbe@0: * jbe@0: */ jbe@0: jbe@0: jbe@0: /* jbe@0: * File name: pgsql/utf8proc_pgsql.c jbe@3: * Version: 1.0 jbe@3: * Last changed: 2006-09-17 jbe@0: * jbe@0: * Description: jbe@0: * PostgreSQL extension to provide a function 'unifold', which can be used jbe@0: * to case-fold and normalize index fields. jbe@0: */ jbe@0: jbe@0: jbe@0: #include "../utf8proc.c" jbe@0: jbe@0: #include jbe@0: #include jbe@0: #include jbe@1: #include jbe@0: #include jbe@0: #include jbe@0: jbe@5: #ifdef PG_MODULE_MAGIC jbe@5: PG_MODULE_MAGIC; jbe@5: #endif jbe@5: jbe@2: #define UTF8PROC_PGSQL_OPTS ( UTF8PROC_REJECTNA | UTF8PROC_COMPAT | \ jbe@2: UTF8PROC_COMPOSE | UTF8PROC_STABLE | UTF8PROC_IGNORE | UTF8PROC_STRIPCC | \ jbe@3: UTF8PROC_NLF2LF | UTF8PROC_CASEFOLD | UTF8PROC_LUMP ) jbe@1: jbe@0: PG_FUNCTION_INFO_V1(utf8proc_pgsql_unifold); jbe@0: Datum utf8proc_pgsql_unifold(PG_FUNCTION_ARGS) { jbe@1: text *input_string; jbe@1: text *output_string = NULL; jbe@0: ssize_t result; jbe@1: input_string = PG_GETARG_TEXT_P(0); jbe@1: do { jbe@1: result = utf8proc_decompose( jbe@1: VARDATA(input_string), VARSIZE(input_string) - VARHDRSZ, jbe@1: NULL, 0, UTF8PROC_PGSQL_OPTS jbe@1: ); jbe@1: if (result < 0) break; jbe@1: if (result > (SIZE_MAX-1-VARHDRSZ)/sizeof(int32_t)) { jbe@1: result = UTF8PROC_ERROR_OVERFLOW; jbe@1: break; jbe@1: } jbe@1: output_string = palloc(result * sizeof(int32_t) + 1 + VARHDRSZ); jbe@1: // reserve one extra byte for termination jbe@1: if (!output_string) { jbe@1: result = UTF8PROC_ERROR_NOMEM; jbe@1: break; jbe@1: } jbe@1: result = utf8proc_decompose( jbe@1: VARDATA(input_string), VARSIZE(input_string) - VARHDRSZ, jbe@1: (int32_t *)VARDATA(output_string), result, UTF8PROC_PGSQL_OPTS); jbe@1: if (result < 0) break; jbe@1: result = utf8proc_reencode((int32_t *)VARDATA(output_string), result, jbe@1: UTF8PROC_PGSQL_OPTS); jbe@1: } while (0); jbe@1: PG_FREE_IF_COPY(input_string, 0); jbe@0: if (result < 0) { jbe@0: int sqlerrcode; jbe@1: if (output_string) pfree(output_string); jbe@0: switch(result) { jbe@0: case UTF8PROC_ERROR_NOMEM: jbe@0: sqlerrcode = ERRCODE_OUT_OF_MEMORY; break; jbe@0: case UTF8PROC_ERROR_OVERFLOW: jbe@0: sqlerrcode = ERRCODE_PROGRAM_LIMIT_EXCEEDED; break; jbe@0: case UTF8PROC_ERROR_INVALIDUTF8: jbe@0: case UTF8PROC_ERROR_NOTASSIGNED: jbe@1: PG_RETURN_NULL(); jbe@0: default: jbe@0: sqlerrcode = ERRCODE_INTERNAL_ERROR; jbe@0: } jbe@0: ereport(ERROR, ( jbe@0: errcode(sqlerrcode), jbe@0: errmsg("%s", utf8proc_errmsg(result)) jbe@0: )); jbe@1: } else { jbe@1: VARATT_SIZEP(output_string) = result + VARHDRSZ; jbe@1: PG_RETURN_TEXT_P(output_string); jbe@0: } jbe@1: PG_RETURN_NULL(); // prohibit compiler warning jbe@0: } jbe@0: jbe@0: