text:
using System;
using System.Collections.Generic;
using System.Linq;

namespace AntData.ORM.SqlQuery
{
    using SqlProvider;

    class SelectQueryOptimizer
    {
        public SelectQueryOptimizer(SqlProviderFlags flags, SelectQuery selectQuery)
        {
            _flags = flags;
            _selectQuery = selectQuery;
        }

        readonly SqlProviderFlags _flags;
        readonly SelectQuery _selectQuery;

        public void FinalizeAndValidate(bool isApplySupported, bool optimizeColumns)
        {
#if DEBUG
            if (_selectQuery.IsUpdate)
            {
            }

            var sqlText = _selectQuery.SqlText;

            var dic = new Dictionary<SelectQuery, SelectQuery>();

            new QueryVisitor().VisitAll(_selectQuery, (e, tt) =>
            {
                var sql = e as SelectQuery;

                if (sql != null)
                {
                    if (dic.ContainsKey(sql))
                        throw new InvalidOperationException("SqlQuery circle reference detected.");

                    dic.Add(sql, sql);
                }
            });
#endif

            OptimizeUnions();
            FinalizeAndValidateInternal(isApplySupported, optimizeColumns, new List<ISqlTableSource>());
            ResolveFields();
            _selectQuery.SetAliases();

#if DEBUG
            sqlText = _selectQuery.SqlText;
#endif
        }

        class QueryData
        {
            public SelectQuery Query;
            public List<ISqlExpression> Fields = new List<ISqlExpression>();
            public List<QueryData> Queries = new List<QueryData>();
        }

        void ResolveFields()
        {
            var root = GetQueryData(_selectQuery);

            ResolveFields(root);
        }

        static QueryData GetQueryData(SelectQuery selectQuery)
        {
            var data = new QueryData { Query = selectQuery };

            new QueryVisitor().VisitParentFirst(selectQuery, e =>
            {
                switch (e.ElementType)
                {
                    case QueryElementType.SqlField:
                        {
                            var field = (SqlField)e;

                            if (field.Name.Length != 1 || field.Name[0] != '*')
                                data.Fields.Add(field);

                            break;
                        }

                    case QueryElementType.SqlQuery:
                        {
                            if (e != selectQuery)
                            {
                                data.Queries.Add(GetQueryData((SelectQuery)e));
                                return false;
                            }

                            break;
                        }

                    case QueryElementType.Column:
                        return ((SelectQuery.Column)e).Parent == selectQuery;

                    case QueryElementType.SqlTable:
                        return false;
                }

                return true;
            });

            return data;
        }

        static SelectQuery.TableSource FindField(SqlField field, SelectQuery.TableSource table)
        {
            if (field.Table == table.Source)
                return table;

            foreach (var @join in table.Joins)
            {
                var t = FindField(field, @join.Table);

                if (t != null)
                    return @join.Table;
            }

            return null;
        }

        static ISqlExpression GetColumn(QueryData data, SqlField field)
        {
            foreach (var query in data.Queries)
            {
                var q = query.Query;

                foreach (var table in q.From.Tables)
                {
                    var t = FindField(field, table);

                    if (t != null)
                    {
                        var n = q.Select.Columns.Count;
                        var idx = q.Select.Add(field);

                        if (n != q.Select.Columns.Count)
                            if (!q.GroupBy.IsEmpty || q.Select.Columns.Any(c => IsAggregationFunction(c.Expression)))
                                q.GroupBy.Items.Add(field);

                        return q.Select.Columns[idx];
                    }
                }
            }

            return null;
        }

        static void ResolveFields(QueryData data)
        {
            if (data.Queries.Count == 0)
                return;

            var dic = new Dictionary<ISqlExpression, ISqlExpression>();

            foreach (SqlField field in data.Fields)
            {
                if (dic.ContainsKey(field))
                    continue;

                var found = false;

                foreach (var table in data.Query.From.Tables)
                {
                    found = FindField(field, table) != null;

                    if (found)
                        break;
                }

                if (!found)
                {
                    var expr = GetColumn(data, field);

                    if (expr != null)
                        dic.Add(field, expr);
                }
            }

            if (dic.Count > 0)
                new QueryVisitor().VisitParentFirst(data.Query, e =>
                {
                    ISqlExpression ex;

                    switch (e.ElementType)
                    {
                        case QueryElementType.SqlQuery:
                            return e == data.Query;

                        case QueryElementType.SqlFunction:
                            {
                                var parms = ((SqlFunction)e).Parameters;

                                for (var i = 0; i < parms.Length; i++)
                                    if (dic.TryGetValue(parms[i], out ex))
                                        parms[i] = ex;

                                break;
                            }

                        case QueryElementType.SqlExpression:
                            {
                                var parms = ((SqlExpression)e).Parameters;

                                for (var i = 0; i < parms.Length; i++)
                                    if (dic.TryGetValue(parms[i], out ex))
                                        parms[i] = ex;

                                break;
                            }

                        case QueryElementType.SqlBinaryExpression:
                            {
                                var expr = (SqlBinaryExpression)e;
                                if (dic.TryGetValue(expr.Expr1, out ex)) expr.Expr1 = ex;
                                if (dic.TryGetValue(expr.Expr2, out ex)) expr.Expr2 = ex;
                                break;
                            }

                        case QueryElementType.ExprPredicate:
                        case QueryElementType.NotExprPredicate:
                        case QueryElementType.IsNullPredicate:
                        case QueryElementType.InSubQueryPredicate:
                            {
                                var expr = (SelectQuery.Predicate.Expr)e;
                                if (dic.TryGetValue(expr.Expr1, out ex)) expr.Expr1 = ex;
                                break;
                            }

                        case QueryElementType.ExprExprPredicate:
                            {
                                var expr = (SelectQuery.Predicate.ExprExpr)e;
                                if (dic.TryGetValue(expr.Expr1, out ex)) expr.Expr1 = ex;
                                if (dic.TryGetValue(expr.Expr2, out ex)) expr.Expr2 = ex;
                                break;
                            }

                        case QueryElementType.LikePredicate:
                            {
                                var expr = (SelectQuery.Predicate.Like)e;
                                if (dic.TryGetValue(expr.Expr1, out ex)) expr.Expr1 = ex;
                                if (dic.TryGetValue(expr.Expr2, out ex)) expr.Expr2 = ex;
                                if (dic.TryGetValue(expr.Escape, out ex)) expr.Escape = ex;
                                break;
                            }

                        case QueryElementType.BetweenPredicate:
                            {
                                var expr = (SelectQuery.Predicate.Between)e;
                                if (dic.TryGetValue(expr.Expr1, out ex)) expr.Expr1 = ex;
                                if (dic.TryGetValue(expr.Expr2, out ex)) expr.Expr2 = ex;
                                if (dic.TryGetValue(expr.Expr3, out ex)) expr.Expr3 = ex;
                                break;
                            }

                        case QueryElementType.InListPredicate:
                            {
                                var expr = (SelectQuery.Predicate.InList)e;

                                if (dic.TryGetValue(expr.Expr1, out ex)) expr.Expr1 = ex;

                                for (var i = 0; i < expr.Values.Count; i++)
                                    if (dic.TryGetValue(expr.Values[i], out ex))
                                        expr.Values[i] = ex;

                                break;
                            }

                        case QueryElementType.Column:
                            {
                                var expr = (SelectQuery.Column)e;

                                if (expr.Parent != data.Query)
                                    return false;

                                if (dic.TryGetValue(expr.Expression, out ex)) expr.Expression = ex;

                                break;
                            }

                        case QueryElementType.SetExpression:
                            {
                                var expr = (SelectQuery.SetExpression)e;
                                if (dic.TryGetValue(expr.Expression, out ex)) expr.Expression = ex;
                                break;
                            }

                        case QueryElementType.GroupByClause:
                            {
                                var expr = (SelectQuery.GroupByClause)e;

                                for (var i = 0; i < expr.Items.Count; i++)
                                    if (dic.TryGetValue(expr.Items[i], out ex))
                                        expr.Items[i] = ex;

                                break;
                            }

                        case QueryElementType.OrderByItem:
                            {
                                var expr = (SelectQuery.OrderByItem)e;
                                if (dic.TryGetValue(expr.Expression, out ex)) expr.Expression = ex;
                                break;
                            }
                    }

                    return true;
                });

            foreach (var query in data.Queries)
                if (query.Queries.Count > 0)
                    ResolveFields(query);
        }

        void OptimizeUnions()
        {
            var exprs = new Dictionary<ISqlExpression, ISqlExpression>();

            new QueryVisitor().Visit(_selectQuery, (e, tt) =>
            {
                var sql = e as SelectQuery;

                if (sql == null || sql.From.Tables.Count != 1 || !sql.IsSimple || sql.IsInsert || sql.IsUpdate || sql.IsDelete)
                    return;

                var table = sql.From.Tables[0];

                if (table.Joins.Count != 0 || !(table.Source is SelectQuery))
                    return;

                var union = (SelectQuery)table.Source;

                if (!union.HasUnion)
                    return;

                for (var i = 0; i < sql.Select.Columns.Count; i++)
                {
                    var scol = sql.Select.Columns[i];
                    var ucol = union.Select.Columns[i];

                    if (scol.Expression != ucol)
                        return;
                }

                exprs.Add(union, sql);

                for (var i = 0; i < sql.Select.Columns.Count; i++)
                {
                    var scol = sql.Select.Columns[i];
                    var ucol = union.Select.Columns[i];

                    scol.Expression = ucol.Expression;
                    scol._alias = ucol._alias;

                    exprs.Add(ucol, scol);
                }

                for (var i = sql.Select.Columns.Count; i < union.Select.Columns.Count; i++)
                    sql.Select.Expr(union.Select.Columns[i].Expression);

                sql.From.Tables.Clear();
                sql.From.Tables.AddRange(union.From.Tables);

                sql.Where.SearchCondition.Conditions.AddRange(union.Where.SearchCondition.Conditions);
                sql.Having.SearchCondition.Conditions.AddRange(union.Having.SearchCondition.Conditions);
                sql.GroupBy.Items.AddRange(union.GroupBy.Items);
                sql.OrderBy.Items.AddRange(union.OrderBy.Items);
                sql.Unions.InsertRange(0, union.Unions);
            });

            ((ISqlExpressionWalkable)_selectQuery).Walk(false, expr =>
            {
                ISqlExpression e;

                if (exprs.TryGetValue(expr, out e))
                    return e;

                return expr;
            });
        }

        void FinalizeAndValidateInternal(bool isApplySupported, bool optimizeColumns, List<ISqlTableSource> tables)
        {
            OptimizeSearchCondition(_selectQuery.Where.SearchCondition);
            OptimizeSearchCondition(_selectQuery.Having.SearchCondition);

            _selectQuery.ForEachTable(table =>
            {
                foreach (var join in table.Joins)
                    OptimizeSearchCondition(join.Condition);
            }, new HashSet<SelectQuery>());

            new QueryVisitor().Visit(_selectQuery, (e, tt) =>
            {
                var sql = e as SelectQuery;

                if (sql != null && sql != _selectQuery)
                {
                    sql.ParentSelect = _selectQuery;
                    new SelectQueryOptimizer(_flags, sql).FinalizeAndValidateInternal(isApplySupported, optimizeColumns, tables);

                    if (sql.IsParameterDependent)
                        _selectQuery.IsParameterDependent = true;
                }
            });

            ResolveWeakJoins(tables);
            OptimizeColumns();
            OptimizeApplies(isApplySupported, optimizeColumns);
            OptimizeSubQueries(isApplySupported, optimizeColumns);
            OptimizeApplies(isApplySupported, optimizeColumns);
            OptimizeJoins();
            new QueryVisitor().Visit(_selectQuery, (e, tt) =>
            {
                var sql = e as SelectQuery;

                if (sql != null && sql != _selectQuery)
                    RemoveOrderBy(sql);
            });
        }

        internal static void OptimizeSearchCondition(SelectQuery.SearchCondition searchCondition)
        {
            // This 'if' could be replaced by one simple match:
            //
            // match (searchCondition.Conditions)
            // {
            // | [SearchCondition(true, _) sc] =>
            //     searchCondition.Conditions = sc.Conditions;
            //     OptimizeSearchCondition(searchCodition)
            //
            // | [SearchCondition(false, [SearchCondition(true, [ExprExpr]) sc])] => ...
            //
            // | [Expr(true,  SqlValue(true))]
            // | [Expr(false, SqlValue(false))]
            //     searchCondition.Conditions = []
            // }
            //
            // One day I am going to rewrite all this crap in Nemerle.
            //
            if (searchCondition.Conditions.Count == 1)
            {
                var cond = searchCondition.Conditions[0];
                if (!string.IsNullOrEmpty(cond.StringWhere))
                {
                    return;
                }
                if (cond.Predicate is SelectQuery.SearchCondition)
                {
                    var sc = (SelectQuery.SearchCondition)cond.Predicate;

                    if (!cond.IsNot)
                    {
                        searchCondition.Conditions.Clear();
                        searchCondition.Conditions.AddRange(sc.Conditions);

                        OptimizeSearchCondition(searchCondition);
                        return;
                    }

                    if (sc.Conditions.Count == 1)
                    {
                        var c1 = sc.Conditions[0];

                        if (!c1.IsNot && c1.Predicate is SelectQuery.Predicate.ExprExpr)
                        {
                            var ee = (SelectQuery.Predicate.ExprExpr)c1.Predicate;
                            SelectQuery.Predicate.Operator op;

                            switch (ee.Operator)
                            {
                                case SelectQuery.Predicate.Operator.Equal: op = SelectQuery.Predicate.Operator.NotEqual; break;
                                case SelectQuery.Predicate.Operator.NotEqual: op = SelectQuery.Predicate.Operator.Equal; break;
                                case SelectQuery.Predicate.Operator.Greater: op = SelectQuery.Predicate.Operator.LessOrEqual; break;
                                case SelectQuery.Predicate.Operator.NotLess:
                                case SelectQuery.Predicate.Operator.GreaterOrEqual: op = SelectQuery.Predicate.Operator.Less; break;
                                case SelectQuery.Predicate.Operator.Less: op = SelectQuery.Predicate.Operator.GreaterOrEqual; break;
                                case SelectQuery.Predicate.Operator.NotGreater:
                                case SelectQuery.Predicate.Operator.LessOrEqual: op = SelectQuery.Predicate.Operator.Greater; break;
                                default: throw new InvalidOperationException();
                            }

                            c1.Predicate = new SelectQuery.Predicate.ExprExpr(ee.Expr1, op, ee.Expr2);

                            searchCondition.Conditions.Clear();
                            searchCondition.Conditions.AddRange(sc.Conditions);

                            OptimizeSearchCondition(searchCondition);
                            return;
                        }
                    }
                }

                if (cond.Predicate.ElementType == QueryElementType.ExprPredicate)
                {
                    var expr = (SelectQuery.Predicate.Expr)cond.Predicate;

                    if (expr.Expr1 is SqlValue)
                    {
                        var value = (SqlValue)expr.Expr1;

                        if (value.Value is bool)
                            if (cond.IsNot ? !(bool)value.Value : (bool)value.Value)
                                searchCondition.Conditions.Clear();
                    }
                }
            }

            for (var i = 0; i < searchCondition.Conditions.Count; i++)
            {
                var cond = searchCondition.Conditions[i];
                if (!string.IsNullOrEmpty(cond.StringWhere))
                {
                    continue;
                }
                if (cond.Predicate.ElementType == QueryElementType.ExprPredicate)
                {
                    var expr = (SelectQuery.Predicate.Expr)cond.Predicate;

                    if (expr.Expr1 is SqlValue)
                    {
                        var value = (SqlValue)expr.Expr1;

                        if (value.Value is bool)
                        {
                            if (cond.IsNot ? !(bool)value.Value : (bool)value.Value)
                            {
                                if (i > 0)
                                {
                                    if (searchCondition.Conditions[i - 1].IsOr)
                                    {
                                        searchCondition.Conditions.RemoveRange(0, i);
                                        OptimizeSearchCondition(searchCondition);

                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                else if (cond.Predicate is SelectQuery.SearchCondition)
                {
                    var sc = (SelectQuery.SearchCondition)cond.Predicate;
                    OptimizeSearchCondition(sc);
                    if (sc.Conditions.Count == 0)
                    {
                        if (cond.IsOr)
                        {
                            searchCondition.Conditions.Clear();
                            break;
                        }
                        searchCondition.Conditions.RemoveAt(i);
                        --i;
                    }
                }
            }
        }

        static void RemoveOrderBy(SelectQuery selectQuery)
        {
            if (selectQuery.OrderBy.Items.Count > 0 && selectQuery.Select.SkipValue == null && selectQuery.Select.TakeValue == null)
                selectQuery.OrderBy.Items.Clear();
        }

        internal void ResolveWeakJoins(List<ISqlTableSource> tables)
        {
            Func<SelectQuery.TableSource, bool> findTable = null; findTable = table =>
             {
                 if (tables.Contains(table.Source))
                     return true;

                 foreach (var join in table.Joins)
                 {
                     if (findTable(join.Table))
                     {
                         join.IsWeak = false;
                         return true;
                     }
                 }

                 if (table.Source is SelectQuery)
                     foreach (var t in ((SelectQuery)table.Source).From.Tables)
                         if (findTable(t))
                             return true;

                 return false;
             };

            var areTablesCollected = false;

            _selectQuery.ForEachTable(table =>
            {
                for (var i = 0; i < table.Joins.Count; i++)
                {
                    var join = table.Joins[i];

                    if (join.IsWeak)
                    {
                        if (!areTablesCollected)
                        {
                            areTablesCollected = true;

                            Action<IQueryElement, string> tableCollector = (expr, tt) =>
                             {
                                 var field = expr as SqlField;

                                 if (field != null && !tables.Contains(field.Table))
                                     tables.Add(field.Table);
                             };

                            var visitor = new QueryVisitor();

                            visitor.VisitAll(_selectQuery.Select, tableCollector);
                            visitor.VisitAll(_selectQuery.Where, tableCollector);
                            visitor.VisitAll(_selectQuery.GroupBy, tableCollector);
                            visitor.VisitAll(_selectQuery.Having, tableCollector);
                            visitor.VisitAll(_selectQuery.OrderBy, tableCollector);

                            if (_selectQuery.IsInsert)
                                visitor.VisitAll(_selectQuery.Insert, tableCollector);

                            if (_selectQuery.IsUpdate)
                                visitor.VisitAll(_selectQuery.Update, tableCollector);

                            if (_selectQuery.IsDelete)
                                visitor.VisitAll(_selectQuery.Delete, tableCollector);

                            visitor.VisitAll(_selectQuery.From, (expr, tt) =>
                            {
                                var tbl = expr as SqlTable;

                                if (tbl != null && tbl.TableArguments != null)
                                {
                                    var v = new QueryVisitor();

                                    foreach (var arg in tbl.TableArguments)
                                        v.VisitAll(arg, tableCollector);
                                }
                            });
                        }

                        if (findTable(join.Table))
                        {
                            join.IsWeak = false;
                        }
                        else
                        {
                            table.Joins.RemoveAt(i);
                            i--;
                        }
                    }
                }
            }, new HashSet<SelectQuery>());
        }

        SelectQuery.TableSource OptimizeSubQuery(
            SelectQuery.TableSource source,
            bool optimizeWhere,
            bool allColumns,
            bool isApplySupported,
            bool optimizeValues,
            bool optimizeColumns)
        {
            foreach (var jt in source.Joins)
            {
                var table = OptimizeSubQuery(
                    jt.Table,
                    jt.JoinType == SelectQuery.JoinType.Inner || jt.JoinType == SelectQuery.JoinType.CrossApply,
                    false,
                    isApplySupported,
                    jt.JoinType == SelectQuery.JoinType.Inner || jt.JoinType == SelectQuery.JoinType.CrossApply,
                    optimizeColumns);

                if (table != jt.Table)
                {
                    var sql = jt.Table.Source as SelectQuery;

                    if (sql != null && sql.OrderBy.Items.Count > 0)
                        foreach (var item in sql.OrderBy.Items)
                            _selectQuery.OrderBy.Expr(item.Expression, item.IsDescending);

                    jt.Table = table;
                }
            }

            return source.Source is SelectQuery ?
                RemoveSubQuery(source, optimizeWhere, allColumns && !isApplySupported, optimizeValues, optimizeColumns) :
                source;
        }

        static bool CheckColumn(SelectQuery.Column column, ISqlExpression expr, SelectQuery query, bool optimizeValues, bool optimizeColumns)
        {
            if (expr is SqlField || expr is SelectQuery.Column)
                return false;

            if (expr is SqlValue)
                return !optimizeValues && 1.Equals(((SqlValue)expr).Value);

            if (expr is SqlBinaryExpression)
            {
                var e = (SqlBinaryExpression)expr;

                if (e.Operation == "*" && e.Expr1 is SqlValue)
                {
                    var value = (SqlValue)e.Expr1;

                    if (value.Value is int && (int)value.Value == -1)
                        return CheckColumn(column, e.Expr2, query, optimizeValues, optimizeColumns);
                }
            }

            var visitor = new QueryVisitor();

            if (optimizeColumns &&
                visitor.Find(expr, e => e is SelectQuery || IsAggregationFunction(e)) == null)
            {
                var n = 0;
                var q = query.ParentSelect ?? query;

                visitor.VisitAll(q, (e, tt) => { if (e == column) n++; });

                return n > 2;
            }

            return true;
        }

        SelectQuery.TableSource RemoveSubQuery(
            SelectQuery.TableSource childSource,
            bool concatWhere,
            bool allColumns,
            bool optimizeValues,
            bool optimizeColumns)
        {
            var query = (SelectQuery)childSource.Source;

            var isQueryOK = query.From.Tables.Count == 1;

            isQueryOK = isQueryOK && (concatWhere || query.Where.IsEmpty && query.Having.IsEmpty);
            isQueryOK = isQueryOK && !query.HasUnion && query.GroupBy.IsEmpty && !query.Select.HasModifier;
            //isQueryOK = isQueryOK && (_flags.IsDistinctOrderBySupported || query.Select.IsDistinct );

            if (!isQueryOK)
                return childSource;

            var isColumnsOK =
                (allColumns && !query.Select.Columns.Any(c => IsAggregationFunction(c.Expression))) ||
                !query.Select.Columns.Any(c => CheckColumn(c, c.Expression, query, optimizeValues, optimizeColumns));

            if (!isColumnsOK)
                return childSource;

            var map = new Dictionary<ISqlExpression, ISqlExpression>(query.Select.Columns.Count);

            foreach (var c in query.Select.Columns)
                map.Add(c, c.Expression);

            var top = _selectQuery;

            while (top.ParentSelect != null)
                top = top.ParentSelect;

            ((ISqlExpressionWalkable)top).Walk(false, expr =>
            {
                ISqlExpression fld;
                return map.TryGetValue(expr, out fld) ? fld : expr;
            });

            new QueryVisitor().Visit(top, (expr, tt) =>
            {
                if (expr.ElementType == QueryElementType.InListPredicate)
                {
                    var p = (SelectQuery.Predicate.InList)expr;

                    if (p.Expr1 == query)
                        p.Expr1 = query.From.Tables[0];
                }
            });

            query.From.Tables[0].Joins.AddRange(childSource.Joins);

            if (query.From.Tables[0].Alias == null)
                query.From.Tables[0].Alias = childSource.Alias;

            if (!query.Where.IsEmpty) ConcatSearchCondition(_selectQuery.Where, query.Where);
            if (!query.Having.IsEmpty) ConcatSearchCondition(_selectQuery.Having, query.Having);

            ((ISqlExpressionWalkable)top).Walk(false, expr =>
            {
                if (expr is SelectQuery)
                {
                    var sql = (SelectQuery)expr;

                    if (sql.ParentSelect == query)
                        sql.ParentSelect = query.ParentSelect ?? _selectQuery;
                }

                return expr;
            });

            return query.From.Tables[0];
        }

        static bool IsAggregationFunction(IQueryElement expr)
        {
            if (expr is SqlFunction)
                switch (((SqlFunction)expr).Name)
                {
                    case "Count":
                    case "Average":
                    case "Min":
                    case "Max":
                    case "Sum": return true;
                }

            return false;
        }

        void OptimizeApply(SelectQuery.TableSource tableSource, SelectQuery.JoinedTable joinTable, bool isApplySupported, bool optimizeColumns)
        {
            var joinSource = joinTable.Table;

            foreach (var join in joinSource.Joins)
                if (join.JoinType == SelectQuery.JoinType.CrossApply || join.JoinType == SelectQuery.JoinType.OuterApply)
                    OptimizeApply(joinSource, join, isApplySupported, optimizeColumns);

            if (isApplySupported && !joinTable.CanConvertApply)
                return;

            if (joinSource.Source.ElementType == QueryElementType.SqlQuery)
            {
                var sql = (SelectQuery)joinSource.Source;
                var isAgg = sql.Select.Columns.Any(c => IsAggregationFunction(c.Expression));

                //if (isApplySupported && (isAgg || sql.Select.TakeValue != null || sql.Select.SkipValue != null))
                if (isApplySupported && (isAgg || sql.Select.HasModifier))
                    return;

                var searchCondition = new List<SelectQuery.Condition>(sql.Where.SearchCondition.Conditions);

                sql.Where.SearchCondition.Conditions.Clear();

                if (!ContainsTable(tableSource.Source, sql))
                {
                    if (!(joinTable.JoinType == SelectQuery.JoinType.CrossApply &&
                          searchCondition.Count == 0) // CROSS JOIN
                        && sql.Select.HasModifier)
                    {
                        throw new LinqToDBException("Database do not support CROSS/OUTER APPLY join required by the query.");
                    }

                     joinTable.JoinType = joinTable.JoinType == SelectQuery.JoinType.CrossApply ? SelectQuery.JoinType.Inner : SelectQuery.JoinType.Left;
                    joinTable.Condition.Conditions.AddRange(searchCondition);
                }
                else
                {
                    sql.Where.SearchCondition.Conditions.AddRange(searchCondition);

                    var table = OptimizeSubQuery(
                        joinTable.Table,
                        joinTable.JoinType == SelectQuery.JoinType.Inner || joinTable.JoinType == SelectQuery.JoinType.CrossApply,
                        joinTable.JoinType == SelectQuery.JoinType.CrossApply,
                        isApplySupported,
                        joinTable.JoinType == SelectQuery.JoinType.Inner || joinTable.JoinType == SelectQuery.JoinType.CrossApply,
                        optimizeColumns);

                    if (table != joinTable.Table)
                    {
                        var q = joinTable.Table.Source as SelectQuery;

                        if (q != null && q.OrderBy.Items.Count > 0)
                            foreach (var item in q.OrderBy.Items)
                                _selectQuery.OrderBy.Expr(item.Expression, item.IsDescending);

                        joinTable.Table = table;

                        OptimizeApply(tableSource, joinTable, isApplySupported, optimizeColumns);
                    }
                }
            }
            else
            {
                if (!ContainsTable(tableSource.Source, joinSource.Source))
                    joinTable.JoinType = joinTable.JoinType == SelectQuery.JoinType.CrossApply ? SelectQuery.JoinType.Inner : SelectQuery.JoinType.Left;
            }
        }

        static bool ContainsTable(ISqlTableSource table, IQueryElement sql)
        {
            return null != new QueryVisitor().Find(sql, e =>
                e == table ||
                e.ElementType == QueryElementType.SqlField && table == ((SqlField)e).Table ||
                e.ElementType == QueryElementType.Column && table == ((SelectQuery.Column)e).Parent);
        }

        static void ConcatSearchCondition(SelectQuery.WhereClause where1, SelectQuery.WhereClause where2)
        {
            if (where1.IsEmpty)
            {
                where1.SearchCondition.Conditions.AddRange(where2.SearchCondition.Conditions);
            }
            else
            {
                if (where1.SearchCondition.Precedence < Precedence.LogicalConjunction)
                {
                    var sc1 = new SelectQuery.SearchCondition();

                    sc1.Conditions.AddRange(where1.SearchCondition.Conditions);

                    where1.SearchCondition.Conditions.Clear();
                    where1.SearchCondition.Conditions.Add(new SelectQuery.Condition(false, sc1));
                }

                if (where2.SearchCondition.Precedence < Precedence.LogicalConjunction)
                {
                    var sc2 = new SelectQuery.SearchCondition();

                    sc2.Conditions.AddRange(where2.SearchCondition.Conditions);

                    where1.SearchCondition.Conditions.Add(new SelectQuery.Condition(false, sc2));
                }
                else
                    where1.SearchCondition.Conditions.AddRange(where2.SearchCondition.Conditions);
            }
        }

        void OptimizeSubQueries(bool isApplySupported, bool optimizeColumns)
        {
            for (var i = 0; i < _selectQuery.From.Tables.Count; i++)
            {
                var table = OptimizeSubQuery(_selectQuery.From.Tables[i], true, false, isApplySupported, true, optimizeColumns);

                if (table != _selectQuery.From.Tables[i])
                {
                    var sql = _selectQuery.From.Tables[i].Source as SelectQuery;

                    if (!_selectQuery.Select.Columns.All(c => IsAggregationFunction(c.Expression)))
                        if (sql != null && sql.OrderBy.Items.Count > 0)
                            foreach (var item in sql.OrderBy.Items)
                                _selectQuery.OrderBy.Expr(item.Expression, item.IsDescending);

                    _selectQuery.From.Tables[i] = table;
                }
            }
        }

        void OptimizeApplies(bool isApplySupported, bool optimizeColumns)
        {
            foreach (var table in _selectQuery.From.Tables)
                foreach (var join in table.Joins)
                    if (join.JoinType == SelectQuery.JoinType.CrossApply || join.JoinType == SelectQuery.JoinType.OuterApply)
                        OptimizeApply(table, join, isApplySupported, optimizeColumns);
        }

        void OptimizeColumns()
        {
            ((ISqlExpressionWalkable)_selectQuery.Select).Walk(false, expr =>
            {
                var query = expr as SelectQuery;

                if (query != null && query.From.Tables.Count == 0 && query.Select.Columns.Count == 1)
                {
                    new QueryVisitor().Visit(query.Select.Columns[0].Expression, (e, tt) =>
                    {
                        if (e.ElementType == QueryElementType.SqlQuery)
                        {
                            var q = (SelectQuery)e;

                            if (q.ParentSelect == query)
                                q.ParentSelect = query.ParentSelect;
                        }
                    });

                    return query.Select.Columns[0].Expression;
                }

                return expr;
            });
        }
        private bool CanRemoveSecond(SelectQuery.JoinedTable join1,
             SelectQuery.JoinedTable join2)
        {
            var result = join1.Condition.Precedence == join2.Condition.Precedence;

            if (!result)
                return false;

            var table1 = join1.Table.Source as SqlTable;
            var table2 = join2.Table.Source as SqlTable;

            result = IsEqualTables(table1, table2);
            result = result && table1 != null && table1.GetKeys(false).Count > 0; // table has keys
            result = result && IsSameEqualConditions(join1, join2);

            return result;
        }

        private bool IsEqualTables(SqlTable table1, SqlTable table2)
        {
            var result =
                table1 != null && table2 != null
                && table1.Database == table2.Database
                && table1.Owner == table2.Owner
                && table1.Name == table2.Name;
            return result;
        }
        private bool IsSameEqualConditions(SelectQuery.JoinedTable join1,
        SelectQuery.JoinedTable join2)
        {
            var c1 = join1.Condition;
            var c2 = join2.Condition;

            Func<SelectQuery.Condition, bool> allowed =
                c =>
                {
                    var expr = c.Predicate as SelectQuery.Predicate.ExprExpr;
                    return expr != null && expr.Operator == SelectQuery.Predicate.Operator.Equal && !c.IsOr;
                };

            if (!c1.Conditions.All(allowed) || !c2.Conditions.All(allowed))
                return false;

            var result = c1.Conditions.Count == c2.Conditions.Count;

            if (result)
            {
                Func<ISqlExpression, ISqlExpression, HashSet<int>, bool> isEqual = (e1, e2, pks) =>
                {
                    var er = e1.ElementType == e2.ElementType && e1.Precedence == e2.Precedence;
                    if (er)
                    {
                        switch (e1.ElementType)
                        {
                            case QueryElementType.Column:
                                {
                                    var col1 = ((SelectQuery.Column)e1).Expression as SqlField;
                                    var col2 = ((SelectQuery.Column)e2).Expression as SqlField;
                                    er = col1 != null && col2 != null
                                         && col1.Name == col2.Name
                                         && col1.Table.SourceID == col2.Table.SourceID;
                                    break;
                                }

                            case QueryElementType.SqlField:
                                {
                                    var col1 = (SqlField)e1;
                                    var col2 = (SqlField)e2;

                                    er = col1.Name == col2.Name
                                         && IsEqualTables(col1.Table as SqlTable, col2.Table as SqlTable);

                                    if (er && (col1.Table.SourceID == join2.Table.SourceID || col2.Table.SourceID == join2.Table.SourceID))
                                    //                                if (er && IsEqualTables(col1.Table as SqlTable, join2.Table.Source as SqlTable))
                                    {
                                        if (col1.IsPrimaryKey && col2.IsPrimaryKey)
                                            pks.Add(Math.Max(1, col1.PrimaryKeyOrder));
                                    }

                                    break;
                                }
                            default:
                                er = false;
                                break;
                        }
                    }
                    return er;
                };

                var c2C = c2.Conditions.ToList();
                var primary = new HashSet<int>();

                for (int i1 = 0; i1 < c1.Conditions.Count; i1++)
                {
                    var it1 = c1.Conditions[i1].Predicate as SelectQuery.Predicate.ExprExpr;
                    if (it1 == null)
                    {
                        result = false;
                        break;
                    }

                    var found = false;

                    for (int i2 = 0; i2 < c2C.Count; i2++)
                    {
                        var it2 = c2C[i2].Predicate as SelectQuery.Predicate.ExprExpr;
                        if (it2 == null)
                        {
                            result = false;
                            break;
                        }

                        if ((isEqual(it1.Expr1, it2.Expr1, primary) && isEqual(it1.Expr2, it2.Expr2, primary)) ||
                            (isEqual(it2.Expr1, it1.Expr1, primary) && isEqual(it2.Expr2, it1.Expr2, primary)))
                        {
                            found = true;
                            c2C.RemoveAt(i2);
                            break;
                        }
                    }

                    if (!found)
                        result = false;

                    if (!result)
                        break;
                }

                if (c2C.Count > 0)
                    result = false;

                // check that all keys used in comparison
                result = result && (join2.Table.Source.GetKeys(false).Count == primary.Count);
            }

            return result;
        }

        bool IsDependent(SelectQuery.JoinedTable joinedTable, SelectQuery.JoinedTable tested)
        {
            var dependent = false;
            var sourceId = tested.Table.Source.SourceID;

            // check everyting that can be dependent on specific table
            new QueryVisitor().VisitParentFirst(joinedTable, e =>
            {
                if (dependent)
                    return false;

                // do not check tested join
                if (e == tested)
                    return false;

                if (e.ElementType == QueryElementType.SqlField)
                {
                    var sqlField = (SqlField)e;

                    dependent = sqlField.Table.SourceID == sourceId;
                }

                return !dependent;
            });

            return dependent;
        }

        void FlattenInnerJoins()
        {
            foreach (var table in _selectQuery.From.Tables)
            {
                for (int i = 0; i < table.Joins.Count; i++)
                {
                    var j = table.Joins[i];
                    if (j.JoinType != SelectQuery.JoinType.Inner)
                        continue;
                    for (int si = 0; si < j.Table.Joins.Count; si++)
                    {
                        var sj = j.Table.Joins[si];
                        if (sj.JoinType == SelectQuery.JoinType.Inner && !IsDependent(j, sj))
                        {
                            table.Joins.Add(sj);
                            j.Table.Joins.RemoveAt(si);
                            --si;
                        }
                    }
                }
            }
        }

        void OptimizeJoins()
        {
            FlattenInnerJoins();

            foreach (var table in _selectQuery.From.Tables)
            {
                if (table.Joins.Count > 1)
                {
                    for (int i1 = 0; i1 < table.Joins.Count; i1++)
                    {
                        var j1 = table.Joins[i1];
                        if (j1.JoinType != SelectQuery.JoinType.Inner)
                            continue;

                        for (int i2 = i1 + 1; i2 < table.Joins.Count; i2++)
                        {
                            var j2 = table.Joins[i2];
                            if (j2.JoinType != SelectQuery.JoinType.Inner)
                                continue;

                            var canRemove = CanRemoveSecond(j1, j2);

                            if (canRemove)
                            {
                                table.Joins.RemoveAt(i2);
                                j1.Table.Joins.AddRange(j2.Table.Joins);
                                --i2;

                                new QueryVisitor().Visit(_selectQuery, (element, tt) =>
                                {
                                    switch (element.ElementType)
                                    {
                                        case QueryElementType.SqlField:
                                            {
                                                var sqlField = (SqlField)element;
                                                if (sqlField.Table.SourceID == j2.Table.Source.SourceID)
                                                    sqlField.Table = j1.Table.Source;
                                                break;
                                            }
                                    }
                                });
                            }
                        }
                    }
                }
            }
        }

    }
}

redpajama_set_name: RedPajamaGithub


text:
Larry Hall
Larry Hall's first instrumental performance was at the tender age at 7 in the Thomas Park Bandstand constructed by his grandfather. His pursuit of music led him to accept a teaching position in Ashland, where he served as the sole music teacher for both the elementary and the high school from 1962 to 1999. Upon retiring from teaching, he was approached to manage a music store in Presque Isle called Aroostook Music Company and serve as the store's band instrument technician. When the owner of Aroostook Music closed the company, Mr. Hall joined with his two former employees to form a new music store called KMH Music (he's the 'H'). In 2014, Ashland District School recognized his indelible impact on generations of students by dedicating their performing arts auditorium in his honor. His former students fondly refer to it as "The Larry Hall."
In addition to creating and managing his community chorus The Aroostook River Voices, Mr. Hall somehow found the time to play trombone with and write arrangements for The Star City Syndicate. During pauses in rehearsals, he was often found quietly leading sectionals for the trombone section and tweaking the parts to perfection.
Mr. Hall passed away in June of 2018. But he will forever be a part of The Syndicate. We love him a lot. If you listen closely, you can hear us honor him every time we sing our version of "Saturday In The Park." We hope you'll remember him too.

redpajama_set_name: RedPajamaCommonCrawl


What is better Wrike or Basecamp? Choosing the best Project Management Software for your company is hard with various functions, choices, and terms to choose from. However, using our review platform will help you to cut down the selection steps by reading all major software in a single place.
For instance, you can contrast Wrike and Basecamp for their tools and overall scores, in this case, 9.7 and 8.5, respectively. Furthermore, you can compare which one has better general user satisfaction rating: 99% (Wrike) and 100% (Basecamp) to determine which product is the better option for your company. Don't just pick the software with the cheapest price, but the software that has the best value.
We know that not all companies have the time to scrutinize a large number of different solutions, so we came up with a list of suggestions that you may find useful. Our top choices for the Project Management Software category are: Monday.com, Wrike, Asana.
The solutions examined on this page are merely a sliver of our complete Project Management Software category and you should remember that there might be more reliable options available. If you want to ensure you make the best possible choice for your business we definitely suggest that you test more apps first. It may also be a good idea to study our top 10 Project Management Software list to see which software are at the moment the best ones and leaders in the market.


text:
Look At The Big Picture
Two news items and one personal item that intersect. First news item: the Olympic torch is being attacked and might not make it out of San Francisco alive.
As you already know, people around the world are ready to use the Chinese-hosted Olympic games to bring to light China's occupation/oppression of Tibet. If you're unfamiliar with what's behind these charges, go Google it and see what you come up with.
Second news item: The state of Ohio is opening a department of development in Beijing.Â
Apparently the state is starting to do this in various countries throughout the world in an effort to encourage trade.
My personal item: I bought a new pair of Italian shoes this week.
Seriously, before you start making fun of me, it sounds more "yuppy" than it is. They're more casual shoes that don't even look Italian. I bought them at DSW for a really good price.
So how do these three items connect?
China has been thrilled about the Olympics as they're viewing it as their international coming-out ceremony. With over one billion consumers and the ability to produce goods on the cheap, China is a cash cow. But the fact remains that China, while enjoying the wealth that accompanies free markets, still operates as a steel-fisted regime capable of committing numerous human rights autrocities without accountibility [see Tibet]. That's why the Olympics are the perfect target for protesters. China is now on an international stage. They're attempting to paint an "everything-is-normal" picture for the world. Protesters are going to use this once-in-a-lifetime opportunity to hit China hard, knowing that there's very little the Communist government can do about it while the world is watching.
But shouldn't this also be the perfect opportunity for the other world superpowers to step up, give international governmental support to these protesters and demand that China make specific changes in support of human rights? You would think so. But they won't. There's one major problem concerning such a demand: there's too much money at stake. Governments aren't too excited about upsetting the applecart just to make a plea for human rights. There are two sides getting rich here who don't want to ruin a good thing.
Take for example American politicians. The perception in our country is the Republicans are big-business, in favor of open markets and, by nature, will overlook human rights issues. Meanwhile, Democrats are usually viewed as the party that fights against oppression. Yet in this situation, no one is moving. Sure, Democrats might spout certain rhetoric that expresses their disdain, saying they favor something akin to an un-official rebuke, but they're just as culpable as the Republicans. It should be noted that Ohio's government is currently under control of the Democrats. Opening up a trade office in downtown Beijing doesn't really vibe with the "Free Tibet" message.
I'm not a social liberal, but we should really think a little about this. These facts bring up some interesting ethical questions. What is America's responsibility in all of this? By our "business as usual" attitude are we empowering the Chinese government to continue oppression? As a Christian, what role should we play in resolving this conflict?
I hold that there are no easy answers to those questions. And, despite how other Christian leaders come down on the issue, I'm not convinced that they have black-and-white Biblical answers; there's a lot of grey to navigate. But the very least I should do is think through them and put any conclusions into application.
Oh, and what does all of this have to do with my Italian shoes? A careful examination of the shoe box revealed some small print that made me laugh:
"Made In China."
Newer PostReason I'm A Geek #432
Older PostHonoring Our Fallen


text:
L'île aux Serpents est un îlot inhabité situé à quelques dizaines de kilomètres au nord de l'île Maurice et dépendant de la République de Maurice. Il forme une réserve naturelle du pays.

Géographie

Géographie physique
Lorsque le  l'îlot fut approché par l'expédition Baudin, le Français Jean-Baptiste Bory de Saint-Vincent le décrivit depuis le Naturaliste où il était installé en affirmant que c'est en fait « un rocher éloigné de la grande terre de près de cinq lieues ». L'île atteint une hauteur de 162 mètres.

Faune et flore
En 1801, Jean-Baptiste Bory de Saint-Vincent affirme que l'on prétend qu'on y trouve « de petites couleuvres, tandis qu'il n'en existe ni sur les rochers voisins, ni sur l'île-de-France ». En fait, cet on-dit est faux : on trouve sur l'île Ronde voisine des boas qui sont absents sur l'île aux Serpents.

Références

Île à Maurice
Île dans l'océan Indien
Île inhabitée
Volcan à Maurice
Ile aux Serpents
Ile aux Serpents

redpajama_set_name: RedPajamaWikipedia


Through a press release that you find at the end of article, LG has officially announced the arrival in Italy of LG K8 4 g, the first smartphone of LG's new family K to be launched on the market with Android 6.0 Marshmallow.
LG K8 4 g, according to the manufacturer, is a smartphone designed for a young audience and attentive to detail, thanks to the presence of a 2.5 D displays with slightly curved edges and a back cover which proposes a special texture that makes it stylish and comfortable the new LG smartphone.
With regard to technical specifications, we find a front panel 5 " HD 720 presolution, processor MediaTek MT6735 quad core at 64 bit, 1.5 GB of RAM, 8 GB of internal memory expandable, main camera from 8 Megapixels, 5 MegaPixel front, 4 g LTE connectivity, WiFi, Bluetooth and NFC 4.2. There is also a removable battery 2150 mAh and Android 6.0 Marshmallow, through which you can, among other things, use external memory main memory.
LG 4 g has measuring 75 144.6 x L0 x 8.7 mm and will be available during the month of may in two colors Indigo and White for a suggested retail price of € 179.90.
Milan, may 2016 – after launching 4 g 4 g & K7 K10, K4, LG introduces K8 4 g, the first model of the K series features Android Marshmallow 6.0. A smartphone targeted at trendy audiences who likes to stand out for its style and share their feelings on social networks.
Thanks to LG K8 4 g users have finally available the latest release of Google's operating system at one low end smartphone. More versatility, security and optimization: these are the advantages of Android 6.0 Marshmellow onto new K series model, but not only. Thanks to the "Adoptable Storage" external memory you can save on all applications, eliminating any worries of internal memory consumption. A problem in mind to a younger market used to download several apps every day and that is found often in trouble with the low-end Android models and with little internal memory.
Unveiled at the CES 2016, the K series from LG offers a user experience derived directly from higher end models and an advanced camera at a competitive price. LG 4 g also inherits the new design K8 glossy pebble of the K series that makes it look more exclusive and expensive than it actually is.
LG K8 4 g is characterized by a modern style with a curved finish and completed by beveled glass 2.5 D of LG. The back cover has a surface inspired by the complex Web of a fabric and provides a secure grip and more comfortable. The HD display delivers crisp, clear images while the front camera 5MP camera ensures amazing famous capabilities such as indexed gesture recognition and the virtual flash for selfie. The Quad-Core processor with 1.5 GB RAM allows LG K8 4 g to handle any command without uncertainties.
LG K8 4 g goes on sale in the coming days at a recommended retail price of € 179.90.
LG K8 is available online from Monclick to 159 euros. The value for money is discreet. There are 48 better models.


text:
Latest COVID-19 PCR test results for UK Biobank released
The latest tranche of COVID-19 PCR test result data for UK Biobank participants, collated from Public Health England data, has been released. This latest data covers the period March 16 - May 3. For details of how to access the data, see this post.
The updated data contains 5356 test results, 1806 of them positive. The tests correspond to 3002 participants, broken down as follows:
1073 returned one or more positive tests, of whom 825 returned tests while a hospital inpatient*
1929 never returned a positive test, of whom 1260 returned tests while a hospital inpatient
* This definition of COVID-19 positive inpatient does not require that the positive test and the test while an inpatient necessarily coincide in participants with multiple tests. Requiring them to coincide on the same test reduces this number from 825 to 818.
Here is a new version of Figure 4 of our paper, updated to reflect this latest tranche of test results. For a daily updating summary of lab-confirmed cases in England, visit coronavirus.data.gov.uk.
Labels: COVID-19, data linkage, Public Health England, UK Biobank
This easy poker game is well-liked for its simple game pace and the camaraderie you construct with other players while trying to beat the dealer. It's simple to like half in} as a result of|as a end result of} there are only three playing cards to handle and the bets are constant. Our 3-Card Poker tables are on the gaming ground near Palo Verde Lounge and Ocean Trail. Free cocktail service is out there to all prospects half in}. Mississippi Stud is a 5-card poker game that allows players to bet a lot as} 10 models on a single hand. Mississippi Stud allows players to compete against a pay table quite than the dealer, and win if their 온라인카지노 hand is a pair of Jacks or higher.


Come with your family, friends and neighbors to foster a sense of community and help clean up a space that holds a lot of memories and meaning for all of us in the Cleveland Heights area! Tools will be provided. Hope to see you there!


text:
Scaptognathus trouessarti is een mijtensoort uit de familie van de Halacaridae. De wetenschappelijke naam van de soort is voor het eerst geldig gepubliceerd in 1915 door Halbert.

Halacaridae


> Does it seem good to you ?
> > the bing image is better for mapping, more clear.
> > around and a unregular form.
> >> image they have acquired over the city of Kunduz in Afghanistan.
> >> (DigitalGlobe) and was acquired the 12th of October 2012.
> >> I am available if you need any other information.


text:
Faribault County Register
Minnesota Sports
Print Ad Directory
COVID-19 Update as of 1-5-21
No. 3 Bucs enter Sub-Section tourney
By Staff | Oct 23, 2016
Lindsey Jacobs, above, digs a pass for the Blue Earth Area Buccaneers.
Touting a 7-3 record in the Big South Conference, the Blue Earth Area Buccaneers are slated to kick off the Class AA South Sub-Section tournament with a match on their home court, taking a 17-7 record into postseason play.
Downed by Jackson County Central on Tuesday, Oct. 18, the Bucs now have their sights set on Oct. 27, when they are scheduled to host New Richland-Hartland-Ellendale-Geneva as the No. 3-seeded team in the tourney.
In the event the maroon and gold top NRHEG on Thursday night, BEA would move on to play either No. 2 St. Peter or No. 7 Fairmont on Nov. 1 at Mankato East, 30 minutes after the conclusion of a match between teams in the top half of Sub-Section bracket competition.
Against Jackson County Central on Oct. 18, the Bucs suffered a 3-1 defeat at the hands of the Huskies in their final showdown before the tournament.
JCC's victory came courtesy of 25-12 and 25-13 wins to start the match, as well as a 25-21 decision in game four of the evening.
Lindsey's sister, Kaylor, looks to record her own dig for the maroon and gold, who will enter Sub-Section tournament play as the No. 3 seed with a match on Oct. 27
BEA battled back by taking the third game, 25-23, but was ultimately unable to overcome its slow start against the Huskies.
Lindsey Norman, who logged six digs, also led the maroon and gold with eight kills on the night, while Sidney Blair and Samantha Barslou chipped in with six apiece.
Lindsey's sister, Alissa, helped balance the BEA offense with 23 set assists.
Barslou and Lindsey Jacobs combined for another 15 digs against JCC.
Rebels are ready to play basketball
Wrestlers are ready to hit the mat
Veteran players to lead BEA boys
Copyright © Faribault County Register | https://www.faribaultcountyregister.com | 125 N. Main St., Blue Earth, MN 56013 | 507-526-7324 | Ogden Newspapers | The Nutting Company


text:
Injectable protein may not affect fertility in Clomid users
Endometriosis is a painful uterine disorder that results from angiogenesis, or the creation and changing of blood vessels.
Endometriosis is a painful uterine disorder that results from angiogenesis, or the creation and changing of blood vessels. The disorder can lead to declining fertility rates for females, which many combat with the use of Clomid.
However, a new study from Tel Aviv University's Sackler Faculty of Medicine may have pinpointed a treatment for endometriosis, according to the university.
By injecting a physiological anti-angiogentic factor (PEDF), a type of protein, into mice, researchers at the university discovered that there was a reduction in the painful symptoms associated with endometriosis. Speculating that this new treatment might harm fertility, they monitored the ovulation and pregnancy rates of the mice and found no negative side effects.
In fact, they noted an increase in the number of ovulated eggs in the mice with endometriosis, which may indicate improved fertility with use of the protein.
There is currently no treatment for endometriosis, and the scientists who conducted the experiment theorized that the condition is under-diagnosed. Most physicians dismiss the symptoms as severe menstrual pain.
Before the treatment can be made available to humans, further tests are needed. If proven safe, it could provide hope for women experiencing endometriosis and infertility.
Stats from the American Society for Reproductive Medicine show that between 30 and 50 percent of women with endometriosis have issues with fertility. The reasons for the effect on fertility include scarred fallopian tubes, altered egg quality and distorted anatomy of the pelvis.
The source also says that birth control pills are one of the few pharmaceuticals that are known to prevent the painful symptoms of the disorder. However, for women with infertility issues, this is problematic.
The use of Clomid remains one of the best options for improving fertility and it can purchased for a discounted rate at an online pharmacy.


HERSHEY, Pa. — It's not an uncommon scenario. An athlete is sailing through the air or making a quick turn when all of a sudden he or she hears a "pop" in the knee. An athlete who experiences this followed by sudden pain and swelling often receives the much-feared diagnosis of an anterior cruciate ligament (ACL) tear.
"Young, growing athletes are at high risk for ACL injuries, so it is important to work with coaches, trainers and medical professionals to minimize the risk of injury today, as well as the likelihood of re-injury or arthritis many years from now," said Dr. Paul Sherbondy, an orthopedic surgeon at Penn State Health Medical Group – Park Avenue in State College.
According to Sherbondy, the ACL is one of the four major ligaments in the knee and the most commonly injured. It connects the thigh bone to the shin bone and helps stabilize the knee joint. ACL injuries range from a mild overextension to a full tear. "Anyone who has injured this ligament is at higher risk for re-injury, as well as early-onset osteoarthritis of the knee," he said.
ACL injuries are most common in sports that involve these maneuvers, including basketball, football, soccer and lacrosse.
Treatment for an ACL injury depends on the severity and type of damage, as well as on the patient's long-term goals. First, a physician may order X-rays, a MRI or an ultrasound to fully define the injury and rule out fractures or other problems. Minor ACL injuries often can be treated with several months of physical therapy plus a knee brace and crutches to support healing.
After surgery, the focus is not on a quick return to play, but rather on effective rehabilitation for long-term stability and avoidance of re-injury. Deciding factors for the return-to-play timeline can include testing of aerobic capacity and isokinetic and dynamic muscle strength — for example, when hopping on one leg. Proper rehabilitation can take eight to 12 months.
At the collegiate level, athletic teams often provide strength and conditioning programs for all athletes. At the high school level, availability may depend on funding and coach awareness.
"If an athlete participates in a team without a strength and conditioning program, it can be helpful to seek private assistance from a physical therapist or sports performance center to prevent injuries and enhance overall performance," Sherbondy said.
In addition, athletes should always wear the proper protective gear for their sports, including sport-specific footwear.
"Athletes also should seek evaluation and treatment, where needed, for minor knee pain to prevent a small injury from advancing to a full ACL tear," he said.
The Medical Minute: Knee pain -- when should you be concerned?


text:
S R Nathan Education Upliftment Fund – Providing students with the needed leg-up
Growing up in a poor family, the late former President of Singapore Mr S R Nathan knew what it was like to struggle with school and making ends meet.
In his teens, he dropped out of school, ran away from home and tried to eke out a living amidst troubled times. While working, he continued his education and was eventually awarded a bursary that enabled him to graduate with a Diploma in Social Studies from then University of Malaya.
"Those of you who have read my memoir will recall – my youth was a very troubled one. Left to despair over my fate, I realised that life was not always fair. Coming face to face with all sorts of hardships, it was the unexpected help from some unknown person that my life turned for the better," said Mr Nathan.
In 2011 when Mr Nathan published his memoir 'An Unexpected Journey: Path to the Presidency,' he established the S R Nathan Education Upliftment Fund (SRNEUF) to help students by providing them with the financial assistance to keep them in school and enable them to pursue their tertiary education. Mr Nathan firmly believed that education was an important social leveler which provides students from disadvantaged backgrounds an opportunity to seek a better life for themselves and their families.
Managed by the Community Foundation of Singapore (CFS), the fund supports programmes like the Institute of Technical Education (ITE)'s Monthly Financial Assistance Scheme (MFAS) which provides needy students with allowances for transport and meals to lessen their financial burden and allow them to focus on their studies.
Mike Goh, a former beneficiary of the MFAS at ITE and currently a student at Republic Polytechnic, began working in his early teens to support himself after both his parents fell severely ill. Recounting the challenges of juggling his academic studies with work, Mike expressed, "If I did not have time to work, the allowance from the fund had helped me manage day by day, and I'm really thankful for that.
Raised in a single-parent home, Yasmin Raihanah Bte Shahrin, a student at ITE College Central, expressed gratitude for the timely support from the fund, "Initially when I started my studies at ITE, I was worried. My mother's income was not high, and I had to rely on my work income to support my daily expenses. With the award, I felt relieved because I could pay for my school necessities and food."
The fund also awards bursaries and scholarships to students from local polytechnics and universities. Ding Jian Han, an awardee of the 2018/19 S R Nathan Music Scholarship, was an aspiring composer at the Yong Siew Toh Conservatory of Music, National University of Singapore. Jian Han, who plays the violin, piano and clarinet, credits the support from the fund for enabling him to pursue his passion in music. "My father passed away when I was young, but I was fortunate to be awarded scholarships so that I was able to help my mum and pay for my school fees," said Jian Han.
Since 2012, the fund has disbursed over $3 million to support more than 1,500 ITE, polytechnic and university students by providing bursaries, scholarships as well as monthly financial assistance. In 2019, the fund will be establishing the S R Nathan Student Grant at the Singapore University of Social Sciences, as well as the S R Nathan Book Prize and the S R Nathan Special Assistance Scheme at ITE.
Mr Bobby Chin, Chairman of the SRNEUF Grant Advisory Committee said, "Thanks to the vision and generosity of our late former president S R Nathan and the on-going support of donors, we have extended our reach significantly over the last seven years. With CFS's continued trusted facilitation, the SRNEUF will continue to play a crucial role in helping our youths overcome difficult circumstances in their schooling years, go on to pursue their dreams and forge a brighter future for themselves and their families."
#MyGivingJourney X Ravina Kirpalani: Taking family philanthropy to new heights
#MyGivingJourney X Jeya Ayadurai: Bringing her people and strategic skills to nonprofits
December 17, 2021·
#MyGivingJourney x Year of Celebrating SG Women


text:
Q: Creating sObject via REST - date format Currently, I've used the postman to make a request to standard Saleforce API.
At the Date field I inputted year only.

As I expected, that should be inserted fail for that case.
But actually, the record inserted successful. And I've taken a look at the date field, it populated the first day of inputted year.

That's so strange.
As I known that salesforce API allow only the input date with format: yyyy-MM-dd.
I tried to research why but no luck.
Could anyone give me an explanation or related document about this??
Thanks in advance!

A: Edit: As I suspected, the JSON parser used by the REST API allows extra formats that are not documented in the documentation. It is strongly recommended that you use only the documented date format specification (YYYY-MM-DD).

The SOAP API specifically requires (YYYY-MM-DD) for date fields. For the REST API, you can use (almost?) any ISO 8601 format, including such options as:

Format
Example
Note

YYYY
2022
Assumes Jan 1st (1/1/2022)

YYYY-MM
2022-07
Assumes first day of month (7/1/2022)

YYYY-MM-DD
2022-07-09
n/a

YYYY-Www
2022-W27
Returns Monday of that week (7/4/2022)

YYYY-Www-D
2022-W27-6
1=Monday, 7=Sunday (7/9/2022)

YYYY-DDD
2022-190
1=Jan 1, 365=Dec 31 in non-leap year (7/9/2022)

I'm not entirely sure where this is called out in the documentation, however. Just be aware that you can use a variety of date formats with the REST API.

redpajama_set_name: RedPajamaStackExchange


text:
Elephant-sized asteroid passes Earth in one of closest encounters ever | ...
Home›World News›Whole family, including a young child, among hundreds of victims found in newly discovered mass grave in Ukraine
Whole family, including a young child, among hundreds of victims found in newly discovered mass grave in Ukraine
Izyum, Ukraine, is one of many towns that have been under the control of Russian forces for months, who have relentlessly shelled the area and its residents. The city was only recently liberated from Ukraine and it was discovered that so many people were being killed so quickly that hundreds were buried inside shallow mass graves – including at least one whole family.
CBS News foreign correspondent Debora Patta visited the site on Friday, where she learned the makeshift cemetery held those killed by shelling. Others buried had been executed, including some, according to Reuters, who were still buried with ropes around their necks and their hands tied.
Dmytro Lubinets, the Ukrainian parliament's human rights commissioner, said in a video posted to Telegram on Friday that among those buried was "a whole family" — a mother and father in their 30s, their parents and their 5 or 6-year-olds -year-old -old daughter. The remains of the family are marked with plywood crosses and small yellow and purple flowers planted in the dirt covering them.
The remains of an entire family, including grandparents and a young child, have been found in a newly discovered mass grave in Izyum, Ukraine. Hundreds of victims were found at the site. https://t.co/dKS6WPvIkH pic.twitter.com/tPtRYptTdi
— CBS News (@CBSNews) 09/16/2022
"We have testimonies from locals saying that they were all killed in an airstrike carried out by Russian Federation military planes," Lubinets was translated into Ukrainian.
Russian troops controlled the city more than six months until Ukrainian forces were able to recapture it earlier this week.
Izyum resident Serhii Shtanko told Reuters that he believes his neighbor's entire family, totaling seven, are also buried in the mass grave.
Patta reported that the bodies found there will be exhumed and identified in the coming days.
Oleh Synehubov, the governor of the Kharkiv region, told Reuters that Ukrainian officials received information about mass deaths while Russian forces were still occupying the region, but so far they have not been able to confirm the victims. Ukraine's national police chief Ihor Klymenko said early Friday that many of the bodies are believed to have been buried since March.
"We didn't have reliable information then, but now we have facts," he said. "There are many children, there are corpses with their hands tied behind their backs. Each of these facts will be investigated and they will be legally verified. However, all of this can only testify that the world must recognize that this is a genocide by the Ukrainian people."
Oleksandr Ilyenkov, the chief prosecutor for war crimes in Kharkiv, told Reuters there are believed to be about 500 civilian bodies at the site. Those numbers would make it the largest mass burial in Europe since discoveries after the Balkan Wars, Reuters said.
Li Cohen
Li Cohen is a social media producer and trending reporter for CBS News, focusing on social justice issues.
আন্তর্জাতিক সংবাদ। Today 07 May 2022 । World News 24। আন্তর্জাতিক খবর।International ...
Virginia Gov. Glenn Youngkin lifts protections for transgender students
Ukraine Russia Conflict: War से पॉपुलर पुतिन | Vladimir Putin | World News | Hindi ...
International News Today 9 July 2022 World News Today International Bangla News Today Times News
Air India: At least 4.5 million data from people after IT system hack | Science ...
Sam Mewis announced Monday that she had to undergo further surgery on ...
The mystery of the wreck of a 17th-century warship off the coast of Britain is ...


text:
Q: Why cannot xdg-desktop-menu-dummy.menu be backed up? I am using deja dup for backups. Since a few weeks it keeps on complaining
Could not backup the following files< Please make sure you are able to open them.
/home/username/.config/menus/applications-merged/xdg-desktop-menu-dummy.menu

I do not recall having changed anything to that file. It's permissions are -rw------- (like all other files in that directory).
Any idea how to fix this problem? Should I just delete the file?

A: That file is empty and is a dummy, so, when is empty is not used, when is not empty DejaDup don't ignore him.
It doesn't say error... at most is an INFO message, in my system the file is empty and was recreated whenever I moved it. This kind of message can be safely ignored.


text:
Zvi Tohar (Berlijn, 1915 – Londen, 10 oktober 1970) was de hoofdpiloot van El Al, de nationale luchtvaartmaatschappij van Israël.

Hij is best bekend voor het overvliegen van de nazi Adolf Eichmann op 20 mei 1960 naar Israël, waar hij terechtstond voor zijn oorlogsmisdaden.

Tohar overleed op 55-jarige leeftijd, onderweg naar London Heathrow Airport, aan een hartaanval.

Referenties

Israëlisch vliegenier


A source in one of the developing campaigns for two Ontario Liberals who have been laying groundwork for a federal leadership bid for several months said initial activity by McGuinty organizers has included extensive public opinion polling.
"I've heard from a couple of sources this morning that the McGuinty camp has been polling for over a month, they've done two polls," the source said.
He told The Hill Times that if McGuinty enters the race, with the vast network of organizers he and his campaign teams have built over the past 16 years in Ontario, the effect could be devastating for prospective Ontario candidates David Bertschi and George Takach.
A toast to McGuinty or a toast to his departure?
Every pundit, commentator, and Joe Schmoe with a Twitter account has weighed in on Dalton McGuinty's legacy today. The range of opinions is vast, as you might expect for any leader who has been in power for nearly a decade – even one as bland, centrist, and pragmatic as Dalton McGuinty. I'm sure we'll see the same spectrum of analysis when Stephen Harper finally decides to call it a career and focus all of his energies on finishing the hockey book.
While I found McGuinty a bit too risk-averse for my liking during his first term, I've grown rather fond of the man since moving to Ontario, so I won't pretend to be unbiased in my assessment. I do think you can objectively say he made tangible improvements to Ontario's education system, and struggled to get the province's financial house in order during a recession that hit Ontario especially hard.
Faced with the downturn, he did show boldness bringing in the HST and trying to get civil servant contracts under control. I think those moves were for the better, others will feel they were for the worse (including many Liberals), but you can't say he did them as a cynical vote grab – those were gutsy decisions, taken to dig Ontario out from under a mound of debt. To me, they elevate McGuinty beyond being merely a political autobot programmed to hold power, into a true leader who is worthy of adoration or hate. That's why we're seeing the full gamut of emotions today.
On the whole, voters themselves likely passed the fairest judgment on the McGuinty legacy. He was given a rare third term after a campaign in which he ran hard on his record – but it was far from a resounding endorsement. So, "good but not great"…which is better than voters will say about most politicians.
There was obviously a lot more to Dalton McGuinty's time as Premier than that, but how you view his legacy will depend largely on your political stripes. Personally, I feel both the Liberal Party and Ontario benefited from McGuinty's time in power, and will be worse off with his departure.
Ontario Premier Dalton McGuinty threatened to take Ontario to a general election Thursday if the opposition parties couldn't agree on a deal to pass the budget.
"This is about Ontario's economic livelihood and our ability to continue steering the province in the right direction in these challenging times," McGuinty said in a statement.
The NDP had appeared ready to support the minority Liberal budget in exchange for a new tax on incomes over $500,000, and to get more hearings into the fiscal plan before next week's vote.
But on Thursday, McGuinty accused NDP leader Andrea Horwath of reneging on the deal.
"Earlier today, the NDP turned their backs — yet again — on an agreement to pass our budget," McGuinty said. "They joined forces with the PCs to gut the government's budget bill.
As I wrote on election night last fall, the line between majority and minority isn't as rigid as it's often made out to be. When the margin is this thin, one case of appendicitis can tip the scales and change the course of history.
On Friday, Dalton McGuinty proved how fluid that majority line is, by appointing veteran PC MLA Elizabeth Witmer as the chair of the WSIB, setting the stage for an "all in" by election in Kitchener-Waterloo, and hundreds of "battle of Waterloo" metaphors.
An MPP with over 20 years in office has to be worth at least 5 points at the ballot box, making Witmer's old seat very much a toss up. It's a riding Andrew Telegdi won handily for the federal Liberals as recently as 2006, before razor-thin losses in 2008 and 2011.
While there's no doubt a temptation to strike early and call a snap by election, McGuinty has the cover of the NDP budget deal to get him through the spring session, so there's no immediate rush. After all, it's a student riding, so there's something to be said for a fall by election, when thousands Waterloo and Laurier students notice a cool 30% reduction on their tuition bills.
Regardless on timing, the election is going to be all about whether voters want a majority or a minority government. For the next few months, the eyes of the province will be on Kitchener-Waterloo.
During the minority government era in federal politics, we all grew accustomed to the annual spring budget dance – a popular budget full of election treats, and never ending speculation over whether or not it would trigger an election.
Yet Dalton McGuinty's first minority government budget felt different. Sure, Tim Hudak pushed out his chest and boldly declared he'd vote against it (despite not giving any kind of coherent explanation on how he'd balance the books). And yes, Andrea Horwath was not pleased and will now "consult" with Ontarians over what to do. But the reality is the NDP will support the budget, if only because none of the parties want – or can afford – an election.
The budget itself was decidedly "treat-free" – there's not a single ounce of sugar in it. Not even a Harper-esque tax credit for buying sunscreen. Rather, the Liberal story of the budget was about what the government didn't do – they didn't scrap all day kindergarten, they didn't cut Health Care, they didn't increase class sizes.
Of course, if the benchmark is the Drummond Report, then what the government didn't do, might be enough to help the public swallow this tough medicine budget. I feel like most Ontarians recognize tough decisions are needed, and the cutbacks and wage freezes McGuinty has proposed will be far less painful than Rae Days, tax hikes, or health care cuts.
Unless you're in a union, that is. A public sector wage freeze is easier said than done, so Ontario is in for a year of labour unrest.
While McGuinty's budget will ensure campaign signs stay locked up, it's time to pull out the strike signs.


text:
Q: Correlated subquery friends Query:
select friends_of_first.friend
from (
    select id2 as friend from friend_relastionship where id1 = '4'
    union
    select id1 as friend from friend_relastionship where id2 = '4'
    ) friends_of_first
join (
    select id2 as friend from friend_relastionship where id1 = '7'
    union
    select id1 as friend from friend_relastionship where id2 = '7'
    ) friends_of_second
on friends_of_first.friend = friends_of_second.friend;

This query finds the mutual friends between users 4 and 7.
I want to use this as a basis of finding all pairs of mutual friends inside the table friend_relastionship so that I can select the top pairs with the most mutual friends. My understanding is that I can run this on every pairing with a correlated subquery but I am unsure how.
The table is designed in such a way that id1 < id2  and if a friendship exists between 1 and 7 then it is listed as 1,7 and never 7,1. So a friendship appears once.
Here is a sqlfiddle : http://sqlfiddle.com/#!2/48eb0/1
In this sqlfiddle it should display
 USER1      USER2      COUNT
     3          4          3
     6          7          2
     4         45          2
     2          7          2
     2          6          2
     1          2          2
     1         45          2
     0          2          2

...
Indicating that 3 and 4 should be friends, as they have 3 mutual friends.

A: You have not shown the table structure so you will have to replace my column names with the actual column names, but this should work:
Select fof1.connection, fof1.friend, fof2.friend
from friend_relationship fof1
join friend_relationship fof2 on fof1.connection = fof2.connection
where fof1.friend < fof2.friend
You can then just do a count on each connection to see who has the most rows.

A: Here is another shot using the data in SQL Fiddle:
select a.friend1 as ID1, b.friend1 as ID2, count(distinct a.friend2) as connections
from ((select id1 as friend1, id2 as friend2
from friend_relastionship)
UNION
(select id2 as friend1, id1 as friend2
from friend_relastionship))a
join ((select id1 as friend1, id2 as friend2
from friend_relastionship)
UNION
(select id2 as friend1, id1 as friend2
from friend_relastionship))b on a.friend2 = b.friend2
where a.friend1 < b.friend1
group by ID1, ID2
having connections > 1
order by connections desc
You should consider reviewing how this data is stored or making it more query friendly by adding the UNION statement below as view.


I was taking photos the other day (as you do) and Matilda asked me if she could have a turn.
I paused... my precious camera... sure you can... stay here with me though!
"You can take 10 photos... make them precious ones"
I was rather taken with her view of the world, her composition and thought.
It inspired us to give her a camera of her own, a second hand one that she could experiment with, away from my watchful eye... she had a birthday coming up and so we did!


Three Talented Nesher teens (singers, actors, youth counselors etc.) will come to Broward during the Yoms week (Yom Hazikaron-Yom Haatzmaut= memorial day and independence day). The teens will lead workshops at school about the uniqueness of the week in Israel, participate in the ceremonies and happenings, and bring Israel to the community. The group will be chaperoned by volunteer/ P2G staff and an IDF officer from Nesher who can also share his personal story from his IDF service.