New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to XML type #14

Closed
rafaelreuber opened this Issue Apr 21, 2017 · 13 comments

Comments

Projects
None yet
4 participants
@rafaelreuber
Copy link

rafaelreuber commented Apr 21, 2017

Hi,

The XML type is not supported on cx_Oracle. When I run a code like below, I get the error: AttributeError: 'cx_Oracle.OBJECT' object has no attribute 'read'

result = cursor.execute(
  """SELECT XMLElement("Date", hire_date)
  FROM hr.employees
  WHERE employee_id = 203"""
 )

for res in result:
	# The exception occours right here
	raw_xml = res[0].read()

But there are simple workaround. Just use the function GETCLOBVAL:

result = cursor.execute(
  """SELECT XMLElement("Date", hire_date).GETCLOBVAL()
  FROM hr.employees
  WHERE employee_id = 203"""
 )

for res in result:
	import xml.etree.ElementTree as ET
	xml_string = res[0].read()
	tree = ET.fromstring(xml_string)

The workaround works. But I think that would more pythonic if the cx_Oracle do this automatically:

result = cursor.execute(
  """SELECT XMLElement("Date", hire_date)
  FROM hr.employees
  WHERE employee_id = 203"""
 )

for res in result:
	xml = res[0].read()
	type(xml) # <class 'xml.etree.ElementTree.Element'>
@anthony-tuininga

This comment has been minimized.

Copy link
Member

anthony-tuininga commented May 3, 2017

XMLType is returned as an Oracle object with no attributes. It has functions that can only be called from SQL or PL/SQL -- which defeats the purpose! The workaround you have noted already works for you. Another one is to use an output type handler, as in this code:

import cx_Oracle

def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
    if defaultType == cx_Oracle.OBJECT:
        return cursor.var(cx_Oracle.LONG_STRING, arraysize = cursor.arraysize)

conn = cx_Oracle.Connection("cx_Oracle/dev@localhost/orcl")
conn.outputtypehandler = OutputTypeHandler
cursor = conn.cursor()
cursor.execute("select XMLCol from testxml where rownum <= 1")
row = cursor.fetchone()
print(row)    # will be returned as a string

I will look into making this happen automatically since the XMLType objects returned aren't helpful by themselves. In the meantime, hopefully this is a helpful addition.

@ghost

This comment has been minimized.

Copy link

ghost commented Jan 26, 2018

+1

@zhaowei198311

This comment has been minimized.

Copy link

zhaowei198311 commented Sep 3, 2018

yes

@gitrevisor

This comment has been minimized.

Copy link

gitrevisor commented Nov 9, 2018

Any update on this? Would be really nice to have....

@anthony-tuininga

This comment has been minimized.

Copy link
Member

anthony-tuininga commented Nov 9, 2018

I did some initial research last year and discussed with the XMLType group internally. A few enhancements to the OCI library are planned which will make working with this type simpler. In the meantime, however, I can look at better workarounds. Thanks for bringing it back to my attention. I'll take another look at it. :-)

@anthony-tuininga

This comment has been minimized.

Copy link
Member

anthony-tuininga commented Nov 29, 2018

I just created a patch to ODPI-C (which cx_Oracle depends on) which automatically intercepts SYS.XMLTYPE and returns a (LONG) string instead. It is awaiting internal review but I hope to have it available publicly in a few days. Thanks for your patience.

@gitrevisor

This comment has been minimized.

Copy link

gitrevisor commented Nov 29, 2018

Excellent news! Thanks for your hard work!

@rafaelreuber

This comment has been minimized.

Copy link
Author

rafaelreuber commented Nov 29, 2018

Awesome!

anthony-tuininga added a commit to oracle/odpi that referenced this issue Dec 3, 2018

Added support for fetching SYS.XMLTYPE by modifying the type informat…
…ion to

return (LONG) VARCHAR2 when SYS.XMLTYPE is detected
(oracle/python-cx_Oracle#14).
@anthony-tuininga

This comment has been minimized.

Copy link
Member

anthony-tuininga commented Dec 3, 2018

The patch has landed. Let me know if you have any difficulties with it!

@gitrevisor

This comment has been minimized.

Copy link

gitrevisor commented Dec 14, 2018

The patch is brilliant except when trying to load xml files larger than 4000 bytes from an Oracle 12c database I get ORA-19011: Character string buffer too small. Any way around this? Thanks

@anthony-tuininga

This comment has been minimized.

Copy link
Member

anthony-tuininga commented Dec 14, 2018

Yes, I noticed that myself in my own testing. If you enable extended string functionality you can get up to 32 KB, but I'm not aware of any way to go beyond that currently. I've asked internally if/when this restriction is going to be lifted.

@gitrevisor

This comment has been minimized.

Copy link

gitrevisor commented Dec 14, 2018

Thanks for your work on this.

@anthony-tuininga

This comment has been minimized.

Copy link
Member

anthony-tuininga commented Feb 5, 2019

Implemented in cx_Oracle 7.1 which was released yesterday.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment