Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix for prop pivot out with array source #1794

Merged
merged 2 commits into from
Jul 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions synapse/lib/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1662,7 +1662,7 @@ async def run(self, runt, genr):
if valu is None:
continue

if isinstance(prop.type, s_types.Array):
if prop.type.isarray:
fname = prop.type.arraytype.name
if runt.model.forms.get(fname) is None:
if not warned:
Expand Down Expand Up @@ -1704,6 +1704,9 @@ async def run(self, runt, genr):


class PropPivot(PivotOper):
'''
:foo -> bar:foo
'''

async def run(self, runt, genr):
warned = False
Expand All @@ -1720,14 +1723,24 @@ async def run(self, runt, genr):
if self.isjoin:
yield node, path

valu = await self.kids[0].compute(path)
srcprop, valu = await self.kids[0].getPropAndValu(path)
if valu is None:
continue

# TODO cache/bypass normalization in loop!
try:
# pivoting from an array prop to a non-array prop needs an extra loop
if srcprop.type.isarray and not prop.type.isarray:

for arrayval in valu:
async for pivo in runt.snap.nodesByPropValu(prop.full, '=', arrayval):
yield pivo, path.fork(pivo)

continue

async for pivo in runt.snap.nodesByPropValu(prop.full, '=', valu):
yield pivo, path.fork(pivo)

except (s_exc.BadTypeValu, s_exc.BadLiftValu) as e:
if not warned:
logger.warning(f'Caught error during pivot: {e.items()}')
Expand Down Expand Up @@ -2069,7 +2082,7 @@ async def cond(node, path):
mesg = f'No property named {name}.'
raise s_exc.NoSuchProp(name=name)

if not isinstance(prop.type, s_types.Array):
if not prop.type.isarray:
mesg = f'Array filter syntax is invalid for non-array prop {name}.'
raise s_exc.BadCmprType(mesg=mesg)

Expand Down
6 changes: 6 additions & 0 deletions synapse/lib/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class Type:
_opt_defs = ()
stortype: int = None # type: ignore

# a fast-access way to determine if the type is an array
# ( due to hot-loop needs in the storm runtime )
isarray = False

def __init__(self, modl, name, info, opts):
'''
Construct a new Type object.
Expand Down Expand Up @@ -379,6 +383,8 @@ def repr(self, valu):

class Array(Type):

isarray = True

def postTypeInit(self):

self.isuniq = self.opts.get('uniq', False)
Expand Down
6 changes: 6 additions & 0 deletions synapse/tests/test_lib_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,12 @@ async def test_ast_array_pivot(self):
nodes = await core.nodes('test:arrayprop:ints -> test:int')
self.len(3, nodes)

nodes = await core.nodes('test:arrayprop:ints :ints -> test:int')
self.len(3, nodes)

nodes = await core.nodes('test:arrayprop:ints :ints -> *')
self.len(3, nodes)

nodes = await core.nodes('test:arrayprop:ints -> *')
self.len(3, nodes)

Expand Down