Midwest RUGs Taming Python for Db2 for z/OS Jørn Thyssen, Rocket
42 Slides2.51 MB
Midwest RUGs Taming Python for Db2 for z/OS Jørn Thyssen, Rocket Software 2022 IBM Champion
Agenda Introduction About Python Python and databases The DB-API Installing ibm db on z/OS Objectives: Install the ibm db python library on z/OS Write your python programs on z/OS connecting to Db2 for z/OS Python program examples REST, stored procedures, excel Db2 queries, Db2 commands, Db2 utilities, Visual Explain, Explain tables, accelerator management, General z/OS: datasets, jobs, More details on python and ibm-db: https://www.youtube.com/watch?v Dhc0dg2dPic
What is python Interpreted programming language First released in 1991 by Guido van Rossum Designed to be simple (See “The Zen of Python”) 3
Why Python Python continuously ranks in the top 3 over popular programming languages TIOBE (May 2022): #1, overtaking C PYPL (May 2022): #1, almost 2x Java Jobs available: #3 behind C and SQL It is widely taught at educational institutions If you’re my age or younger you’ve probably been exposed to Python I learned it at university in the mid-1990s 4
Why Python, cont’ed Widely used in Machine Learning Data Science Infrastructure provisioning Ansible Scientific computing Web sites Google, Instagram, Spotify, Netflix, Dropbox, Uber, 5
Typical use cases for Python on z/OS Productivity aid programs; internal services Replacement for REXX for “young” programmers Pipelines, automated testing, . REXX has much better z/OS support Python has many modules, easy to code, more people knows python, Ansible (infrastructure provisioning) Machine learning and analytics Reporting 6
Order IBM Open Enterprise SDK for Python from IBM ShopZ (optional support available) Get python for z/OS or Download PAX https://www.ibm.com/products/open-enterprise-python-zos/details or Rocket OpenApp Dev for z https://www.rocketsoftware.com/openappdev-for-z Conda install or SMP/E (with support) Includes IBM Python Also includes git and many other open source tools for application developers 7
Python and databases Python DB-API v2.0 specification “Identical” code to access databases across all platforms & database vendors Python ibmdb project Maintained by Db2 Connect development team Uses ODBC drivers ibm db: python drivers for IBM Db2 ibm db dbi: implementation of the DB-API v2.0 specification You get both then you install ibm db Source code: https://github.com/ibmdb/python-ibmdb API doc: https://github.com/ibmdb/python-ibmdb/wiki/APIs Blog by John Maenpaa: https://www.idug.org/blogs/johnmaenpaa1/2021/01/22/db2-python-programing-hdbc-vs-hdbi 8
ibm db – distributed platform On distributed platform: Uses Db2 Connect CLI drivers (IBM Data Server Driver) Connect to Db2 for z/OS using DRDA Need Db2 Connect for z/OS license to connect to Db2 for z/OS ODBC Python LUW ibm db IBM Data Server Driver DRDA Db2 for z/OS Db2 Connect License required 9
ibm db – z/OS On z/OS: CAF (Call Attachment Facility) RRSAF (Resource Recovery Services attachment Facility) Default plan DSNACLI Bind ODBC plans & packages: HLQ.SDSNSAMP(DSNTIJCL) No additional licenses required ! Python USS ODBC ibm db Db2 for z/OS CAF or RRSAF Db2 for z/OS FMID JDBCC17 “DB2 ODBC” 11
Installing ibm db on z/OS No pre-compiled binaries available like distributed platform Pip3 install ibm db will Download source Compile ibm db C modules (IBM z/OS C/C compilers required) Install into your site-packages library Important prereqs: IBM Python V3.8.3 (from IBM or Rocket z Open App Dev ) Db2 V12 PTF UI72859: Python related bugfixes for ODBC driver No PTFs required for Db2 V13 More details here: https://github.com/ibmdb/python-ibmdb/blob/master/install.md 12
First ibm db program Set STEPLIB so Python can find the ODBC Db2 z/OS drivers Create an ODBC ini file Set environment variable DSNAOINI to point to the ODBC ini file (ibm python env) export STEPLIB PDS1.SDSNEXIT:HLQ.SDSNLOD2:HLQ.SDSNLOAD (ibm python env) export DSNAOINI " HOME/ODBC PDS1 CAF" ODBC PDS1 CAF file: https://www.ibm.com/support/knowledgecenter/ SSEPEK 12.0.0/odbc/src/tpc/db2z hdckeyw.html Name of ODBC ini file is arbitrary With lots of SSIDs I just prefer to have SSID in the name [COMMON] MVSDEFAULTSSID RS01PDS1 FLOAT IEEE CURRENTAPPENSCH ASCII APPLTRACE 0 APPLTRACEFILENAME /u/xxxxx/odbc trace [RS01PDS1] AUTOCOMMIT 1 MVSATTACHTYPE CAF PLANNAME DSNACLI 15
First ibm db program, cont’ed Simple program using ibm db import ibm db conn ibm db.connect('','','') if conn: sql "SELECT * FROM SYSIBM.SYSTABLES FETCH FIRST 10 ROWS ONLY" stmt ibm db.exec immediate(conn, sql) result ibm db.fetch both(stmt) while( result ): print(result[1].strip() "." result[0].strip()) result ibm db.fetch both(stmt) ibm db.close(conn) 16
First ibm db program, cont’ed (ibm python env) python3 simple-test.py SYSIBM.DBDR SYSIBM.IPLIST SYSIBM.IPNAMES SYSIBM.LOCATIONS SYSIBM.LULIST SYSIBM.LUMODES SYSIBM.LUNAMES SYSIBM.MODESELECT SYSIBM.SCTR SYSIBM.SPTR 17
Calling a stored procedure Issue a REORG from a python program Call SYSPROC.DSNUTILU / SYSPROC.DSNUTILV ibm db.callproc – call procedure ibm db.fetch assoc – fetch row from result set ibm db.next result – next result set 31
Calling a stored procedure, cont’ed utility id 'REORGDEF' restart 'NO' utstmt 'TEMPLATE FCOPY DSN RSTEST.IC.&SSID.&SN.P&PA.&UNIQ. UNIT 3390 TEMPLATE REC1 DSN &USERID.&SSID.UNLD.&DB.&TS. UNI T 3390 DISP(OLD,CATLG,CATLG) TEMPLATE WORK1 DSN &USERID.&SSID.SYSUT1 UNIT 3390 TEMPLATE WORK2 DSN &USERID.&SSID.SORTOUT U NIT 3390 REORG TABLESPACE TS5941.GLWSDPT LOG NO SORTDATA SHRLEVEL CHANGE KEEPDICTIONARY STATISTICS TABLE(ALL) SAMPLE 60 INDEX( ALL) COPYDDN(FCOPY) UNLDDN(REC1), WORKDDN(WORK1,WORK2)' retcode 0 stmt, utility id,restart,utstmt,retcode \ ibm db.callproc(conn, 'SYSPROC.DSNUTILU', (utility id,restart,utstmt,retcode) ) 32
Calling a stored procedure, cont’ed while stmt1: # result set available row ibm db.fetch assoc(stmt1) while row: print(row[“TEXT”]) row ibm db.fetch assoc(stmt1) stmt1 ibm db.next result(stmt) 33
Calling a stored procedure, cont’ed (test2) python call-sp.py RS01PDS1 TS5941.GLWSDPT Running REORG for tablespace TS5941.GLWSDPT on DSN RS01PDS1 Successfully connected to DSN RS01PDS1 1DSNU000I 297 11:43:16.65 DSNUGUTC - OUTPUT START FOR UTILITY, UTILID REORGDEF DSNU1045I 297 11:43:16.66 DSNUGTIS - PROCESSING SYSIN AS UNICODE UTF-8 0DSNU050I 297 11:43:16.66 DSNUGUTC - TEMPLATE FCOPY DSN RSTEST.IC.&SSID.&SN.P&PA.&UNIQ. UNIT 3390 DSNU1035I 297 11:43:16.67 DSNUJTDR - TEMPLATE STATEMENT PROCESSED SUCCESSFULLY [snip] DSNU610I !PCA1 297 11:43:18.33 DSNUSUCD - SYSCOLDIST CATALOG UPDATE FOR TS5941.GLWXDPT2 SUCCESSFUL DSNU620I !PCA1 297 11:43:18.33 DSNUSEOF - RUNSTATS CATALOG TIMESTAMP 2020-10-23-11.43.17.393547 DSNU3357I 297 11:43:18.71 DSNUGUTC - MAXIMUM SORT AMOUNT ESTIMATION VARIATION WAS 0 PERCENT DSNU3355I 297 11:43:18.71 DSNUGUTC - TOTAL SORT MEMORY BELOW THE BAR: OPTIMAL 24 MB, USED 24 MB DSNU010I 297 11:43:18.73 DSNUGBAC - UTILITY EXECUTION COMPLETE, HIGHEST RETURN CODE 4 34
Calling a stored procedure – ADMIN COMMAND DB2 Issue command on DSN RS01PDS1: -DISPLAY GROUP Succesfully connected to DSN RS01PDS1 Result set DSN7100I !PCA1 DSN7GCMD *** BEGIN DISPLAY OF GROUP(PDS1 ) CATALOG LEVEL(V12R1M509) CURRENT FUNCTION LEVEL(V12R1M510) HIGHEST ACTIVATED FUNCTION LEVEL(V12R1M510) HIGHEST POSSIBLE FUNCTION LEVEL(V12R1M510) PROTOCOL LEVEL(2) GROUP ATTACH NAME(PDS1) --------------------------------------------------------------------DB2 SUB DB2 SYSTEM IRLM MEMBER ID SYS CMDPREF STATUS LVL NAME SUBSYS IRLMPROC -------- --- ---- -------- -------- ------ -------- ----------PCA1 1 PCA1 !PCA1 ACTIVE 121510 RS01 IR05 PCA1IRLM PCB1 2 PCB1 !PCB1 QUIESCED 121510 RS02 IR06 PCB1IRLM --------------------------------------------------------------------SCA STRUCTURE SIZE: 16384 KB, STATUS AC, SCA IN USE: 7 % LOCK1 STRUCTURE SIZE: 64512 KB NUMBER LOCK ENTRIES: 16777216 NUMBER LIST ENTRIES: 36345, LIST ENTRIES IN USE: 15 SPT01 INLINE LENGTH: 32138 *** END DISPLAY OF GROUP(PDS1 ) DSN9022I !PCA1 DSN7GCMD 'DISPLAY GROUP ' NORMAL COMPLETION python3 disgroup.py Issue command: -DISPLAY GROUP Successfully connected to Db2 Member Status Version LPAR PCA1 ACTIVE 121510 RS01 PCB1 QUIESCED 121510 RS02 35
Python and all the libraries Big advantage of python is 1000s of libraries Many work out-of-the-box Some require porting of C-code (like ibm db) Interesting libraries – my personal list: ibm db – of course Requests – for making REST calls Flask – for making web apps Jupyter / pandas / matplotlib XLSX – for creating Excel spreadsheets 36
Calling a Db2 native REST service Response [200] {'TESTIDC4': {'serviceName': 'TESTIDC4', 'serviceCollectionID': import requests 'TS5941', 'version': 'V1', 'isDefaultVersion': True, import sys 'serviceProvider': 'db2service-1.0', 'serviceDescription': 'TEST IDENTICALLY NAMED COLUMNS 4', 'alternateServiceURL': if len(sys.argv) 3: 'https://rs01.rocketsoftware.com:3713/services/TS5941/TESTIDC4', print("Usage: %s userid password " % (sys.argv[0])) 'serviceURL': exit(-1) 'https://rs01.rocketsoftware.com:3713/services/TS5941/TESTIDC4/V1', 'serviceStatus': 'started', 'RequestSchema': {}, 'ResponseSchema': userid sys.argv[1] {' schema': 'http://json-schema.org/draft-04/schema#', 'type': password sys.argv[2] 'object', 'properties': {'ResultSet Output': {'type': 'array', 'items': {'type': 'object', 'properties': {'CREATOR': {'type': collection 'TS5941' 'string', 'maxLength': 128, 'description': 'VARCHAR(128)'}, 'NAME': service 'TESTIDC4' {'type': 'string', 'maxLength': 128, 'description': 'VARCHAR(128)'}}, 'required': ['CREATOR', 'NAME', 'NAME'], url 'https://rs01.rocketsoftware.com:3713/services/' collection '/' service 'description': 'ResultSet Row'}}, 'StatusDescription': {'type': auth requests.auth.HTTPBasicAuth(userid,password) 'string', 'description': 'Service invocation status description'}, 'StatusCode': {'type': 'integer', 'multipleOf': 1, 'minimum': 100, resp requests.get(url,auth auth,verify False) 'maximum': 600, 'description': 'Service invocation HTTP status print(resp) code'}}, 'required': ['StatusDescription', 'StatusCode', 'ResultSet print(resp.json()) Output'], 'description': 'Service TESTIDC4 invocation HTTP response 37 body'}}}
Tune a query using IBM Db2 Tuning Services Db2 Accessories Suite for z/OS – Database Services Expansion Pack Feature (no-charge, available from IBM ShopZ) UI available through VS Code IBM Db2 Developer Extension and web-based IBM Db2 Administration Foundation But you can also call tuning services from a program or pipeline This example Logon to Tuning Services Submit Runstats advisor “job” (job async task in the Tuning Service server) Wait for “job” to complete Show result 38
Tune a query using IBM Db2 Tuning Services #Submit Runstats advisor url baseUrl '/tuningservice/v1/sa' resp requests.post(url,json vebody,verify verify,headers headers) job id resp.json()['job id'] Logon TMS Response [200] Submit Runstats advisor Response [202] TMSJOB0002I: The job has been submitted with Job ID 1714307214070517760. Job ID 1714307214070517760 status RUNNING Job ID 1714307214070517760 status COMPLETED Runstats advisor results Response [200] Runstats recommended: RUNSTATS TABLESPACE DSNDB06.SYSTSTAB TABLE(SYSIBM.SYSTABLES) COLUMN(ALTEREDTS,ARCHIVING SCHEMA,ARCHIVING TABLE,AUDITING,CARD, CHECKFLAG,CHECKRID,CLUSTERTYPE,COLCOUNT,CONTROL, CREATEDBY,CREATEDTS,CREATOR,DBID,DBNAME, 39
Tune a query using IBM Db2 Tuning Services #Submit Visual Explain advisor print("Submit Visual Explain advisor") url baseUrl '/tuningservice/v1/ve' resp requests.post(url,json vebody,verify verify,headers headers) print(resp) job id resp.json()['job id'] Logon TMS Response [200] Submit Visual Explain advisor Response [202] TMSJOB0002I: The job has been submitted with Job ID 1743841672647675904. Job ID 1743841672647675904 status RUNNING Job ID 1743841672647675904 status COMPLETED Visual Explain advisor results Response [200] URL for Visual Explain: https://rs01.rocketsoftware.com:9944/tuningservice/v1/ve/viewer/1e7d ff89-d2f1-46ad-b6f2-1412f500637e 40
Upgrade EXPLAIN tables – inspired from IDUG-L Db2 for z/OS ships stored procedure ADMIN EXPLAIN MAINT to create, upgrade and create alias for explain tables Alternatively use the Db2 Tuning Service REST endpoint Logon TMS Response [200] Run Explain table maintenance Response [200] {'code': 200, 'status': 'success', 'payload': {'result': [{'ALIAS CREATED': '0', 'TB NOT UNICODE': '0', 'TB EXAMINED': '0', 'TS DROPPED': '0', 'AUX CREATED': '5', 'TB DROPPED': '0', 'TB CREATED': '23', 'DB CREATED': '1', 'TB ALTERED': '0', 'IX CREATED': '26', 'TS CREATED': '28’, explaintbbody { "action": "CREATE", "auth id": "TS5941", "bp16kblob": "BP16K0", "bp32kblob": "BP32K", "bp4kblob": "BP0", "bp8kblob": "BP8K0", "connection": "profile1", "database name": "TS5941EE", "ixbufferpool": "BP0", "managealias": "NO", "mode": "RUN", "schema alias": "", "schema name": "TS5941EE", "storagegroup": "DB2EA", "storagegroup idx": "DB2EA", "tableset": "ALL", "ts16kbufferpool": "BP16K0", "ts32kbufferpool": "BP32K", "ts4kbufferpool": "BP0", "ts8kbufferpool": "BP8K0" } url baseUrl '/tuningservice/v1/explaintb' resp requests.post(url,json explaintbbody,verify verify,h eaders headers) 41
Manage Db2 Analytics Accelerator Uses IBM Db2 Analytics Accelerator Administration Services Available from IBM Fix Central https://ibm.biz/BdfWns UI available through web-based IBM Db2 Administration Foundation But you can also call tuning services from a program or pipeline This example Logon to Accelerator Admin Services Load a table 42
Load table in Db2 Analytics Accelerator # Generate JWT auth token print("Logon Accel Admin Svc") url baseUrl '/token' resp requests.post(url,json loginbody,verify verify) print(resp) token resp.json()['result']['token'] #print(token) headers {'Authorization':'Bearer ' token} print(f"Load table {schema}.{table}") url baseUrl '/table/partition/load' resp requests.post(url,json loadbody,verify verify,header s headers) print(resp) print(resp.json()) Logon Accel Admin Svc Response [201] Load table TS5941.TESTMD Response [200] {'result': {'name': 'IDAAZ30'}, 'message': [], 'status': 'SUCCESS'} 43
Jupyter install on z/OS conda create -n jupyter env notebook pip xlc-wrapper cython "panda*" matplotlib matplotlib conda activate jupyter env pip install ibm db jupyter notebook --generate-config [edit config – I added my SSL cert and change port#] mkdir my-notebooks cd my-notesbooks jupyter notebook [I 02:31:15.307 NotebookApp] Notebook authentication will be used. The hashed password should be in the configuration file. [I 02:31:15.977 NotebookApp] Serving notebooks from local directory: /u/userid/devel/jupyter-notebooks [I 02:31:15.977 NotebookApp] The Jupyter Notebook is running at: [I 02:31:15.977 NotebookApp] https://rs01.rocketsoftware.com:8888/? token a21db5d98377c28af0527d3157ac9444e0d9688549f693dc [I 02:31:15.977 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). [C 02:31:15.983 NotebookApp] To access the notebook, open this file in a browser: file:///u/userid /.local/share/jupyter/runtime/nbserver-131433-open.html Or copy and paste one of these URLs: https://rs01.rocketsoftware.com:8888/?token a21db5d98377c28af0527d3157ac9444e0d9688549f693dc 44
Jupyter Get db2.ipynb from https://github.com/IBM/db2-jupyter/blob/master/db2.ipynb
Write excel file from Db2 query Report generation from SQL statement Output written as XLSX Uses xlsxwriter library import ibm db import sys import xlsxwriter print(ibm db. version ) conn ibm db.connect('','','') workbook xlsxwriter.Workbook('simple-excel.xlsx') worksheet workbook.add worksheet() cell format0 workbook.add format({'bold': True, 'font color': 'red'}) row 0 worksheet.write(row,0,"CREATOR",cell format0) worksheet.write(row,1,"NAME",cell format0) row row 1 if conn: sql "SELECT CREATOR,NAME FROM SYSIBM.SYSTABLES WHERE CREATOR 'SYSIBM' AND NAME LIKE 'SYS%' FETCH FIRST 10 ROWS ONLY" stmt ibm db.exec immediate(conn, sql) result ibm db.fetch both(stmt) while( result ): worksheet.write(row,0,result[0].strip()) worksheet.write(row,1,result[1].strip()) row row 1 result ibm db.fetch both(stmt) ibm db.commit(conn) ibm db.close(conn) workbook.close() 46
Write excel file from Db2 query Zowe zos-files download uss-file "/u/ts5941/devel/python-samples/excel/simple-excel.xlsx" -f "simpleexcel.xlsx" –b "C:\Program Files\Microsoft Office\root\Office16\EXCEL.EXE" simpleexcel.xlsx 47
Bonus topic – interact with z/OS Datasets Jobs Other z/OS services Very little native support IBM Z Open Automation Utilities 48
Interact with z/OS Use os.system, os.popen, subprocess.open import os stream os.popen('uname') output stream.read() if output.startswith("OS/390"): print("Yeah, running on z/OS!") import os stream os.popen('tsocmd "alloc da(from.python) space(1,1) new"') output stream.read() print(output) 49
Interact with z/OS IBM Z Open Automation Utilities No charge Wraps MVS utilities like IEBCOPY, IDCAMS, IKJEFT01, etc Wraps SDSF REXX API ZOAU 1.2 rewrote some functions in C for better performance Supports shell scripts and Python https://www.ibm.com/docs/en/zoau/1.2.0 50
IBM Z Open Automation Utilities Example: run query and write to sequential dataset import ibm db import sys from zoautil py import datasets print(ibm db. version ) conn ibm db.connect('','','') print("Connected",conn) datasetname "TS5941.PYTHON.REPORT.TXT" if datasets.exists(datasetname): datasets.delete(datasetname) datasets.create(datasetname, type "SEQ", record length 133, record format "FB", primary space "10k") content "" if conn: sql "SELECT * FROM SYSIBM.SYSTABLES " stmt ibm db.exec immediate(conn, sql) result ibm db.fetch both(stmt) while( result ): content content result[1].strip() "." result[0].strip() "\n" result ibm db.fetch both(stmt) ibm db.close(conn) datasets.write(datasetname,content content) 51
Interact with z/OS z/OSMF REST APIs Also expensive to call Will work on both z/OS and distributed import requests url 'https://rs01.rocketsoftware.com:11443/zosmf/restjobs/jobs ?prefix IZPS*&owner *' auth requests.auth.HTTPBasicAuth('userid', 'password') print(auth) resp requests.get(url,auth auth,verify False) if resp.ok: print("%8s %8s %8s %8s %8s" % \ ("Jobname", "JobId", "Owner", "Status","Retcode")) for j in resp.json(): print("%8s %8s %8s %8s %8s" % \ ( j["jobname"], j["jobid"], j["owner"], j["status"], j["retcode"] )) 52
Interact with z/OS Jobname JobId z/OSMF REST APIs IZPSRV STC01178 IZPSRV STC04386 Also expensive to call IZPSRVP STC04120 STC04121 Will work IZPSRVP on both z/OS IZPSRVP STC04113 IZPSRVP STC04119 and distributed IZPSRVP IZPSRVP IZPSRVP IZPSRV IZPSRVP IZPSRV2 STC04112 STC04111 STC04110 STC04387 STC04122 STC07395 import requests url Owner Status Retcode 'https://rs01.rocketsoftware.com:11443/zosmf/restjobs/jobs DOESTC OUTPUT CC 0000 ?prefix IZPS*&owner *' DOESTC OUTPUT CC 0000 auth requests.auth.HTTPBasicAuth('userid', 'password') DOESTC OUTPUT CC 0000 print(auth) DOESTC OUTPUT CC 0000 DOESTC OUTPUT CC 0000 resp requests.get(url,auth auth,verify False) DOESTC OUTPUT CC 0000 if resp.ok: DOESTC OUTPUT CC 0000 print("%8s %8s %8s %8s %8s" % \ DOESTC OUTPUT CC 0000 ("Jobname", "JobId", "Owner", "Status","Retcode")) DOESTC OUTPUT CC 0000 for j in resp.json(): DOESTC ACTIVE None print("%8s %8s %8s %8s %8s" % \ DOESTC ACTIVE None ( j["jobname"], j["jobid"], j["owner"], DOESTC ACTIVE None j["status"], j["retcode"] )) 53
Interact with z/OS CFFI Create python wrapper over C libraries, e.g., “access()” to check if file exists 54
Python is popular Conclusion Python can talk to Db2 for z/OS Python can run on z/OS (read: USS) Python can run on z/OS and now also talk to Db2 for z/OS 55
Install on LPAR w/o internet access Pip download ibm db – on your laptop Transfer to USS; unzip cd python-ibmdb-v.r.m/IBM DB/ibm db chtag –R –tc ISO8859-1 . Pip install . 56
Troubleshooting (1) “Exception” on connect without detailed error messages Most likely an encoding error with the ODBC ini file MUST BE encoded in IBM-1047 MUST BE tagged IBM-1047 “text” tag must be off Check file contents, e.g., [ and ] (hex 0xAD and 0xBD) Traceback (most recent call last): File "simple-test.py", line 5, in module conn ibm db.connect('','','') Exception 57
import requests import sys import time if len(sys.argv) 3: print("Usage: %s userid password " % (sys.argv[0])) exit(-1) userid sys.argv[1] password sys.argv[2] baseUrl 'https://rs01.rocketsoftware.com:9944' verify '/u/ts5941/cert/RS01.ROCKET.BASE64' maxretry 10 loginbody { "userid": userid, "password": password } vebody { "connection": "profile1", "sql text": "SELECT NAME, CREATOR, TSNAME, COLCOUNT, CARD, NPAGES FROM SYSIBM.SYSTABLES WHERE TSNAME 'ANLSPC08';", "schema": "TS5941", "explain schema": "TS5941" } # Generate JWT auth token print("Logon TMS")