Skip to content

Commit dc4111c

Browse files
authored
Update python-oracledb examples (#451)
Signed-off-by: Christopher Jones <[email protected]>
1 parent 2b0ef07 commit dc4111c

30 files changed

+1000
-129
lines changed

python/python-oracledb/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ Oracle Database.
2929

3030
### Examples in a Container
3131

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

3536
### Notebooks
3637

python/python-oracledb/async_gather.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -----------------------------------------------------------------------------
2-
# Copyright (c) 2023, 2024, Oracle and/or its affiliates.
2+
# Copyright (c) 2023, 2025, Oracle and/or its affiliates.
33
#
44
# This software is dual-licensed to you under the Universal Permissive License
55
# (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
@@ -27,55 +27,67 @@
2727
#
2828
# Demonstrates using a connection pool with asyncio and gather().
2929
#
30-
# Multiple database sessions will be opened and used by each coroutine. The
31-
# number of connections opened can depend on the speed of your environment.
30+
# This also shows the use of pool_alias for connection pool caching, so the
31+
# pool handle does not need to passed through the app.
32+
#
33+
# Each coroutine invocation will acquire a connection from the connection pool.
34+
# The number of connections in the pool will depend on the speed of your
35+
# environment. In some cases existing connections will get reused. In other
36+
# cases up to CONCURRENCY connections will be created by the pool.
3237
# -----------------------------------------------------------------------------
3338

3439
import asyncio
3540

3641
import oracledb
3742
import sample_env
3843

44+
# Pool name for the connection pool cache
45+
POOL_ALIAS_NAME = "mypool"
46+
3947
# Number of coroutines to run
4048
CONCURRENCY = 5
4149

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

4755

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

5462

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

6373

6474
async def main():
65-
pool = oracledb.create_pool_async(
75+
oracledb.create_pool_async(
6676
user=sample_env.get_main_user(),
6777
password=sample_env.get_main_password(),
6878
dsn=sample_env.get_connect_string(),
6979
params=sample_env.get_pool_params(),
7080
min=1,
7181
max=CONCURRENCY,
7282
session_callback=init_session,
83+
pool_alias=POOL_ALIAS_NAME,
7384
)
7485

75-
coroutines = [query(pool) for i in range(CONCURRENCY)]
86+
coroutines = [query() for i in range(CONCURRENCY)]
7687

7788
await asyncio.gather(*coroutines)
7889

90+
pool = oracledb.get_pool(POOL_ALIAS_NAME)
7991
await pool.close()
8092

8193

python/python-oracledb/bind_insert.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
# Inserting a single bind still needs tuples
8787
# -----------------------------------------------------------------------------
8888

89-
rows = [("Eleventh",), ("Twelth",)]
89+
rows = [("Eleventh",), ("Twelfth",)]
9090

9191
with connection.cursor() as cursor:
9292
cursor.executemany("insert into mytab(id, data) values (12, :1)", rows)

python/python-oracledb/bind_insert_async.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ async def main():
9292
# Inserting a single bind still needs tuples
9393
# -------------------------------------------------------------------------
9494

95-
rows = [("Eleventh",), ("Twelth",)]
95+
rows = [("Eleventh",), ("Twelfth",)]
9696

9797
await connection.executemany(
9898
"insert into mytab(id, data) values (12, :1)", rows

python/python-oracledb/bulk_aq.py

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -----------------------------------------------------------------------------
2-
# Copyright (c) 2019, 2023, Oracle and/or its affiliates.
2+
# Copyright (c) 2019, 2025, Oracle and/or its affiliates.
33
#
44
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
55
#
@@ -53,8 +53,9 @@
5353
"The twelfth and final message",
5454
]
5555

56-
# this script is currently only supported in python-oracledb thick mode
57-
oracledb.init_oracle_client(lib_dir=sample_env.get_oracle_client())
56+
# determine whether to use python-oracledb thin mode or thick mode
57+
if not sample_env.get_is_thin():
58+
oracledb.init_oracle_client(lib_dir=sample_env.get_oracle_client())
5859

5960
# connect to database
6061
connection = oracledb.connect(
@@ -64,39 +65,36 @@
6465
)
6566

6667
# create a queue
67-
with connection.cursor() as cursor:
68-
queue = connection.queue(QUEUE_NAME)
69-
queue.deqoptions.wait = oracledb.DEQ_NO_WAIT
70-
queue.deqoptions.navigation = oracledb.DEQ_FIRST_MSG
68+
queue = connection.queue(QUEUE_NAME)
69+
queue.deqoptions.wait = oracledb.DEQ_NO_WAIT
70+
queue.deqoptions.navigation = oracledb.DEQ_FIRST_MSG
7171

72-
# dequeue all existing messages to ensure the queue is empty, just so that
73-
# the results are consistent
74-
while queue.deqone():
75-
pass
72+
# dequeue all existing messages to ensure the queue is empty, just so that
73+
# the results are consistent
74+
while queue.deqone():
75+
pass
7676

7777
# enqueue a few messages
78-
with connection.cursor() as cursor:
79-
print("Enqueuing messages...")
80-
batch_size = 6
81-
data_to_enqueue = PAYLOAD_DATA
82-
while data_to_enqueue:
83-
batch_data = data_to_enqueue[:batch_size]
84-
data_to_enqueue = data_to_enqueue[batch_size:]
85-
messages = [connection.msgproperties(payload=d) for d in batch_data]
86-
for data in batch_data:
87-
print(data)
88-
queue.enqmany(messages)
89-
connection.commit()
78+
print("Enqueuing messages...")
79+
batch_size = 6
80+
data_to_enqueue = PAYLOAD_DATA
81+
while data_to_enqueue:
82+
batch_data = data_to_enqueue[:batch_size]
83+
data_to_enqueue = data_to_enqueue[batch_size:]
84+
messages = [connection.msgproperties(payload=d) for d in batch_data]
85+
for data in batch_data:
86+
print(data)
87+
queue.enqmany(messages)
88+
connection.commit()
9089

9190
# dequeue the messages
92-
with connection.cursor() as cursor:
93-
print("\nDequeuing messages...")
94-
batch_size = 8
95-
while True:
96-
messages = queue.deqmany(batch_size)
97-
if not messages:
98-
break
99-
for props in messages:
100-
print(props.payload.decode())
101-
connection.commit()
102-
print("\nDone.")
91+
print("\nDequeuing messages...")
92+
batch_size = 8
93+
while True:
94+
messages = queue.deqmany(batch_size)
95+
if not messages:
96+
break
97+
for props in messages:
98+
print(props.payload.decode())
99+
connection.commit()
100+
print("\nDone.")
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# -----------------------------------------------------------------------------
2+
# Copyright (c) 2025, Oracle and/or its affiliates.
3+
#
4+
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
5+
#
6+
# Portions Copyright 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta,
7+
# Canada. All rights reserved.
8+
#
9+
# This software is dual-licensed to you under the Universal Permissive License
10+
# (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
11+
# 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
12+
# either license.
13+
#
14+
# If you elect to accept the software under the Apache License, Version 2.0,
15+
# the following applies:
16+
#
17+
# Licensed under the Apache License, Version 2.0 (the "License");
18+
# you may not use this file except in compliance with the License.
19+
# You may obtain a copy of the License at
20+
#
21+
# https://www.apache.org/licenses/LICENSE-2.0
22+
#
23+
# Unless required by applicable law or agreed to in writing, software
24+
# distributed under the License is distributed on an "AS IS" BASIS,
25+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26+
# See the License for the specific language governing permissions and
27+
# limitations under the License.
28+
# -----------------------------------------------------------------------------
29+
30+
# -----------------------------------------------------------------------------
31+
# bulk_aq_async.py
32+
#
33+
# Demonstrates how to use bulk enqueuing and dequeuing of messages with
34+
# advanced queuing using asyncio. It makes use of a RAW queue created in the
35+
# sample setup.
36+
# -----------------------------------------------------------------------------
37+
38+
import asyncio
39+
40+
import oracledb
41+
import sample_env
42+
43+
QUEUE_NAME = "DEMO_RAW_QUEUE"
44+
PAYLOAD_DATA = [
45+
"The first message",
46+
"The second message",
47+
"The third message",
48+
"The fourth message",
49+
"The fifth message",
50+
"The sixth message",
51+
"The seventh message",
52+
"The eighth message",
53+
"The ninth message",
54+
"The tenth message",
55+
"The eleventh message",
56+
"The twelfth and final message",
57+
]
58+
59+
60+
async def main():
61+
62+
# connect to database
63+
async with oracledb.connect_async(
64+
user=sample_env.get_main_user(),
65+
password=sample_env.get_main_password(),
66+
dsn=sample_env.get_connect_string(),
67+
) as connection:
68+
69+
# create a queue
70+
queue = connection.queue(QUEUE_NAME)
71+
queue.deqoptions.wait = oracledb.DEQ_NO_WAIT
72+
queue.deqoptions.navigation = oracledb.DEQ_FIRST_MSG
73+
74+
# dequeue all existing messages to ensure the queue is empty, just so
75+
# that the results are consistent
76+
while await queue.deqone():
77+
pass
78+
79+
# enqueue a few messages
80+
print("Enqueuing messages...")
81+
batch_size = 6
82+
data_to_enqueue = PAYLOAD_DATA
83+
while data_to_enqueue:
84+
batch_data = data_to_enqueue[:batch_size]
85+
data_to_enqueue = data_to_enqueue[batch_size:]
86+
messages = [
87+
connection.msgproperties(payload=d) for d in batch_data
88+
]
89+
for data in batch_data:
90+
print(data)
91+
await queue.enqmany(messages)
92+
await connection.commit()
93+
94+
# dequeue the messages
95+
print("\nDequeuing messages...")
96+
batch_size = 8
97+
while True:
98+
messages = await queue.deqmany(batch_size)
99+
if not messages:
100+
break
101+
for props in messages:
102+
print(props.payload.decode())
103+
await connection.commit()
104+
print("\nDone.")
105+
106+
107+
asyncio.run(main())

0 commit comments

Comments
 (0)