Example #1
0
        // 递归函数,得一个节点的集合,外面doSearch调该函数
        // parameter:
        //		nodeRoot	当前根节点
        //		resultSet	结果集。返回时不能确保结果集已经排序。需要看resultset.Sorted成员
        // return:
        //		-1	出错
        //		-6	无权限
        //		0	成功
        public int DoQuery(
            SessionInfo sessioninfo,
            string strOutputStyle,
            XmlElement nodeRoot,
            ref DpResultSet resultSet,
            ChannelHandle handle,
            // Delegate_isConnected isConnected,
            out string strError)
        {

            DateTime start_time = DateTime.Now;
            Debug.WriteLine("Begin DoQuery()");

            try
            {

                strError = "";
                if (nodeRoot == null)
                {
                    strError = "DoQuery() nodeRoot参数不能为null。";
                    return -1;
                }

#if NO
                if (resultSet == null)
                {
                    strError = "DoQuery() resultSet参数不能为null。";
                    return -1;
                }
#endif

                if (resultSet != null)
                {
                    // 先清空一下
                    resultSet.Clear();
                }

                // 到item时不再继续递归
                if (nodeRoot.Name == "item")
                {
                    if (resultSet == null)
                        resultSet = sessioninfo.NewResultSet(); // 延迟创建
                    // return:
                    //		-1	出错
                    //		-6	无足够的权限
                    //		0	成功
                    return doItem(
                        sessioninfo,
                        strOutputStyle,
                        nodeRoot,
                        ref resultSet,
                        handle,
                        // isConnected,
                        out strError);
                }

                //如果为扩展节点,则不递归
                if (nodeRoot.Name == "operator"
                    || nodeRoot.Name == "lang")
                {
                    return 0;
                }

                //将正常顺序变成逆波兰表序
                ArrayList rpn;
                // return:
                //		-1  出错 例如:括号不匹配;找不到某操作符的优先级
                //      0   可用节点数为 0。等于没有任何可检索的必要
                //		1   成功
                int nRet = Infix2RPN(nodeRoot,
                    out rpn,
                    out strError);
                if (nRet == -1)
                {
                    strError = "逆波兰表错误:" + strError;
                    return -1;
                }
                if (nRet == 0)
                    return -1;

                //属于正常情况
                if (rpn.Count == 0)
                    return 0;

                // return:
                //		-1  出错
                //		-6	无足够的权限
                //		0   成功
                nRet = ProceedRPN(
                    sessioninfo,
                    strOutputStyle,
                    rpn,
                    ref resultSet,
                    handle,
                    // isConnected,
                    out strError);
                if (nRet <= -1)
                    return nRet;

                return 0;
            }
            finally
            {
                TimeSpan delta = DateTime.Now - start_time;
                Debug.WriteLine("End DoQuery() 耗时 " + delta.ToString());
            }
        }
Example #2
0
        // 运算逆波兰表,得到结果集
        // parameter:
        //		rpn         逆波兰表
        //		resultSet  结果集
        // return:
        //		0   成功
        //		-1  出错 原因可能如下:
        //			1)rpn参数为null
        //			2)oResultSet参数为null
        //			3)栈里的某成员出错(node和result都为null)
        //			4)从栈中pop()或peek()元素时,出现栈空
        //			5)pop的类型,不是实际存在的类型
        //			6)通过一个节点,得到结果集,即调DoQuery()函数出错
        //			7)做运算时,调DpResultSetManager.Merge()函数出错
        //			8)最后栈里的元素多于1,则逆波兰表出错
        //			9)最后结果集为空
        //		-6	无足够的权限
        public int ProceedRPN(
            SessionInfo sessioninfo,
            string strOutputStyle,
            ArrayList rpn,
            ref DpResultSet resultSet,
            ChannelHandle handle,
            // Delegate_isConnected isConnected,
            out string strError)
        {
            DateTime start_time = DateTime.Now;
            Debug.WriteLine("Begin ProceedRPN()");

            try
            {
                strError = "";
                //???要搞清楚用不用清空
                //应该清空,后面的运算使用的结果集是堆栈变量,最后把运算结果拷贝到该结果集
                //DoQuery处,也应该先清空
                //doItem处,一进去先清空,但再对数据库循环检索时,千万不清空

                if (resultSet != null)
                    resultSet.Clear();

                if (rpn == null)
                {
                    strError = "rpn不能为null";
                    return -1;
                }
#if NO
                if (resultSet == null)
                {
                    strError = "resultSet不能为null";
                    return -1;
                }
#endif

                if (rpn.Count == 0)
                    return 0;

                int ret;

                // 声明栈,ReversePolishStack栈是自定义的类
                // 决定用一个栈做运算,如果遇到遇到操作数,就直接push到栈里
                // 遇到操作符,如果是双目,从栈里pop两项,进行运算
                // 注意SUB运算是,用后一次pop的对象减前一次pop的对象
                //
                // oReversePolandStack的成员为ReversePolishItem,
                // ReversePolishItem是一个复杂对象,
                // 包含m_int(类型),m_node(节点),m_resultSet.
                // 实际运用中,m_node和m_resultSet只有一项值有效,另一顶是null
                // m_int用于判断哪个值有效,
                // 0表示node有效,1表示resultSet有效
                ReversePolishStack oReversePolandStack =
                    new ReversePolishStack();

                //做循环
                for (int i = 0; i < rpn.Count; i++)
                {
                    XmlElement node = (XmlElement)rpn[i];

                    if (node.Name != "operator")  //操作数直接push到栈里
                    {
                        oReversePolandStack.PushNode(node);
                    }
                    else
                    {
                        string strOpreator = DomUtil.GetAttr(node, "value");

#if NO
                        //三个输出用于输入的参数,因为是指针,所以不用out
                        DpResultSet oTargetLeft = sessioninfo.NewResultSet();   // new DpResultSet();
                        DpResultSet oTargetMiddle = sessioninfo.NewResultSet();   // new DpResultSet();
                        DpResultSet oTargetRight = sessioninfo.NewResultSet();   // new DpResultSet();
#endif

                        //做一个两个成员的ArrayList,
                        //成员类型为DpResultSet,
                        //存放从栈里pop出的(如果是node,需要进行计算)的结果集
                        List<DpResultSet> oSource = new List<DpResultSet>();
                        oSource.Add(sessioninfo.NewResultSet());   // new DpResultSet()
                        oSource.Add(sessioninfo.NewResultSet());   // new DpResultSet()
                        try
                        {
                            for (int j = 0; j < 2; j++)
                            {
                                //类型为-1,表示node和resultSet都为null,出现错误
                                if (oReversePolandStack.PeekType() == -1)
                                {
                                    strError = strOpreator + "时,PeekType()等于-1,则表示两项都是null,出错,返回-1<br/>";
                                    return -1;
                                }

                                //表示放得是node
                                if (oReversePolandStack.PeekType() == 0)
                                {
                                    XmlElement nodePop;
                                    nodePop = oReversePolandStack.PopNode();
                                    if (nodePop == null)
                                    {
                                        strError = "nodePop不为又能为null";
                                        return -1;
                                    }

                                    DpResultSet temp = oSource[j];
                                    // return:
                                    //		-1	出错
                                    //		-6	无权限
                                    //		0	成功
                                    ret = this.DoQuery(
                                        sessioninfo,
                                        strOutputStyle,
                                        nodePop,
                                        ref temp,
                                        handle,
                                        // isConnected,
                                        out strError);
                                    if (ret <= -1)
                                        return ret;
                                    if (temp != oSource[j])
                                    {
                                        // 2014/3/11
                                        if (oSource[j] != null)
                                            oSource[j].Close();
                                        oSource[j] = temp;
                                    }
                                }
                                else
                                {
                                    DpResultSet temp = oReversePolandStack.PopResultSet();
                                    Debug.Assert(temp != oSource[j], "");

                                    // 2014/3/11
                                    if (oSource[j] != null)
                                        oSource[j].Close();
                                    oSource[j] = temp;

                                    if (oSource[j] == null)
                                    {
                                        strError = "PopResultSet() return null";
                                        return -1;
                                    }
                                }
                            }
                        }
                        catch (StackUnderflowException /*ex*/)
                        {
                            // 2008/12/4
                            string strOutXml = "";
                            if (node.ParentNode != null)
                            {
                                int nRet = DomUtil.GetIndentXml(node.ParentNode.OuterXml,
                                    out strOutXml,
                                    out strError);
                            }
                            strError = strOpreator + " 是二元操作符,它缺乏操作数。";

                            if (String.IsNullOrEmpty(strOutXml) == false)
                                strError += "\r\n" + strOutXml;

                            // strError = "StackUnderflowException :" + ex.Message;
                            return -1;
                        }

                        // string strDebugInfo;

                        //OR,AND,SUB运算都是调的DpResultSetManager.Merge()函数,
                        //注意参数的使用
                        if (strOpreator == "OR")
                        {
                            bool bOutputKeyCount = StringUtil.IsInList("keycount", strOutputStyle);
                            bool bOutputKeyID = StringUtil.IsInList("keyid", strOutputStyle);

                            DpResultSet left = oSource[1];
                            DpResultSet right = oSource[0];

#if DEBUG
                            Debug.Assert(left.IsClosed == false, "");
                            Debug.Assert(right.IsClosed == false, "");
#endif

                            {
                                // 直接相加
                                if (left.Count == 0)
                                {
                                    oReversePolandStack.PushResultSet(
                                        right
                                        );
                                    // 2014/3/11
                                    Debug.Assert(left != right, "");
                                    left.Close();
                                }
                                else if (right.Count == 0)
                                {
                                    oReversePolandStack.PushResultSet(
                                        left
                                        );
                                    // 2014/3/11
                                    Debug.Assert(left != right, "");
                                    right.Close();
                                }
                                else
                                {
                                    if (EnsureSorted(left, handle, out strError) == -1)
                                        return -1;
                                    if (EnsureSorted(right, handle, out strError) == -1)
                                        return -1;
                                    // return:
                                    //      -1  出错
                                    //      0   没有交叉部分
                                    //      1   有交叉部分
                                    ret = DpResultSetManager.IsCross(left,
                                        right,
                                        out strError);
                                    if (ret == -1)
                                        return -1;
                                    if (ret == 0)
                                    {
                                        DpResultSet left_save = left;
                                        // 注意:函数执行过程,可能交换 left 和 right。也就是说返回后, left == right
                                        ret = DpResultSetManager.AddResults(ref left,
                                            right,
                                            out strError);
                                        if (ret == -1)
                                            return -1;

                                        oReversePolandStack.PushResultSet(
                                            left
                                            );
                                        // 2014/3/11
                                        if (left != right)
                                        {
                                            Debug.Assert(left_save == left, "");
                                            right.Close();
                                        }
                                        else
                                        {
                                            Debug.Assert(left_save != left, "");
                                            left_save.Close();
                                        }
                                    }
                                    else
                                    {
                                        if (left.Asc != right.Asc)
                                        {
                                            right.Asc = left.Asc;
                                            right.Sorted = false;
                                        }

                                        if (EnsureSorted(left, handle, out strError) == -1)
                                            return -1;
                                        if (EnsureSorted(right, handle, out strError) == -1)
                                            return -1;

                                        {
                                            DpResultSet oTargetMiddle = sessioninfo.NewResultSet();   // new DpResultSet();
                                            StringBuilder debugInfo = null;
                                            ret = DpResultSetManager.Merge(LogicOper.OR,
        left,
        right,
        strOutputStyle,
        null,
        oTargetMiddle,
        null,
                                                // false,
        querystop,
        handle,
        ref debugInfo,
        out strError);
                                            if (ret == -1)
                                                return -1;

                                            oReversePolandStack.PushResultSet(oTargetMiddle);
                                            // 2014/3/11
                                            Debug.Assert(left != oTargetMiddle, "");
                                            Debug.Assert(right != oTargetMiddle, "");
                                            left.Close();
                                            right.Close();
                                        }
                                    }
                                }
                            }

                            continue;
                        }

                        if (strOpreator == "AND")
                        {
                            DpResultSet left = oSource[1];
                            DpResultSet right = oSource[0];
#if DEBUG
                            Debug.Assert(left.IsClosed == false, "");
                            Debug.Assert(right.IsClosed == false, "");
#endif

                            if (left.Asc != right.Asc)
                            {
                                right.Asc = left.Asc;
                                right.Sorted = false;
                            }

                            if (EnsureSorted(left, handle, out strError) == -1)
                                return -1;
                            if (EnsureSorted(right, handle, out strError) == -1)
                                return -1;

                            // 优化
                            if (left.Count == 0)
                            {
                                oReversePolandStack.PushResultSet(
                                    left
                                    );
                                // 2014/3/11
                                Debug.Assert(left != right, "");
                                right.Close();
                            }
                            else if (right.Count == 0)
                            {
                                oReversePolandStack.PushResultSet(
                                    right
                                    );
                                // 2014/3/11
                                Debug.Assert(left != right, "");
                                left.Close();
                            }
                            else
                            {
                                DpResultSet oTargetMiddle = sessioninfo.NewResultSet();   // new DpResultSet();

                                StringBuilder debugInfo = null;

                                ret = DpResultSetManager.Merge(LogicOper.AND,
                                    left,
                                    right,
                                    strOutputStyle,
                                    null,    //oTargetLeft
                                    oTargetMiddle,
                                    null,   //oTargetRight
                                    // false,
                                    querystop,
                                    handle,
                                    ref debugInfo,
                                    out strError);
                                if (ret == -1)
                                    return -1;

                                oReversePolandStack.PushResultSet(oTargetMiddle);
                                // 2014/3/11
                                Debug.Assert(left != oTargetMiddle, "");
                                Debug.Assert(right != oTargetMiddle, "");
                                left.Close();
                                right.Close();
                            }

                            continue;
                        }

                        if (strOpreator == "SUB")
                        {
                            //因为使用从栈里pop,所以第0个是后面的,第1个是前面的
                            DpResultSet left = oSource[1];
                            DpResultSet right = oSource[0];
#if DEBUG
                            Debug.Assert(left.IsClosed == false, "");
                            Debug.Assert(right.IsClosed == false, "");
#endif

                            if (left.Asc != right.Asc)
                            {
                                right.Asc = left.Asc;
                                right.Sorted = false;
                            }

                            if (EnsureSorted(left, handle, out strError) == -1)
                                return -1;
                            if (EnsureSorted(right, handle, out strError) == -1)
                                return -1;

                            // 优化
                            if (left.Count == 0)
                            {
                                oReversePolandStack.PushResultSet(
                                    left
                                    );
                                // 2014/3/11
                                Debug.Assert(left != right, "");
                                right.Close();
                            }
                            else if (right.Count == 0)
                            {
                                oReversePolandStack.PushResultSet(
                                    left
                                    );
                                // 2014/3/11
                                Debug.Assert(left != right, "");
                                right.Close();
                            }
                            else
                            {
                                DpResultSet oTargetLeft = sessioninfo.NewResultSet();   // new DpResultSet();

                                StringBuilder debugInfo = null;

                                ret = DpResultSetManager.Merge(LogicOper.SUB,
                                    left,
                                    right,
                                    strOutputStyle,
                                    oTargetLeft,
                                    null, //oTargetMiddle
                                    null, //oTargetRight
                                    // false,
                                    querystop,
                                    handle,
                                    ref debugInfo,
                                    out strError);
                                if (ret == -1)
                                {
                                    return -1;
                                }

                                oReversePolandStack.PushResultSet(oTargetLeft);
                                // 2014/3/11
                                Debug.Assert(left != oTargetLeft, "");
                                Debug.Assert(right != oTargetLeft, "");
                                left.Close();
                                right.Close();
                            }

                            continue;
                        }
                    }
                }
                if (oReversePolandStack.Count > 1)
                {
                    strError = "逆波兰出错";
                    return -1;
                }
                try
                {
                    int nTemp = oReversePolandStack.PeekType();
                    //如果类型为0,表示存放的是节点
                    if (nTemp == 0)
                    {
                        XmlElement node = oReversePolandStack.PopNode();

                        // return:
                        //		-1	出错
                        //		-6	无权限
                        //		0	成功
                        ret = this.DoQuery(
                            sessioninfo,
                            strOutputStyle,
                            node,
                            ref resultSet,
                            handle,
                            // isConnected,
                            out strError);
                        if (ret <= -1)
                            return ret;
                    }
                    else if (nTemp == 1)
                    {
                        // 调DpResultSet的copy函数

                        // TODO: 测算这个Copy所花费的时间。
                        // resultSet.Copy((DpResultSet)(oReversePolandStack.PopResultSet()));
                        resultSet = (DpResultSet)(oReversePolandStack.PopResultSet());
                    }
                    else
                    {
                        strError = "oReversePolandStack的类型不可能为" + Convert.ToString(nTemp);
                        return -1;
                    }
                }
                catch (StackUnderflowException)
                {
                    strError = "peek或pop时,抛出StackUnderflowException异常";
                    return -1;
                }

                //最后结果集为null,返回出错
                if (resultSet == null)
                {
                    strError = "运算结束后PopResultSet为null" + Convert.ToString(oReversePolandStack.PeekType());
                    return -1;
                }

                return 0;
            }
            finally
            {
                TimeSpan delta = DateTime.Now - start_time;
                Debug.WriteLine("End ProceedRPN() 耗时 " + delta.ToString());
            }
        }
Example #3
0
        // 检索单元item的信息,对库进行检索
        // parameter:
        //		nodeItem	item节点
        //		resultSet	结果集。返回时不能确保结果集已经排序。需要看resultset.Sorted成员
        //		            传进结果集,????????每次清空,既然每次清空,那还不如返回一个结果集呢
        //		isConnected	是否连接
        //		strError	out参数,返回出错信息
        // return:
        //		-1	出错
        //		-6	无足够的权限
        //		0	成功
        public int doItem(
            SessionInfo sessioninfo,
            string strOutputStyle,
            XmlElement nodeItem,
            ref DpResultSet resultSet,
            ChannelHandle handle,
            // Delegate_isConnected isConnected,
            out string strError)
        {
            strError = "";
            if (nodeItem == null)
            {
                strError = "doItem() nodeItem参数为null.";
                return -1;
            }

            if (resultSet == null)
            {
                strError = "doItem() oResult参数为null.";
                return -1;
            }

            string strResultSetName = nodeItem.GetAttribute("resultset");
            if (string.IsNullOrEmpty(strResultSetName) == false)
            {
                resultSet.Close();
                resultSet = null;

                DpResultSet source = null;
                if (KernelApplication.IsGlobalResultSetName(strResultSetName) == true)
                {
                    source = this.m_dbColl.KernelApplication.ResultSets.GetResultSet(strResultSetName.Substring(1), false);
                }
                else
                {
                    source = sessioninfo.GetResultSet(strResultSetName, false);
                }

                if (source == null)
                {
                    strError = "没有找到名为 '" + strResultSetName + "' 的结果集对象";
                    return -1;
                }
                resultSet = source.Clone("handle");
                resultSet.ReadOnly = true;
                return 0;
            }

            //先清空一下
            resultSet.Clear();

            int nRet;

            //调processRelation对检索单元的成员检查是否存在矛盾
            //如果返回0,则可能对item的成员进行了修改,所以后面重新提取内容
            nRet = ProcessRelation(nodeItem);
            if (nRet == -1)
            {
                // strError = "doItem()里调processRelation出错";
                strError = "检索式局部有错: " + nodeItem.OuterXml;
                return -1;
            }

            // 根据nodeItem得到检索信息
            string strTarget;
            string strWord;
            string strMatch;
            string strRelation;
            string strDataType;
            string strIdOrder;
            string strKeyOrder;
            string strOrderBy;
            string strHint = "";
            int nMaxCount;
            nRet = QueryUtil.GetSearchInfo(nodeItem,
                strOutputStyle,
                out strTarget,
                out strWord,
                out strMatch,
                out strRelation,
                out strDataType,
                out strIdOrder,
                out strKeyOrder,
                out strOrderBy,
                out nMaxCount,
                out strHint,
                out strError);
            if (nRet == -1)
                return -1;

            bool bSearched = false;
            bool bNeedSort = false;

            bool bFirst = StringUtil.IsInList("first", strHint);    // 是否为 命中则停止继续检索

            // 将 target 以 ; 号分成多个库
            string[] aDatabase = strTarget.Split(new Char[] { ';' });
            foreach (string strOneDatabase in aDatabase)
            {
                if (strOneDatabase == "")
                    continue;

                string strDbName;
                string strTableList;

                // 拆分库名与途径
                nRet = DatabaseUtil.SplitToDbNameAndForm(strOneDatabase,
                    out strDbName,
                    out strTableList,
                    out strError);
                if (nRet == -1)
                    return -1;

                // 得到库
                Database db = m_dbColl.GetDatabase(strDbName);
                if (db == null)
                {
                    strError = "未找到'" + strDbName + "'库";
                    return -1;
                }

                // 2009/7/19
                if (db.InRebuildingKey == true)
                {
                    strError = "数据库 '" + db.GetCaption(null) + "' 正处在重建检索点状态,不能进行检索...";
                    return -1;
                }

                string strTempRecordPath = db.GetCaption("zh-CN") + "/" + "record";
                string strExistRights = "";
                bool bHasRight = this.m_oUser.HasRights(strTempRecordPath,
                    ResType.Record,
                    "read",
                    out strExistRights);
                if (bHasRight == false)
                {
                    strError = "您的帐户名为'" + m_oUser.Name + "'" +
                        ",对'" + strDbName + "'" +
                        "数据库中的记录没有'读(read)'权限,目前的权限为'" + strExistRights + "'。";
                    return -6;
                }

                SearchItem searchItem = new SearchItem();
                searchItem.TargetTables = strTableList;
                searchItem.Word = strWord;
                searchItem.Match = strMatch;
                searchItem.Relation = strRelation;
                searchItem.DataType = strDataType;
                searchItem.IdOrder = strIdOrder;
                searchItem.KeyOrder = strKeyOrder;
                searchItem.OrderBy = strOrderBy;
                searchItem.MaxCount = nMaxCount;

                // 注: SearchByUnion不清空resultSet,从而使多个库的结果集放在一起
                string strWarningInfo = "";
                //		-1	出错
                //		0	成功
                //      1   成功,但resultset需要再行排序一次
                nRet = db.SearchByUnion(
                    strOutputStyle,
                    searchItem,
                    handle,
                    // isConnected,
                    resultSet,
                    this.m_nWarningLevel,
                    out strError,
                    out strWarningInfo);
                if (nRet == -1)
                    return -1;

                bSearched = true;

                if (nRet == 1)
                    bNeedSort = true;

                if (nRet >= 1 && bFirst == true)
                    break;
            }

            // 2010/5/17
            if (bSearched == true)
            {
                // 2010/5/11
                resultSet.EnsureCreateIndex();   // 确保创建了索引

                // 排序
                // TODO: 其实可以使用EnsureSorted()函数
                if (bNeedSort == true)
                {
                    if (DoSort(resultSet, handle/*isConnected*/) == true)
                    {
                        strError = "前端中断";
                        return -1;
                    }
                }
                // TODO: 也可以延迟排序,本函数返回一个值表希望排序。等到最后不得不排序时候再排序最好了

                //resultSet.RemoveDup();
            }

            return 0;
        }