// 按ID检索记录 // parameter: // searchItem SearchItem对象,包括检索信息 // isConnected 连接对象的delegate // resultSet 结果集对象,存放命中记录 // return: // -1 出错 // 0 成功 // 线:不安全 private int SearchByID(SearchItem searchItem, Delegate_isConnected isConnected, DpResultSet resultSet, out string strError) { strError = ""; Debug.Assert(searchItem != null, "SearchByID()调用错误,searchItem参数值不能为null。"); Debug.Assert(isConnected != null, "SearchByID()调用错误,isConnected参数值不能为null。"); Debug.Assert(resultSet != null, "SearchByID()调用错误,resultSet参数值不能为null。"); SqlConnection connection = new SqlConnection(this.m_strConnString); connection.Open(); try { List<SqlParameter> aSqlParameter = new List<SqlParameter>(); string strWhere = ""; if (searchItem.Match == "left" || searchItem.Match == "") { strWhere = " WHERE id LIKE @id and id like N'[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' "; SqlParameter temp = new SqlParameter("@id", SqlDbType.NVarChar); temp.Value = searchItem.Word + "%"; aSqlParameter.Add(temp); } else if (searchItem.Match == "middle") { strWhere = " WHERE id LIKE @id and id like N'[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' "; SqlParameter temp = new SqlParameter("@id", SqlDbType.NVarChar); temp.Value = "%" + searchItem.Word + "%"; aSqlParameter.Add(temp); } else if (searchItem.Match == "right") { strWhere = " WHERE id LIKE @id and id like N'[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' "; SqlParameter temp = new SqlParameter("@id", SqlDbType.NVarChar); temp.Value = "%" + searchItem.Word; aSqlParameter.Add(temp); } else if (searchItem.Match == "exact") { if (searchItem.DataType == "string") searchItem.Word = DbPath.GetID10(searchItem.Word); if (searchItem.Relation == "draw") { int nPosition; nPosition = searchItem.Word.IndexOf("-"); if (nPosition >= 0) { string strStartID; string strEndID; StringUtil.SplitRange(searchItem.Word, out strStartID, out strEndID); strStartID = DbPath.GetID10(strStartID); strEndID = DbPath.GetID10(strEndID); strWhere = " WHERE @idMin <=id and id<= @idMax and id like N'[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' "; SqlParameter temp = new SqlParameter("@idMin", SqlDbType.NVarChar); temp.Value = strStartID; aSqlParameter.Add(temp); temp = new SqlParameter("@idMax", SqlDbType.NVarChar); temp.Value = strEndID; aSqlParameter.Add(temp); } else { string strOperator; string strRealText; StringUtil.GetPartCondition(searchItem.Word, out strOperator, out strRealText); strRealText = DbPath.GetID10(strRealText); strWhere = " WHERE id " + strOperator + " @id and id like N'[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' "; SqlParameter temp = new SqlParameter("@id", SqlDbType.NVarChar); temp.Value = strRealText; aSqlParameter.Add(temp); } } else { searchItem.Word = DbPath.GetID10(searchItem.Word); strWhere = " WHERE id " + searchItem.Relation + " @id and id like N'[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' "; SqlParameter temp = new SqlParameter("@id", SqlDbType.NVarChar); temp.Value = searchItem.Word; aSqlParameter.Add(temp); } } string strTop = ""; if (searchItem.MaxCount != -1) // 只命中指定的条数 strTop = " TOP " + Convert.ToString(searchItem.MaxCount) + " "; string strOrderBy = ""; if (searchItem.IdOrder != "") strOrderBy = "ORDER BY id " + searchItem.IdOrder + " "; string strCommand = "use " + this.m_strSqlDbName + " SELECT " + " DISTINCT " + strTop + " id " + " FROM records " + strWhere + " " + strOrderBy + "\n"; strCommand += " use master " + "\n"; SqlCommand command = new SqlCommand(strCommand, connection); command.CommandTimeout = 20 * 60; // 把检索时间变大 foreach (SqlParameter sqlParameter in aSqlParameter) { command.Parameters.Add(sqlParameter); } DatabaseCommandTask task = new DatabaseCommandTask(command); try { Thread t1 = new Thread(new ThreadStart(task.ThreadMain)); t1.Start(); bool bRet; while (true) { if (isConnected != null) //只是不再检索了 { if (isConnected() == false) { strError = "用户中断"; return -1; } } bRet = task.m_event.WaitOne(100, false); //millisecondsTimeout if (bRet == true) break; } if (task.bError == true) { strError = task.ErrorString; return -1; } if (task.DataReader == null) return 0; if (task.DataReader.HasRows == false) { return 0; } int nLoopCount = 0; while (task.DataReader.Read()) { if (nLoopCount % 10000 == 0) { if (isConnected != null) { if (isConnected() == false) { strError = "用户中断"; return -1; } } } string strID = ((string)task.DataReader[0]); if (strID.Length != 10) { strError = "结果集中出现了长度不是10位的记录号,不正常"; return -1; } string strId = this.FullID + "/" + strID; //记录路径格式:库ID/记录号 resultSet.Add(new DpRecord(strId)); nLoopCount++; Thread.Sleep(0); } } finally { if (task != null && task.DataReader != null) task.DataReader.Close(); } } catch (SqlException sqlEx) { if (sqlEx.Errors is SqlErrorCollection) strError = "数据库'" + this.GetCaption("zh") + "'尚未初始化。"; else strError = sqlEx.Message; return -1; } catch (Exception ex) { strError = ex.Message; return -1; } finally // 连接 { connection.Close(); } return 0; }
// 得到检索条件,私有函数,被SearchByUnion()函数调 // 可能会抛出的异常:NoMatchException(检索方式与数据类型) // parameters: // searchItem SearchItem对象 // nodeConvertQueryString 字符串型检索词的处理信息节点 // nodeConvertQueryNumber 数值型检索词的处理信息节点 // strPostfix Sql命令参数名称后缀,以便多个参数合在一起时区分 // aParameter 参数数组 // strKeyCondition out参数,返回Sql检索式条件部分 // strError out参数,返回出错信息 // return: // -1 出错 // 0 成功 // 线:不安全 // ???该函数抛出异常的处理不太顺 private int GetKeyCondition(SearchItem searchItem, XmlNode nodeConvertQueryString, XmlNode nodeConvertQueryNumber, string strPostfix, ref List<SqlParameter> aSqlParameter, out string strKeyCondition, out string strError) { strKeyCondition = ""; strError = ""; //检索三项是否有矛盾,该函数可能会抛出NoMatchException异常 QueryUtil.VerifyRelation(ref searchItem.Match, ref searchItem.Relation, ref searchItem.DataType); int nRet = 0; KeysCfg keysCfg = null; nRet = this.GetKeysCfg(out keysCfg, out strError); if (nRet == -1) return -1; //3.根据数据类型,对检索词进行加工 string strKeyValue = searchItem.Word.Trim(); if (searchItem.DataType == "string") //字符类型调字符的配置,对检索词进行加工 { if (nodeConvertQueryString != null && keysCfg != null) { List<string> keys = null; nRet = keysCfg.ConvertKeyWithStringNode( null,//dataDom strKeyValue, nodeConvertQueryString, out keys, out strError); if (nRet == -1) return -1; if (keys.Count != 1) { strError = "不支持把检索词通过'split'样式加工成多个."; return -1; } strKeyValue = keys[0]; } } else if (searchItem.DataType == "number") //数字型调数字格式的配置,对检索词进行加工 { if (nodeConvertQueryNumber != null && keysCfg != null) { string strMyKey; nRet = KeysCfg.ConvertKeyWithNumberNode( strKeyValue, nodeConvertQueryNumber, out strMyKey, out strError); if (nRet == -1) return -1; strKeyValue = strMyKey; } } string strParameterName; //4.根据match的值,分别得到不同的检索表达式 if (searchItem.Match == "left" || searchItem.Match == "") //如果strMatch为空,则按"左方一致" { //其实一开始就已经检查了三顶是否矛盾,如果有矛盾抛出抛异,这里重复检查无害,更严格 if (searchItem.DataType != "string") { NoMatchException ex = new NoMatchException("在匹配方式值为left或空时,与数据类型值" + searchItem.DataType + "矛盾,数据类型应该为string"); throw (ex); } strParameterName = "@keyValue" + strPostfix; strKeyCondition = "keystring LIKE " + strParameterName + " "; SqlParameter temp = new SqlParameter(strParameterName, SqlDbType.NVarChar); temp.Value = strKeyValue + "%"; aSqlParameter.Add(temp); } else if (searchItem.Match == "middle") { //其实一开始就已经检查了三顶是否矛盾,如果有矛盾抛出抛异,这里重复检查无害,更严格 if (searchItem.DataType != "string") { NoMatchException ex = new NoMatchException("在匹配方式值为middle或空时,与数据类型值" + searchItem.DataType + "矛盾,数据类型应该为string"); throw (ex); } strParameterName = "@keyValue" + strPostfix; strKeyCondition = "keystring LIKE " + strParameterName + " "; //N'%" + strKeyValue + "'"; SqlParameter temp = new SqlParameter(strParameterName, SqlDbType.NVarChar); temp.Value = "%" + strKeyValue + "%"; aSqlParameter.Add(temp); } else if (searchItem.Match == "right") { //其实一开始就已经检查了三顶是否矛盾,如果有矛盾抛出抛异,这里重复检查无害,更严格 if (searchItem.DataType != "string") { NoMatchException ex = new NoMatchException("在匹配方式值为left或空时,与数据类型值" + searchItem.DataType + "矛盾,数据类型应该为string"); throw (ex); } strParameterName = "@keyValue" + strPostfix; strKeyCondition = "keystring LIKE " + strParameterName + " "; //N'%" + strKeyValue + "'"; SqlParameter temp = new SqlParameter(strParameterName, SqlDbType.NVarChar); temp.Value = "%" + strKeyValue; aSqlParameter.Add(temp); } else if (searchItem.Match == "exact") //先看match,再看relation,最后看dataType { //从词中汲取,较复杂,注意 if (searchItem.Relation == "draw") { int nPosition; nPosition = searchItem.Word.IndexOf("-"); //应按"-"算 if (nPosition >= 0) { string strStartText; string strEndText; StringUtil.SplitRange(searchItem.Word, out strStartText, out strEndText); if (searchItem.DataType == "string") { if (nodeConvertQueryString != null && keysCfg != null) { // 加工首 List<string> keys = null; nRet = keysCfg.ConvertKeyWithStringNode( null,//dataDom strStartText, nodeConvertQueryString, out keys, out strError); if (nRet == -1) return -1; if (keys.Count != 1) { strError = "不支持把检索词通过'split'样式加工成多个."; return -1; } strStartText = keys[0]; // 加工尾 nRet = keysCfg.ConvertKeyWithStringNode( null,//dataDom strEndText, nodeConvertQueryString, out keys, out strError); if (nRet == -1) return -1; if (keys.Count != 1) { strError = "不支持把检索词通过'split'样式加工成多个."; return -1; } strEndText = keys[0]; } string strParameterMinName = "@keyValueMin" + strPostfix; string strParameterManName = "@keyValueMan" + strPostfix; strKeyCondition = " " + strParameterMinName + " <=keystring and keystring<= " + strParameterManName + " "; SqlParameter temp = new SqlParameter(strParameterMinName, SqlDbType.NVarChar); temp.Value = strStartText; aSqlParameter.Add(temp); temp = new SqlParameter(strParameterManName, SqlDbType.NVarChar); temp.Value = strEndText; aSqlParameter.Add(temp); } else if (searchItem.DataType == "number") { if (nodeConvertQueryNumber != null && keysCfg != null) { // 首 string strMyKey; nRet = KeysCfg.ConvertKeyWithNumberNode( strStartText, nodeConvertQueryNumber, out strMyKey, out strError); if (nRet == -1) return -1; strStartText = strMyKey; // 尾 nRet = KeysCfg.ConvertKeyWithNumberNode( strEndText, nodeConvertQueryNumber, out strMyKey, out strError); if (nRet == -1) return -1; strEndText = strMyKey; } strKeyCondition = strStartText + " <= keystringnum and keystringnum <= " + strEndText + " and keystringnum <> -1"; } } else { string strOperator; string strRealText; //如果词中没有包含关系符,则按=号算 StringUtil.GetPartCondition(searchItem.Word, out strOperator, out strRealText); if (strOperator == "!=") strOperator = "<>"; if (searchItem.DataType == "string") { if (nodeConvertQueryString != null && keysCfg != null) { List<string> keys = null; nRet = keysCfg.ConvertKeyWithStringNode( null,//dataDom strRealText, nodeConvertQueryString, out keys, out strError); if (nRet == -1) return -1; if (keys.Count != 1) { strError = "不支持把检索词通过'split'样式加工成多个."; return -1; } strRealText = keys[0]; } strParameterName = "@keyValue" + strPostfix; strKeyCondition = " keystring" + strOperator + " " + strParameterName + " "; SqlParameter temp = new SqlParameter(strParameterName, SqlDbType.NVarChar); temp.Value = strRealText; aSqlParameter.Add(temp); } else if (searchItem.DataType == "number") { if (nodeConvertQueryNumber != null && keysCfg != null) { string strMyKey; nRet = KeysCfg.ConvertKeyWithNumberNode( strRealText, nodeConvertQueryNumber, out strMyKey, out strError); if (nRet == -1) return -1; strRealText = strMyKey; } strKeyCondition = " keystringnum" + strOperator + strRealText + " and keystringnum <> -1"; } } } else //普通的关系操作符 { //当关系操作符为空为,按等于算 if (searchItem.Relation == "") searchItem.Relation = "="; if (searchItem.Relation == "!=") searchItem.Relation = "<>"; if (searchItem.DataType == "string") { strParameterName = "@keyValue" + strPostfix; strKeyCondition = " keystring " + searchItem.Relation + " " + strParameterName + " "; SqlParameter temp = new SqlParameter(strParameterName, SqlDbType.NVarChar); temp.Value = strKeyValue; aSqlParameter.Add(temp); } else if (searchItem.DataType == "number") { strKeyCondition = " keystringnum " + searchItem.Relation + strKeyValue + " and keystringnum <> -1"; } } } return 0; }
// 检索 internal override int SearchByUnion( string strOutputStyle, SearchItem searchItem, ChannelHandle handle, // Delegate_isConnected isConnected, DpResultSet resultSet, int nWarningLevel, out string strError, out string strWarning) { strError = ""; strWarning = ""; //************对数据库加读锁************** m_db_lock.AcquireReaderLock(m_nTimeOut); #if DEBUG_LOCK this.container.WriteDebugInfo("SearchByUnion(),对'" + this.GetCaption("zh-CN") + "'数据库加读锁。"); #endif try { int nRet; bool bHasID; List<TableInfo> aTableInfo = null; nRet = this.TableNames2aTableInfo(searchItem.TargetTables, out bHasID, out aTableInfo, out strError); if (nRet == -1) return -1; if (bHasID == true) { nRet = SearchByID(searchItem, handle, // isConnected, resultSet, out strError); if (nRet == -1) return -1; } if (aTableInfo == null || aTableInfo.Count == 0) { return 0; } for (int i = 0; i < aTableInfo.Count; i++) { TableInfo tableInfo = aTableInfo[i]; ; string strTiaoJian = ""; try { nRet = GetKeyCondition( searchItem, tableInfo.nodeConvertQueryString, tableInfo.nodeConvertQueryNumber, out strTiaoJian, out strError); if (nRet == -1) return -1; } catch (NoMatchException ex) { strWarning += ex.Message; if (nWarningLevel == 0) return -1; } XmlDocument dom = new XmlDocument(); dom.PreserveWhitespace = true; //设PreserveWhitespace为true string strTablePath = this.TableName2TableFileName(tableInfo.SqlTableName); try { dom.Load(strTablePath); } catch (Exception ex) { strError = "加载检索点表'" + tableInfo.SqlTableName + "'到dom出错:" + ex.Message; return -1; } string strXpath = "/root/key[" + strTiaoJian + "]/idstring"; XmlNodeList listIdstring; try { listIdstring = dom.SelectNodes(strXpath); } catch (System.Xml.XPath.XPathException ex) { strError += "Xpath出错:" + strXpath + "-------" + ex.Message + "<br/>"; return -1; } for (int j = 0; j < listIdstring.Count; j++) { string strIdstring = listIdstring[j].InnerText.Trim(); // 2012/2/16 string strId = this.FullID + "/" + strIdstring; resultSet.Add(new DpRecord(strId)); } } //排序 resultSet.Sort(); //去重 resultSet.RemoveDup(); return 0; } finally { //*********对数据库解读锁************ m_db_lock.ReleaseReaderLock(); #if DEBUG_LOCK this.container.WriteDebugInfo("SearchByUnion(),对'" + this.GetCaption("zh-CN") + "'数据库解读锁。"); #endif } }
// 检索 // parameters: // searchItem SearchItem对象,存放检索词等信息 // isConnected 连接对象 // resultSet 结果集对象,存放命中记录 // strLang 语言版本, // return: // -1 出错 // 0 成功 internal override int SearchByUnion(SearchItem searchItem, Delegate_isConnected isConnected, DpResultSet resultSet, int nWarningLevel, out string strError, out string strWarning) { strError = ""; strWarning = ""; //**********对数据库加读锁************** m_lock.AcquireReaderLock(m_nTimeOut); #if DEBUG_LOCK_SQLDATABASE this.container.WriteDebugInfo("SearchByUnion(),对'" + this.GetCaption("zh-cn") + "'数据库加读锁。"); #endif try { bool bHasID; List<TableInfo> aTableInfo = null; int nRet = this.TableNames2aTableInfo(searchItem.TargetTables, out bHasID, out aTableInfo, out strError); if (nRet == -1) return -1; if (bHasID == true) { nRet = SearchByID(searchItem, isConnected, resultSet, out strError); if (nRet == -1) return -1; } // 对sql库来说,通过ID检索后,记录已排序,去重 if (aTableInfo == null || aTableInfo.Count == 0) return 0; string strCommand = ""; // Sql命令参数数组 List<SqlParameter> aSqlParameter = new List<SqlParameter>(); string strSelectKeystring = ""; if (searchItem.KeyOrder != "") { if (aTableInfo.Count > 1) strSelectKeystring = ",keystring"; } // 循环每一个检索途径 for (int i = 0; i < aTableInfo.Count; i++) { TableInfo tableInfo = aTableInfo[i]; // 参数名的后缀 string strPostfix = Convert.ToString(i); string strConditionAboutKey = ""; try { nRet = GetKeyCondition( searchItem, tableInfo.nodeConvertQueryString, tableInfo.nodeConvertQueryNumber, strPostfix, ref aSqlParameter, out strConditionAboutKey, out strError); if (nRet == -1) return -1; } catch (NoMatchException ex) { strWarning = ex.Message; strError = strWarning; return -1; } // 如果限制了一个最大数,则按每个途径都是这个最大数算 string strTop = ""; if (searchItem.MaxCount != -1) //限制的最大数 strTop = " TOP " + Convert.ToString(searchItem.MaxCount) + " "; string strWhere = ""; if (strConditionAboutKey != "") strWhere = " WHERE " + strConditionAboutKey; string strOneCommand = ""; if (i == 0)// 第一个表 { strOneCommand = "use " + this.m_strSqlDbName + " " + " SELECT " + " DISTINCT " + strTop + " idstring" + strSelectKeystring + " " + " FROM " + tableInfo.SqlTableName + " " + strWhere; } else { strOneCommand = " union SELECT " + " DISTINCT " + strTop + " idstring" + strSelectKeystring + " " //DISTINCT 去重 + " FROM " + tableInfo.SqlTableName + " " + strWhere; } strCommand += strOneCommand; } string strOrderBy = ""; if (searchItem.OrderBy != "") strOrderBy = "ORDER BY " + searchItem.OrderBy + " "; strCommand += strOrderBy; strCommand += " use master " + "\n"; if (aSqlParameter == null) { strError = "一个参数也没是不可能的情况"; return -1; } SqlCommand command = null; SqlConnection connection = new SqlConnection(this.m_strConnString); connection.Open(); try { command = new SqlCommand(strCommand, connection); foreach (SqlParameter sqlParameter in aSqlParameter) { command.Parameters.Add(sqlParameter); } command.CommandTimeout = 20 * 60; // 把检索时间变大 // 调新线程处理 DatabaseCommandTask task = new DatabaseCommandTask(command); try { if (task == null) { strError = "test为null"; return -1; } Thread t1 = new Thread(new ThreadStart(task.ThreadMain)); t1.Start(); bool bRet; while (true) { if (isConnected != null) { if (isConnected() == false) { strError = "用户中断"; return -1; } } bRet = task.m_event.WaitOne(100, false); //1/10秒看一次 if (bRet == true) break; } if (task.DataReader == null || task.DataReader.HasRows == false) { return 0; } int nGetedCount = 0; while (task.DataReader.Read()) { if (isConnected != null && (nGetedCount % 10000) == 0) { if (isConnected() == false) { strError = "用户中断"; return -1; } } string strId = this.FullID + "/" + (string)task.DataReader[0]; // 记录格式为:库id/记录号 resultSet.Add(new DpRecord(strId)); nGetedCount++; // 超过最大数了 if (searchItem.MaxCount != -1 && nGetedCount >= searchItem.MaxCount) break; Thread.Sleep(0); } } finally { if (task.DataReader != null) task.DataReader.Close(); } } catch (SqlException sqlEx) { if (sqlEx.Errors is SqlErrorCollection) strError = "数据库'" + this.GetCaption("zh") + "'尚未初始化。"; else strError = sqlEx.Message; return -1; } catch (Exception ex) { strError = ex.Message; return -1; } finally // 连接 { connection.Close(); } } catch (Exception ex) { strError = ex.Message; return -1; } finally { //*****************对数据库解读锁*************** m_lock.ReleaseReaderLock(); #if DEBUG_LOCK_SQLDATABASE this.container.WriteDebugInfo("SearchByUnion(),对'" + this.GetCaption("zh-cn") + "'数据库解读锁。"); #endif } return 0; }
// 按ID检索记录 // parameter: // searchItem SearchItem对象,包括检索信息 // isConnected 连接对象的delegate // resultSet 结果集对象,存放命中记录 // return: // -1 出错 // 0 成功 // 线:不安全 private int SearchByID(SearchItem searchItem, ChannelHandle handle, // Delegate_isConnected isConnected, DpResultSet resultSet, out string strError) { strError = ""; // 从库目录里得到所有似记录文件 string[] files = Directory.GetFiles(this.m_strSourceFullPath, "??????????.xml"); ArrayList records = new ArrayList(); foreach (string fileName in files) { FileInfo fileInfo = new FileInfo(fileName); string strFileName = fileInfo.Name; if (this.IsRecord(strFileName) == false) continue; records.Add(this.XmlFileName2RecordID(strFileName)); } //前方一致 if (searchItem.Match == "left" || searchItem.Match == "") { foreach (string recordID in records) { if (recordID.Length < searchItem.Word.Length) continue; string strFirstPart = recordID.Substring(0, searchItem.Word.Length); if (strFirstPart == searchItem.Word) { string strRecPath = this.FullID + "/" + recordID; resultSet.Add(new DpRecord(strRecPath)); } } } else if (searchItem.Match == "exact") { // 从检索词时分析出来关系 if (searchItem.Relation == "draw" || searchItem.Relation == "range") { foreach (string recordID in records) { string strStartID; string strEndID; bool bRet = StringUtil.SplitRangeEx(searchItem.Word, out strStartID, out strEndID); if (bRet == true) { strStartID = DbPath.GetID10(strStartID); strEndID = DbPath.GetID10(strEndID); if (String.Compare(recordID, strStartID, true) >= 0 && String.Compare(recordID, strEndID, true) <= 0) { string strRecPath = this.FullID + "/" + recordID; resultSet.Add(new DpRecord(strRecPath)); continue; } } else { string strOperator; string strCanKaoID; StringUtil.GetPartCondition(searchItem.Word, out strOperator, out strCanKaoID); strCanKaoID = DbPath.GetID10(strCanKaoID); if (StringUtil.CompareByOperator(recordID, strOperator, strCanKaoID) == true) { string strRecPath = this.FullID + "/" + recordID; resultSet.Add(new DpRecord(strRecPath)); continue; } } } } else { foreach (string recordID in records) { searchItem.Word = DbPath.GetID10(searchItem.Word); if (StringUtil.CompareByOperator(recordID, searchItem.Relation, searchItem.Word) == true) { string strRecPath = this.FullID + "/" + recordID; resultSet.Add(new DpRecord(strRecPath)); continue; } } } } return 0; }
// 得到关于key的条件 // parameter: // searchItem 检索信息对象 // nodeCovertQuery 处理检索词的配置节点 // 可能会抛出的异常:NoMatchException(检索方式与数据类型) private int GetKeyCondition(SearchItem searchItem, XmlNode nodeConvertQueryString, XmlNode nodeConvertQueryNumber, out string strKeyCondition, out string strError) { strError = ""; strKeyCondition = ""; QueryUtil.VerifyRelation(ref searchItem.Match,//strMatch, ref searchItem.Relation,//strRelation, ref searchItem.DataType); //strDataType); int nRet; KeysCfg keysCfg = null; nRet = this.GetKeysCfg(out keysCfg, out strError); if (nRet == -1) return -1; string strKeyValue = searchItem.Word.Trim(); if (searchItem.DataType == "string") { if (nodeConvertQueryString != null && keysCfg != null) { List<string> keys = null; nRet = keysCfg.ConvertKeyWithStringNode( null, //dataDom strKeyValue, nodeConvertQueryString, out keys, out strError); if (nRet == -1) return -1; if (keys.Count != 1) { // strError = "检索词配置不合法,不应变成多个。"; strError = "不支持把检索词通过'split'样式加工成多个."; return -1; } strKeyValue = keys[0]; } } else if (searchItem.DataType == "number") { if (nodeConvertQueryNumber != null && keysCfg != null) { string strMyKey; nRet = keysCfg.ConvertKeyWithNumberNode( null, strKeyValue, nodeConvertQueryNumber, out strMyKey, out strError); if (nRet == -1 || nRet == 1) return -1; strKeyValue = strMyKey; } } strKeyValue = strKeyValue.Trim(); // 4. 如果strMatch为空,则按"左方一致" if (searchItem.Match == "left" || searchItem.Match == "") { //判断选择的数据类型 if (searchItem.DataType != "string") { NoMatchException ex = new NoMatchException("在匹配方式为left时或为空时,数据类型不匹配,应该为string"); throw (ex); } //这句是保险的,因为上面已抛出异常 int nLength = searchItem.Word.Trim().Length; strKeyCondition = " (substring(keystring,1," + Convert.ToString(nLength) + ")='" + strKeyValue + "') "; } // TODO: 为什么没有支持中间一致?2007/10/9 if (searchItem.Match == "middle") { strError = "对于文件方式的数据库 '"+this.GetCaption("zh")+"',不支持中间一致(middle)匹配方式"; return -1; } //右方一致 if (searchItem.Match == "right") { if (searchItem.DataType != "string") { NoMatchException ex = new NoMatchException("在匹配方式为right时,数据类型不匹配,应该为string"); throw (ex); } //注意这里要改成右方一致 int nLength = searchItem.Word.Trim().Length; strKeyCondition = " (substring(keystring,1," + Convert.ToString(nLength) + ")='" + strKeyValue + "') "; } //精确一致 if (searchItem.Match == "exact") { //从词中汲取,较复杂,注意 if (searchItem.Relation == "draw" || searchItem.Relation == "range") { string strStartText; string strEndText; bool bRet = StringUtil.SplitRangeEx(searchItem.Word, out strStartText, out strEndText); //先按"-"算 if (bRet == true) { if (searchItem.DataType == "string") { if (nodeConvertQueryString != null && keysCfg != null) { // 加工首 List<string> keys = null; nRet = keysCfg.ConvertKeyWithStringNode(null,//dataDom strStartText, nodeConvertQueryString, out keys, out strError); if (nRet == -1) return -1; if (keys.Count != 1) { strError = "不支持把检索词通过'split'样式加工成多个."; return -1; } strStartText = keys[0]; // 加工尾 nRet = keysCfg.ConvertKeyWithStringNode(null,//dataDom strEndText, nodeConvertQueryString, out keys, out strError); if (nRet == -1) return -1; if (keys.Count != 1) { strError = "不支持把检索词通过'split'样式加工成多个."; return -1; } strEndText = keys[0]; } strKeyCondition = " keystring >= '" + strStartText + "' and keystring<= '" + strEndText + "'"; } else if (searchItem.DataType == "number") { if (nodeConvertQueryNumber != null && keysCfg != null) { // 首 string strMyKey; nRet = keysCfg.ConvertKeyWithNumberNode( null, strStartText, nodeConvertQueryNumber, out strMyKey, out strError); if (nRet == -1 || nRet == 1) return -1; strStartText = strMyKey; // 尾 nRet = keysCfg.ConvertKeyWithNumberNode( null, strEndText, nodeConvertQueryNumber, out strMyKey, out strError); if (nRet == -1 || nRet == 1) return -1; strEndText = strMyKey; } strKeyCondition = " keystringnum >= " + strStartText + " and keystringnum<= " + strEndText + ""; } } else // 再算 比较符号 { string strOperator; string strRealText; StringUtil.GetPartCondition(searchItem.Word, out strOperator, out strRealText); //SQL与Xpath比较运算符的差别 if (strOperator == "<>") strOperator = "!="; if (searchItem.DataType == "string") { if (nodeConvertQueryString != null && keysCfg != null) { List<string> keys = null; nRet = keysCfg.ConvertKeyWithStringNode(null,//dataDom strRealText, nodeConvertQueryString, out keys, out strError); if (nRet == -1) return -1; if (keys.Count != 1) { strError = "不支持把检索词通过'split'样式加工成多个."; return -1; } strRealText = keys[0]; } strKeyCondition = "keystring" + strOperator + "'" + strRealText + "'"; } else if (searchItem.DataType == "number") { if (nodeConvertQueryNumber != null && keysCfg != null) { string strMyKey; nRet = keysCfg.ConvertKeyWithNumberNode( null, strRealText, nodeConvertQueryNumber, out strMyKey, out strError); if (nRet == -1 || nRet == 1) return -1; strRealText = strMyKey; } strKeyCondition = "keystringnum" + strOperator + strRealText + " and keystringnum!=-1"; } } } else { // 当关系操作符为空为,按等于算 if (searchItem.Relation == "") searchItem.Relation = "="; if (searchItem.Relation == "<>") searchItem.Relation = "!="; if (searchItem.DataType == "string") { strKeyCondition = " keystring " + searchItem.Relation + "'" + strKeyValue + "'"; } else if (searchItem.DataType == "number") { strKeyCondition = "keystringnum" + searchItem.Relation + "" + strKeyValue + ""; } } } return 0; }
// 从所有帐户库的所有表中查找帐户 // parameter // strUserName 用户名 // resultSet 结果集,用于存放查找到的用户 // strError out参数,返回出错信息 // return: // -1 出错 // 0 成功 // 线:不安全 private int SearchUserInternal(string strUserName, DpResultSet resultSet, out string strError) { strError = ""; foreach (Database db in this) { if (StringUtil.IsInList("account", db.GetDbType()) == false) continue; if (strUserName.Length > db.KeySize) continue; string strWarning = ""; SearchItem searchItem = new SearchItem(); searchItem.TargetTables = ""; searchItem.Word = strUserName; searchItem.Match = "exact"; searchItem.Relation = "="; searchItem.DataType = "string"; searchItem.MaxCount = -1; searchItem.OrderBy = ""; // 帐户库不能去非用字 // return: // -1 出错 // 0 成功 int nRet = db.SearchByUnion(searchItem, null, //用于中断 , deleget resultSet, 0, out strError, out strWarning); if (nRet == -1) return -1; } return 0; }
// 检索单元item的信息,对库进行检索 // parameter: // nodeItem item节点 // resultSet 传进结果集,????????每次清空,既然每次清空,那还不如返回一个结果集呢 // isConnected 是否连接 // strError out参数,返回出错信息 // return: // -1 出错 // -6 无足够的权限 // 0 成功 public int doItem(XmlNode nodeItem, DpResultSet resultSet, 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); } //先清空一下 resultSet.Clear(); int nRet; //调processRelation对检索单元的成员检查是否存在矛盾 //如果返回0,则可能对item的成员进行了修改,所以后面重新提取内容 nRet = ProcessRelation(nodeItem); if (nRet == -1) { strError = "doItem()里调processRelation出错"; return(-1); } // 根据nodeItem得到检索信息 string strTarget; string strWord; string strMatch; string strRelation; string strDataType; string strIdOrder; string strKeyOrder; string strOrderBy; int nMaxCount; nRet = QueryUtil.GetSearchInfo(nodeItem, out strTarget, out strWord, out strMatch, out strRelation, out strDataType, out strIdOrder, out strKeyOrder, out strOrderBy, out nMaxCount, out strError); if (nRet == -1) { return(-1); } //将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); } 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 = ""; nRet = db.SearchByUnion(searchItem, isConnected, resultSet, this.m_nWarningLevel, out strError, out strWarningInfo); if (nRet == -1) { return(-1); } // 多个库的排序去重功能暂不做 //resultSet.Sort(); //按具体的风格排序 //resultSet.RemoveDup(); } return(0); }
// 检索 // parameter: // strOutpuStyle 输出的风格。如果为keycount,则输出归并统计后的key+count;否则,或者缺省,为传统的输出记录id // searchItem SearchItem对象 // isConnected IsConnection对象,用于判断通讯是否连接 // resultSet 结果集对象,存放命中记录。本函数并不在检索前清空结果集,因此,对同一结果集对象多次执行本函数,则可以把命中结果追加在一起 // nWarningLevel 处理警告级别 0:表示特别强烈,出现警告也当作出错;1:表示不强烈,不返回出错,继续执行 // strError out参数,返回出错信息 // strWarning out参数,返回警告信息 // return: // -1 出错 // >=0 命中记录数 // 线: 安全的 internal virtual int SearchByUnion( string strOutputStyle, SearchItem searchItem, ChannelHandle handle, // Delegate_isConnected isConnected, DpResultSet resultSet, int nWarningLevel, out string strError, out string strWarning) { strError = ""; strWarning = ""; return 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; }
// 检索 // parameter: // searchItem SearchItem对象 // isConnected IsConnection对象,用于判断通讯是否连接 // resultSet 存入检索结果的结果集 // nWarningLevel 处理警告级别 0:表示特别强烈,出现警告也当作出错;1:表示不强烈,不返回出错,继续执行 // strError out参数,返回出错信息 // strWarning out参数,返回警告信息 // return: // -1 出错 // >=0 命中记录数 // 线: 安全的 internal virtual int SearchByUnion(SearchItem searchItem, Delegate_isConnected isConnected, DpResultSet resultSet, int nWarningLevel, out string strError, out string strWarning) { strError = ""; strWarning = ""; return 0; }