internal static TableExpressionFromSet GenerateFromSet(TableSelectExpression selectExpression, ITableSpaceContext db)
        {
            // Get the 'from_clause' from the table expression
            FromClause fromClause = selectExpression.From;

            // Create a TableExpressionFromSet for this table expression
            var fromSet = new TableExpressionFromSet(db.IsInCaseInsensitive);

            // Add all tables from the 'fromClause'
            foreach (FromTable fromTable in fromClause.AllTables)
            {
                string     uniqueKey = fromTable.UniqueKey;
                ObjectName alias     = fromTable.Alias;

                // If this is a sub-command table,
                if (fromTable.IsSubQueryTable)
                {
                    // eg. FROM ( SELECT id FROM Part )
                    TableSelectExpression  subQuery        = fromTable.SubSelect;
                    TableExpressionFromSet subQueryFromSet = GenerateFromSet(subQuery, db);

                    // The aliased name of the table
                    ObjectName aliasTableName = null;
                    if (alias != null)
                    {
                        aliasTableName = alias.Clone();
                    }

                    var source = new FromTableSubQuerySource(db.IsInCaseInsensitive, uniqueKey, subQuery, subQueryFromSet, aliasTableName);
                    // Add to list of subquery tables to add to command,
                    fromSet.AddTable(source);
                }
                else
                {
                    // Else must be a standard command table,
                    ObjectName name = fromTable.Name;

                    // Resolve to full table name
                    ObjectName tableName = db.ResolveTableName(name);

                    if (!db.TableExists(tableName))
                    {
                        throw new ApplicationException("Table '" + tableName + "' was not found.");
                    }

                    ObjectName givenName = null;
                    if (alias != null)
                    {
                        givenName = alias.Clone();
                    }

                    // Get the ITableQueryInfo object for this table name (aliased).
                    ITableQueryInfo tableQueryInfo = db.GetTableQueryInfo(tableName, givenName);
                    var             source         = new FromTableDirectSource(db.IsInCaseInsensitive, tableQueryInfo, uniqueKey, givenName, tableName);

                    fromSet.AddTable(source);
                }
            }              // foreach

            // Set up functions, aliases and exposed variables for this from set,

            // For each column being selected
            foreach (SelectColumn col in selectExpression.Columns)
            {
                // Is this a glob?  (eg. Part.* )
                if (col.IsGlob)
                {
                    // Find the columns globbed and add to the 'selectedColumns' result.
                    if (col.IsAll)
                    {
                        fromSet.ExposeAllColumns();
                    }
                    else
                    {
                        // Otherwise the glob must be of the form '[table name].*'
                        string     tname = col.GlobPrefix;
                        ObjectName tn    = ObjectName.Parse(tname);
                        fromSet.ExposeAllColumnsFromSource(tn);
                    }
                }
                else
                {
                    // Otherwise must be a standard column reference.  Note that at this
                    // time we aren't sure if a column expression is correlated and is
                    // referencing an outer source.  This means we can't verify if the
                    // column expression is valid or not at this point.

                    // If this column is aliased, add it as a function reference to the
                    // TableExpressionFromSet.
                    var varExpression = (VariableExpression)col.Expression;

                    ObjectName alias       = col.Alias;
                    ObjectName v           = varExpression.VariableName;
                    bool       aliasMatchV = (v != null && alias != null && fromSet.StringCompare(v.Name, alias.Name));
                    if (alias != null && !aliasMatchV)
                    {
                        fromSet.AddFunctionRef(alias.Name, col.Expression);
                        fromSet.ExposeVariable(alias.Clone());
                    }
                    else if (v != null)
                    {
                        ObjectName resolved = fromSet.ResolveReference(v);
                        fromSet.ExposeVariable(resolved ?? v);
                    }
                    else
                    {
                        string funName = col.Expression.ToString();
                        fromSet.AddFunctionRef(funName, col.Expression);
                        fromSet.ExposeVariable(ObjectName.Parse(funName));
                    }
                }
            }              // for each column selected

            return(fromSet);
        }
        internal static TableExpressionFromSet GenerateFromSet(TableSelectExpression selectExpression, ITableSpaceContext db)
        {
            // Get the 'from_clause' from the table expression
            FromClause fromClause = selectExpression.From;

            // Create a TableExpressionFromSet for this table expression
            var fromSet = new TableExpressionFromSet(db.IsInCaseInsensitive);

            // Add all tables from the 'fromClause'
            foreach (FromTable fromTable in fromClause.AllTables) {
                string uniqueKey = fromTable.UniqueKey;
                ObjectName alias = fromTable.Alias;

                // If this is a sub-command table,
                if (fromTable.IsSubQueryTable) {
                    // eg. FROM ( SELECT id FROM Part )
                    TableSelectExpression subQuery = fromTable.SubSelect;
                    TableExpressionFromSet subQueryFromSet = GenerateFromSet(subQuery, db);

                    // The aliased name of the table
                    ObjectName aliasTableName = null;
                    if (alias != null)
                        aliasTableName = alias.Clone();

                    var source = new FromTableSubQuerySource(db.IsInCaseInsensitive, uniqueKey, subQuery, subQueryFromSet, aliasTableName);
                    // Add to list of subquery tables to add to command,
                    fromSet.AddTable(source);
                } else {
                    // Else must be a standard command table,
                    ObjectName name = fromTable.Name;

                    // Resolve to full table name
                    ObjectName tableName = db.ResolveTableName(name);

                    if (!db.TableExists(tableName))
                        throw new ApplicationException("Table '" + tableName + "' was not found.");

                    ObjectName givenName = null;
                    if (alias != null)
                        givenName = alias.Clone();

                    // Get the ITableQueryInfo object for this table name (aliased).
                    ITableQueryInfo tableQueryInfo = db.GetTableQueryInfo(tableName, givenName);
                    var source = new FromTableDirectSource(db.IsInCaseInsensitive, tableQueryInfo, uniqueKey, givenName, tableName);

                    fromSet.AddTable(source);
                }
            }  // foreach

            // Set up functions, aliases and exposed variables for this from set,

            // For each column being selected
            foreach (SelectColumn col in selectExpression.Columns) {
                // Is this a glob?  (eg. Part.* )
                if (col.IsGlob) {
                    // Find the columns globbed and add to the 'selectedColumns' result.
                    if (col.IsAll) {
                        fromSet.ExposeAllColumns();
                    } else {
                        // Otherwise the glob must be of the form '[table name].*'
                        string tname = col.GlobPrefix;
                        ObjectName tn = ObjectName.Parse(tname);
                        fromSet.ExposeAllColumnsFromSource(tn);
                    }
                } else {
                    // Otherwise must be a standard column reference.  Note that at this
                    // time we aren't sure if a column expression is correlated and is
                    // referencing an outer source.  This means we can't verify if the
                    // column expression is valid or not at this point.

                    // If this column is aliased, add it as a function reference to the
                    // TableExpressionFromSet.
                    var varExpression = (VariableExpression)col.Expression;

                    ObjectName alias = col.Alias;
                    ObjectName v =  varExpression.VariableName;
                    bool aliasMatchV = (v != null && alias != null && fromSet.StringCompare(v.Name, alias.Name));
                    if (alias != null && !aliasMatchV) {
                        fromSet.AddFunctionRef(alias.Name, col.Expression);
                        fromSet.ExposeVariable(alias.Clone());
                    } else if (v != null) {
                        ObjectName resolved = fromSet.ResolveReference(v);
                        fromSet.ExposeVariable(resolved ?? v);
                    } else {
                        string funName = col.Expression.ToString();
                        fromSet.AddFunctionRef(funName, col.Expression);
                        fromSet.ExposeVariable(ObjectName.Parse(funName));
                    }
                }

            }  // for each column selected

            return fromSet;
        }