dbobj3 0.4.0__tar.gz → 0.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: dbobj3
3
- Version: 0.4.0
3
+ Version: 0.6.0
4
4
  Summary: High-level MySQL/MSSQL/Oracle access module
5
5
  Requires-Python: >=3.6
6
6
  Requires-Dist: pymysql
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "dbobj3"
7
- version = "0.4.0"
7
+ version = "0.6.0"
8
8
  description = "High-level MySQL/MSSQL/Oracle access module"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.6"
@@ -16,7 +16,7 @@ dependencies = [
16
16
  packages = ["src/dbobj3.py"]
17
17
 
18
18
  [tool.bumpversion]
19
- current_version = "0.4.0"
19
+ current_version = "0.6.0"
20
20
  commit = true
21
21
  tag = true
22
22
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)"
@@ -21,7 +21,7 @@ Example:
21
21
  rsServices.next()
22
22
 
23
23
  """
24
- __version__ = "0.4.0"
24
+ __version__ = "0.6.0"
25
25
 
26
26
  from sys import version as sys_version, exit
27
27
  pyversion = sys_version[0:sys_version.find(' ')]
@@ -95,9 +95,15 @@ try:
95
95
  import requests
96
96
  lstLoadedDrivers.append({"requests": "Loaded (API)"})
97
97
  except ImportError:
98
- #print('could not import pyodbc')
98
+ #print('could not import requests')
99
99
  lstLoadedDrivers.append({"requests": "Not Loaded (API)"})
100
100
 
101
+ try:
102
+ import jaydebeapi
103
+ lstLoadedDrivers.append({"jaydebeapi": "Loaded (JDBC)"})
104
+ except ImportError:
105
+ lstLoadedDrivers.append({"jaydebeapi": "Not Loaded (JDBC)"})
106
+
101
107
  try:
102
108
  import json
103
109
  except ImportError:
@@ -156,6 +162,8 @@ class dbObjCursor:
156
162
  self.createProgress()
157
163
  elif(prmDBType=="API"):
158
164
  self.createAPI()
165
+ elif(prmDBType=="JDBC"):
166
+ self.createJDBC()
159
167
 
160
168
  def createMySql(self):
161
169
  self.cursor = self.connection.cursor(MySQLdb.cursors.DictCursor)
@@ -177,6 +185,9 @@ class dbObjCursor:
177
185
  def createAPI(self):
178
186
  self.lstRecords = []
179
187
 
188
+ def createJDBC(self):
189
+ self.cursor = self.connection.cursor()
190
+
180
191
  def moveNext(self):
181
192
  """Same as next"""
182
193
  self.next()
@@ -195,6 +206,8 @@ class dbObjCursor:
195
206
  self.progressNext()
196
207
  elif(self.dbType == "API"):
197
208
  self.apiNext()
209
+ elif(self.dbType == "JDBC"):
210
+ self.jdbcNext()
198
211
 
199
212
  def mySqlNext(self):
200
213
  resultSet = self.cursor.fetchone()
@@ -275,6 +288,51 @@ class dbObjCursor:
275
288
  else:
276
289
  self.EOF = 1
277
290
 
291
+ def jdbcNext(self):
292
+ try:
293
+ resultSet = self.cursor.fetchone()
294
+ except Exception as e:
295
+ print(e)
296
+ self.EOF = 1
297
+ return
298
+ if(resultSet != None):
299
+ columns = [column[0] for column in self.cursor.description]
300
+ self.fieldByName = (dict(zip(columns, resultSet)))
301
+ #self.fieldNames.append(cursorFieldname[0])
302
+ self.fields = self.fieldByName
303
+ self.EOF = 0
304
+ else:
305
+ self.EOF = 1
306
+
307
+ '''
308
+ if(self.recordPointer <= self.numRows): #???? what about 0?
309
+ self.fieldByName = {}
310
+ self.fieldNames = []
311
+ print(self.recordPointer)
312
+ print(self.numRows)
313
+ print(self.cursor)
314
+ print("-----------------------------------------------------")
315
+ #print(self.cursor.description)
316
+ print(self.lstRecords)
317
+ print(self.recordPointer <= self.numRows)
318
+ print(self.recordPointer)
319
+ print(self.numRows)
320
+ print(type(self.recordPointer))
321
+ print(type(self.numRows))
322
+ columns = [column[0] for column in self.cursor.description]
323
+ self.fieldByName = (dict(zip(columns, self.lstRecords[self.recordPointer])))
324
+ #fieldNo = 0
325
+ #for cursorFieldname in self.cursor.description:
326
+ # self.fieldByName[cursorFieldname[0]] = self.lstRecords[(self.recordPointer-1)][fieldNo]
327
+ # self.fieldNames.append(cursorFieldname[0])
328
+ # fieldNo = fieldNo + 1
329
+ self.fields = self.fieldByName
330
+ self.recordPointer += 1
331
+ self.EOF = 0
332
+ else:
333
+ self.EOF = 1
334
+ '''
335
+
278
336
  def first(self):
279
337
  """Move to the next record in the record set and loads the data into the fields property. Sets EOF at end of records."""
280
338
  if(self.dbType == "MYSQL"):
@@ -323,13 +381,22 @@ class dbObjCursor:
323
381
  self.recordPointer = 1
324
382
  #print('progressExecute (fetchs all) time.time()-t0: ',str(round(time.time()-t0,3)),' seconds')
325
383
 
384
+ def jdbcExecute(self, prmSql):
385
+ self.cursor.execute(prmSql)
386
+ self.lstRecords = self.cursor.fetchall()
387
+ self.numRows = len(self.lstRecords)
388
+ self.numFields = len(self.cursor.description)
389
+ if(self.numRows > 0):
390
+ self.recordPointer = 1
391
+
326
392
  class dbObjConnection:
327
393
  """
328
394
  dbObjConnection is the database connection object. It is responsible for connecting to
329
395
  the database. This object supports access to MySQL, Microsoft SQL Server, Oracle,
330
396
  SQLite3, and Progress DataDirect.
331
397
 
332
- prmDBType can be: MYSQL, MSSQL, ORACLE, SQLITE3, PROGRESS, or API
398
+ prmDBType can be: MYSQL, MSSQL, ORACLE, SQLITE3, PROGRESS, API, or JDBC
399
+
333
400
  """
334
401
  def __init__(self,
335
402
  prmDBType="MYSQL",
@@ -341,6 +408,7 @@ class dbObjConnection:
341
408
  envOracle={},
342
409
  envProgress={},
343
410
  driver='',
411
+ driverClass="",
344
412
  prmApiBaseUrl="",
345
413
  prmApiKey="",
346
414
  prmApiKeyName="sk"):
@@ -355,6 +423,7 @@ class dbObjConnection:
355
423
  self.reconnect_attempts = 0
356
424
  self.using_pymysql = using_pymysql
357
425
  self.drivers = lstLoadedDrivers
426
+ self.driverClass = driverClass
358
427
  if(prmDBType == "API"):
359
428
  self.apiBaseUrl = prmApiBaseUrl
360
429
  self.apiKeyName = prmApiKeyName
@@ -416,6 +485,8 @@ class dbObjConnection:
416
485
  return self.sqlite3Connect(prmDb)
417
486
  elif(self.dbType == "PROGRESS"):
418
487
  return self.progressConnect(prmHost, prmDb, prmUser, prmPass, prmPort)
488
+ elif(self.dbType == "JDBC"):
489
+ return self.jdbcConnect(prmHost, prmDb, prmUser, prmPass)
419
490
 
420
491
  def setConnectSuccess(self):
421
492
  self.reconnect_attempts = 0
@@ -506,6 +577,18 @@ class dbObjConnection:
506
577
  self.setConnectSuccess()
507
578
  return self.msgObj
508
579
 
580
+ def jdbcConnect(self, prmConnString, prmDriver, prmUser, prmPass):
581
+ try:
582
+ self.connHandle = jaydebeapi.connect(self.driverClass, prmConnString, [prmUser, prmPass], prmDriver)
583
+ if(self.connHandle):
584
+ self.setConnectSuccess()
585
+ else:
586
+ self.setConnectFail()
587
+ except Exception as e:
588
+ self.setConnectFail(e)
589
+ print(e)
590
+ return self.msgObj
591
+
509
592
  def reconnect(self):
510
593
  # https://dev.mysql.com/doc/refman/8.0/en/gone-away.html
511
594
  mysql_lost_msg = '''
@@ -569,6 +652,8 @@ class dbObjConnection:
569
652
  return self.progressGetCursor()
570
653
  elif(self.dbType == "API"):
571
654
  return self.apiGetCursor()
655
+ elif(self.dbType == "JDBC"):
656
+ return self.jdbcGetCursor()
572
657
 
573
658
  def setCursorSuccess(self, cursor):
574
659
  if cursor:
@@ -629,6 +714,14 @@ class dbObjConnection:
629
714
  except Exception as e:
630
715
  self.setCursorFail(e)
631
716
 
717
+ def jdbcGetCursor(self):
718
+ try:
719
+ cursor = dbObjCursor(self.connHandle, self.dbType)
720
+ self.setCursorSuccess(cursor)
721
+ return cursor
722
+ except Exception as e:
723
+ self.setCursorFail(e)
724
+
632
725
  def disconnect(self):
633
726
  """Disconnect the connection handle to the database"""
634
727
  if(self.dbType == "MYSQL"):
@@ -641,6 +734,8 @@ class dbObjConnection:
641
734
  self.sqlite3Disconnect()
642
735
  elif(self.dbType == "PROGRESS"):
643
736
  self.progressDisconnect()
737
+ elif(self.dbType == "JDBC"):
738
+ self.jdbcDisconnect()
644
739
 
645
740
  def mySqlDisconnect(self):
646
741
  if self.connHandle and self.connHandle.open:
@@ -670,6 +765,11 @@ class dbObjConnection:
670
765
  def apiDisconnect(self):
671
766
  pass
672
767
 
768
+ def jdbcDisconnect(self):
769
+ if self.connHandle:
770
+ self.connHandle.close()
771
+ self.connHandle = None
772
+
673
773
  def execute(self, prmSql, *args):
674
774
  """Execute the SQL and return a record set if applicable"""
675
775
  if(self.dbType == "MYSQL"):
@@ -684,6 +784,8 @@ class dbObjConnection:
684
784
  return self.progressExecute(prmSql)
685
785
  if(self.dbType in ("API")):
686
786
  return self.apiExecute(prmSql)
787
+ if(self.dbType in ("JDBC")):
788
+ return self.jdbcExecute(prmSql)
687
789
 
688
790
  def fetchall(self, prmSql, *args):
689
791
  """Returns result set as a list of dictionaries"""
@@ -694,18 +796,33 @@ class dbObjConnection:
694
796
  crsr.next()
695
797
  return rset
696
798
 
799
+
697
800
  def fetchone(self, prmSql, *args):
698
801
  """Returns a single row as a dictionary"""
699
802
  crsr = self.execute( prmSql, *args )
700
803
  dictRow = {} if crsr.EOF else crsr.fields
701
804
  return dictRow
702
805
 
806
+
703
807
  def fetchval(self, prmSql, *args):
704
808
  """Returns a single value"""
705
809
  dictRow = self.fetchone( prmSql, *args )
706
810
  listVals = list(dictRow.values())
707
811
  return None if not listVals else listVals[0]
708
812
 
813
+
814
+ def fetchlistvals(self, prmSql, *args):
815
+ """Returns a list of vals; if more than one key/column, returns a list of value tuples"""
816
+ listvals = []
817
+ rset = self.fetchall(prmSql, *args)
818
+ if not rset:
819
+ return []
820
+ for dictRow in rset:
821
+ vals = list(dictRow.values())[0] if len(dictRow.values())==1 else list(dictRow.values())
822
+ listvals.append( vals )
823
+ return listvals
824
+
825
+
709
826
  def insert(self, table, prmDict, update_on_duplicate=False):
710
827
  if update_on_duplicate:
711
828
  keystr = ','.join(prmDict.keys())
@@ -818,7 +935,10 @@ class dbObjConnection:
818
935
  def mySqlExecute(self, prmSql, *args):
819
936
  mySqlCursor = self.getCursor()
820
937
  try:
821
- mySqlCursor.cursor.execute(prmSql, args)
938
+ if args:
939
+ mySqlCursor.cursor.execute(prmSql, args)
940
+ else:
941
+ mySqlCursor.cursor.execute(prmSql)
822
942
  self.msgObj.message = "SQL Executed: "+prmSql
823
943
  self.msgObj.success = True
824
944
  mySqlCursor.numRows = mySqlCursor.cursor.rowcount
@@ -937,7 +1057,6 @@ class dbObjConnection:
937
1057
  try:
938
1058
  # convert sqls to url safe version
939
1059
  #sqls = requests.compat.quote_plus( prmSql )
940
- #r = requests.post(self.apiBaseUrl + "/execute", data = {self.apiKeyName: self.apiKey, "sql": sqls})
941
1060
  sqls = prmSql
942
1061
  headers = {'Content-type':'application/json'}
943
1062
  payload = {self.apiKeyName: self.apiKey, "sql": sqls}
@@ -976,6 +1095,24 @@ class dbObjConnection:
976
1095
  apiCursor.success = False
977
1096
  return apiCursor
978
1097
 
1098
+ def jdbcExecute(self, prmSql):
1099
+ jdbcCursor = self.getCursor()
1100
+ try:
1101
+ jdbcCursor.cursor.execute(prmSql)
1102
+ self.msgObj.message = "SQL Executed: "+prmSql
1103
+ self.msgObj.success = True
1104
+ except Exception as e:
1105
+ self.msgObj.message = "SQL Failed: "+prmSql+" - "+str(e)
1106
+ self.msgObj.success = False
1107
+ jdbcCursor.numFields = 0
1108
+ jdbcCursor.numRows = 0
1109
+ jdbcCursor.EOF = 1
1110
+ jdbcCursor.success = False
1111
+ print(self.msgObj.message)
1112
+ return jdbcCursor
1113
+ jdbcCursor.next()
1114
+ return jdbcCursor
1115
+
979
1116
  def commit(self):
980
1117
  if(self.dbType == "MYSQL"):
981
1118
  self.connHandle.commit()
File without changes