Skip to content
This repository has been archived by the owner on Aug 5, 2024. It is now read-only.

Commit

Permalink
fix: Add support for handling enums in a jsonb column
Browse files Browse the repository at this point in the history
  • Loading branch information
rsavoye committed Feb 28, 2024
1 parent f7e6930 commit 71d8709
Showing 1 changed file with 93 additions and 13 deletions.
106 changes: 93 additions & 13 deletions tm_admin/pgsupport.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
from tm_admin.yamlfile import YamlFile
from tm_admin.projects.projects_class import ProjectsTable
from shapely.geometry import Polygon, Point, shape

from tm_admin.projects.projects_teams_class import Projects_teamsTable
# from tm_admin.teams.teams_members_class import Teams_membersTable

# Find the other files for this project
import tm_admin as tma
Expand Down Expand Up @@ -106,9 +107,7 @@ async def deleteRecord(self,
record_ids: list,
):
"""
Insert a record in a database table. All the primary tables auto-increment
the id column. If id is set in the record, then it uses that value, otherwise
it increments.
Delete a record from a database table.
Args:
record_id (list): The record IDs to delete
Expand Down Expand Up @@ -182,7 +181,7 @@ async def insertRecords(self,
keys = str(list(data.keys())).replace("'", "")[1:-1]
values = str(list(data.values()))[1:-1]
sql = f"INSERT INTO {self.table}({keys}) VALUES({values})"
print(sql)
# print(sql)
result = await self.execute(sql)

if len(result) == 0:
Expand Down Expand Up @@ -251,27 +250,95 @@ async def appendColumns(self,

async def getColumns(self,
columns: list,
where: str = None,
where: list = list(),
):
"""
Get columns from a database table.
Args:
where (str): The condition to limit the records, might return
column (list): The column names to include in the output
where (list): The conditions to limit the records, might return
more than one
column (str): The column name
jsonb (bool): Whether to loop through and convert the jsonb to a dict
Returns:
(list): The data of this column
(list): The data for this column
"""
get = str(columns)[1:-1].replace("'", "")

check = str()
for test in where:
for k, v in test.items():
if type(v) == dict:
for k1, v1 in v.items():
# teams->'teams' @? '$[*] ? (@.role == 1)
# FIXME: is it an internal Enum ?
check = f"{k}->'{k}' @? '$[*] ? (@.{k1} == {v1})'"
continue
# if k in self.types:
# if self.types[k] == 'jsonb':
# breakpoint()
if v == 'null':
check = f"{k} IS NOT NULL"
elif len(check) == 0:
check = f"{k}={v}"

if where:
sql = f"SELECT {get} FROM {self.table} {where}"
sql = f"SELECT {get} FROM {self.table} WHERE {check}"
else:
sql = f"SELECT {get} FROM {self.table}"
# print(sql)
results = await self.execute(sql)

types = dict()
# We only need to get the data types once
for key, value in results[0].items():
if type(value) == str and value[0] == "{":
item = eval(value)
for k, v in item[key][0].items():
obj = eval(f"{self.table.capitalize()}_{key}Table({v})")
xx = obj.data[k]
# It's an internal data structure from a *_class.py file
if type(xx) != int and type(xx) != str:
types[k] = xx

data = list()
raw = False # FIXME: for now force converting the enums
if raw:
for record in results:
# print(record)
for k, v in record.items():
# it's a dictionary masquarading as a string, but for us it's
# a jsonb column
if self.types[k] == 'jsonb':
entry = eval(f"%s" % record.get(k))
if not entry:
continue
new = dict()
# Entry = eval(f"{record.get(k)})
if k in entry:
for item in entry[k]:
for k1, v1 in item.items():
# It's in types_tm.py, so convert the value to the Enum
if k1 in types:
enumval = type(types[k1])
if v1 == 0:
newenum = enumval(1)
else:
newenum = enumval(v1)
new[k1] = newenum
else:
new[k1] = v1
else:
# We see this in old data, just one entry
new = entry
data.append(new)
else:
data.append({k: v})
return data

# SELECT * FROM teams WHERE EXISTS (SELECT TRUE FROM jsonb_array_elements(team_members->'members') x WHERE x->>'function'='MANAGER');

return results

async def main():
Expand Down Expand Up @@ -311,7 +378,7 @@ async def main():

geom = Polygon()
center = Point()
results = await pgs.getColumns(["id", "name"])
# results = await pgs.getColumns(["id", "name"])
pt = ProjectsTable(author_id=1, geometry=geom, centroid=center,
created='2021-12-15 09:58:02.672236',
task_creation_mode='GRID', status='DRAFT',
Expand All @@ -328,9 +395,22 @@ async def main():
# print(f"ID: {id}")
# await pgs.updateProject(pt2)

await pgs.deleteRecord([id])
log.info(f"Deleted {id} from the database")
# await pgs.deleteRecord([id])
# log.info(f"Deleted {id} from the database")

data = await pgs.getColumns(['id', 'teams'])
print(f"{len(data)} records returned from simple")

foo = {'id': 12315}
data = await pgs.getColumns(['id', 'teams'], [foo])
print(f"{len(data)} records returned from foo")

foo = {'teams': {"role": tm_admin.types_tm.Teamroles.TEAM_READ_ONLY, "team_id": 144}}
data = await pgs.getColumns(['id', 'teams'], [foo])
print(f"{len(data)} records returned from NULL")
# print(data)


# user = UsersTable(username='foobar', name='barfoo', picture_url='URI', email_address="[email protected]", mapping_level='INTERMEDIATE', role='VALIDATOR')
# await pgs.insertRecords([user])

Expand Down

0 comments on commit 71d8709

Please sign in to comment.