Skip to content

Commit 2f740ee

Browse files
Connecting to a database with national character set UTF8 is now
supported; an error is now raised only when the first attempt to use NCHAR, NVARCHAR2 or NCLOB data is made (#16).
1 parent 53b041a commit 2f740ee

File tree

3 files changed

+25
-8
lines changed

3 files changed

+25
-8
lines changed

Diff for: doc/src/release_notes.rst

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ oracledb 1.0.2 (July 2022)
1313
Thin Mode Changes
1414
+++++++++++++++++
1515

16+
#) Connecting to a database with national character set `UTF8` is now
17+
supported; an error is now raised only when the first attempt to use
18+
NCHAR, NVARCHAR2 or NCLOB data is made
19+
(`issue 16 <https://github.com/oracle/python-oracledb/issues/16>`__).
1620
#) When using the connection parameter `https_proxy` while using protocol
1721
`tcp`, a more meaningful exception is now raised:
1822
`DPY-2029: https_proxy requires use of the tcps protocol`.

Diff for: src/oracledb/impl/thin/capabilities.pyx

+11
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ cdef class Capabilities:
3434
cdef:
3535
uint16_t protocol_version
3636
uint8_t ttc_field_version
37+
uint16_t charset_id
38+
uint16_t ncharset_id
3739
bytearray compile_caps
3840
bytearray runtime_caps
3941
bint char_conversion
@@ -58,6 +60,15 @@ cdef class Capabilities:
5860
cdef void _adjust_for_server_runtime_caps(self, bytearray server_caps):
5961
pass
6062

63+
cdef int _check_ncharset_id(self) except -1:
64+
"""
65+
Checks that the national character set id is AL16UTF16, which is the
66+
only id that is currently supported.
67+
"""
68+
if self.ncharset_id != TNS_CHARSET_UTF16:
69+
errors._raise_err(errors.ERR_NCHAR_CS_NOT_SUPPORTED,
70+
charset_id=self.ncharset_id)
71+
6172
@cython.boundscheck(False)
6273
cdef void _init_compile_caps(self):
6374
self.ttc_field_version = TNS_CCAP_FIELD_VERSION_MAX

Diff for: src/oracledb/impl/thin/messages.pyx

+10-8
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,8 @@ cdef class MessageWithData(Message):
540540
elif ora_type_num == TNS_DATA_TYPE_VARCHAR \
541541
or ora_type_num == TNS_DATA_TYPE_CHAR \
542542
or ora_type_num == TNS_DATA_TYPE_LONG:
543+
if csfrm == TNS_CS_NCHAR:
544+
buf._caps._check_ncharset_id()
543545
column_value = buf.read_str(csfrm)
544546
elif ora_type_num == TNS_DATA_TYPE_RAW \
545547
or ora_type_num == TNS_DATA_TYPE_LONG_RAW:
@@ -944,9 +946,10 @@ cdef class MessageWithData(Message):
944946
elif ora_type_num == TNS_DATA_TYPE_VARCHAR \
945947
or ora_type_num == TNS_DATA_TYPE_CHAR \
946948
or ora_type_num == TNS_DATA_TYPE_LONG:
947-
if var_impl.dbtype._csfrm == 1:
949+
if var_impl.dbtype._csfrm == TNS_CS_IMPLICIT:
948950
temp_bytes = (<str> value).encode()
949951
else:
952+
buf._caps._check_ncharset_id()
950953
temp_bytes = (<str> value).encode(TNS_ENCODING_UTF16)
951954
buf.write_bytes_chunked(temp_bytes)
952955
elif ora_type_num == TNS_DATA_TYPE_RAW \
@@ -1976,6 +1979,7 @@ cdef class LobOpMessage(Message):
19761979
buf.write_bytes(self.dest_lob_impl._locator)
19771980
if self.operation == TNS_LOB_OP_CREATE_TEMP:
19781981
if self.source_lob_impl.dbtype._csfrm == TNS_CS_NCHAR:
1982+
buf._caps._check_ncharset_id()
19791983
buf.write_ub4(TNS_CHARSET_UTF16)
19801984
else:
19811985
buf.write_ub4(TNS_CHARSET_UTF8)
@@ -2068,9 +2072,10 @@ cdef class ProtocolMessage(Message):
20682072
cdef int _process_message(self, ReadBuffer buf,
20692073
uint8_t message_type) except -1:
20702074
cdef:
2071-
uint16_t num_elem, fdo_length, charset_id, ncharset_id
2075+
uint16_t num_elem, fdo_length
20722076
bytearray server_compile_caps
20732077
bytearray server_runtime_caps
2078+
Capabilities caps = buf._caps
20742079
const char_type *fdo
20752080
ssize_t ix
20762081
uint8_t c
@@ -2080,19 +2085,16 @@ cdef class ProtocolMessage(Message):
20802085
buf.read_ub1(&c)
20812086
if c == 0:
20822087
break
2083-
buf.read_uint16(&charset_id, BYTE_ORDER_LSB)
2084-
buf._caps.char_conversion = charset_id != TNS_CHARSET_UTF8
2088+
buf.read_uint16(&caps.charset_id, BYTE_ORDER_LSB)
2089+
buf._caps.char_conversion = caps.charset_id != TNS_CHARSET_UTF8
20852090
buf.skip_ub1() # skip server flags
20862091
buf.read_uint16(&num_elem, BYTE_ORDER_LSB)
20872092
if num_elem > 0: # skip elements
20882093
buf.skip_raw_bytes(num_elem * 5)
20892094
buf.read_uint16(&fdo_length)
20902095
fdo = buf.read_raw_bytes(fdo_length)
20912096
ix = 6 + fdo[5] + fdo[6]
2092-
ncharset_id = (fdo[ix + 3] << 8) + fdo[ix + 4]
2093-
if ncharset_id != TNS_CHARSET_UTF16:
2094-
errors._raise_err(errors.ERR_NCHAR_CS_NOT_SUPPORTED,
2095-
charset_id=ncharset_id)
2097+
caps.ncharset_id = (fdo[ix + 3] << 8) + fdo[ix + 4]
20962098
server_compile_caps = bytearray(buf.read_bytes())
20972099
server_runtime_caps = bytearray(buf.read_bytes())
20982100
if not server_compile_caps[TNS_CCAP_LOGON_TYPES] & TNS_CCAP_O7LOGON:

0 commit comments

Comments
 (0)