rda-python-common 2.0.0__py3-none-any.whl

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.
@@ -0,0 +1,260 @@
1
+ #
2
+ ###############################################################################
3
+ #
4
+ # Title : pg_split.py -- PostgreSQL DataBase Interface foe table wfile
5
+ # Author : Zaihua Ji, zji@ucar.edu
6
+ # Date : 09/010/2024
7
+ # 2025-01-10 transferred to package rda_python_common from
8
+ # https://github.com/NCAR/rda-shared-libraries.git
9
+ # 2025-12-01 convert to class PgSplit
10
+ # Purpose : Python library module to handle query and manipulate table wfile
11
+ #
12
+ # Github : https://github.com/NCAR/rda-python-common.git
13
+ #
14
+ ###############################################################################
15
+
16
+ import os
17
+ import re
18
+ from os import path as op
19
+ from .pg_dbi import PgDBI
20
+ from .pg_util import PgUtil
21
+
22
+ class PgSplit(PgDBI):
23
+
24
+ def __init__(self):
25
+ super().__init__() # initialize parent class
26
+
27
+ # compare wfile records between tables wfile and wfile_dNNNNNN,
28
+ # and return the records need to be added, modified and deleted
29
+ @staticmethod
30
+ def compare_wfile(wfrecs, dsrecs):
31
+ flds = dsrecs.keys()
32
+ flen = len(flds)
33
+ arecs = dict(zip(flds, [[]]*flen))
34
+ mrecs = {}
35
+ drecs = []
36
+ wfcnt = len(wfrecs['wid'])
37
+ dscnt = len(dsrecs['wid'])
38
+ pi = pj = -1
39
+ i = j = 0
40
+ while i < wfcnt and j < dscnt:
41
+ if i > pi:
42
+ wfrec = PgUtil.onerecord(wfrecs, i)
43
+ wwid = wfrec['wid']
44
+ pi = i
45
+ if j > pj:
46
+ dsrec = PgUtil.onerecord(dsrecs, j)
47
+ dwid = dsrec['wid']
48
+ pj = j
49
+ if wwid == dwid:
50
+ mrec = PgSplit.compare_one_record(flds, wfrec, dsrec)
51
+ if mrec: mrecs[wwid] = mrec
52
+ i += 1
53
+ j += 1
54
+ elif wwid > dwid:
55
+ drecs.append(dwid)
56
+ j += 1
57
+ else:
58
+ for fld in flds:
59
+ arecs[fld].append(wfrec[fld])
60
+ i += 1
61
+ if i < wfcnt:
62
+ for fld in flds:
63
+ arecs[fld].extend(wfrecs[fld][i:wfcnt])
64
+ elif j < dscnt:
65
+ drecs.extend(dsrecs['wid'][j:dscnt])
66
+ if len(arecs['wid']) == 0: arecs = {}
67
+ return (arecs, mrecs, drecs)
68
+
69
+ # Compare column values and return the new one; empty if the same
70
+ @staticmethod
71
+ def compare_one_record(flds, wfrec, dsrec):
72
+ mrec = {}
73
+ for fld in flds:
74
+ if wfrec[fld] != dsrec[fld]: mrec[fld] = wfrec[fld]
75
+ return mrec
76
+
77
+ # convert wfile records to wfile_dsid records
78
+ @staticmethod
79
+ def wfile2wdsid(wfrecs, wids = None):
80
+ dsrecs = {}
81
+ if wfrecs:
82
+ for fld in wfrecs:
83
+ if fld == 'dsid': continue
84
+ dsrecs[fld] = wfrecs[fld]
85
+ if wids: dsrecs['wid'] = wids
86
+ return dsrecs
87
+
88
+ # trim wfile records
89
+ @staticmethod
90
+ def trim_wfile_fields(wfrecs):
91
+ records = {}
92
+ if 'wfile' in wfrecs: records['wfile'] = wfrecs['wfile']
93
+ if 'dsid' in wfrecs: records['dsid'] = wfrecs['dsid']
94
+ return records
95
+
96
+ # check the condition string, and add dsid if needed
97
+ @staticmethod
98
+ def get_dsid_condition(dsid, condition):
99
+ if condition:
100
+ if re.search(r'(^|.| )(wid|dsid)\s*=', condition):
101
+ return condition
102
+ else:
103
+ dscnd = "wfile.dsid = '{}' ".format(dsid)
104
+ if not re.match(r'^\s*(ORDER|GROUP|HAVING|OFFSET|LIMIT)\s', condition, re.I): dscnd += 'AND '
105
+ return dscnd + condition # no where clause, append directly
106
+ else:
107
+ return "wfile.dsid = '{}'".format(dsid)
108
+
109
+ # insert one record into wfile and/or wfile_dsid
110
+ def pgadd_wfile(self, dsid, wfrec, logact = None, getid = None):
111
+ if logact is None: logact = self.LOGERR
112
+ record = {'wfile' : wfrec['wfile'],
113
+ 'dsid' : (wfrec['dsid'] if 'dsid' in wfrec else dsid)}
114
+ wret = self.pgadd('wfile', record, logact, 'wid')
115
+ if wret:
116
+ record = self.wfile2wdsid(wfrec, wret)
117
+ self.pgadd('wfile_' + dsid, record, logact|self.ADDTBL)
118
+ if logact&self.AUTOID or getid:
119
+ return wret
120
+ else:
121
+ return 1 if wret else 0
122
+
123
+ # insert multiple records into wfile and/or wfile_dsid
124
+ def pgmadd_wfile(self, dsid, wfrecs, logact = None, getid = None):
125
+ if logact is None: logact = self.LOGERR
126
+ records = {'wfile' : wfrecs['wfile'],
127
+ 'dsid' : (wfrecs['dsid'] if 'dsid' in wfrecs else [dsid]*len(wfrecs['wfile']))}
128
+ wret = self.pgmadd('wfile', records, logact, 'wid')
129
+ wcnt = wret if isinstance(wret, int) else len(wret)
130
+ if wcnt:
131
+ records = self.wfile2wdsid(wfrecs, wret)
132
+ self.pgmadd('wfile_' + dsid, records, logact|self.ADDTBL)
133
+ if logact&self.AUTOID or getid:
134
+ return wret
135
+ else:
136
+ return wcnt
137
+
138
+ # update one or multiple rows in wfile and/or wfile_dsid
139
+ # exclude dsid in condition
140
+ def pgupdt_wfile(self, dsid, wfrec, condition, logact = None):
141
+ if logact is None: logact = self.LOGERR
142
+ record = self.trim_wfile_fields(wfrec)
143
+ if record:
144
+ wret = self.pgupdt('wfile', record, self.get_dsid_condition(dsid, condition), logact)
145
+ else:
146
+ wret = 1
147
+ if wret:
148
+ record = self.wfile2wdsid(wfrec)
149
+ if record: wret = self.pgupdt("wfile_" + dsid, record, condition, logact|self.ADDTBL)
150
+ return wret
151
+
152
+ # update one row in wfile and/or wfile_dsid with dsid change
153
+ # exclude dsid in condition
154
+ def pgupdt_wfile_dsid(self, dsid, odsid, wfrec, wid, logact = None):
155
+ if logact is None: logact = self.LOGERR
156
+ record = self.trim_wfile_fields(wfrec)
157
+ cnd = 'wid = {}'.format(wid)
158
+ if record:
159
+ wret = self.pgupdt('wfile', record, cnd, logact)
160
+ else:
161
+ wret = 1
162
+ if wret:
163
+ record = self.wfile2wdsid(wfrec)
164
+ tname = 'wfile_' + dsid
165
+ doupdt = True
166
+ if odsid and odsid != dsid:
167
+ oname = 'wfile_' + odsid
168
+ pgrec = self.pgget(oname, '*', cnd, logact|self.ADDTBL)
169
+ if pgrec:
170
+ for fld in record:
171
+ pgrec[fld] = record[fld]
172
+ wret = self.pgadd(tname, pgrec, logact|self.ADDTBL)
173
+ if wret: self.pgdel(oname, cnd, logact)
174
+ doupdt = False
175
+ if doupdt and record:
176
+ wret = self.pgupdt(tname, record, cnd, logact|self.ADDTBL)
177
+ return wret
178
+
179
+ # delete one or multiple rows in wfile and/or wfile_dsid, and add the record(s) into wfile_delete
180
+ # exclude dsid in conidtion
181
+ def pgdel_wfile(self, dsid, condition, logact = None):
182
+ if logact is None: logact = self.LOGERR
183
+ pgrecs = self.pgmget_wfile(dsid, '*', condition, logact|self.ADDTBL)
184
+ wret = self.pgdel('wfile', self.get_dsid_condition(dsid, condition), logact)
185
+ if wret: self.pgdel("wfile_" + dsid, condition, logact)
186
+ if wret and pgrecs: self.pgmadd('wfile_delete', pgrecs, logact)
187
+ return wret
188
+
189
+ # delete one or multiple rows in sfile, and add the record(s) into sfile_delete
190
+ def pgdel_sfile(self, condition, logact = None):
191
+ if logact is None: logact = self.LOGERR
192
+ pgrecs = self.pgmget('sfile', '*', condition, logact)
193
+ sret = self.pgdel('sfile', condition, logact)
194
+ if sret and pgrecs: self.pgmadd('sfile_delete', pgrecs, logact)
195
+ return sret
196
+
197
+ # update one or multiple rows in wfile and/or wfile_dsid for multiple dsid
198
+ # exclude dsid in condition
199
+ def pgupdt_wfile_dsids(self, dsid, dsids, brec, bcnd, logact = None):
200
+ if logact is None: logact = self.LOGERR
201
+ record = self.trim_wfile_fields(brec)
202
+ if record:
203
+ wret = self.pgupdt("wfile", record, bcnd, logact)
204
+ else:
205
+ wret = 1
206
+ if wret:
207
+ record = self.wfile2wdsid(brec)
208
+ if record:
209
+ wret = 0
210
+ dids = [dsid]
211
+ if dsids: dids.extend(dsids.split(','))
212
+ for did in dids:
213
+ wret += self.pgupdt("wfile_" + did, record, bcnd, logact|self.ADDTBL)
214
+ return wret
215
+
216
+ # get one record from wfile or wfile_dsid
217
+ # exclude dsid in fields and condition
218
+ def pgget_wfile(self, dsid, fields, condition, logact = None):
219
+ if logact is None: logact = self.LOGERR
220
+ tname = "wfile_" + dsid
221
+ flds = fields.replace('wfile.', tname + '.')
222
+ cnd = condition.replace('wfile.', tname + '.')
223
+ record = self.pgget(tname, flds, cnd, logact|self.ADDTBL)
224
+ if record and flds == '*': record['dsid'] = dsid
225
+ return record
226
+
227
+ # get one record from wfile or wfile_dsid joing other tables
228
+ # exclude dsid in fields and condition
229
+ def pgget_wfile_join(self, dsid, tjoin, fields, condition, logact = None):
230
+ if logact is None: logact = self.LOGERR
231
+ tname = "wfile_" + dsid
232
+ flds = fields.replace('wfile.', tname + '.')
233
+ jname = tname + ' ' + tjoin.replace('wfile.', tname + '.')
234
+ cnd = condition.replace('wfile.', tname + '.')
235
+ record = self.pgget(jname, flds, cnd, logact|self.ADDTBL)
236
+ if record and flds == '*': record['dsid'] = dsid
237
+ return record
238
+
239
+ # get multiple records from wfile or wfile_dsid
240
+ # exclude dsid in fields and condition
241
+ def pgmget_wfile(self, dsid, fields, condition, logact = None):
242
+ if logact is None: logact = self.LOGERR
243
+ tname = "wfile_" + dsid
244
+ flds = fields.replace('wfile.', tname + '.')
245
+ cnd = condition.replace('wfile.', tname + '.')
246
+ records = self.pgmget(tname, flds, cnd, logact|self.ADDTBL)
247
+ if records and flds == '*': records['dsid'] = [dsid]*len(records['wid'])
248
+ return records
249
+
250
+ # get multiple records from wfile or wfile_dsid joining other tables
251
+ # exclude dsid in fields and condition
252
+ def pgmget_wfile_join(self, dsid, tjoin, fields, condition, logact = None):
253
+ if logact is None: logact = self.LOGERR
254
+ tname = "wfile_" + dsid
255
+ flds = fields.replace('wfile.', tname + '.')
256
+ jname = tname + ' ' + tjoin.replace('wfile.', tname + '.')
257
+ cnd = condition.replace('wfile.', tname + '.')
258
+ records = self.pgmget(jname, flds, cnd, logact|self.ADDTBL)
259
+ if records and flds == '*': records['dsid'] = [dsid]*len(records['wid'])
260
+ return records