Skip to content
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

Update examples for python-oracledb 2.3 #378

Merged
merged 1 commit into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions python/python-oracledb/json_duality.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# -----------------------------------------------------------------------------
# Copyright (c) 2024, 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.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# json_duality.py
#
# Demonstrates Oracle Database 23ai JSON-Relational Duality Views.
#
# Also see soda_json_duality.py
#
# Reference: https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=ADJSN
# -----------------------------------------------------------------------------

import json
import sys

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())

connection = oracledb.connect(
user=sample_env.get_main_user(),
password=sample_env.get_main_password(),
dsn=sample_env.get_connect_string(),
)

if not connection.thin:
client_version = oracledb.clientversion()[0]
db_version = int(connection.version.split(".")[0])

# this script only works with Oracle Database 23ai
if db_version < 23:
sys.exit("This example requires Oracle Database 23 or later. ")

with connection.cursor() as cursor:

# Create a JSON-Relational Duality View over the SampleJRDVAuthorTab and
# SampleJRDVBookTab tables
sql = """
create or replace json relational duality view BookDV as
SampleJRDVBookTab @insert @update @delete
{
_id: BookId,
book_title: BookTitle,
author: SampleJRDVAuthorTab @insert @update
{
author_id: AuthorId,
author_name: AuthorName
}
}"""
cursor.execute(sql)

with connection.cursor() as cursor:

# Insert a new book and author into the Duality View and show the resulting
# new records in the relational tables
data = dict(
_id=101,
book_title="Cooking at Home",
author=dict(author_id=201, author_name="Dave Smith"),
)
inssql = "insert into BookDV values (:1)"
if connection.thin or client_version >= 21:
# Take advantage of direct binding
cursor.setinputsizes(oracledb.DB_TYPE_JSON)
cursor.execute(inssql, [data])
else:
# Insert the data as a JSON string
cursor.execute(inssql, [json.dumps(data)])

print("Authors in the relational table:")
for row in cursor.execute(
"select * from SampleJRDVAuthorTab order by AuthorId"
):
print(row)

print("\nBooks in the relational table:")
for row in cursor.execute(
"select * from SampleJRDVBookTab order by BookId"
):
print(row)

# Select from the duality view

with connection.cursor() as cursor:

print("\nDuality view query for an author's books:")
sql = """select b.data.book_title, b.data.author.author_name
from BookDV b
where b.data.author.author_id = :1"""
for r in cursor.execute(sql, [1]):
print(r)

print("\nDuality view query of all records:")
sql = """select data from BookDV"""
if connection.thin or client_version >= 21:
for (j,) in cursor.execute(sql):
print(j)
else:
for (j,) in cursor.execute(sql):
print(json.loads(j.read()))
2 changes: 1 addition & 1 deletion python/python-oracledb/oracledb_upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
# set lib_dir; instead set LD_LIBRARY_PATH or configure ldconfig before running
# Python.
lib_dir = None
if platform.system() == "Darwin" and platform.machine() == "x86_64":
if platform.system() == "Darwin":
lib_dir = os.environ.get("HOME") + "/Downloads/instantclient_19_8"
elif platform.system() == "Windows":
lib_dir = r"C:\oracle\instantclient_19_14"
Expand Down
112 changes: 112 additions & 0 deletions python/python-oracledb/plsql_rowtype.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# -----------------------------------------------------------------------------
# Copyright (c) 2024, 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.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# plsql_rowtype.py
#
# Demonstrates how to use a PL/SQL %ROWTYPE attribute
# -----------------------------------------------------------------------------

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())

connection = oracledb.connect(
user=sample_env.get_main_user(),
password=sample_env.get_main_password(),
dsn=sample_env.get_connect_string(),
)

with connection.cursor() as cursor:

cursor.execute(
"""
begin
begin
execute immediate 'drop table RTSampleTable';
exception
when others then
if sqlcode <> -942 then
raise;
end if;
end;

execute immediate 'create table RTSampleTable (
city varchar2(10))';

execute immediate
'insert into RTSampleTable values (''London'')';

commit;

end;
"""
)

cursor.execute(
"""
create or replace function TestFuncOUT return RTSampleTable%rowtype as
r RTSampleTable%rowtype;
begin
select * into r from RTSampleTable where rownum < 2 order by 1;
return r;
end;"""
)
if cursor.warning:
print(cursor.warning)

cursor.execute(
"""
create or replace procedure TestProcIN(
r in RTSampleTable%rowtype, city out varchar2) as
begin
city := r.city;
end;"""
)
if cursor.warning:
print(cursor.warning)

# Getting a %ROWTYPE from PL/SQL returns a python-oracledb DbObject record

rt = connection.gettype("RTSAMPLETABLE%ROWTYPE")
r = cursor.callfunc("TESTFUNCOUT", rt)
print("1. City is:", r.CITY)
# dump_object(r) # This is defined in object_dump.py

# An equivalent record can be directly constructed

obj = rt.newobject()
obj.CITY = "My Town"

# Passing a record to a %ROWTYPE parameter

c = cursor.var(oracledb.DB_TYPE_VARCHAR)
cursor.callproc("TESTPROCIN", [r, c])
print("2. City is:", c.getvalue())

cursor.callproc("TESTPROCIN", [obj, c])
print("3. City is:", c.getvalue())
4 changes: 1 addition & 3 deletions python/python-oracledb/sample_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,7 @@ def get_admin_connection():


def get_oracle_client():
if (
platform.system() == "Darwin" and platform.machine() == "x86_64"
) or platform.system() == "Windows":
if platform.system() == "Darwin" or platform.system() == "Windows":
return get_value(
"PYO_SAMPLES_ORACLE_CLIENT_PATH", "Oracle Instant Client Path"
)
Expand Down
4 changes: 2 additions & 2 deletions python/python-oracledb/soda_basic.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -----------------------------------------------------------------------------
# Copyright (c) 2018, 2023, Oracle and/or its affiliates.
# Copyright (c) 2018, 2024, 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
Expand Down Expand Up @@ -85,7 +85,7 @@

# Fetch the document back
doc = collection.find().key(key).getOne() # A SodaDocument
content = doc.getContent() # A JavaScript object
content = doc.getContent()
print("Retrieved SODA document dictionary is:")
print(content)
content = doc.getContentAsString() # A JSON string
Expand Down
117 changes: 117 additions & 0 deletions python/python-oracledb/soda_json_duality.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# -----------------------------------------------------------------------------
# Copyright (c) 2024, 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.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# soda_json_duality.py
#
# An example of accessing Oracle Database 23ai JSON-Relational views using
# Simple Oracle Document Access (SODA).
#
# Oracle Client must be at 23.4 or higher.
# Oracle Database must be at 23.4 or higher.
# The user must have been granted the SODA_APP privilege.
#
# Also see json_duality.py
# -----------------------------------------------------------------------------

import sys
import oracledb
import sample_env

# this script is currently only supported in python-oracledb thick mode
oracledb.init_oracle_client(lib_dir=sample_env.get_oracle_client())

# this script only works with Oracle Database & Client 23.4 or later
if sample_env.get_server_version() < (23, 4):
sys.exit("This example requires Oracle Database 23.4 or later.")
if oracledb.clientversion()[:2] < (23, 4):
sys.exit("This example requires Oracle Client 23.4 or later")

connection = oracledb.connect(
user=sample_env.get_main_user(),
password=sample_env.get_main_password(),
dsn=sample_env.get_connect_string(),
)

with connection.cursor() as cursor:

# Create a JSON-Relational Duality View over the SampleJRDVAuthorTab and
# SampleJRDVBookTab tables
sql = """
create or replace json relational duality view BookDV as
SampleJRDVBookTab @insert @update @delete
{
_id: BookId,
book_title: BookTitle,
author: SampleJRDVAuthorTab @insert @update
{
author_id: AuthorId,
author_name: AuthorName
}
}"""
cursor.execute(sql)

# Create the parent object for SODA
soda = connection.getSodaDatabase()

# The duality view can be opened as if it were a collection
collection = soda.openCollection("BOOKDV")

# Count all documents
c = collection.find().count()
print("Collection has", c, "documents")

# Perform a query-by-example on the duality view
print("Books starting with 'The':")
qbe = {"book_title": {"$like": "The%"}}
for doc in collection.find().filter(qbe).getDocuments():
content = doc.getContent()
print(content["book_title"])

# Insert a document
content = {
"_id": 201,
"book_title": "Rainbows and Unicorns",
"author": {"author_id": 401, "author_name": "Merlin"},
}
doc = collection.insertOneAndGet(content)
key = doc.key

# Fetch the document back and print the title
doc = collection.find().key(key).getOne()
content = doc.getContent()
print("Retrieved SODA document title is:")
print(content["book_title"])

# The new book can also be queried relationally from the base tables
print("Relational query:")
with connection.cursor() as cursor:
sql = """
select AuthorName, BookTitle
from SampleJRDVAuthorTab, SampleJRDVBookTab
where SampleJRDVAuthorTab.AuthorName = 'Merlin'
and SampleJRDVAuthorTab.AuthorId = SampleJRDVBookTab.AuthorId"""

for r in cursor.execute(sql):
print(r)
Loading