From 3c4d83fe6c438e646e373cdf5991d9eac2257fdf Mon Sep 17 00:00:00 2001 From: Anthony Tuininga Date: Wed, 19 Jun 2019 16:02:55 -0600 Subject: [PATCH] Adjusted tutorial to use new AQ syntax. --- ...cle-Database-Scripting-for-the-Future.html | 96 ++++++++++++------- samples/tutorial/aq.py | 56 ++++++----- samples/tutorial/solutions/aq-dequeue.py | 22 +++-- samples/tutorial/solutions/aq-enqueue.py | 33 ++++--- samples/tutorial/solutions/aq-queuestart.py | 6 +- 5 files changed, 130 insertions(+), 83 deletions(-) diff --git a/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html b/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html index bb66c3a..31ea9b1 100644 --- a/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html +++ b/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html @@ -104,7 +104,7 @@
  1. Python (3.6 preferred but 2.7 should work)
  2. -
  3. cx_Oracle (version 7 preferred but 6.3 or later should work) and Oracle Instant Client Package - Basic (version 18.3 preferred but 12.2 should work) +
  4. cx_Oracle (version 7.2 preferred but 6.3 or later should work, except for the section on Advanced Queuing which requires version 7.2 or later) and Oracle Instant Client Package - Basic (version 19.3 preferred but 18.3 or 12.2 should also work)
    • Linux
    • macOS - please note the special instructions for macOS in the link.
    • @@ -1976,7 +1976,7 @@ cur.execute( end if; end;""") -# Create type +# Create a type print("Creating books type UDT_BOOK...") cur.execute(""" create type %s as object ( @@ -1988,38 +1988,47 @@ cur.execute(""" # Create queue table and queue and start the queue print("Creating queue table...") cur.callproc("dbms_aqadm.create_queue_table", - (QUEUE_TABLE_NAME, BOOK_TYPE_NAME)) + (QUEUE_TABLE_NAME, BOOK_TYPE_NAME)) cur.callproc("dbms_aqadm.create_queue", (QUEUE_NAME, QUEUE_TABLE_NAME)) cur.callproc("dbms_aqadm.start_queue", (QUEUE_NAME,)) -# Enqueue a few messages booksType = con.gettype(BOOK_TYPE_NAME) -book1 = booksType.newobject() -book1.TITLE = "The Fellowship of the Ring" -book1.AUTHORS = "Tolkien, J.R.R." -book1.PRICE = decimal.Decimal("10.99") -book2 = booksType.newobject() -book2.TITLE = "Harry Potter and the Philosopher's Stone" -book2.AUTHORS = "Rowling, J.K." -book2.PRICE = decimal.Decimal("7.99") -options = con.enqoptions() -messageProperties = con.msgproperties() -for book in (book1, book2): - print("Enqueuing book", book.TITLE) - con.enq(QUEUE_NAME, options, messageProperties, book) -con.commit() +queue = con.queue(QUEUE_NAME, booksType) + +# Enqueue a few messages +print("Enqueuing messages...") + +BOOK_DATA = [ + ("The Fellowship of the Ring", "Tolkien, J.R.R.", decimal.Decimal("10.99")), + ("Harry Potter and the Philosopher's Stone", "Rowling, J.K.", + decimal.Decimal("7.99")) +] + +for title, authors, price in BOOK_DATA: + book = booksType.newobject() + book.TITLE = title + book.AUTHORS = authors + book.PRICE = price + print(title) + queue.enqOne(con.msgproperties(payload=book)) + con.commit() # Dequeue the messages -options = con.deqoptions() -options.navigation = cx_Oracle.DEQ_FIRST_MSG -options.wait = cx_Oracle.DEQ_NO_WAIT -while con.deq(QUEUE_NAME, options, messageProperties, book): - print("Dequeued book", book.TITLE) -con.commit() +print("\nDequeuing messages...") +queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT +while True: + props = queue.deqOne() + if not props: + break + print(props.payload.TITLE) + con.commit() + +print("\nDone.")

      This file sets up Advanced Queuing using Oracle's DBMS_AQADM -package. The queue is used for passing Oracle UDT_BOOK objects.

      +package. The queue is used for passing Oracle UDT_BOOK objects. The +file uses AQ interface features enhanced in cx_Oracle 7.2.

      Run the file:

      @@ -2030,14 +2039,37 @@ package. The queue is used for passing Oracle UDT_BOOK objects.

      To experiment, split the code into three files: one to create and start the queue, and two other files to queue and dequeue messages. Experiment running the queue and dequeue files concurrently in -separate terminal windows. If you are stuck, look in the -solutions directory at the aq-dequeue.py, -aq-enqueue.py and aq-queuestart.py -files.

      +separate terminal windows.

      + +

      Try removing the commit() call in +aq-dequeue.py. Now run aq-enqueue.py once +and then aq-dequeue.py several times. The same messages +will be available each time you try to dequeue them.

      + +

      Change aq-dequeue.py to commit in a separate +transaction by changing the "visibility" setting:

      + +
      +queue.deqOptions.visibility = cx_Oracle.DEQ_IMMEDIATE
      +
      + +

      This gives the same behavior as the original code.

      + +

      Now change the options of enqueued messages so that they expire from the +queue if they have not been dequeued after four seconds:

      + +
      +queue.enqOne(con.msgproperties(payload=book, expiration=4))
      +
      + +

      Now run aq-enqueue.py and wait four seconds before you +run aq-dequeue.py. There should be no messages to +dequeue.

      + +

      If you are stuck, look in the solutions directory at +the aq-dequeue.py, aq-enqueue.py and +aq-queuestart.py files.

      -

      Try changing the dequeue options and mode. For example change the -dequeue options.wait value to -cx_Oracle.DEQ_WAIT_FOREVER.

  5. diff --git a/samples/tutorial/aq.py b/samples/tutorial/aq.py index 1e795bb..a345135 100644 --- a/samples/tutorial/aq.py +++ b/samples/tutorial/aq.py @@ -3,7 +3,7 @@ #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. #------------------------------------------------------------------------------ from __future__ import print_function @@ -32,7 +32,7 @@ cur.execute( end if; end;""") -# Create type +# Create a type print("Creating books type UDT_BOOK...") cur.execute(""" create type %s as object ( @@ -44,31 +44,39 @@ cur.execute(""" # Create queue table and queue and start the queue print("Creating queue table...") cur.callproc("dbms_aqadm.create_queue_table", - (QUEUE_TABLE_NAME, BOOK_TYPE_NAME)) + (QUEUE_TABLE_NAME, BOOK_TYPE_NAME)) cur.callproc("dbms_aqadm.create_queue", (QUEUE_NAME, QUEUE_TABLE_NAME)) cur.callproc("dbms_aqadm.start_queue", (QUEUE_NAME,)) -# Enqueue a few messages booksType = con.gettype(BOOK_TYPE_NAME) -book1 = booksType.newobject() -book1.TITLE = "The Fellowship of the Ring" -book1.AUTHORS = "Tolkien, J.R.R." -book1.PRICE = decimal.Decimal("10.99") -book2 = booksType.newobject() -book2.TITLE = "Harry Potter and the Philosopher's Stone" -book2.AUTHORS = "Rowling, J.K." -book2.PRICE = decimal.Decimal("7.99") -options = con.enqoptions() -messageProperties = con.msgproperties() -for book in (book1, book2): - print("Enqueuing book", book.TITLE) - con.enq(QUEUE_NAME, options, messageProperties, book) -con.commit() +queue = con.queue(QUEUE_NAME, booksType) + +# Enqueue a few messages +print("Enqueuing messages...") + +BOOK_DATA = [ + ("The Fellowship of the Ring", "Tolkien, J.R.R.", decimal.Decimal("10.99")), + ("Harry Potter and the Philosopher's Stone", "Rowling, J.K.", + decimal.Decimal("7.99")) +] + +for title, authors, price in BOOK_DATA: + book = booksType.newobject() + book.TITLE = title + book.AUTHORS = authors + book.PRICE = price + print(title) + queue.enqOne(con.msgproperties(payload=book)) + con.commit() # Dequeue the messages -options = con.deqoptions() -options.navigation = cx_Oracle.DEQ_FIRST_MSG -options.wait = cx_Oracle.DEQ_NO_WAIT -while con.deq(QUEUE_NAME, options, messageProperties, book): - print("Dequeued book", book.TITLE) -con.commit() +print("\nDequeuing messages...") +queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT +while True: + props = queue.deqOne() + if not props: + break + print(props.payload.TITLE) + con.commit() + +print("\nDone.") diff --git a/samples/tutorial/solutions/aq-dequeue.py b/samples/tutorial/solutions/aq-dequeue.py index 9178bd4..706f69e 100644 --- a/samples/tutorial/solutions/aq-dequeue.py +++ b/samples/tutorial/solutions/aq-dequeue.py @@ -3,7 +3,7 @@ #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. #------------------------------------------------------------------------------ from __future__ import print_function @@ -20,12 +20,16 @@ QUEUE_NAME = "BOOKS" QUEUE_TABLE_NAME = "BOOK_QUEUE_TABLE" # Dequeue the messages -options = con.deqoptions() -options.navigation = cx_Oracle.DEQ_FIRST_MSG -options.wait = cx_Oracle.DEQ_NO_WAIT -messageProperties = con.msgproperties() booksType = con.gettype(BOOK_TYPE_NAME) -book = booksType.newobject() -while con.deq(QUEUE_NAME, options, messageProperties, book): - print("Dequeued book", book.TITLE) -con.commit() +queue = con.queue(QUEUE_NAME, booksType) +queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT +queue.deqOptions.visibility = cx_Oracle.DEQ_IMMEDIATE + +print("\nDequeuing messages...") +while True: + props = queue.deqOne() + if not props: + break + print(props.payload.TITLE) + +print("\nDone.") diff --git a/samples/tutorial/solutions/aq-enqueue.py b/samples/tutorial/solutions/aq-enqueue.py index baf15ad..89055bd 100644 --- a/samples/tutorial/solutions/aq-enqueue.py +++ b/samples/tutorial/solutions/aq-enqueue.py @@ -3,7 +3,7 @@ #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. #------------------------------------------------------------------------------ from __future__ import print_function @@ -20,18 +20,21 @@ QUEUE_NAME = "BOOKS" QUEUE_TABLE_NAME = "BOOK_QUEUE_TABLE" # Enqueue a few messages +print("Enqueuing messages...") + +BOOK_DATA = [ + ("The Fellowship of the Ring", "Tolkien, J.R.R.", decimal.Decimal("10.99")), + ("Harry Potter and the Philosopher's Stone", "Rowling, J.K.", decimal.Decimal("7.99")) +] + booksType = con.gettype(BOOK_TYPE_NAME) -book1 = booksType.newobject() -book1.TITLE = "The Fellowship of the Ring" -book1.AUTHORS = "Tolkien, J.R.R." -book1.PRICE = decimal.Decimal("10.99") -book2 = booksType.newobject() -book2.TITLE = "Harry Potter and the Philosopher's Stone" -book2.AUTHORS = "Rowling, J.K." -book2.PRICE = decimal.Decimal("7.99") -options = con.enqoptions() -messageProperties = con.msgproperties() -for book in (book1, book2): - print("Enqueuing book", book.TITLE) - con.enq(QUEUE_NAME, options, messageProperties, book) -con.commit() +queue = con.queue(QUEUE_NAME, booksType) + +for title, authors, price in BOOK_DATA: + book = booksType.newobject() + book.TITLE = title + book.AUTHORS = authors + book.PRICE = price + print(title) + queue.enqOne(con.msgproperties(payload=book, expiration=4)) + con.commit() diff --git a/samples/tutorial/solutions/aq-queuestart.py b/samples/tutorial/solutions/aq-queuestart.py index ceee45a..929c1f3 100644 --- a/samples/tutorial/solutions/aq-queuestart.py +++ b/samples/tutorial/solutions/aq-queuestart.py @@ -3,7 +3,7 @@ #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. #------------------------------------------------------------------------------ from __future__ import print_function @@ -32,7 +32,7 @@ cur.execute( end if; end;""") -# Create type +# Create a type print("Creating books type UDT_BOOK...") cur.execute(""" create type %s as object ( @@ -44,6 +44,6 @@ cur.execute(""" # Create queue table and queue and start the queue print("Creating queue table...") cur.callproc("dbms_aqadm.create_queue_table", - (QUEUE_TABLE_NAME, BOOK_TYPE_NAME)) + (QUEUE_TABLE_NAME, BOOK_TYPE_NAME)) cur.callproc("dbms_aqadm.create_queue", (QUEUE_NAME, QUEUE_TABLE_NAME)) cur.callproc("dbms_aqadm.start_queue", (QUEUE_NAME,))