Re: [PATCHES] xpath_array with namespaces support
What about it? W/o this not large patch XML functionality in 8.3 will be weak... Will it be accepted? On 3/5/07, Nikolay Samokhvalov [EMAIL PROTECTED] wrote: On 3/4/07, Nikolay Samokhvalov [EMAIL PROTECTED] wrote: I'll fix these issues and extend the patch with resgression tests and docs for xpath_array(). I'll resubmit it very soon. Here is a new version of the patch. I didn't change any part of docs yet. Since there were no objections I've changed the name of the function to xmlpath(). -- Best regards, Nikolay Index: src/backend/utils/adt/xml.c === RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/xml.c,v retrieving revision 1.34 diff -u -r1.34 xml.c --- src/backend/utils/adt/xml.c 3 Mar 2007 19:32:55 - 1.34 +++ src/backend/utils/adt/xml.c 5 Mar 2007 01:14:57 - @@ -47,6 +47,8 @@ #include libxml/uri.h #include libxml/xmlerror.h #include libxml/xmlwriter.h +#include libxml/xpath.h +#include libxml/xpathInternals.h #endif /* USE_LIBXML */ #include catalog/namespace.h @@ -67,6 +69,7 @@ #include utils/datetime.h #include utils/lsyscache.h #include utils/memutils.h +#include access/tupmacs.h #include utils/xml.h @@ -88,6 +91,7 @@ static int parse_xml_decl(const xmlChar *str, size_t *lenp, xmlChar **version, xmlChar **encoding, int *standalone); static bool print_xml_decl(StringInfo buf, const xmlChar *version, pg_enc encoding, int standalone); static xmlDocPtr xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, xmlChar *encoding); +static text *xml_xmlnodetotext(xmlNodePtr cur); #endif /* USE_LIBXML */ @@ -1463,7 +1467,6 @@ return buf.data; } - /* * Map SQL value to XML value; see SQL/XML:2003 section 9.16. */ @@ -2403,3 +2406,247 @@ else appendStringInfoString(result, /row\n\n); } + + +/* + * XPath related functions + */ + +#ifdef USE_LIBXML +/* + * Convert XML node to text (return value only, it's not dumping) + */ +text * +xml_xmlnodetotext(xmlNodePtr cur) +{ + xmlChar *str; + text *result; + size_t len; + + str = xmlXPathCastNodeToString(cur); + len = strlen((char *) str); + result = (text *) palloc(len + VARHDRSZ); + SET_VARSIZE(result, len + VARHDRSZ); + memcpy(VARDATA(result), str, len); + + return result; +} +#endif + +/* + * Evaluate XPath expression and return array of XML values. + * As we have no support of XQuery sequences yet, this functions seems + * to be the most useful one (array of XML functions plays a role of + * some kind of substritution for XQuery sequences). + + * Workaround here: we parse XML data in different way to allow XPath for + * fragments (see XPath for fragment TODO comment inside). + */ +Datum +xmlpath(PG_FUNCTION_ARGS) +{ +#ifdef USE_LIBXML + ArrayBuildState *astate = NULL; + xmlParserCtxtPtr ctxt = NULL; + xmlDocPtr doc = NULL; + xmlXPathContextPtr xpathctx = NULL; + xmlXPathCompExprPtr xpathcomp = NULL; + xmlXPathObjectPtr xpathobj = NULL; + int32len, xpath_len; + xmlChar*string, *xpath_expr; + boolres_is_null = FALSE; + int i; + xmltype*data; + text*xpath_expr_text; + ArrayType *namespaces; + int *dims, ndims, ns_count = 0, bitmask = 1; + char*ptr; + bits8*bitmap; + char**ns_names = NULL, **ns_uris = NULL; + int16typlen; + booltypbyval; + chartypalign; + + /* the function is not strict, we must check first two args */ + if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) + PG_RETURN_NULL(); + + xpath_expr_text = PG_GETARG_TEXT_P(0); + data = PG_GETARG_XML_P(1); + + /* Namespace mappings passed as text[]. + * Assume that 2-dimensional array has been passed, + * the 1st subarray is array of names, the 2nd -- array of URIs, + * example: ARRAY[ARRAY['myns', 'myns2'], ARRAY['http://example.com', 'http://example2.com']]. + */ + if (!PG_ARGISNULL(2)) + { + namespaces = PG_GETARG_ARRAYTYPE_P(2); + ndims = ARR_NDIM(namespaces); + dims = ARR_DIMS(namespaces); + + /* Sanity check */ + if (ndims != 2) + ereport(ERROR, (errmsg(invalid array passed for namespace mappings), + errdetail(Only 2-dimensional array may be used for namespace mappings.))); + + Assert(ARR_ELEMTYPE(namespaces) == TEXTOID); + + ns_count = ArrayGetNItems(ndims, dims) / 2; + get_typlenbyvalalign(ARR_ELEMTYPE(namespaces), + typlen, typbyval, typalign); + ns_names = (char **) palloc(ns_count * sizeof(char *)); + ns_uris = (char **) palloc(ns_count * sizeof(char *)); + ptr = ARR_DATA_PTR(namespaces); + bitmap = ARR_NULLBITMAP(namespaces); + bitmask = 1; + + for (i = 0; i ns_count * 2; i++) + { + if (bitmap (*bitmap bitmask) == 0) +ereport(ERROR, (errmsg(neither namespace nor URI may be NULL))); /* TODO: better message */ + else + { +if (i ns_count) + ns_names[i] = DatumGetCString(DirectFunctionCall1(textout, + PointerGetDatum(ptr))); +else + ns_uris[i - ns_count] = DatumGetCString(DirectFunctionCall1(textout, +
Re: [PATCHES] xpath_array with namespaces support
Nikolay Samokhvalov wrote: What about it? W/o this not large patch XML functionality in 8.3 will be weak... Will it be accepted? In principle I am in favor of the patch. Would it be better to use some more unlikely name for the dummy root element used to process fragments than x ? Perhaps even something in a special namespace? cheers andrew ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
Re: [PATCHES] xpath_array with namespaces support
Nikolay Samokhvalov wrote: On 3/17/07, Andrew Dunstan [EMAIL PROTECTED] wrote: In principle I am in favor of the patch. Would it be better to use some more unlikely name for the dummy root element used to process fragments than x ? Perhaps even something in a special namespace? I did think about it, but I didn't find any difficulties with simple x.../x. The thing is that regardless the element name we have corresponding shift in XPath epression -- so, there cannot be any problem from my point of view... But maybe I don't see something and it's better to avoid _possible_ problem. It depends on PostgreSQL code style itself -- what is the best approach in such cases? To avoid unknown possible difficulties or to be clear? If you are sure that it won't cause a problem then I think it's ok to leave it, as long as there is a comment in the code that says why we are sure it's ok. cheers andrew ---(end of broadcast)--- TIP 6: explain analyze is your friend
[PATCHES] ecpg threading vs win32
This patch replaces the pthreads code in ecpg with native win32 threads, in order to make it threadsafe. The idea is not to have to download the non-standard pthreads library on windows. Does it seem like it should be doing the right thing? Does somebody have a good test-case where ecpg breaks when not built thread-safe? (which would then also break when built thread-safe with a broken implementation) //Magnus Index: connect.c === RCS file: /projects/cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v retrieving revision 1.39 diff -u -r1.39 connect.c --- connect.c 12 Jan 2007 10:00:12 - 1.39 +++ connect.c 14 Mar 2007 12:47:48 - @@ -4,7 +4,11 @@ #include postgres_fe.h #ifdef ENABLE_THREAD_SAFETY +#ifndef WIN32 #include pthread.h +#else +#include ecpg-pthread-win32.h +#endif #endif #include ecpgtype.h #include ecpglib.h @@ -13,9 +17,14 @@ #include sqlca.h #ifdef ENABLE_THREAD_SAFETY +#ifndef WIN32 static pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_key_t actual_connection_key; static pthread_once_t actual_connection_key_once = PTHREAD_ONCE_INIT; +#else +static HANDLE connections_mutex = INVALID_HANDLE_VALUE; +static DWORD actual_connection_key; +#endif /* WIN32 */ #endif static struct connection *actual_connection = NULL; static struct connection *all_connections = NULL; @@ -30,7 +39,13 @@ void ecpg_pthreads_init(void) { +#ifndef WIN32 pthread_once(actual_connection_key_once, ecpg_actual_connection_init); +#else + static long has_run = 0; + if (InterlockedCompareExchange(has_run, 1, 0) == 0) + ecpg_actual_connection_init(); +#endif } #endif Index: misc.c === RCS file: /projects/cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v retrieving revision 1.34 diff -u -r1.34 misc.c --- misc.c 12 Jan 2007 10:00:13 - 1.34 +++ misc.c 14 Mar 2007 12:48:03 - @@ -6,7 +6,11 @@ #include limits.h #include unistd.h #ifdef ENABLE_THREAD_SAFETY +#ifndef WIN32 #include pthread.h +#else +#include ecpg-pthread-win32.h +#endif #endif #include ecpgtype.h #include ecpglib.h @@ -58,9 +62,13 @@ }; #ifdef ENABLE_THREAD_SAFETY +#ifndef WIN32 static pthread_key_t sqlca_key; static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT; #else +static DWORD sqlca_key; +#endif +#else static struct sqlca_t sqlca = { { @@ -90,8 +98,13 @@ #endif #ifdef ENABLE_THREAD_SAFETY +#ifndef WIN32 static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER; +#else +static HANDLE debug_mutex = INVALID_HANDLE_VALUE; +static HANDLE debug_init_mutex = INVALID_HANDLE_VALUE; +#endif /* WIN32 */ #endif static int simple_debug = 0; static FILE *debugstream = NULL; @@ -138,8 +151,13 @@ { #ifdef ENABLE_THREAD_SAFETY struct sqlca_t *sqlca; - +#ifdef WIN32 + static long has_run = 0; + if (InterlockedCompareExchange(has_run, 1, 0) == 0) + ecpg_sqlca_key_init(); +#else pthread_once(sqlca_key_once, ecpg_sqlca_key_init); +#endif sqlca = pthread_getspecific(sqlca_key); if (sqlca == NULL) /* $PostgreSQL$ */ /* * pthread mapping macros for win32 native thread implementation */ #ifndef _ECPG_PTHREAD_WIN32_H #define _ECPG_PTHREAD_WIN32_H #define pthread_mutex_lock(x) do { \ if (*x == INVALID_HANDLE_VALUE) \ *x = CreateMutex(NULL, FALSE, NULL); \ WaitForSingleObject(*x, INFINITE); \ } while (0); #define pthread_mutex_unlock(x) ReleaseMutex(*x) #define pthread_getspecific(x) TlsGetValue(x) #define pthread_setspecific(x,y) TlsSetValue(x,y) #define pthread_key_create(x,y) *x = TlsAlloc(); #endif ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
Re: [PATCHES] Code-Cleanup: char* - const char*
Stefan Huehner wrote: attached patches marks several char* variables as const where they are initialized with constant strings. I really wonder how much value there is in using the const modifier very widely. const for function parameters is valuable (because it adds information about the function's behavior to its interface). It also makes sense to use const on global variables, when it reduces the size of the binary's data segment. Beyond that, you reach the point of diminishing returns fairly quickly, IMHO. (In C, anyway; it makes more sense to use it widely in C++, of course.) I also don't see the value in modifying the regexp code, as that is just an import of Henry Spencer's regexp package. I'm not sure whether we're planning on merging any upstream changes any time soon, but making cosmetic changes to the RE code will only make that more difficult. Anyway, I'll apply this tomorrow without the RE changes, barring any objections. BTW, the preferred format for patches is context diffs, not unified diffs. -Neil ---(end of broadcast)--- TIP 4: Have you searched our list archives? http://archives.postgresql.org
Re: [PATCHES] Code-Cleanup: function declarations (void, and kr style)
Stefan Huehner wrote: attached patch fixes some function declarations: - () - (void) - kr style - ansi C Applied, thanks for the patch. -Neil ---(end of broadcast)--- TIP 6: explain analyze is your friend
Re: [PATCHES] patch adding new regexp functions
Jeremy Drake wrote: The patch has been sitting in the unapplied patches queue for a while Barring any objections, I'll apply this tomorrow. -Neil ---(end of broadcast)--- TIP 1: if posting/reading through Usenet, please send an appropriate subscribe-nomail command to [EMAIL PROTECTED] so that your message can get through to the mailing list cleanly