Class PassXML

  • All Implemented Interfaces:
    SQLData

    @SQLAction(provides="postgresql_xml",install="SELECT CASE (SELECT 1 FROM pg_type WHERE typname = \'xml\') WHEN 1 THEN set_config(\'pljava.implementors\', \'postgresql_xml,\' ||  current_setting(\'pljava.implementors\'), true) END") @SQLAction(implementor="postgresql_xml",requires="echoXMLParameter",install="WITH s(how) AS (SELECT generate_series(1, 7)), t(x) AS (  SELECT table_to_xml(\'pg_catalog.pg_operator\', true, false, \'\') ), r(howin, howout, isdoc) AS (  SELECT   i.how, o.how,   javatest.echoxmlparameter(x, i.how, o.how) IS DOCUMENT  FROM   t, s AS i, s AS o  WHERE   NOT (i.how = 6 and o.how = 7) ) SELECT CASE WHEN every(isdoc)  THEN javatest.logmessage(\'INFO\', \'SQLXML echos succeeded\')  ELSE javatest.logmessage(\'WARNING\', \'SQLXML echos had problems\') END FROM r") @SQLAction(implementor="postgresql_xml",requires="proxiedXMLEcho",install="WITH s(how) AS (SELECT unnest(\'{1,2,4,5,6,7}\'::int[])), t(x) AS (  SELECT table_to_xml(\'pg_catalog.pg_operator\', true, false, \'\') ), r(how, isdoc) AS (  SELECT\thow,\tjavatest.proxiedxmlecho(x, how) IS DOCUMENT  FROM\tt, s )SELECT CASE WHEN every(isdoc)  THEN javatest.logmessage(\'INFO\', \'proxied SQLXML echos succeeded\')  ELSE javatest.logmessage(\'WARNING\',       \'proxied SQLXML echos had problems\') END FROM r") @SQLAction(implementor="postgresql_xml",requires="lowLevelXMLEcho",install={"SELECT preparexmlschema(\'schematest\', $$<xs:schema xmlns:xs=\'http://www.w3.org/2001/XMLSchema\' targetNamespace=\'urn:testme\' elementFormDefault=\'qualified\'> <xs:element name=\'row\'>  <xs:complexType>   <xs:sequence>    <xs:element name=\'textcol\' type=\'xs:string\' nillable=\'true\'/>    <xs:element name=\'intcol\' type=\'xs:integer\' nillable=\'true\'/>   </xs:sequence>  </xs:complexType> </xs:element></xs:schema>$$, \'http://www.w3.org/2001/XMLSchema\', 5)","WITH s(how) AS (SELECT unnest(\'{4,5,7}\'::int[])), r(isdoc) AS ( SELECT  javatest.lowlevelxmlecho(   query_to_xml(    \'SELECT \'\'hi\'\' AS textcol, 1 AS intcol\', true, true, \'urn:testme\'   ), how, params) IS DOCUMENT FROM  s,  (SELECT \'schematest\' AS schema) AS params )SELECT CASE WHEN every(isdoc)  THEN javatest.logmessage(\'INFO\', \'XML Schema tests succeeded\')  ELSE javatest.logmessage(\'WARNING\',       \'XML Schema tests had problems\') END FROM r"}) @SQLAction(implementor="postgresql_xml",requires={"prepareXMLTransform","transformXML"},install={"REVOKE EXECUTE ON FUNCTION javatest.prepareXMLTransformWithJava (pg_catalog.varchar, pg_catalog.xml, integer, boolean, boolean,  pg_catalog.RECORD) FROM PUBLIC","SELECT javatest.prepareXMLTransform(\'distinctElementNames\',\'<xsl:transform version=\'\'1.0\'\' xmlns:xsl=\'\'http://www.w3.org/1999/XSL/Transform\'\' xmlns:exsl=\'\'http://exslt.org/common\'\' xmlns:set=\'\'http://exslt.org/sets\'\' extension-element-prefixes=\'\'exsl set\'\'> <xsl:output method=\'\'xml\'\' indent=\'\'no\'\'/> <xsl:template match=\'\'/\'\'>  <xsl:variable name=\'\'enames\'\'>   <xsl:for-each select=\'\'//*\'\'>    <ename><xsl:value-of select=\'\'local-name()\'\'/></ename>   </xsl:for-each>  </xsl:variable>  <xsl:for-each   select=\'\'set:distinct(exsl:node-set($enames)/ename)\'\'>   <xsl:sort select=\'\'string()\'\'/>   <den><xsl:value-of select=\'\'.\'\'/></den>  </xsl:for-each> </xsl:template></xsl:transform>\', how => 5, enableExtensionFunctions => true)","SELECT javatest.prepareXMLTransformWithJava(\'getPLJavaVersion\',\'<xsl:transform version=\'\'1.0\'\' xmlns:xsl=\'\'http://www.w3.org/1999/XSL/Transform\'\' xmlns:java=\'\'http://xml.apache.org/xalan/java\'\' exclude-result-prefixes=\'\'java\'\'> <xsl:template match=\'\'/\'\'>  <xsl:value-of   select=\'\'java:java.lang.System.getProperty(    \"org.postgresql.pljava.version\")\'\'  /> </xsl:template></xsl:transform>\', enableExtensionFunctions => true)","SELECT CASE WHEN  javatest.transformXML(\'distinctElementNames\',   \'<a><c/><e/><b/><b/><d/></a>\', 5, 5)::text  =   \'<den>a</den><den>b</den><den>c</den><den>d</den><den>e</den>\'  THEN javatest.logmessage(\'INFO\', \'XSLT 1.0 test succeeded\')  ELSE javatest.logmessage(\'WARNING\', \'XSLT 1.0 test failed\') END","SELECT CASE WHEN  javatest.transformXML(\'getPLJavaVersion\', \'\')::text  OPERATOR(pg_catalog.=) extversion  THEN javatest.logmessage(\'INFO\', \'XSLT 1.0 with Java succeeded\')  ELSE javatest.logmessage(\'WARNING\', \'XSLT 1.0 with Java failed\') END FROM pg_catalog.pg_extension WHERE extname = \'pljava\'"}) @SQLAction(implementor="postgresql_xml",provides="xml_java_ge_22",requires="javaSpecificationGE",install="SELECT CASE WHEN javatest.javaSpecificationGE(\'22\') THEN set_config(\'pljava.implementors\', \'xml_java_ge_22,\' ||  current_setting(\'pljava.implementors\'), true) END") @SQLAction(implementor="xml_java_ge_22",requires="lowLevelXMLEcho",install="WITH s(how) AS (SELECT unnest(\'{5,6,7}\'::int[])), r(isdoc) AS ( SELECT  javatest.lowlevelxmlecho(   \'<!DOCTYPE a []><a/>\'::xml, how, params) IS DOCUMENT FROM  s,  (SELECT null::void AS ignoreDTD) AS params )SELECT CASE WHEN every(isdoc)  THEN javatest.logmessage(\'INFO\',    \'jdk.xml.dtd.support=ignore OK\')  ELSE javatest.logmessage(\'WARNING\', \'jdk.xml.dtd.support=ignore NG\') END FROM r")
    @MappedUDT(schema="javatest",
               name="onexml",
               structure="c1 xml",
               implementor="postgresql_xml",
               comment="A composite type mapped by the PassXML example class")
    public class PassXML
    extends Object
    implements SQLData
    Class illustrating use of SQLXML to operate on XML data.

    This class also serves as the mapping class for a composite type javatest.onexml, the better to verify that SQLData input/output works too. That's why it has to implement SQLData.

    Everything mentioning the type XML here needs a conditional implementor tag in case of being loaded into a PostgreSQL instance built without that type.

    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      static class  PassXML.SQLXMLMock
      Class that will mock an SQLXML instance, returning only binary or character stream data from a byte array or string supplied at construction.
      static class  PassXML.SQLXMLProxy
      Class that will proxy methods to another SQLXML class.
    • Constructor Summary

      Constructors 
      Constructor Description
      PassXML()
      No-arg constructor required of objects that will implement SQLData.
    • Method Summary

      Modifier and Type Method Description
      static void allowFragment​(DOMResult r)
      Configure a DOMResult to accept CONTENT (a/k/a document fragment), not only the more restrictive DOCUMENT.
      static <T extends org.postgresql.pljava.Adjusting.XML.Parsing<? super T>>
      T
      applyAdjustments​(ResultSet adjust, T axp)
      Apply adjustments (supplied as a row type with a named column for each desired adjustment and its value) to an instance of Adjusting.XML.Parsing.
      static SQLXML bounceXMLParameter​(SQLXML sx)
      "Echo" an XML parameter not by creating a new writable SQLXML object at all, but simply returning the passed-in readable one untouched.
      static SQLXML bounceXMLParameter_​(SQLXML sx)
      Just like bounceXMLParameter(java.sql.SQLXML) but with parameter and return typed as text, and so usable on a PostgreSQL instance lacking the XML type.
      static SQLXML castTextXML​(SQLXML sx)
      Just like bounceXMLParameter(java.sql.SQLXML) but with the parameter typed as text and the return type left as XML, so functions as a cast.
      static SQLXML echoXMLParameter​(SQLXML sx, int howin, int howout)
      Echo an XML parameter back, exercising seven different ways (howin => 1-7) of reading an SQLXML object, and seven (howout => 1-7) of returning one.
      static SQLXML echoXMLParameter_​(SQLXML sx, int howin, int howout)
      Echo an XML parameter back, but with parameter and return types of PostgreSQL text.
      static SQLXML ensureClosed​(Result r, SQLXML sx, int how)
      Ensure the closing of whatever method was used to add content to an SQLXML object.
      String getSQLTypeName()  
      static SQLXML inStringoutXML​(String in)  
      static String inXMLoutString​(SQLXML in)  
      static String lowLevelXMLEcho​(String x)
      Low-level XML echo where the Java parameter and return type are String.
      static SQLXML lowLevelXMLEcho​(SQLXML sx, int how, ResultSet adjust)
      Echo the XML parameter back, using lower-level manipulations than echoXMLParameter.
      static SQLXML lowLevelXMLEcho_​(SQLXML sx, int how, ResultSet adjust)
      Text-typed variant of lowLevelXMLEcho (does not require XML type).
      static SQLXML mockedXMLEcho​(byte[] bytes)
      Supply a sequence of bytes to be the exact (encoded) content of an XML value, which will be returned; if the encoding is not UTF-8, the value should begin with an XML Decl that names the encoding.
      static SQLXML mockedXMLEcho​(String chars)
      Supply a sequence of characters to be the exact (Unicode) content of an XML value, which will be returned; if the value begins with an XML Decl that names an encoding, the content will be assumed to contain only characters representable in that encoding.
      static void prepareXMLSchema​(String name, SQLXML source, String lang, int how)
      Precompile a schema source in schema language lang and save it (for the current session) as name.
      static void prepareXMLTransform​(String name, SQLXML source, int how, boolean enableExtensionFunctions, boolean builtin, ResultSet adjust)
      Precompile an XSL transform source and save it (for the current session) as name.
      static void prepareXMLTransformWithJava​(String name, SQLXML source, int how, boolean enableExtensionFunctions, boolean builtin, ResultSet adjust)
      Precompile an XSL transform source and save it (for the current session) as name, where the transform may call Java methods.
      static SQLXML proxiedXMLEcho​(SQLXML sx, int how)
      Proxy a PL/Java SQLXML source object as if it were of a non-PL/Java implementing class, to confirm that it can still be returned successfully to PostgreSQL.
      void readSQL​(SQLInput stream, String typeName)  
      static SQLXML transformXML​(String transformName, SQLXML source, int howin, int howout, ResultSet adjust, Boolean indent, Integer indentWidth)
      Transform some XML according to a named transform prepared with prepareXMLTransform.
      static void unclosedSQLXML​(int howmany, int how)
      Create and leave some number of SQLXML objects unclosed, unused, and unreferenced, as a test of reclamation.
      void writeSQL​(SQLOutput stream)  
      static SQLXML xmlFromComposite()
      Test the MappedUDT (in one direction anyway).
      static boolean xmlInStmtAndRS​(ResultSet out)
      Create some XML, pass it to a SELECT ? prepared statement, retrieve it from the result set, and return it via the out-parameter result set of this RECORD-returning function.
      static SQLXML xmlTextNode​(byte[] stuff, String encoding, int how, boolean inElement)
      Test serialization into the PostgreSQL server encoding by returning a text node, optionally wrapped in an element, containing the supplied stuff.
    • Constructor Detail

      • PassXML

        public PassXML()
        No-arg constructor required of objects that will implement SQLData.
    • Method Detail

      • echoXMLParameter

        @Function(schema="javatest",
                  implementor="postgresql_xml",
                  provides="echoXMLParameter")
        public static SQLXML echoXMLParameter​(SQLXML sx,
                                              int howin,
                                              int howout)
                                       throws SQLException
        Echo an XML parameter back, exercising seven different ways (howin => 1-7) of reading an SQLXML object, and seven (howout => 1-7) of returning one.

        If howin => 0, the XML parameter is simply saved in a static. It can be read in a subsequent call with sx => null, but only in the same transaction.

        The "echoing" is done (in the echoXML method below) using a Transformer, that is, the "TrAX" Transformation API for XML supplied in Java. It illustrates how an identity Transformer can be used to get the XML content from the source to the result for any of the APIs selectable by howin and howout.

        It also illustrates something else. When using StAX (6 for howin or howout) and XML of the CONTENT flavor (multiple top-level elements, characters outside the top element, etc.), it is easy to construct examples that fail. The fault is not really with the StAX API, nor with TrAX proper, but with the small handful of bridge classes that were added to the JRE with StAX's first appearance, to make it interoperate with TrAX. It is not that those classes completely overlook the CONTENT case: they make some efforts to handle it. Just not the right ones, and given the Java developers' usual reluctance to change such longstanding behavior, that's probably not getting fixed.

        Moral: StAX is a nice API, have no fear to use it directly in freshly-developed code, but: when using TrAX, make every effort to supply a Transformer with Source and Result objects of any kind other than StAX.

        Throws:
        SQLException
      • echoXMLParameter_

        @Function(schema="javatest",
                  name="echoXMLParameter",
                  type="text")
        public static SQLXML echoXMLParameter_​(@SQLType("text")
                                               SQLXML sx,
                                               int howin,
                                               int howout)
                                        throws SQLException
        Echo an XML parameter back, but with parameter and return types of PostgreSQL text.

        The other version of this method needs a conditional implementor tag because it cannot be declared in a PostgreSQL instance that was built without libxml support and the PostgreSQL XML type. But this version can, simply by mapping the SQLXML parameter and return types to the SQL text type. The Java code is no different.

        Note that it's possible for both declarations to coexist in PostgreSQL (because as far as it is concerned, their signatures are different), but these two Java methods cannot have the same name (because they differ only in annotations, not in the declared Java types). So, this one needs a slightly tweaked name, and a name attribute in the annotation so PostgreSQL sees the right name.

        Throws:
        SQLException
      • bounceXMLParameter

        @Function(schema="javatest",
                  implementor="postgresql_xml")
        public static SQLXML bounceXMLParameter​(SQLXML sx)
                                         throws SQLException
        "Echo" an XML parameter not by creating a new writable SQLXML object at all, but simply returning the passed-in readable one untouched.
        Throws:
        SQLException
      • castTextXML

        @Function(schema="javatest",
                  implementor="postgresql_xml")
        public static SQLXML castTextXML​(@SQLType("text")
                                         SQLXML sx)
                                  throws SQLException
        Just like bounceXMLParameter(java.sql.SQLXML) but with the parameter typed as text and the return type left as XML, so functions as a cast.

        Slower than the other cases, because it must verify that the input really is XML before blindly calling it a PostgreSQL XML type. But the speed compares respectably to PostgreSQL's own CAST(text AS xml), at least for larger values; I am seeing Java pull ahead right around 32kB of XML data and beat PG by a factor of 2 or better at sizes of 1 or 2 MB. Unsurprisingly, PG has the clear advantage when values are very short.

        Throws:
        SQLException
      • prepareXMLTransform

        @Function(schema="javatest",
                  implementor="postgresql_xml",
                  provides="prepareXMLTransform")
        public static void prepareXMLTransform​(String name,
                                               SQLXML source,
                                               @SQLType(defaultValue="0")
                                               int how,
                                               @SQLType(defaultValue="false")
                                               boolean enableExtensionFunctions,
                                               @SQLType(defaultValue="true")
                                               boolean builtin,
                                               @SQLType(defaultValue={})
                                               ResultSet adjust)
                                        throws SQLException
        Precompile an XSL transform source and save it (for the current session) as name.

        Each value of how, 1-7, selects a different way of presenting the SQLXML object to the XSL processor.

        Passing true for enableExtensionFunctions allows the transform to use extensions that the Java XSLT implementation supports, such as functions from EXSLT. Those are disabled by default.

        Passing false for builtin will allow a TransformerFactory other than Java's built-in one to be found using the usual search order and the context class loader (normally the PL/Java class path for the schema where this function is declared). The default of true ensures that the built-in Java XSLT 1.0 implementation is used. A transformer implementation other than Xalan may not recognize the feature controlled by enableExtensionFunctions, so failure to configure that feature will be logged as a warning if builtin is false, instead of thrown as an exception.

        Out of the box, Java's transformers only support XSLT 1.0. See the S9 example for more capabilities (at the cost of downloading the Saxon jar).

        Throws:
        SQLException
      • prepareXMLTransformWithJava

        @Function(schema="javatest",
                  implementor="postgresql_xml",
                  provides="prepareXMLTransform")
        public static void prepareXMLTransformWithJava​(String name,
                                                       SQLXML source,
                                                       @SQLType(defaultValue="0")
                                                       int how,
                                                       @SQLType(defaultValue="false")
                                                       boolean enableExtensionFunctions,
                                                       @SQLType(defaultValue="true")
                                                       boolean builtin,
                                                       @SQLType(defaultValue={})
                                                       ResultSet adjust)
                                                throws SQLException
        Precompile an XSL transform source and save it (for the current session) as name, where the transform may call Java methods.

        Otherwise identical to prepareXMLTransform, this version sets the TransformerFactory's extensionClassLoader (to the context class loader, normally the PL/Java class path for the schema where this function is declared), so the transform will be able to use xalan's Java call syntax to call any public Java methods that would be accessible to this class. (That can make a big difference in usefulness for the otherwise rather limited XSLT 1.0.)

        As with enableExtensionFunctions, failure by the transformer implementation to recognize or allow the extensionClassLoader property will be logged as a warning if builtin is false, rather than thrown as an exception.

        This example function will be installed with EXECUTE permission revoked from PUBLIC, as it essentially confers the ability to create arbitrary new Java functions, so should only be granted to roles you would be willing to grant USAGE ON LANGUAGE java.

        Because this function only prepares the transform, and transformXML applies it, there is some division of labor in determining what limits apply to its behavior. The use of this method instead of prepareXMLTransform determines whether the transform is allowed to see external Java methods at all; it will be the policy permissions granted to transformXML that control what those methods can do when the transform is applied. For now, that method is defined in the trusted/sandboxed java language, so this function could reasonably be granted to any role with USAGE on java. If, by contrast, transformXML were declared in the 'untrusted' javaU, it would be prudent to allow only superusers access to this function, just as only they can CREATE FUNCTION in an untrusted language.

        Throws:
        SQLException
      • transformXML

        @Function(schema="javatest",
                  implementor="postgresql_xml",
                  provides="transformXML")
        public static SQLXML transformXML​(String transformName,
                                          SQLXML source,
                                          @SQLType(defaultValue="0")
                                          int howin,
                                          @SQLType(defaultValue="0")
                                          int howout,
                                          @SQLType(defaultValue={})
                                          ResultSet adjust,
                                          @SQLType(optional=true)
                                          Boolean indent,
                                          @SQLType(optional=true)
                                          Integer indentWidth)
                                   throws SQLException
        Transform some XML according to a named transform prepared with prepareXMLTransform.

        Pass null for transformName to get a plain identity transform (not such an interesting thing to do, unless you also specify indenting).

        Throws:
        SQLException
      • prepareXMLSchema

        @Function(schema="javatest",
                  implementor="postgresql_xml")
        public static void prepareXMLSchema​(String name,
                                            SQLXML source,
                                            String lang,
                                            int how)
                                     throws SQLException
        Precompile a schema source in schema language lang and save it (for the current session) as name.

        Each value of how, 1-7, selects a different way of presenting the SQLXML object to the schema parser.

        The lang parameter is a URI that identifies a known schema language. The only language a Java runtime is required to support is W3C XML Schema 1.0, with URI http://www.w3.org/2001/XMLSchema.

        Throws:
        SQLException
      • lowLevelXMLEcho

        @Function(schema="javatest",
                  implementor="postgresql_xml",
                  provides="lowLevelXMLEcho")
        public static SQLXML lowLevelXMLEcho​(SQLXML sx,
                                             int how,
                                             @SQLType(defaultValue={})
                                             ResultSet adjust)
                                      throws SQLException
        Echo the XML parameter back, using lower-level manipulations than echoXMLParameter.

        This illustrates how the simple use of t.transform(src,rlt) in echoSQLXML substitutes for a lot of fiddly case-by-case code, but when coding for a specific case, all the generality of transform may not be needed. It can be interesting to compare memory use when XML values are large.

        This method has been revised to demonstrate, even for low-level manipulations, how much fiddliness can now be avoided through use of the Adjusting.XML.SourceResult class, and how to make adjustments to parsing restrictions by passing the optional row-typed parameter adjust, which defaults to an empty row. For example, passing

         adjust => (select a from
                    (true as allowdtd, true as expandentityreferences) as a)
        
        would allow a document that contains an internal DTD subset and uses entities defined there.

        The older, pre-SourceResult code for doing low-level XML echo has been moved to the oldSchoolLowLevelEcho method below. It can still be exercised by calling this method, explicitly passing adjust => NULL.

        Throws:
        SQLException
      • applyAdjustments

        public static <T extends org.postgresql.pljava.Adjusting.XML.Parsing<? super T>> T applyAdjustments​(ResultSet adjust,
                                                                                                            T axp)
                                                                                                     throws SQLException
        Apply adjustments (supplied as a row type with a named column for each desired adjustment and its value) to an instance of Adjusting.XML.Parsing.

        Column names in the adjust row are case-insensitive versions of the method names in Adjusting.XML.Parsing, and the value of each column should be of the appropriate type (if the method has a parameter).

        Parameters:
        adjust - A row type as described above, possibly of no columns if no adjustments are wanted
        axp - An instance of Adjusting.XML.Parsing
        Returns:
        axp, after applying any adjustments
        Throws:
        SQLException
      • proxiedXMLEcho

        @Function(schema="javatest",
                  implementor="postgresql_xml",
                  provides="proxiedXMLEcho")
        public static SQLXML proxiedXMLEcho​(SQLXML sx,
                                            int how)
                                     throws SQLException
        Proxy a PL/Java SQLXML source object as if it were of a non-PL/Java implementing class, to confirm that it can still be returned successfully to PostgreSQL.
        Parameters:
        sx - readable SQLXML object to proxy
        how - 1,2,4,5,6,7 determines what subclass of Source will be returned by getSource.
        Throws:
        SQLException
      • mockedXMLEcho

        @Function(schema="javatest",
                  implementor="postgresql_xml",
                  provides="mockedXMLEchoB")
        public static SQLXML mockedXMLEcho​(byte[] bytes)
                                    throws SQLException
        Supply a sequence of bytes to be the exact (encoded) content of an XML value, which will be returned; if the encoding is not UTF-8, the value should begin with an XML Decl that names the encoding.

        Constructs an SQLXML instance that will return the supplied content as a StreamSource wrapping an InputStream, or via getBinaryStream, but fail if asked for any other form.

        Throws:
        SQLException
      • mockedXMLEcho

        @Function(schema="javatest",
                  implementor="postgresql_xml",
                  provides="mockedXMLEchoC")
        public static SQLXML mockedXMLEcho​(String chars)
                                    throws SQLException
        Supply a sequence of characters to be the exact (Unicode) content of an XML value, which will be returned; if the value begins with an XML Decl that names an encoding, the content will be assumed to contain only characters representable in that encoding.

        Constructs an SQLXML instance that will return the supplied content as a StreamSource wrapping a Reader, or via getCharacterStream, but fail if asked for any other form.

        Throws:
        SQLException
      • lowLevelXMLEcho_

        @Function(schema="javatest",
                  name="lowLevelXMLEcho",
                  type="text")
        public static SQLXML lowLevelXMLEcho_​(@SQLType("text")
                                              SQLXML sx,
                                              int how,
                                              @SQLType(defaultValue={})
                                              ResultSet adjust)
                                       throws SQLException
        Text-typed variant of lowLevelXMLEcho (does not require XML type).
        Throws:
        SQLException
      • lowLevelXMLEcho

        @Function(schema="javatest",
                  implementor="postgresql_xml",
                  type="xml")
        public static String lowLevelXMLEcho​(@SQLType("xml")
                                             String x)
                                      throws SQLException
        Low-level XML echo where the Java parameter and return type are String.
        Throws:
        SQLException
      • xmlInStmtAndRS

        @Function(schema="javatest",
                  type="RECORD")
        public static boolean xmlInStmtAndRS​(ResultSet out)
                                      throws SQLException
        Create some XML, pass it to a SELECT ? prepared statement, retrieve it from the result set, and return it via the out-parameter result set of this RECORD-returning function.
        Throws:
        SQLException
      • xmlTextNode

        @Function(schema="javatest",
                  implementor="postgresql_xml")
        public static SQLXML xmlTextNode​(byte[] stuff,
                                         String encoding,
                                         int how,
                                         boolean inElement)
                                  throws Exception
        Test serialization into the PostgreSQL server encoding by returning a text node, optionally wrapped in an element, containing the supplied stuff.

        The stuff is supplied as a bytea and a named encoding, so it is easy to supply stuff that isn't in the server encoding and see what the serializer does with it.

        As of this writing, if the stuff, decoded according to encoding, contains characters that are not representable in the server encoding, the serializers supplied in the JRE will:

        • SAX, DOM: replace the character with a numeric character reference if the node is wrapped in an element, but not outside of an element; there, PL/Java ensures an UnmappableCharacterException is thrown, as the serializer would otherwise silently lose information by replacing the character with a ?.
        • StAX: replace the character with a numeric character reference whether wrapped in an element or not (outside of an element, this officially violates the letter of the XML spec, but does not lose information, and is closer to the spirit of SQL/XML with its XML(CONTENT) type).
        Parameters:
        stuff - Content to be used in the text node
        encoding - Name of an encoding; stuff will be decoded to Unicode according to this encoding, and then serialized into the server encoding, where possible.
        how - Integer specifying which XML API to test, like every other how in this class; here the only valid choices are 5 (SAX), 6 (StAX), or 7 (DOM).
        inElement - True if the text node should be wrapped in an element.
        Returns:
        The resulting XML content.
        Throws:
        Exception
      • unclosedSQLXML

        @Function(schema="javatest")
        public static void unclosedSQLXML​(int howmany,
                                          int how)
                                   throws SQLException
        Create and leave some number of SQLXML objects unclosed, unused, and unreferenced, as a test of reclamation.
        Parameters:
        howmany - Number of SQLXML instances to create.
        how - If nonzero, the flavor of writing to request on the object before abandoning it; if zero, it is left in its initial, writable state.
        Throws:
        SQLException
      • ensureClosed

        public static SQLXML ensureClosed​(Result r,
                                          SQLXML sx,
                                          int how)
                                   throws SQLException
        Ensure the closing of whatever method was used to add content to an SQLXML object.

        Before a SQLXML object that has been written to can be used by PostgreSQL (returned as a function result, plugged in as a prepared statement parameter or into a ResultSet, etc.), the method used for writing it must be "closed" to ensure the writing is complete.

        If it is set with setString, nothing more is needed; setString obviously sets the whole value at once. Any OutputStream or Writer obtained from setBinaryStream or setCharacterStream, or from setResult(StreamResult.class), has to be explicitly closed (a Transformer does not close its Result when the transformation is complete!). Those are cases 1, 2, and 4 here.

        Cases 5 (SAXResult) and 6 (StAXResult) need no special attention; though the Transformer does not close them, the ones returned by this SQLXML implementation are set up to close themselves when the endDocument event is written.

        Case 3 (test of setString is handled specially here. As this class allows testing of all techniques for writing the SQLXML object, and most of those involve a Result, case 3 is handled by also constructing a Result over a StringWriter and having the content written into that; this method then extracts the content from the StringWriter and passes it to setString. For cases 1 and 2, likewise, the stream obtained with getBinaryStream or getCharacterStream has been wrapped in a Result for generality in this example.

        A typical application will not need the generality seen here; it will usually know which technique it is using to write the SQLXML object, and only needs to know how to close that if it needs closing.

        Parameters:
        r - The Result onto which writing was done.
        sx - The SQLXML object being written.
        how - The integer used in this example class to select which method of writing the SQLXML object was to be tested.
        Returns:
        The SQLXML object sx, because why not?
        Throws:
        SQLException
      • allowFragment

        public static void allowFragment​(DOMResult r)
                                  throws SQLException
        Configure a DOMResult to accept CONTENT (a/k/a document fragment), not only the more restrictive DOCUMENT.

        The other forms of Result that can be requested will happily accept XML(CONTENT) and not just XML(DOCUMENT). The DOMResult is pickier, however: if you first call setNode with a DocumentFragment, it will accept either form, but if you leave the node unset when passing the DOMResult to a transformer, the transformer will default to putting a Document node there, and then it will not accept a fragment.

        If you need to handle fragments, this method illustrates how to pre-load the DOMResult with an empty DocumentFragment. Note that if you use some XML processing package that supplies its own classes implementing DOM nodes, you may need to use a DocumentFragment instance obtained from that package.

        Throws:
        SQLException
      • xmlFromComposite

        @Function(schema="javatest",
                  implementor="postgresql_xml")
        public static SQLXML xmlFromComposite()
                                       throws SQLException
        Test the MappedUDT (in one direction anyway).

        Creates a PassXML object, the Java class that maps the javatest.onexml composite type, which has one member, of XML type. Stores a SQLXML value in that field of the PassXML object, and passes that to an SQL query that expects and returns javatest.onexml. Retrieves the XML from the value field of the PassXML object created to map the result of the query.

        Returns:
        The original XML value, if all goes well.
        Throws:
        SQLException