Added samples that were originally created for Open World 2016.

This commit is contained in:
Anthony Tuininga 2017-07-14 17:18:57 -06:00
parent 340dcb7195
commit 3243261f52
12 changed files with 520 additions and 0 deletions

View File

@ -0,0 +1,51 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# ArrayDMLRowCounts.py
#
# Demonstrate the use of the 12.1 feature that allows cursor.executemany()
# to return the number of rows affected by each individual execution as a list.
# The parameter "arraydmlrowcounts" must be set to True in the call to
# cursor.executemany() after which cursor.getarraydmlrowcounts() can be called.
#
# This script requires cx_Oracle 5.2 and higher.
#------------------------------------------------------------------------------
from __future__ import print_function
import cx_Oracle
import SampleEnv
connection = cx_Oracle.Connection(SampleEnv.MAIN_CONNECT_STRING)
cursor = connection.cursor()
# show the number of rows for each parent ID as a means of verifying the
# output from the delete statement
for parentId, count in cursor.execute("""
select ParentId, count(*)
from ChildTable
group by ParentId
order by ParentId"""):
print("Parent ID:", parentId, "has", int(count), "rows.")
print()
# delete the following parent IDs only
parentIdsToDelete = [2, 3, 5]
print("Deleting Parent IDs:", parentIdsToDelete)
print()
# enable array DML row counts for each iteration executed in executemany()
cursor.executemany("""
delete from ChildTable
where ParentId = :1""",
[(i,) for i in parentIdsToDelete],
arraydmlrowcounts = True)
# display the number of rows deleted for each parent ID
rowCounts = cursor.getarraydmlrowcounts()
for parentId, count in zip(parentIdsToDelete, rowCounts):
print("Parent ID:", parentId, "deleted", count, "rows.")

88
samples/BatchErrors.py Normal file
View File

@ -0,0 +1,88 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# BatchErrors.py
#
# Demonstrate the use of the Oracle Database 12.1 feature that allows
# cursor.executemany() to complete successfully, even if errors take
# place during the execution of one or more of the individual
# executions. The parameter "batcherrors" must be set to True in the
# call to cursor.executemany() after which cursor.getbatcherrors() can
# be called, which will return a list of error objects.
#
# This script requires cx_Oracle 5.2 and higher.
#------------------------------------------------------------------------------
from __future__ import print_function
import cx_Oracle
import SampleEnv
connection = cx_Oracle.connect(SampleEnv.MAIN_CONNECT_STRING)
cursor = connection.cursor()
# define data to insert
dataToInsert = [
(1016, 1, 'Child 2 of Parent 1'),
(1017, 1, 'Child 3 of Parent 1'),
(1018, 2, 'Child 4 of Parent 2'),
(1018, 2, 'Child 4 of Parent 2'), # duplicate key
(1019, 3, 'Child 3 of Parent 3'),
(1020, 3, 'Child 4 of Parent 4'),
(1021, 6, 'Child 1 of Parent 6'), # parent does not exist
(1022, 4, 'Child 6 of Parent 4'),
]
# retrieve the number of rows in the table
cursor.execute("""
select count(*)
from ChildTable""")
count, = cursor.fetchone()
print("number of rows in child table:", int(count))
print("number of rows to insert:", len(dataToInsert))
# old method: executemany() with data errors results in stoppage after the
# first error takes place; the row count is updated to show how many rows
# actually succeeded
try:
cursor.executemany("insert into ChildTable values (:1, :2, :3)",
dataToInsert)
except cx_Oracle.DatabaseError as e:
error, = e.args
print("FAILED with error:", error.message)
print("number of rows which succeeded:", cursor.rowcount)
# demonstrate that the row count is accurate
cursor.execute("""
select count(*)
from ChildTable""")
count, = cursor.fetchone()
print("number of rows in child table after failed insert:", int(count))
# roll back so we can perform the same work using the new method
connection.rollback()
# new method: executemany() with batch errors enabled (and array DML row counts
# also enabled) results in no immediate error being raised
cursor.executemany("insert into ChildTable values (:1, :2, :3)", dataToInsert,
batcherrors = True, arraydmlrowcounts = True)
# where errors have taken place, the row count is 0; otherwise it is 1
rowCounts = cursor.getarraydmlrowcounts()
print("Array DML row counts:", rowCounts)
# display the errors that have taken place
errors = cursor.getbatcherrors()
print("number of errors which took place:", len(errors))
for error in errors:
print("Error", error.message.rstrip(), "at row offset", error.offset)
# demonstrate that all of the rows without errors have been successfully
# inserted
cursor.execute("""
select count(*)
from ChildTable""")
count, = cursor.fetchone()
print("number of rows in child table after successful insert:", int(count))

36
samples/BindInsert.py Normal file
View File

@ -0,0 +1,36 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# BindInsert.py
#
# Demonstrate how to insert a row into a table using bind variables.
#------------------------------------------------------------------------------
from __future__ import print_function
import cx_Oracle
import SampleEnv
connection = cx_Oracle.connect(SampleEnv.MAIN_CONNECT_STRING)
rows = [ (1, "First" ),
(2, "Second" ),
(3, "Third" ),
(4, "Fourth" ),
(5, "Fifth" ),
(6, "Sixth" ),
(7, "Seventh" ) ]
cursor = connection.cursor()
cursor.executemany("insert into mytab(id, data) values (:1, :2)", rows)
# Don't commit - this lets us run the demo multiple times
#connection.commit()
# Now query the results back
for row in cursor.execute('select * from mytab'):
print(row)

34
samples/BindQuery.py Normal file
View File

@ -0,0 +1,34 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# BindQuery.py
#
# Demonstrate how to perform a simple query limiting the rows retrieved using
# a bind variable. Since the query that is executed is identical, no additional
# parsing is required, thereby reducing overhead and increasing performance. It
# also permits data to be bound without having to be concerned about escaping
# special characters or SQL injection attacks.
#------------------------------------------------------------------------------
from __future__ import print_function
import cx_Oracle
import SampleEnv
connection = cx_Oracle.connect(SampleEnv.MAIN_CONNECT_STRING)
cursor = connection.cursor()
sql = 'select * from SampleQueryTab where id = :bvid'
print("Query results with id = 4")
for row in cursor.execute(sql, bvid = 4):
print(row)
print()
print("Query results with id = 1")
for row in cursor.execute(sql, bvid = 1):
print(row)
print()

View File

@ -0,0 +1,49 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# GenericRowFactory.py
#
# Demonstrate the ability to return named tuples for all queries using a
# subclassed cursor and row factory.
#------------------------------------------------------------------------------
from __future__ import print_function
import collections
import cx_Oracle
import SampleEnv
class Connection(cx_Oracle.Connection):
def cursor(self):
return Cursor(self)
class Cursor(cx_Oracle.Cursor):
def execute(self, statement, args = None):
prepareNeeded = (self.statement != statement)
result = super(Cursor, self).execute(statement, args or [])
if prepareNeeded:
description = self.description
if description:
names = [d[0] for d in description]
self.rowfactory = collections.namedtuple("GenericQuery", names)
return result
# create new subclassed connection and cursor
connection = Connection(SampleEnv.MAIN_CONNECT_STRING)
cursor = connection.cursor()
# the names are now available directly for each query executed
for row in cursor.execute("select ParentId, Description from ParentTable"):
print(row.PARENTID, "->", row.DESCRIPTION)
print()
for row in cursor.execute("select ChildId, Description from ChildTable"):
print(row.CHILDID, "->", row.DESCRIPTION)
print()

View File

@ -0,0 +1,42 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# PLSQLCollection.py
#
# Demonstrate how to get the value of a PL/SQL collection from a stored
# procedure.
#
# This feature is new in cx_Oracle 5.3 and is only available in Oracle
# Database 12.1 and higher.
#------------------------------------------------------------------------------
from __future__ import print_function
import cx_Oracle
import SampleEnv
connection = cx_Oracle.connect(SampleEnv.MAIN_CONNECT_STRING)
# create new empty object of the correct type
# note the use of a PL/SQL type defined in a package
typeObj = connection.gettype("PKG_DEMO.UDT_STRINGLIST")
obj = typeObj.newobject()
# call the stored procedure which will populate the object
cursor = connection.cursor()
cursor.callproc("pkg_Demo.DemoCollectionOut", (obj,))
# show the indexes that are used by the collection
print("Indexes and values of collection:")
ix = obj.first()
while ix is not None:
print(ix, "->", obj.getelement(ix))
ix = obj.next(ix)
print()
# show the values as a simple list
print("Values of collection as list:")
print(obj.aslist())

21
samples/PLSQLFunction.py Normal file
View File

@ -0,0 +1,21 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# PLSQLFunction.py
#
# Demonstrate how to call a PL/SQL function and get its return value.
#------------------------------------------------------------------------------
from __future__ import print_function
import cx_Oracle
import SampleEnv
connection = cx_Oracle.connect(SampleEnv.MAIN_CONNECT_STRING)
cursor = connection.cursor()
res = cursor.callfunc('myfunc', int, ('abc', 2))
print(res)

23
samples/PLSQLProcedure.py Normal file
View File

@ -0,0 +1,23 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# PLSQLProcedure.py
#
# Demonstrate how to call a PL/SQL stored procedure and get the results of an
# OUT variable.
#------------------------------------------------------------------------------
from __future__ import print_function
import cx_Oracle
import SampleEnv
connection = cx_Oracle.connect(SampleEnv.MAIN_CONNECT_STRING)
cursor = connection.cursor()
myvar = cursor.var(int)
cursor.callproc('myproc', (123, myvar))
print(myvar.getvalue())

48
samples/PLSQLRecord.py Normal file
View File

@ -0,0 +1,48 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# PLSQLRecord.py
#
# Demonstrate how to bind (in and out) a PL/SQL record.
#
# This feature is new in cx_Oracle 5.3 and is only available in Oracle
# Database 12.1 and higher.
#------------------------------------------------------------------------------
from __future__ import print_function
import cx_Oracle
import SampleEnv
import datetime
connection = cx_Oracle.connect(SampleEnv.MAIN_CONNECT_STRING)
# create new object of the correct type
# note the use of a PL/SQL record defined in a package
typeObj = connection.gettype("PKG_DEMO.UDT_DEMORECORD")
obj = typeObj.newobject()
obj.NUMBERVALUE = 6
obj.STRINGVALUE = "Test String"
obj.DATEVALUE = datetime.datetime(2016, 5, 28)
obj.BOOLEANVALUE = False
# show the original values
print("NUMBERVALUE ->", obj.NUMBERVALUE)
print("STRINGVALUE ->", obj.STRINGVALUE)
print("DATEVALUE ->", obj.DATEVALUE)
print("BOOLEANVALUE ->", obj.BOOLEANVALUE)
print()
# call the stored procedure which will modify the object
cursor = connection.cursor()
cursor.callproc("pkg_Demo.DemoRecordsInOut", (obj,))
# show the modified values
print("NUMBERVALUE ->", obj.NUMBERVALUE)
print("STRINGVALUE ->", obj.STRINGVALUE)
print("DATEVALUE ->", obj.DATEVALUE)
print("BOOLEANVALUE ->", obj.BOOLEANVALUE)
print()

41
samples/Query.py Normal file
View File

@ -0,0 +1,41 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Query.py
#
# Demonstrate how to perform a query in different ways.
#------------------------------------------------------------------------------
from __future__ import print_function
import cx_Oracle
import SampleEnv
connection = cx_Oracle.connect(SampleEnv.MAIN_CONNECT_STRING)
sql = """
select * from SampleQueryTab
where id < 6
order by id"""
print("Get all rows via iterator")
cursor = connection.cursor()
for result in cursor.execute(sql):
print(result)
print()
print("Query one row at a time")
cursor.execute(sql)
row = cursor.fetchone()
print(row)
row = cursor.fetchone()
print(row)
print()
print("Fetch many rows")
cursor.execute(sql)
res = cursor.fetchmany(numRows=3)
print(res)

31
samples/QueryArraysize.py Normal file
View File

@ -0,0 +1,31 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# QueryArraysize.py
#
# Demonstrate how to alter the array size on a cursor in order to reduce the
# number of network round trips and overhead required to fetch all of the rows
# from a large table.
#------------------------------------------------------------------------------
from __future__ import print_function
import time
import cx_Oracle
import SampleEnv
connection = cx_Oracle.connect(SampleEnv.MAIN_CONNECT_STRING)
start = time.time()
cursor = connection.cursor()
cursor.arraysize = 1000
cursor.execute('select * from bigtab')
res = cursor.fetchall()
# print(res) # uncomment to display the query results
elapsed = (time.time() - start)
print("Retrieved", len(res), "rows in", elapsed, "seconds")

56
samples/Subclassing.py Normal file
View File

@ -0,0 +1,56 @@
#------------------------------------------------------------------------------
# Copyright 2016, 2017, Oracle and/or its affiliates. All rights reserved.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Subclassing.py
#
# Demonstrate how to subclass cx_Oracle connections and cursors in order to
# add additional functionality (like logging) or create specialized interfaces
# for paticular applications.
#------------------------------------------------------------------------------
from __future__ import print_function
import cx_Oracle
import SampleEnv
# sample subclassed connection which overrides the constructor (so no
# parameters are required) and the cursor() method (so that the subclassed
# cursor is returned instead of the default cursor implementation)
class Connection(cx_Oracle.Connection):
def __init__(self):
connectString = SampleEnv.MAIN_CONNECT_STRING
print("CONNECT to database")
return super(Connection, self).__init__(connectString)
def cursor(self):
return Cursor(self)
# sample subclassed cursor which overrides the execute() and fetchone()
# methods in order to perform some simple logging
class Cursor(cx_Oracle.Cursor):
def execute(self, statement, args):
print("EXECUTE", statement)
print("ARGS:")
for argIndex, arg in enumerate(args):
print(" ", argIndex + 1, "=>", repr(arg))
return super(Cursor, self).execute(statement, args)
def fetchone(self):
print("FETCH ONE")
return super(Cursor, self).fetchone()
# create instances of the subclassed connection and cursor
connection = Connection()
cursor = connection.cursor()
# demonstrate that the subclassed connection and cursor are being used
cursor.execute("select count(*) from ChildTable where ParentId = :1", (3,))
count, = cursor.fetchone()
print("COUNT:", int(count))