Skip to content

Commit

Permalink
fixed expression.with_alias(name) and added support for expression.wi…
Browse files Browse the repository at this point in the history
…th_alias("tablename.fieldname")
  • Loading branch information
mdipierro committed Nov 30, 2024
1 parent 136e501 commit 16c9395
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 14 deletions.
16 changes: 12 additions & 4 deletions pydal/adapters/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,10 +288,18 @@ def _parse(
#: otherwise we set the value in extras
else:
#: fields[j] may be None if only 'colnames' was specified in db.executesql()
f_itype, ftype = (
fields[j] and [fields[j]._itype, fields[j].type] or [None, None]
)
field = fields[j]
f_itype, ftype = (field and [field._itype, field.type] or [None, None])
value = self.parse_value(value, f_itype, ftype, blob_decode)
# for aliased fields use the aliased name
if isinstance(field, Expression) and field.op == self.dialect._as:
colname = field.second
# if the alias is a tablename.fieldname add the column to the table
if field.tablename:
if field.tablename not in new_row:
new_row[field.tablename] = self.db.Row()
new_row[field.tablename][colname] = value
continue
extras[colname] = value
if not fields[j]:
new_row[colname] = value
Expand All @@ -300,7 +308,7 @@ def _parse(
if new_column_match is not None:
new_column_name = new_column_match.group(1)
new_row[new_column_name] = value
#: add extras if needed (eg. operations results)
#: add extra if not empty
if extras:
new_row["_extra"] = extras
#: add virtuals
Expand Down
41 changes: 31 additions & 10 deletions pydal/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -1483,12 +1483,23 @@ def __new__(cls, *args, **kwargs):
new_cls = super(Expression, cls).__new__(cls)
return new_cls

def __init__(self, db, op, first=None, second=None, type=None, **optional_args):
def __init__(
self,
db,
op,
first=None,
second=None,
type=None,
tablename=None,
**optional_args,
):
self.db = db
self.op = op
self.first = first
self.second = second
self._table = getattr(first, "_table", None)
# this used to place an expression with alias inside a table
self.tablename = tablename
if not type and first and hasattr(first, "type"):
self.type = first.type
else:
Expand Down Expand Up @@ -1592,6 +1603,11 @@ def __getitem__(self, i):
return self[i : i + 1]

def __str__(self):
if self.op == self._dialect._as:
return self.second
return str(self.db._adapter.expand(self, self.type))

def __repr__(self):
return str(self.db._adapter.expand(self, self.type))

def __or__(self, other): # for use in sortby
Expand Down Expand Up @@ -1733,12 +1749,11 @@ def contains(self, value, all=False, case_sensitive=False):
)

def with_alias(self, alias):
return Expression(self.db, self._dialect._as, self, alias, self.type)

@property
def alias(self):
if self.op == self._dialect._as:
return self.second
if "." in alias:
tablename, alias = alias.split(".", 1)
else:
tablename = None
return Expression(self.db, self._dialect._as, self, alias, self.type, tablename)

# GIS expressions

Expand Down Expand Up @@ -3359,10 +3374,16 @@ def __getslice__(self, a, b):
)

def __getitem__(self, i):
"""
This extract a row from a set of rows and tries to compactify
- if there are columns from more than one table, it returns a dict of dicts
- if there are columns for a single table it returns a single dict
- if there are extra columns (including aliased) and a single table, adds the extra columns to the one table
"""
if isinstance(i, slice):
return self.__getslice__(i.start, i.stop)
row = self.records[i]
keys = list(row.keys())
keys = list(row)
if self.compact and len(keys) == 1 and keys[0] != "_extra":
return row[keys[0]]
return row
Expand Down Expand Up @@ -3604,7 +3625,7 @@ def render(self, i=None, fields=None):
representer in DAL instance"
)
row = copy.deepcopy(self.records[i])
keys = list(row.keys())
keys = list(row)
if not fields:
fields = [f for f in self.fields if isinstance(f, Field) and f.represent]
for field in fields:
Expand Down Expand Up @@ -3676,7 +3697,7 @@ def __next__(self):
# in
# <Row {'id': 1L, 'name': 'web2py'}>
# normally accomplished by Rows.__get_item__
keys = list(row.keys())
keys = list(row)
if len(keys) == 1 and keys[0] != "_extra":
row = row[keys[0]]
return row
Expand Down

0 comments on commit 16c9395

Please sign in to comment.