Package: nzpy
nzpy: Pure python driver for IBM NetezzaScopenzpy is a pure-Python IBM Netezza driver that complies with DB-API 2.0. It is tested on Python versions 3.5+. It is supported with NPS 11.1.2.x and later. Although nzpy works with older NPS versions but it do not support few features such as external table, parameter style query etc.InstallationTo install nzpy using pip type:pipinstallnzpyTo install nzpy using setup.py:pythonsetup.pyinstallInteractive ExampleThis examples make use of the nzpy extensions to the DB-API 2.0 standard,Import nzpy, connect to the database, create a table, add some rows and then query the table:importnzpyconn=nzpy.connect(user="admin",password="password",host='localhost',port=5480,database="db1",securityLevel=1,logLevel=0)withconn.cursor()ascursor:try:cursor.execute("create table customerAddress(Id int, Name varchar(10), Address varchar(50), Email varchar(20) )")print("Table customerAddress created successfully")exceptExceptionase:print(str(e))#insert data using parameters markercursor.execute("insert into customerAddress values (?,?,?,?)",(1,'Jack','High street, London','jack4321@ibm.com'))print(cursor.rowcount,'rows inserted')cursor.execute("insert into customerAddress values (?,?,?,?)",(2,'Tom','Park street, NY','tom1234@ibm.com'))print(cursor.rowcount,'rows inserted')cursor.execute("insert into customerAddress values (?,?,?,?)",(3,'James','MG street, SG','james678@ibm.com'))print(cursor.rowcount,'rows inserted')# Using parameters (IMPORTANT: YOU SHOULD USE TUPLE TO PASS PARAMETERS)# Python note: a tuple with just one element must have a trailing comma, otherwise is just a enclosed variablecursor.execute("select * from customerAddress where Id = ? and Name = ?",(1,'Jack'))results=cursor.fetchall()forc1,c2,c3,c4inresults:print("Id =%s"%(c1))print("Name =%s"%(c2))print("Address =%s"%(c3))print("Email =%s"%(c4))try:cursor.execute("create table customerData(Id int, FirstName varchar(20), LastName varchar(20), Age int)")print("Table customerData created successfully")exceptExceptionase:print(str(e))#insert data using parameters marker in customerData tablecursor.execute("insert into customerData values (?,?,?,?)",(1,'Jack','Bentley',42))print(cursor.rowcount,'rows inserted')cursor.execute("insert into customerData values (?,?,?,?)",(2,'Tom','Banks',28))print(cursor.rowcount,'rows inserted')cursor.execute("insert into customerData values (?,?,?,?)",(3,'James','Grant',30))print(cursor.rowcount,'rows inserted')cursor.execute("select ca.Id,cd.FirstName, cd.LastName, cd.Age, ca.Address, ca.Email from customerAddress ca, customerData cd where ca.Id = ? and ca.Id = cd.Id",(2,))results=cursor.fetchall()forc1,c2,c3,c4,c5,c6inresults:print("Id =%s"%(c1))print("FirstName =%s"%(c2))print("LastName =%s"%(c3))print("Age =%s"%(c4))print("Address =%s"%(c5))print("Email =%s"%(c6))# rowcount beforecursor.execute("select count(*) from customerAddress")results=cursor.fetchall()forc1inresults:print("Table row count is%s"%(c1))# using remotesource 'python', create named external table and unload table datatry:cursor.execute("create external table et1 '/tmp/et10' using ( remotesource 'python' delimiter '|') as select * from customerAddress")print("Create external table created successfully")exceptExceptionase:print(str(e))# load data from external table onto user tabletry:cursor.execute("insert into customerAddress select * from external '/tmp/et10' using ( remotesource 'python' delimiter '|' socketbufsize 8388608 ctrlchars 'yes'  encoding 'internal' timeroundnanos 'yes' crinstring 'off' maxerrors 3 LogDir '/tmp')")print("External Table loaded successfully")exceptExceptionase:print(str(e))# rowcount after load from external tablecursor.execute("select count(*) from customerAddress")results=cursor.fetchall()forc1inresults:print("After load from External Table, table row count is%s"%(c1))AutocommitAs autocommit is on by default in IBM Netezza the default value of autocommit is on. It can be turned off by using the autocommit property of the connection.conn.autocommit=False#autocommit is on by default. It can be turned off by using the autocommit property of the connection.withconn.cursor()ascursor:cursor.execute("create table t2(c1 numeric (10,5), c2 varchar(10),c3 nchar(5))")cursor.execute("insert into t2 values (123.54,'xcfd','xyz')")conn.rollback()NoticesIBM Netezza notices are stored in a deque called cursor.notices and added using the append() method. Here’s an example:withconn.cursor()ascursor:cursor.execute("call CUSTOMER();")print(cursor.notices)ThecustomernameisalphaIf backend returns multiple notices:withconn.cursor()ascursor:cursor.execute("call CUSTOMER();")fornoticeincursor.notices:print(notice)ThecustomernameisalphaThecustomerlocationisbetaLoggingYou can set logLevel to control logging verbosity. In order to enable logging, you need to pass logLevel in your application using connection string.conn=nzpy.connect(user="admin",password="password",host='localhost',port=5480,database="db1",securityLevel=0,logLevel=logging.DEBUG)In addition there are 3 more options to control logging. One or more of these can be specified usinglogOptionsargument tonzpy.connectInherit the logging settings of the parent / callerThis isnzpy.LogOptions.Inheritoption. The logging from nzpy is propgated to the logging configured by the parentlogging.basicConfig(filename="myapplication.log")logging.info("...")# ..conn=nzpy.connect(user="admin",password="password",host='localhost',port=5480,database="db1",securityLevel=0,logOptions=nzpy.LogOptions.Inherit)# .. all of nzpy logs will go to the inherited log settingsLogging details to a logfileThis isnzpy.LogOptions.Logfileoption. The logging from nzpy is sent to 'nzpy.log' in the current directory. The file is rotated after 10 G. Ifnzpy.LogOptions.Inheritis set as well then both are honoredlogging.basicConfig(filename="myapplication.log")logging.info("...")# ..conn1=nzpy.connect(user="admin",password="password",host='localhost',port=5480,database="db1",securityLevel=0,logOptions=nzpy.LogOptions.Logfile)# .. all of conn1's nzpy logs will go to the nzpy.log onlyconn2=nzpy.connect(user="admin",password="password",host='localhost',port=5480,database="db1",securityLevel=0,logOptions=nzpy.LogOptions.Logfile|nzpy.LogOptions.Inherit)# .. all of conn2's nzpy logs will go to the nzpy.log _and_ to myapplication.logconn3=nzpy.connect(user="admin",password="password",host='localhost',port=5480,database="db1",securityLevel=0,logOptions=nzpy.LogOptions.Disabled)# .. conn3's logging is completely disabledDisable nzpy loggingThis isnzpy.LogOptions.DisabledoptionYou can configure logLevel as per your requirement. Any levels in standardloggingmodule can be used. The default islogging.INFOSecurityLevelThe level of security (SSL/TLS) that the driver uses for the connection to the data store.onlyUnSecured: The driver does not use SSL. 
preferredUnSecured: If the server provides a choice, the driver does not use SSL. 
preferredSecured: If the server provides a choice, the driver uses SSL. 
onlySecured: The driver does not connect unless an SSL connection is available.Similarly, IBM Netezza server has above securityLevel.Cases which would fail :Client tries to connect with 'Only secured' or 'Preferred secured' mode while server is 'Only Unsecured' modeClient tries to connect with 'Only secured' or 'Preferred secured' mode while server is 'Preferred Unsecured' modeClient tries to connect with 'Only Unsecured' or 'Preferred Unsecured' mode while server is 'Only Secured' modeClient tries to connect with 'Only Unsecured' or 'Preferred Unsecured' mode while server is 'Preferred Secured' modeBelow is an example how you could pass securityLevel and ca certificate in connection string:conn = nzpy.connect(user="admin", password="password",host='localhost', port=5480, database="db1", securityLevel=3, logLevel=0, ssl = {'ca_certs' : '/nz/cacert.pem'})Below are the securityLevel you can pass in connection string :0: Preferred Unsecured session
1: Only Unsecured session
2: Preferred Secured session
3: Only Secured sessionConnection StringUse connect to create a database connection with connection parameters:conn = nzpy.connect(user="admin", password="password",host='localhost', port=5480, database="db1", securityLevel=3, logLevel=0, ssl = {'ca_certs' : '/nz/cacert.pem'})The above example opens a database handle on localhost. nzpy driver should connect on port 5480(postgres port). The user is admin, password is password, database is db1 and the location of the ca certificate file is /nz/cacert.pem with securityLevel as 'Only Secured session'Connection ParametersWhen establishing a connection using nzgo you are expected to supply a connection string containing zero or more parameters. Below are subset of the connection parameters supported by nzgo.
The following special connection parameters are supported:database - The name of the database to connect touser - The user to sign in aspassword - The user's passwordhost - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost)port - The port to bind to.securityLevel - Whether or not to use SSL (default is 0)ssl - Python dictionary containing location of the root certificate file. The file must contain PEM encoded data.TransactionsAs autocommit is on by default in IBM Netezza the default value of autocommit is on. It can be turned off by using the autocommit property of the connection.conn.autocommit = False #This would internally called 'begin'

with conn.cursor() as cursor:
    cursor.execute("create table t2(c1 numeric (10,5), c2 varchar(10),c3 nchar(5))")
    conn.commit()  # This will commit create table transaction

    cursor.execute("insert into t2 values (123.54,'xcfd','xyz')")
    conn.rollback() # This will rollback insert into table transactionSupported Data TypesThis package returns the following types for values from the IBM Netezza backend:integer types byteint, smallint, integer, and bigint are returned as intfloating-point types real and double precision are returned as floatcharacter types char, varchar, nchar and nvarchar are returned as stringtemporal types date, time, timetz, timestamp, interval and timestamptz are
returned as stringnumeric and geometry are returned as stringthe boolean type is returned as boolJSON, JSONB and JSONPATH datatypes is returned as stringParameter Stylenzpy do not support all the DB-API parameter styles. It only supports qmark style. Here’s an example of using the 'qmark' parameter style:with conn.cursor() as cursor:
    cursor.execute("select * from t1 where c3 = ? and c2 = ?", ('abc','abcd'))
    results = cursor.fetchall()
    for c1, c2, c3 in results:
        print("c1 = %s, c2 = %s, c3 = %s" % (c1, c2, c3))EncodingUser can provide encoding for char/varchar datatype from application. Default value is 'latin'.
For example, user can set nzpy to support 'UTF8' encoding for char and varchar by passing char_varchar_encoding='utf8' in connection parameter like below:conn = nzpy.connect(user="admin", password="password",host='localhost', port=5480, database="db1", securityLevel=1,logLevel=0, char_varchar_encoding='utf8')External tableYou can unload data from an IBM Netezza database table on a Netezza host system to a remote client. This unload does not remove rows from the database but instead stores the unloaded data in a flat file (external table) that is suitable for loading back into a Netezza database.
Below query would create a file 'et1.txt' on remote system from Netezza table t1 with data delimeted by '|'.cursor.execute("create external table et1 'C:\\et1.txt' using ( remotesource 'python' delimiter '|') as select * from t1")FeaturesSSL/TLSv1.2 crypto supportTransaction support: begin, rollback, commitFull support for all IBM Netezza data typesSupport JSON, JSONB and JSONPATH datatypesFull DDL, DML query syntax support for IBM NetezzaFull external table support (load and unload)Configurable logging featureParameter style supportTestsTo run tests, go to tests folder and run :pytest -xv *To run individual tests, you can run :pytest -xv test_connection.pyContribution and helpAll bug reports, feature requests and contributions are welcome athttp://github.com/IBM/nzpyIf you have any questions or issues you can create a newissue here.Pull requests are very welcome! Make sure your patches are well tested.
Ideally create a topic branch for every separate change you make. For
example:Fork the repo (git clonehttps://github.com/IBM/nzpy.git)Create your feature branch (git checkout -b my-new-feature)Commit your changes (git commit -am 'Added some feature')Push to the branch (git push origin my-new-feature)Create new Pull RequestAssign any one of the reviewers:abhishekjogsandippawar1412shabbir10julyLicenseIf you would like to see the detailed LICENSE clickhere.Copyright:: 2019-2020 IBM, Inc

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

http://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.