From 1c0f626a37a56f4909aaf33cc9e5bec8e0554436 Mon Sep 17 00:00:00 2001 From: Anthony Tuininga Date: Fri, 21 Apr 2023 11:46:59 -0600 Subject: [PATCH] Add Oracle object pretty-printing example. --- doc/src/release_notes.rst | 2 +- samples/insert_geometry.py | 22 +------ samples/object_dump.py | 106 ++++++++++++++++++++++++++++++++++ samples/sql/create_schema.sql | 8 ++- 4 files changed, 116 insertions(+), 22 deletions(-) create mode 100644 samples/object_dump.py diff --git a/doc/src/release_notes.rst b/doc/src/release_notes.rst index 6fd577c..4d23399 100644 --- a/doc/src/release_notes.rst +++ b/doc/src/release_notes.rst @@ -27,7 +27,7 @@ Thin Mode Changes Common Changes ++++++++++++++ -#) Improved test suite. +#) Improved test suite and samples. oracledb 1.3.0 (March 2023) diff --git a/samples/insert_geometry.py b/samples/insert_geometry.py index 7377809..b54fc54 100644 --- a/samples/insert_geometry.py +++ b/samples/insert_geometry.py @@ -1,5 +1,5 @@ #------------------------------------------------------------------------------ -# Copyright (c) 2016, 2022, Oracle and/or its affiliates. +# Copyright (c) 2016, 2023, Oracle and/or its affiliates. # # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved. # @@ -58,25 +58,7 @@ print("Created object", obj) with connection.cursor() as cursor: - - # create sample table - cursor.execute(""" - begin - begin - execute immediate 'drop table TestGeometry'; - exception - when others then - if sqlcode <> -942 then - raise; - end if; - end; - - execute immediate 'create table TestGeometry ( - IntCol number(9) not null, - Geometry MDSYS.SDO_GEOMETRY)'; - end;""") - - + cursor.execute("truncate table TestGeometry") print("Adding row to table...") cursor.execute("insert into TestGeometry values (1, :objbv)", objbv=obj) connection.commit() diff --git a/samples/object_dump.py b/samples/object_dump.py new file mode 100644 index 0000000..d58fe29 --- /dev/null +++ b/samples/object_dump.py @@ -0,0 +1,106 @@ +#------------------------------------------------------------------------------ +# Copyright (c) 2023, Oracle and/or its affiliates. +# +# This software is dual-licensed to you under the Universal Permissive License +# (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License +# 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose +# either license. +# +# If you elect to accept the software under the Apache License, Version 2.0, +# the following applies: +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# object_dump.py +# +# Shows how to pretty-print an Oracle object or collection. +# Also shows how to insert a Python object to an Oracle object column. +#------------------------------------------------------------------------------ + +import oracledb +import sample_env + +# determine whether to use python-oracledb thin mode or thick mode +if not sample_env.get_is_thin(): + oracledb.init_oracle_client(lib_dir=sample_env.get_oracle_client()) + +# Create Oracle connection and cursor objects +connection = oracledb.connect(user=sample_env.get_main_user(), + password=sample_env.get_main_password(), + dsn=sample_env.get_connect_string()) +cursor = connection.cursor() + +# Create a Python class equivalent to an Oracle SDO object +class MySDO(object): + + def __init__(self, gtype, elem_info, ordinates): + self.gtype = gtype + self.elem_info = elem_info + self.ordinates = ordinates + + +# Get Oracle type information +obj_type = connection.gettype("MDSYS.SDO_GEOMETRY") +element_info_type_obj = connection.gettype("MDSYS.SDO_ELEM_INFO_ARRAY") +ordinate_type_obj = connection.gettype("MDSYS.SDO_ORDINATE_ARRAY") + +# Convert a Python object to MDSYS.SDO_GEOMETRY +def sdo_input_type_handler(cursor, value, num_elements): + def sdo_in_converter(value): + obj = obj_type.newobject() + obj.SDO_GTYPE = value.gtype + obj.SDO_ELEM_INFO = element_info_type_obj.newobject() + obj.SDO_ELEM_INFO.extend(value.elem_info) + obj.SDO_ORDINATES = ordinate_type_obj.newobject() + obj.SDO_ORDINATES.extend(value.ordinates) + return obj + + if isinstance(value, MySDO): + return cursor.var(obj_type, arraysize=num_elements, + inconverter=sdo_in_converter) + + +# Create and insert a Python object +sdo = MySDO(2003, [1, 1003, 3], [1, 1, 5, 7]) +cursor.inputtypehandler = sdo_input_type_handler +cursor.execute("truncate table TestGeometry") +cursor.execute("insert into TestGeometry values (1, :1)", [sdo]) + + +# Define a function to pretty-print the contents of an Oracle object +def dump_object(obj, prefix=""): + if obj.type.iscollection: + print(f"{prefix}[") + for value in obj.aslist(): + if isinstance(value, oracledb.DbObject): + dump_object(value, prefix + " ") + else: + print(f"{prefix} {repr(value)}") + print(f"{prefix}]") + else: + print(f"{prefix}{{") + for attr in obj.type.attributes: + value = getattr(obj, attr.name) + if isinstance(value, oracledb.DbObject): + print(f"{prefix} {attr.name}:") + dump_object(value, prefix + " ") + else: + print(f"{prefix} {attr.name}: {repr(value)}") + print(f"{prefix}}}") + +# Query the row back +cursor.execute("select geometry from TestGeometry") +for (obj,) in cursor: + dump_object(obj) diff --git a/samples/sql/create_schema.sql b/samples/sql/create_schema.sql index 2bacfd1..ffb89a2 100644 --- a/samples/sql/create_schema.sql +++ b/samples/sql/create_schema.sql @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------- - * Copyright 2017, 2022, Oracle and/or its affiliates. + * Copyright 2017, 2023, Oracle and/or its affiliates. * * This software is dual-licensed to you under the Universal Permissive License * (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License @@ -245,6 +245,12 @@ create table &main_user..LoadCsvTab ( ) / +create table &main_user..TestGeometry ( + id number(9) not null, + geometry mdsys.sdo_geometry not null +) +/ + declare t_Version number; begin