Skip to content

Update examples for python-oracledb 3.3 #451

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

Merged
merged 1 commit into from
Aug 5, 2025
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
5 changes: 3 additions & 2 deletions python/python-oracledb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ Oracle Database.

### Examples in a Container

The [sample_container](./sample_container) directory has a Dockerfile that will
build a container with the samples and a running Oracle Database.
The [containers/samples_and_db](./containers/samples_and_db) directory has a
Dockerfile for building a container with the samples and a running Oracle
Database.

### Notebooks

Expand Down
36 changes: 24 additions & 12 deletions python/python-oracledb/async_gather.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -----------------------------------------------------------------------------
# Copyright (c) 2023, 2024, Oracle and/or its affiliates.
# Copyright (c) 2023, 2025, 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 @@ -27,55 +27,67 @@
#
# Demonstrates using a connection pool with asyncio and gather().
#
# Multiple database sessions will be opened and used by each coroutine. The
# number of connections opened can depend on the speed of your environment.
# This also shows the use of pool_alias for connection pool caching, so the
# pool handle does not need to passed through the app.
#
# Each coroutine invocation will acquire a connection from the connection pool.
# The number of connections in the pool will depend on the speed of your
# environment. In some cases existing connections will get reused. In other
# cases up to CONCURRENCY connections will be created by the pool.
# -----------------------------------------------------------------------------

import asyncio

import oracledb
import sample_env

# Pool name for the connection pool cache
POOL_ALIAS_NAME = "mypool"

# Number of coroutines to run
CONCURRENCY = 5

# Query the unique session identifier/serial number combination of a connection
SQL = """SELECT UNIQUE CURRENT_TIMESTAMP AS CT, sid||'-'||serial# AS SIDSER
FROM v$session_connect_info
WHERE sid = SYS_CONTEXT('USERENV', 'SID')"""
SQL = """select unique current_timestamp as ct, sid||'-'||serial# as sidser
from v$session_connect_info
where sid = sys_context('userenv', 'sid')"""


# Show the unique session identifier/serial number of each connection that the
# pool opens
# pool creates
async def init_session(connection, requested_tag):
res = await connection.fetchone(SQL)
print(res[0].strftime("%H:%M:%S.%f"), "- init_session SID-SERIAL#", res[1])


# The coroutine simply shows the session identifier/serial number of the
# connection returned by the pool.acquire() call
async def query(pool):
async with pool.acquire() as connection:
# connection returned from the pool
async def query():
async with oracledb.connect_async(
pool_alias=POOL_ALIAS_NAME
) as connection:
await connection.callproc("dbms_session.sleep", [1])
res = await connection.fetchone(SQL)
print(res[0].strftime("%H:%M:%S.%f"), "- query SID-SERIAL#", res[1])


async def main():
pool = oracledb.create_pool_async(
oracledb.create_pool_async(
user=sample_env.get_main_user(),
password=sample_env.get_main_password(),
dsn=sample_env.get_connect_string(),
params=sample_env.get_pool_params(),
min=1,
max=CONCURRENCY,
session_callback=init_session,
pool_alias=POOL_ALIAS_NAME,
)

coroutines = [query(pool) for i in range(CONCURRENCY)]
coroutines = [query() for i in range(CONCURRENCY)]

await asyncio.gather(*coroutines)

pool = oracledb.get_pool(POOL_ALIAS_NAME)
await pool.close()


Expand Down
2 changes: 1 addition & 1 deletion python/python-oracledb/bind_insert.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
# Inserting a single bind still needs tuples
# -----------------------------------------------------------------------------

rows = [("Eleventh",), ("Twelth",)]
rows = [("Eleventh",), ("Twelfth",)]

with connection.cursor() as cursor:
cursor.executemany("insert into mytab(id, data) values (12, :1)", rows)
Expand Down
2 changes: 1 addition & 1 deletion python/python-oracledb/bind_insert_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ async def main():
# Inserting a single bind still needs tuples
# -------------------------------------------------------------------------

rows = [("Eleventh",), ("Twelth",)]
rows = [("Eleventh",), ("Twelfth",)]

await connection.executemany(
"insert into mytab(id, data) values (12, :1)", rows
Expand Down
66 changes: 32 additions & 34 deletions python/python-oracledb/bulk_aq.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -----------------------------------------------------------------------------
# Copyright (c) 2019, 2023, Oracle and/or its affiliates.
# Copyright (c) 2019, 2025, Oracle and/or its affiliates.
#
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
#
Expand Down Expand Up @@ -53,8 +53,9 @@
"The twelfth and final message",
]

# this script is currently only supported in python-oracledb thick mode
oracledb.init_oracle_client(lib_dir=sample_env.get_oracle_client())
# 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())

# connect to database
connection = oracledb.connect(
Expand All @@ -64,39 +65,36 @@
)

# create a queue
with connection.cursor() as cursor:
queue = connection.queue(QUEUE_NAME)
queue.deqoptions.wait = oracledb.DEQ_NO_WAIT
queue.deqoptions.navigation = oracledb.DEQ_FIRST_MSG
queue = connection.queue(QUEUE_NAME)
queue.deqoptions.wait = oracledb.DEQ_NO_WAIT
queue.deqoptions.navigation = oracledb.DEQ_FIRST_MSG

# dequeue all existing messages to ensure the queue is empty, just so that
# the results are consistent
while queue.deqone():
pass
# dequeue all existing messages to ensure the queue is empty, just so that
# the results are consistent
while queue.deqone():
pass

# enqueue a few messages
with connection.cursor() as cursor:
print("Enqueuing messages...")
batch_size = 6
data_to_enqueue = PAYLOAD_DATA
while data_to_enqueue:
batch_data = data_to_enqueue[:batch_size]
data_to_enqueue = data_to_enqueue[batch_size:]
messages = [connection.msgproperties(payload=d) for d in batch_data]
for data in batch_data:
print(data)
queue.enqmany(messages)
connection.commit()
print("Enqueuing messages...")
batch_size = 6
data_to_enqueue = PAYLOAD_DATA
while data_to_enqueue:
batch_data = data_to_enqueue[:batch_size]
data_to_enqueue = data_to_enqueue[batch_size:]
messages = [connection.msgproperties(payload=d) for d in batch_data]
for data in batch_data:
print(data)
queue.enqmany(messages)
connection.commit()

# dequeue the messages
with connection.cursor() as cursor:
print("\nDequeuing messages...")
batch_size = 8
while True:
messages = queue.deqmany(batch_size)
if not messages:
break
for props in messages:
print(props.payload.decode())
connection.commit()
print("\nDone.")
print("\nDequeuing messages...")
batch_size = 8
while True:
messages = queue.deqmany(batch_size)
if not messages:
break
for props in messages:
print(props.payload.decode())
connection.commit()
print("\nDone.")
107 changes: 107 additions & 0 deletions python/python-oracledb/bulk_aq_async.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# -----------------------------------------------------------------------------
# Copyright (c) 2025, Oracle and/or its affiliates.
#
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
#
# Portions Copyright 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta,
# Canada. All rights reserved.
#
# 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.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# bulk_aq_async.py
#
# Demonstrates how to use bulk enqueuing and dequeuing of messages with
# advanced queuing using asyncio. It makes use of a RAW queue created in the
# sample setup.
# -----------------------------------------------------------------------------

import asyncio

import oracledb
import sample_env

QUEUE_NAME = "DEMO_RAW_QUEUE"
PAYLOAD_DATA = [
"The first message",
"The second message",
"The third message",
"The fourth message",
"The fifth message",
"The sixth message",
"The seventh message",
"The eighth message",
"The ninth message",
"The tenth message",
"The eleventh message",
"The twelfth and final message",
]


async def main():

# connect to database
async with oracledb.connect_async(
user=sample_env.get_main_user(),
password=sample_env.get_main_password(),
dsn=sample_env.get_connect_string(),
) as connection:

# create a queue
queue = connection.queue(QUEUE_NAME)
queue.deqoptions.wait = oracledb.DEQ_NO_WAIT
queue.deqoptions.navigation = oracledb.DEQ_FIRST_MSG

# dequeue all existing messages to ensure the queue is empty, just so
# that the results are consistent
while await queue.deqone():
pass

# enqueue a few messages
print("Enqueuing messages...")
batch_size = 6
data_to_enqueue = PAYLOAD_DATA
while data_to_enqueue:
batch_data = data_to_enqueue[:batch_size]
data_to_enqueue = data_to_enqueue[batch_size:]
messages = [
connection.msgproperties(payload=d) for d in batch_data
]
for data in batch_data:
print(data)
await queue.enqmany(messages)
await connection.commit()

# dequeue the messages
print("\nDequeuing messages...")
batch_size = 8
while True:
messages = await queue.deqmany(batch_size)
if not messages:
break
for props in messages:
print(props.payload.decode())
await connection.commit()
print("\nDone.")


asyncio.run(main())
Loading