in src/Kusto.Language/Binder/Binder_NodeBinder.cs [1894:2082]
public override SemanticInfo VisitFindOperator(FindOperator node)
{
var diagnostics = s_diagnosticListPool.AllocateFromPool();
var columns = s_columnListPool.AllocateFromPool();
var refColumns = s_columnListPool.AllocateFromPool();
var refTables = s_tableListPool.AllocateFromPool();
var colNameMap = s_stringSetPool.AllocateFromPool();
try
{
_binder.CheckQueryOperatorParameters(node.Parameters, QueryOperatorParameters.FindParameters, diagnostics);
_binder.CheckIsExactType(node.Condition, ScalarTypes.Bool, diagnostics);
var withSource = node.Parameters.GetParameter(QueryOperatorParameters.WithSource);
string sourceColumnName = (withSource != null) ? GetNameDeclarationName(withSource.Expression) ?? "source_" : "source_";
columns.Add(new ColumnSymbol(sourceColumnName, ScalarTypes.String));
var tables = _binder.GetFindTables(node);
var resultIsOpen = tables.Any(t => t.IsOpen);
var explicitPack = false;
if (node.Project == null || node.Project.ProjectKeyword.Kind == SyntaxKind.ProjectSmartKeyword)
{
// project-smart
// only consider tables that have column references
_binder.GetReferencedColumnsInTree(node.Condition, refColumns);
if (tables.Count == 1)
{
// only one table
refTables.AddRange(tables);
}
else if (ReferencesAllTables(node))
{
// * references all columns from all tables
refTables.AddRange(tables);
}
else
{
// only include tables that have a column the same name as one
// referenced in the condition
foreach (var t in tables)
{
foreach (var c in refColumns)
{
// if the table has a column of the same name
if (t.IsOpen || t.TryGetColumn(c.Name, out _))
{
refTables.Add(t);
break;
}
}
}
}
// any column that is common to all referenced tables
var commonColumnsTable = _binder.GetTableOfCommonColumns(refTables);
columns.AddRange(commonColumnsTable.Columns);
// any columns referenced explicitly in the predicate
foreach (var c in refColumns)
{
if (!columns.Contains(c))
{
columns.Add(c);
}
}
// check to see if there is a table that has extra columns that need to be packed
foreach (var c in columns)
{
colNameMap.Add(c.Name);
}
var packExtraColumns = false;
foreach (var t in refTables)
{
// if table is open, then we don't know what ends up in projected set at execution time
if (t.IsOpen)
continue;
// if the table has more columns than end up in the projected set
// then the rest will appear in a packed_ column
foreach (var c in t.Columns)
{
if (!colNameMap.Contains(c.Name))
{
packExtraColumns = true;
break;
}
}
}
if (packExtraColumns)
{
columns.Add(new ColumnSymbol("pack_", ScalarTypes.Dynamic));
}
UnifyColumnsWithSameNameAndType(columns);
}
else
{
// explicit projection
resultIsOpen = false;
// regular project
for (int i = 0; i < node.Project.Columns.Count; i++)
{
var exp = node.Project.Columns[i].Element;
switch (exp)
{
case PackExpression _:
explicitPack = true;
if (i == node.Project.Columns.Count - 1)
{
columns.Add(new ColumnSymbol("pack_", ScalarTypes.Dynamic));
}
else
{
diagnostics.Add(DiagnosticFacts.GetPackMustBeLastItemInList().WithLocation(exp));
}
break;
case TypedColumnReference tc:
_binder.CheckIsColumn(tc.Column, diagnostics);
if (_binder.GetReferencedSymbol(tc.Column) is ColumnSymbol c)
{
var type = _binder.GetTypeFromTypeExpression(tc.Type, diagnostics);
columns.Add(new ColumnSymbol(c.Name, type));
}
break;
case NameReference nr:
_binder.CheckIsColumn(nr, diagnostics);
if (_binder.GetReferencedSymbol(nr) is ColumnSymbol c2)
{
columns.Add(c2);
}
break;
}
}
}
if (node.ProjectAway != null && node.ProjectAway.Columns.Count > 0)
{
if (node.ProjectAway.Columns[0].Element is StarExpression)
{
columns.RemoveAll(c => c.Name != sourceColumnName && (c.Name != "pack_" || !explicitPack));
}
else
{
// remove specified columns
var columnNamesToRemove = s_stringSetPool.AllocateFromPool();
try
{
for (int i = 0; i < node.ProjectAway.Columns.Count; i++)
{
var columnExp = node.ProjectAway.Columns[i].Element;
if (_binder.GetReferencedSymbol(columnExp) is ColumnSymbol col)
{
columnNamesToRemove.Add(col.Name);
}
}
columns.RemoveAll(c => columnNamesToRemove.Contains(c.Name));
}
finally
{
s_stringSetPool.ReturnToPool(columnNamesToRemove);
}
}
}
var resultTable = new TableSymbol(columns).WithIsOpen(resultIsOpen);
return new SemanticInfo(resultTable, diagnostics);
}
finally
{
s_diagnosticListPool.ReturnToPool(diagnostics);
s_columnListPool.ReturnToPool(columns);
s_columnListPool.ReturnToPool(refColumns);
s_tableListPool.ReturnToPool(refTables);
s_stringSetPool.ReturnToPool(colNameMap);
}
}