Skip to content

Commit 6a5bf79

Browse files
Add SODA to tutorial; tweak defaults used in samples.
1 parent 2a34daf commit 6a5bf79

File tree

7 files changed

+230
-20
lines changed

7 files changed

+230
-20
lines changed

samples/SampleEnv.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
# [//]host_name[:port][/service_name][:server_type][/instance_name]
3030
#
3131
# Commonly just the host_name and service_name are needed
32-
# e.g. "localhost/orclpdb" or "localhost/XE"
32+
# e.g. "localhost/orclpdb1" or "localhost/XE"
3333
#
3434
# If using a tnsnames.ora file, the file can be in a default
3535
# location such as $ORACLE_HOME/network/admin/tnsnames.ora or
@@ -53,7 +53,7 @@
5353
DEFAULT_MAIN_USER = "pythondemo"
5454
DEFAULT_EDITION_USER = "pythoneditions"
5555
DEFAULT_EDITION_NAME = "python_e1"
56-
DEFAULT_CONNECT_STRING = "localhost/orclpdb"
56+
DEFAULT_CONNECT_STRING = "localhost/orclpdb1"
5757

5858
# dictionary containing all parameters; these are acquired as needed by the
5959
# methods below (which should be used instead of consulting this dictionary

samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html

Lines changed: 136 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ <h2>Contents</h2>
9292
<li>10.1 Message passing with Oracle Advanced Queuing</li>
9393
</ul>
9494
</li>
95+
<li><a href="#soda" >11. Simple Oracle Document Access (SODA)</a>
96+
<ul>
97+
<li>11.1 Inserting JSON Documents</li>
98+
<li>11.2 Searching SODA Documents</li>
99+
</ul>
100+
</li>
95101
</ul>
96102
<li><a href="#summary" >Summary</a></li>
97103
<li><a href="#primer" >Appendix: Python Primer</a></li>
@@ -100,24 +106,27 @@ <h2>Contents</h2>
100106

101107
<h2><a name="preface">Preface</a></h2>
102108

103-
<p>If you are running this tutorial in your own environment, install the following required software:</p>
109+
<p>If you are running this tutorial in your own environment, install the required software:</p>
104110

105111
<ol>
106-
<li><a target="_blank" href="https://www.python.org/">Python</a> (3.6 preferred but 2.7 should work)</li>
107-
<li>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)
112+
<li><p><a target="_blank" href="https://www.python.org/">Python</a>. Version 3.6 is preferred.</p></li>
113+
<li><p>cx_Oracle version 7.2 and the Oracle Client libraries.</p>
108114
<ul>
109115
<li><a target="_blank" href="http://cx-oracle.readthedocs.io/en/latest/installation.html#installing-cx-oracle-on-linux">Linux</a></li>
110116
<li><a target="_blank" href="http://cx-oracle.readthedocs.io/en/latest/installation.html#installing-cx-oracle-on-macos">macOS</a> - please note the special instructions for macOS in the link.</li>
111117
<li><a target="_blank" href="http://cx-oracle.readthedocs.io/en/latest/installation.html#installing-cx-oracle-on-windows">Windows</a></li>
112118
</ul>
113119
</li>
114-
<li>Oracle <a target="_blank" href="http://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html">Instant Client Package - SQL*Plus</a>.</li>
120+
121+
<li><p>SQL*Plus such as from the Oracle <a target="_blank" href="http://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html">Instant Client SQL*Plus Package</a>.</p></li>
115122
</ol>
116123

124+
<p>The Advanced Queuing section requires Oracle client 12.2 or later. The SODA section requires Oracle client 18.5, or later, and Oracle Database 18 or later.</p>
125+
117126
<p>To create the schema run:</p>
118127

119128
<pre>
120-
sqlplus sys/yoursyspassword@localhost/orclpdb as sysdba @sql/SetupSamples
129+
sqlplus sys/yoursyspassword@localhost/orclpdb1 as sysdba @sql/SetupSamples
121130
</pre>
122131

123132
<h2><a name="connectioninformation">Connection Information</a></h2>
@@ -130,11 +139,11 @@ <h2><a name="connectioninformation">Connection Information</a></h2>
130139
</p>
131140

132141
<p>The username is "pythonhol" with
133-
the password "welcome". The connect string is "localhost/orclpdb".
142+
the password "welcome". The connect string is "localhost/orclpdb1".
134143
See <code>sql/SampleEnv.sql</code>.</p>
135144

136145
<p>It is easist to have a local pluggable database with the service
137-
'orclpdb' configured. If your database is not local, or has a
146+
'orclpdb1' configured. If your database is not local, or has a
138147
different service, you will need to modify the connection information in db_config.py and db_config.sql.</p>
139148

140149
<p>The following sections may need adjusting, depending on how you
@@ -174,16 +183,16 @@ <h4>1.1 Review the connection credentials</h4>
174183
<pre>
175184
user = "pythonhol"
176185
pw = "welcome"
177-
dsn = "localhost/orclpdb"
186+
dsn = "localhost/orclpdb1"
178187
</pre>
179188
<code>db_config.sql</code>
180189
<pre>
181190
def user = "pythonhol"
182191
def pw = "welcome"
183-
def connect_string = "localhost/orclpdb"
192+
def connect_string = "localhost/orclpdb1"
184193
</pre>
185194

186-
<p>By default they connect to the 'orclpdb' database service on the same machine as Python. You can modify the values in both files to match the connection information for your environment.</p>
195+
<p>By default they connect to the 'orclpdb1' database service on the same machine as Python. You can modify the values in both files to match the connection information for your environment.</p>
187196

188197
</li>
189198

@@ -207,7 +216,7 @@ <h4>1.2 Creating a basic connection</h4>
207216
the db_config.py module. In this case, Oracle's Easy Connect connection
208217
string syntax is used. It consists of the hostname of your
209218
machine, <code>localhost</code>, and the database service name
210-
<code>orclpdb</code>. </p>
219+
<code>orclpdb1</code>. </p>
211220

212221
<p>Open a command terminal and change to the <code>tutorial</code> directory:</p>
213222

@@ -1128,7 +1137,7 @@ <h4>2.5 More DRCP investigation</h4>
11281137
<p>In a terminal window, start SQL*Plus using the lab credentials and connection string, such as:</p>
11291138

11301139
<pre>
1131-
sqlplus pythonhol/welcome@localhost/orclpdb
1140+
sqlplus pythonhol/welcome@localhost/orclpdb1
11321141
</pre>
11331142

11341143
<p>Use the SQL*Plus DESCRIBE command to look at the SDO definition:</p>
@@ -1661,6 +1670,9 @@ <h4>6.1 Basic output type handler</h4>
16611670

16621671
<li><h3><a name="lobs">7. LOBs</a></h3>
16631672

1673+
<p>Oracle Database "LOB" long objects can be streamed using a LOB
1674+
locator, or worked with directly as strings or bytes.</p>
1675+
16641676
<ul>
16651677
<li>
16661678
<h4>7.1 Fetching a CLOB using a locator</h4>
@@ -1694,8 +1706,8 @@ <h4>7.1 Fetching a CLOB using a locator</h4>
16941706
</pre>
16951707

16961708
<p>This inserts some test string data and then fetches one
1697-
record into <code>clob</code>, which is a cx_Oracle LOB Object.
1698-
Methods on LOB include <code>size()</code> and
1709+
record into <code>clob</code>, which is a cx_Oracle character
1710+
LOB Object. Methods on LOB include <code>size()</code> and
16991711
<code>read()</code>.</p>
17001712

17011713
<p>To see the output, run the file:</p>
@@ -1947,7 +1959,7 @@ <h4>7.2 Fetching a CLOB as a string</h4>
19471959

19481960
<li><h3><a name="aq">10. Advanced Queuing</a></h3>
19491961
<ul>
1950-
<li><h4>10.1 Message passing with Oracle Advanced Queuing</h4></li>
1962+
<li><h4>10.1 Message passing with Oracle Advanced Queuing</h4>
19511963

19521964
<p>Review <code>aq.py</code>:</p>
19531965

@@ -2074,6 +2086,114 @@ <h4>7.2 Fetching a CLOB as a string</h4>
20742086
</ul>
20752087
</li>
20762088

2089+
</li>
2090+
2091+
<li><h3><a name="soda">11. Simple Oracle Document Access (SODA)</a></h3>
2092+
2093+
<p>Simple Oracle Document Access is a set of NoSQL-style APIs.
2094+
Documents can be inserted, queried, and retrieved from Oracle
2095+
Database. By default, documents are JSON strings. SODA APIs
2096+
exist in many languages.</p>
2097+
2098+
<ul>
2099+
2100+
<li><h4>11.1 Inserting JSON Documents</h4>
2101+
2102+
<p>Review <code>soda.py</code>:</p>
2103+
2104+
<pre>
2105+
import cx_Oracle
2106+
import db_config
2107+
2108+
con = cx_Oracle.connect(db_config.user, db_config.pw, db_config.dsn)
2109+
2110+
soda = con.getSodaDatabase()
2111+
2112+
collection = soda.createCollection("friends")
2113+
2114+
content = {'name': 'Jared', 'age': 35, 'address': {'city': 'Melbourne'}}
2115+
2116+
doc = collection.insertOneAndGet(content)
2117+
key = doc.key
2118+
2119+
doc = collection.find().key(key).getOne()
2120+
content = doc.getContent()
2121+
print('Retrieved SODA document dictionary is:')
2122+
print(content)
2123+
</pre>
2124+
2125+
<p><code>soda.createCollection()</code> will create a new
2126+
collection, or open an existing collection, if the name is
2127+
already in use.</p>
2128+
2129+
<p><code>insertOneAndGet()</code> inserts the content of a
2130+
document into the database and returns a SODA Document Object.
2131+
This allows access to meta data such as the document key. By
2132+
default, document keys are automatically generated.</p>
2133+
2134+
<p>The <code>find()</code> method is used to begin an operation
2135+
that will act upon documents in the collection.</p>
2136+
2137+
<p><code>content</code> is a dictionary. You can also get a JSON string
2138+
by calling <code>doc.getContentAsString()</code>.</p>
2139+
2140+
<p>Run the file:</p>
2141+
2142+
<pre><strong>python soda.py</strong></pre>
2143+
2144+
<p>The output shows the content of the new document.</p>
2145+
2146+
</li>
2147+
2148+
<li><h4>11.2 Searching SODA Documents</h4>
2149+
2150+
<p>Extend <code>soda.py</code> to insert some more documents and
2151+
perform a find filter operation:</p>
2152+
2153+
<pre>
2154+
myDocs = [
2155+
{'name': 'Gerald', 'age': 21, 'address': {'city': 'London'}},
2156+
{'name': 'David', 'age': 28, 'address': {'city': 'Melbourne'}},
2157+
{'name': 'Shawn', 'age': 20, 'address': {'city': 'San Francisco'}}
2158+
]
2159+
collection.insertMany(myDocs)
2160+
2161+
filterSpec = { "address.city": "Melbourne" }
2162+
myDocuments = collection.find().filter(filterSpec).getDocuments()
2163+
2164+
print('Melbourne people:')
2165+
for doc in myDocuments:
2166+
print(doc.getContent()["name"])
2167+
</pre>
2168+
2169+
<p>Run the script again:</p>
2170+
2171+
<pre><strong>python soda.py</strong></pre>
2172+
2173+
<p>The find operation filters the collection and returns
2174+
documents where the city is Melbourne. Note the
2175+
<code>insertMany()</code> method is currently in preview.</p>
2176+
2177+
<p>SODA supports query by example (QBE) with an extensive set of
2178+
operators. Extend <code>soda.py</code> with a QBE to find
2179+
documents where the age is less than 25:</p>
2180+
2181+
<pre>
2182+
filterSpec = {'age': {'$lt': 25}}
2183+
myDocuments = collection.find().filter(filterSpec).getDocuments()
2184+
2185+
print('Young people:')
2186+
for doc in myDocuments:
2187+
print(doc.getContent()["name"])
2188+
</pre>
2189+
2190+
<p>Running the script displays the names.</p>
2191+
2192+
</li>
2193+
</ul>
2194+
2195+
</li>
2196+
20772197
</ol>
20782198

20792199
<h2><a name="summary">Summary</a></h2>
@@ -2307,7 +2427,7 @@ <h2><a name="resources">Resources</a></h2>
23072427
<div class="footer"></div>
23082428
<table border="0" cellpadding="10" cellspacing="0" width="100%">
23092429
<tbody><tr>
2310-
<td align="right" width="54%">Copyright &copy; 2017, Oracle and/or its affiliates. All rights reserved</td>
2430+
<td align="right" width="54%">Copyright &copy; 2017, 2019, Oracle and/or its affiliates. All rights reserved</td>
23112431
</tr>
23122432
<tr><td colspan="2"></td></tr>
23132433
</tbody>

samples/tutorial/db_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
user = "pythonhol"
22
pw = "welcome"
3-
dsn = "localhost/orclpdb"
3+
dsn = "localhost/orclpdb1"

samples/tutorial/db_config.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
def user = "pythonhol"
22
def pw = "welcome"
3-
def connect_string = "localhost/orclpdb"
3+
def connect_string = "localhost/orclpdb1"

samples/tutorial/soda.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#------------------------------------------------------------------------------
2+
# soda.py (Section 11.1)
3+
#------------------------------------------------------------------------------
4+
5+
#------------------------------------------------------------------------------
6+
# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
7+
#------------------------------------------------------------------------------
8+
9+
from __future__ import print_function
10+
11+
import cx_Oracle
12+
import db_config
13+
14+
con = cx_Oracle.connect(db_config.user, db_config.pw, db_config.dsn)
15+
16+
soda = con.getSodaDatabase()
17+
18+
collection = soda.createCollection("friends")
19+
20+
content = {'name': 'Jared', 'age': 35, 'address': {'city': 'Melbourne'}}
21+
22+
doc = collection.insertOneAndGet(content)
23+
key = doc.key
24+
25+
doc = collection.find().key(key).getOne()
26+
content = doc.getContent()
27+
print('Retrieved SODA document dictionary is:')
28+
print(content)

samples/tutorial/solutions/soda.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#------------------------------------------------------------------------------
2+
# soda.py (Section 11.2)
3+
#------------------------------------------------------------------------------
4+
5+
#------------------------------------------------------------------------------
6+
# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
7+
#------------------------------------------------------------------------------
8+
9+
from __future__ import print_function
10+
11+
import cx_Oracle
12+
import db_config
13+
14+
con = cx_Oracle.connect(db_config.user, db_config.pw, db_config.dsn)
15+
16+
soda = con.getSodaDatabase()
17+
18+
collection = soda.createCollection("friends")
19+
20+
content = {'name': 'Jared', 'age': 35, 'address': {'city': 'Melbourne'}}
21+
22+
doc = collection.insertOneAndGet(content)
23+
key = doc.key
24+
25+
doc = collection.find().key(key).getOne()
26+
content = doc.getContent()
27+
print('Retrieved SODA document dictionary is:')
28+
print(content)
29+
30+
myDocs = [
31+
{'name': 'Gerald', 'age': 21, 'address': {'city': 'London'}},
32+
{'name': 'David', 'age': 28, 'address': {'city': 'Melbourne'}},
33+
{'name': 'Shawn', 'age': 20, 'address': {'city': 'San Francisco'}}
34+
]
35+
collection.insertMany(myDocs)
36+
37+
filterSpec = { "address.city": "Melbourne" }
38+
myDocuments = collection.find().filter(filterSpec).getDocuments()
39+
40+
print('Melbourne people:')
41+
for doc in myDocuments:
42+
print(doc.getContent()["name"])
43+
44+
filterSpec = {'age': {'$lt': 25}}
45+
myDocuments = collection.find().filter(filterSpec).getDocuments()
46+
47+
print('Young people:')
48+
for doc in myDocuments:
49+
print(doc.getContent()["name"])

samples/tutorial/sql/SetupSamples.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ to &main_user;
3838
grant execute on dbms_aqadm to &main_user;
3939
grant execute on dbms_lock to &main_user;
4040

41+
begin
42+
43+
for r in
44+
( select role
45+
from dba_roles
46+
where role in ('SODA_APP')
47+
) loop
48+
execute immediate 'grant ' || r.role || ' to &main_user';
49+
end loop;
50+
51+
end;
52+
/
53+
4154
create table &main_user..testclobs (
4255
id number not null,
4356
myclob clob not null

0 commit comments

Comments
 (0)