public List <Record> DoQuery(string db, string query, string clist, int qid = 0, string qname = "", string slist = "", string options = "") { List <Record> records = new List <Record>(); try { DoQuery.Builder doQuery = new DoQuery.Builder(__ticket, __token, __domain, db); if (query != string.Empty) { doQuery.SetQuery(query); } doQuery.SetCList(clist); if (qid > 0) { doQuery.SetQid(qid); } else if (qname != string.Empty) { doQuery.SetQName(qname); } if (slist != string.Empty) { doQuery.SetSList(slist); } doQuery.SetFmt(true); if (options != string.Empty) { doQuery.SetOptions(options); } var response = doQuery.Build().Post().CreateNavigator(); var errcode = response.SelectSingleNode("/qdbapi/errcode").ToString(); if (errcode == "0") { XmlDocument xml = new XmlDocument(); xml.LoadXml(response.OuterXml); XmlNodeList list = xml.SelectNodes("/qdbapi/table/records/record"); foreach (XmlNode node in list) { Record R = new Record(); var fields = node.SelectNodes("f"); foreach (XmlNode f in fields) { R.setFieldValue(Int32.Parse(f.Attributes["id"].InnerText), f.InnerText); } records.Add(R); } return(records); } else { message = "Error " + response.SelectSingleNode("/qdbapi/errcode").ToString() + ": " + response.SelectSingleNode("/qdbapi/errtext").ToString(); } } catch (Exception ex) { message = ex.Message; } return(null); }
private void _doQuery(DoQuery qry, bool clear) { if (clear) { Records.Clear(); } try { XElement xml = qry.Post(); LoadColumns(xml); //In case the schema changes due to another user, or from a previous query that has a differing subset of columns TODO: remove this requirement LoadRecords(xml); } catch (TooManyCriteriaInQueryException) { //If and only if all elements of a query are OR operations, we can split the query in 99 element chunks string query = qry.Query; if (string.IsNullOrEmpty(query) || QueryCheckRegex.IsMatch(query)) { throw; } string[] args = query.Split(QuerySeparator, StringSplitOptions.None); int argCnt = args.Length; if (argCnt < 100) //We've no idea how to split this, apparently... { throw; } if (args[0].StartsWith("{")) { args[0] = args[0].Substring(1); //remove leading { } if (args[argCnt - 1].EndsWith("}")) { args[argCnt - 1] = args[argCnt - 1].Substring(0, args[argCnt - 1].Length - 1); // remove trailing } } if (args[argCnt - 1].EndsWith("}OR")) { args[argCnt - 1] = args[argCnt - 1].Substring(0, args[argCnt - 1].Length - 3); // remove trailing }OR } int sentArgs = 0; while (sentArgs < argCnt) { int useArgs = Math.Min(99, argCnt - sentArgs); string[] argsToSend = args.Skip(sentArgs).Take(useArgs).ToArray(); string sendQuery = "{" + string.Join("}OR{", argsToSend) + "}"; DoQuery.Builder qBuild = new DoQuery.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId).SetQuery(sendQuery).SetFmt(true); if (!string.IsNullOrEmpty(qry.Collist)) { qBuild = qBuild.SetCList(qry.Collist); } if (!string.IsNullOrEmpty(qry.Options)) { qBuild = qBuild.SetOptions(qry.Options); } DoQuery dqry = qBuild.Build(); var xml = dqry.Post(); if (sentArgs == 0) { LoadColumns(xml); } LoadRecords(xml); sentArgs += useArgs; } } catch (ViewTooLargeException) { //split into smaller queries automagically List <string> optionsList = new List <string>(); string query = qry.Query; string collist = qry.Collist; int maxCount = 0; int baseSkip = 0; if (!string.IsNullOrEmpty(qry.Options)) { string[] optArry = qry.Options.Split('.'); foreach (string opt in optArry) { if (opt.StartsWith("num-")) { maxCount = int.Parse(opt.Substring(4)); } else if (opt.StartsWith("skp-")) { baseSkip = int.Parse(opt.Substring(4)); } else { optionsList.Add(opt); } } } if (maxCount == 0) { DoQueryCount dqryCnt; if (string.IsNullOrEmpty(query)) { dqryCnt = new DoQueryCount.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId).Build(); } else { dqryCnt = new DoQueryCount.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId).SetQuery(query).Build(); } var cntXml = dqryCnt.Post(); maxCount = int.Parse(cntXml.Element("numMatches").Value); } int stride = maxCount / 2; int fetched = 0; while (fetched < maxCount) { List <string> optLst = new List <string>(); optLst.AddRange(optionsList); optLst.Add("skp-" + (fetched + baseSkip)); optLst.Add("num-" + stride); string options = string.Join(".", optLst); DoQuery dqry; if (string.IsNullOrEmpty(query)) { dqry = new DoQuery.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) .SetCList(collist) .SetOptions(options) .SetFmt(true) .Build(); } else { dqry = new DoQuery.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) .SetQuery(query) .SetCList(collist) .SetOptions(options) .SetFmt(true) .Build(); } try { XElement xml = dqry.Post(); if (fetched == 0) { LoadColumns(xml); } LoadRecords(xml); fetched += stride; } catch (ViewTooLargeException) { stride /= 2; } catch (ApiRequestLimitExceededException ex) { TimeSpan waitTime = ex.WaitUntil - DateTime.Now; System.Threading.Thread.Sleep(waitTime); } } } }