From 6b0e0249c3fe9737eed8dfa84c5a75f9fc281194 Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Sat, 4 Oct 2014 11:26:24 -0600 Subject: [PATCH 01/49] Update library to .Net CLR 4.0, VisualStudio 2012, enhance error reporting by returning the errorDetail to give greater clarity into why things fail. --- .gitignore | 4 +++- Intuit.QuickBase.Core/Http.cs | 11 ++++++--- .../Intuit.QuickBase.Core.csproj | 11 +++++++-- Intuit.QuickBase.sln | 24 +++++++++---------- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index 409184b..b0daf6c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -.svn \ No newline at end of file +.svn +Intuit.QuickBase.Client/obj/Debug/Intuit.QuickBase.Client.csproj.FileListAbsolute.txt +Intuit.QuickBase.Core/obj/Debug/Intuit.QuickBase.Core.csproj.FileListAbsolute.txt diff --git a/Intuit.QuickBase.Core/Http.cs b/Intuit.QuickBase.Core/Http.cs index 977e312..5f0107f 100644 --- a/Intuit.QuickBase.Core/Http.cs +++ b/Intuit.QuickBase.Core/Http.cs @@ -87,9 +87,14 @@ internal void GetFile(DownloadFile downloadFile) internal static void CheckForException(XPathDocument xml) { var xmlNav = xml.CreateNavigator(); - var errorcode = xmlNav.SelectSingleNode("/qdbapi/errcode").Value; - var errortext = xmlNav.SelectSingleNode("/qdbapi/errtext").Value; - + string errorcode = xmlNav.SelectSingleNode("/qdbapi/errcode").Value; + string errortext = xmlNav.SelectSingleNode("/qdbapi/errtext").Value; + var errDetailNode = xmlNav.SelectSingleNode("/qdbapi/errdetail"); + if (errDetailNode != null) + { + string errdetail = errDetailNode.Value; + if (errdetail.Length > 0) errortext += ":" + errdetail; + } if ("2".Equals(errorcode)) { throw new InvalidInputException(errortext); diff --git a/Intuit.QuickBase.Core/Intuit.QuickBase.Core.csproj b/Intuit.QuickBase.Core/Intuit.QuickBase.Core.csproj index f96db7d..571a9b1 100644 --- a/Intuit.QuickBase.Core/Intuit.QuickBase.Core.csproj +++ b/Intuit.QuickBase.Core/Intuit.QuickBase.Core.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,12 +10,19 @@ Properties Intuit.QuickBase.Core Intuit.QuickBase.Core - v3.5 + v4.0 512 SAK SAK SAK SAK + + + + + 3.5 + + true diff --git a/Intuit.QuickBase.sln b/Intuit.QuickBase.sln index 15d6769..cce2908 100644 --- a/Intuit.QuickBase.sln +++ b/Intuit.QuickBase.sln @@ -1,25 +1,21 @@  -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intuit.QuickBase.Client", "Intuit.QuickBase.Client\Intuit.QuickBase.Client.csproj", "{F25380B0-B55A-4567-941E-B938723F6E07}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intuit.QuickBase.Core", "Intuit.QuickBase.Core\Intuit.QuickBase.Core.csproj", "{72AE7ED2-1321-499E-8E0E-ECFD91B8C850}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intuit.QuickBase.UnitTests", "Intuit.QuickBase.UnitTests\Intuit.QuickBase.UnitTests.csproj", "{F5896BE7-8236-4A53-AACB-E6F33A436D04}" -EndProject +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Library", "Library", "{2E052995-62F2-44FD-BD11-D481FB2C687C}" ProjectSection(SolutionItems) = preProject Library\nunit.framework.dll = Library\nunit.framework.dll Library\Rhino.Mocks.dll = Library\Rhino.Mocks.dll EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intuit.QuickBase.Client", "Intuit.QuickBase.Client\Intuit.QuickBase.Client.csproj", "{F25380B0-B55A-4567-941E-B938723F6E07}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intuit.QuickBase.Core", "Intuit.QuickBase.Core\Intuit.QuickBase.Core.csproj", "{72AE7ED2-1321-499E-8E0E-ECFD91B8C850}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intuit.QuickBase.UnitTests", "Intuit.QuickBase.UnitTests\Intuit.QuickBase.UnitTests.csproj", "{F5896BE7-8236-4A53-AACB-E6F33A436D04}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intuit.QuickBase.IntegrationTests", "Intuit.QuickBase.IntegrationTests\Intuit.QuickBase.IntegrationTests.csproj", "{D88A7B14-7A52-4A78-B51C-D33BA947F551}" EndProject Global - GlobalSection(SubversionScc) = preSolution - Svn-Managed = True - Manager = AnkhSVN - Subversion Support for Visual Studio - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU @@ -45,4 +41,8 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(SubversionScc) = preSolution + Svn-Managed = True + Manager = AnkhSVN - Subversion Support for Visual Studio + EndGlobalSection EndGlobal From 91b40b1b7339accd3af11ede6939e09dc1cc0a79 Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Sat, 4 Oct 2014 11:27:57 -0600 Subject: [PATCH 02/49] Forgot to include one file in the .Net 4 upgrade commit, also add in XIR and IR query types, simplify and speed up some logic using LINQ. --- Intuit.QuickBase.Client/ComparisonOperator.cs | 10 +++++++++- .../Intuit.QuickBase.Client.csproj | 12 ++++++++++-- Intuit.QuickBase.Client/Query.cs | 8 ++------ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Intuit.QuickBase.Client/ComparisonOperator.cs b/Intuit.QuickBase.Client/ComparisonOperator.cs index 7d5523a..7d0c24f 100644 --- a/Intuit.QuickBase.Client/ComparisonOperator.cs +++ b/Intuit.QuickBase.Client/ComparisonOperator.cs @@ -68,6 +68,14 @@ public enum ComparisonOperator /// /// Is greater than or equal to /// - GTE + GTE, + /// + /// Is in range + /// + IR, + /// + /// Is not in range + /// + XIR } } \ No newline at end of file diff --git a/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj b/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj index ede0358..8909c43 100644 --- a/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj +++ b/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,12 +10,19 @@ Properties Intuit.QuickBase.Client Intuit.QuickBase.Client - v3.5 + v4.0 512 SAK SAK SAK SAK + + + + + 3.5 + + true @@ -35,6 +42,7 @@ 4 + 3.5 diff --git a/Intuit.QuickBase.Client/Query.cs b/Intuit.QuickBase.Client/Query.cs index 98472c5..23e1917 100644 --- a/Intuit.QuickBase.Client/Query.cs +++ b/Intuit.QuickBase.Client/Query.cs @@ -6,6 +6,7 @@ * http://www.opensource.org/licenses/eclipse-1.0.php */ using System.Collections.Generic; +using System.Linq; namespace Intuit.QuickBase.Client { @@ -20,12 +21,7 @@ public void Add(QueryStrings query) public override string ToString() { - var querys = string.Empty; - foreach (var query in _queryStrings) - { - querys += query.ToString(); - } - return querys; + return _queryStrings.Aggregate(string.Empty, (current, query) => current + query.ToString()); } } } From e36a03dfafeeb963428295d491447263c6b984ac Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Sat, 4 Oct 2014 12:07:42 -0600 Subject: [PATCH 03/49] Optimization changes: make it so that QTable.AcceptChanges does not simply iterate over every changed record and upload to the server one at a time: combine deletes into a single API call (potentially split apart if it's too large), and combine uploads via a CSV upload. Also handle support of tables that have a different primary key other than 'Record ID#' API additions: adding in missing query operations (mostly so that you can add the 'options'), create a QRecord.GetAsCSV so that one can get the contents of the DB as a list of CSV strings, also improve error reporting in the case of setting non-existant columns. --- Intuit.QuickBase.Client/IQColumn.cs | 1 + Intuit.QuickBase.Client/IQRecord.cs | 7 + Intuit.QuickBase.Client/IQTable.cs | 6 + Intuit.QuickBase.Client/QColumn.cs | 8 ++ Intuit.QuickBase.Client/QColumnFactory.cs | 4 +- Intuit.QuickBase.Client/QColumnFactoryBase.cs | 2 +- Intuit.QuickBase.Client/QRecord.cs | 46 ++++++- Intuit.QuickBase.Client/QRecordCollection.cs | 40 +++++- Intuit.QuickBase.Client/QTable.cs | 125 ++++++++++++++---- 9 files changed, 200 insertions(+), 39 deletions(-) diff --git a/Intuit.QuickBase.Client/IQColumn.cs b/Intuit.QuickBase.Client/IQColumn.cs index 12f3980..4ce3bd6 100644 --- a/Intuit.QuickBase.Client/IQColumn.cs +++ b/Intuit.QuickBase.Client/IQColumn.cs @@ -14,6 +14,7 @@ public interface IQColumn int ColumnId { get; set; } string ColumnName { get; set; } FieldType ColumnType { get; set; } + bool ColumnVirtual { get; set; } bool Equals(IQColumn column); bool Equals(object obj); int GetHashCode(); diff --git a/Intuit.QuickBase.Client/IQRecord.cs b/Intuit.QuickBase.Client/IQRecord.cs index 022d44a..2b827e1 100644 --- a/Intuit.QuickBase.Client/IQRecord.cs +++ b/Intuit.QuickBase.Client/IQRecord.cs @@ -17,9 +17,16 @@ public interface IQRecord void AcceptChanges(); void DownloadFile(string columnName, string path, int versionId); void ChangeOwnerTo(string newOwner); + string GetAsCSV(string clist); bool Equals(IQRecord record); bool Equals(object obj); int GetHashCode(); string ToString(); } + + internal interface IQRecord_int + { + void ForceUpdateState(int RecordId); + void ForceUpdateState(); + } } diff --git a/Intuit.QuickBase.Client/IQTable.cs b/Intuit.QuickBase.Client/IQTable.cs index 23bd74a..020f001 100644 --- a/Intuit.QuickBase.Client/IQTable.cs +++ b/Intuit.QuickBase.Client/IQTable.cs @@ -13,6 +13,7 @@ public interface IQTable { string TableName { get; } string TableId { get; } + int KeyFID { get; } QRecordCollection Records { get; } QColumnCollection Columns { get; } void Clear(); @@ -21,19 +22,24 @@ public interface IQTable TableInfo GetTableInfo(); int GetServerRecordCount(); void Query(); + void Query(string options); void Query(int[] clist); void Query(int[] clist, string options); void Query(Query query); + void Query(Query query, string options); void Query(Query query, int[] clist); void Query(Query query, int[] clist, int[] slist); void Query(Query query, int[] clist, int[] slist, string options); void Query(int queryId); + void Query(int queryId, string options); int QueryCount(Query query); int QueryCount(int queryId); void PurgeRecords(); void PurgeRecords(int queryId); + void PurgeRecords(Query query); void AcceptChanges(); IQRecord NewRecord(); + void RefreshColumns(); string ToString(); } } \ No newline at end of file diff --git a/Intuit.QuickBase.Client/QColumn.cs b/Intuit.QuickBase.Client/QColumn.cs index 859c2b1..1aacf26 100644 --- a/Intuit.QuickBase.Client/QColumn.cs +++ b/Intuit.QuickBase.Client/QColumn.cs @@ -26,10 +26,18 @@ internal QColumn(int columnId, string columnName, FieldType columnType) ColumnId = columnId; } + internal QColumn(int columnId, string columnName, FieldType columnType, bool columnVirtual) + : this(columnName, columnType) + { + ColumnVirtual = columnVirtual; + ColumnId = columnId; + } + // Properties public int ColumnId { get; set; } public string ColumnName { get; set; } public FieldType ColumnType { get; set; } + public bool ColumnVirtual { get; set; } // Methods public bool Equals(IQColumn column) diff --git a/Intuit.QuickBase.Client/QColumnFactory.cs b/Intuit.QuickBase.Client/QColumnFactory.cs index 4b345ab..6fc3132 100644 --- a/Intuit.QuickBase.Client/QColumnFactory.cs +++ b/Intuit.QuickBase.Client/QColumnFactory.cs @@ -24,9 +24,9 @@ internal static QColumnFactoryBase GetInstance() return _instance; } - internal override IQColumn CreateInstace(int columnId, string columnName, FieldType columnType) + internal override IQColumn CreateInstace(int columnId, string columnName, FieldType columnType, bool columnVirtual) { - return new QColumn(columnId, columnName, columnType); + return new QColumn(columnId, columnName, columnType, columnVirtual); } } } diff --git a/Intuit.QuickBase.Client/QColumnFactoryBase.cs b/Intuit.QuickBase.Client/QColumnFactoryBase.cs index c4a4d2d..8cf0c6e 100644 --- a/Intuit.QuickBase.Client/QColumnFactoryBase.cs +++ b/Intuit.QuickBase.Client/QColumnFactoryBase.cs @@ -11,6 +11,6 @@ namespace Intuit.QuickBase.Client { internal abstract class QColumnFactoryBase { - internal abstract IQColumn CreateInstace(int columnId, string columnName, FieldType columnType); + internal abstract IQColumn CreateInstace(int columnId, string columnName, FieldType columnType, bool columnVirtual); } } diff --git a/Intuit.QuickBase.Client/QRecord.cs b/Intuit.QuickBase.Client/QRecord.cs index 9728995..1a192c0 100644 --- a/Intuit.QuickBase.Client/QRecord.cs +++ b/Intuit.QuickBase.Client/QRecord.cs @@ -8,6 +8,8 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Text; using System.Xml; using System.Xml.XPath; using Intuit.QuickBase.Core; @@ -15,7 +17,7 @@ namespace Intuit.QuickBase.Client { - public class QRecord : IQRecord + public class QRecord : IQRecord, IQRecord_int { // Instance fields private readonly List _fields; @@ -153,6 +155,46 @@ public void AcceptChanges() } } + public string GetAsCSV(string clist) + { + List csvList = new List(); + List cols = clist.Split('.').Select(Int32.Parse).ToList(); + foreach (int col in cols) + { + QField field = _fields.FirstOrDefault(fld => fld.FieldId == col); + if (field == null) + { + csvList.Add(String.Empty); + } + else + { + if (field.Type == FieldType.file) throw new InvalidChoiceException(); + csvList.Add(CSVQuoter(field.Value)); + } + } + return String.Join(",", csvList); + } + + private string CSVQuoter(string inStr) + { + //if the string contains quote character(s), surround the string with quotes + if (inStr.Contains("\"")) + return "\"" + inStr + "\""; + else + return inStr; + } + + public void ForceUpdateState(int RecID) + { + RecordId = RecID; + } + + public void ForceUpdateState() + { + RecordState = RecordState.Unchanged; + IsOnServer = true; + } + private void FillRecord(XPathNavigator recordNode) { IsOnServer = true; @@ -264,7 +306,7 @@ private int GetColumnIndex(string columnName) }); if (index == -1) { - throw new ColumnDoesNotExistInTableExecption("Column not found in table."); + throw new ColumnDoesNotExistInTableExecption(string.Format("Column '{0}' not found in table.", columnName)); } return index; } diff --git a/Intuit.QuickBase.Client/QRecordCollection.cs b/Intuit.QuickBase.Client/QRecordCollection.cs index a6f45ae..62d9350 100644 --- a/Intuit.QuickBase.Client/QRecordCollection.cs +++ b/Intuit.QuickBase.Client/QRecordCollection.cs @@ -5,15 +5,18 @@ * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/eclipse-1.0.php */ -using System.Collections.Generic; + using Intuit.QuickBase.Core; +using System; +using System.Collections.Generic; +using System.Linq; namespace Intuit.QuickBase.Client { // TODO: May want to compose List to hide the complexity of the List type. public sealed class QRecordCollection : List { - private readonly List _recordsToRemove = new List(); + private readonly List _recordsToRemove = new List(); public QRecordCollection(IQApplication application, IQTable table) { @@ -22,24 +25,47 @@ public QRecordCollection(IQApplication application, IQTable table) } private IQApplication Application { get; set; } + private IQTable Table { get; set; } public new bool Remove(IQRecord record) { if (record.IsOnServer) { - _recordsToRemove.Add(record.RecordId); + if (Table.KeyFID == -1) _recordsToRemove.Add(record.RecordId); + else _recordsToRemove.Add(record[Table.KeyFID]); } return base.Remove(record); } internal void RemoveRecords() { - foreach (var recordId in _recordsToRemove) + if (_recordsToRemove.Count > 0) { - var deleteRecord = new DeleteRecord(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, Table.TableId, recordId); - deleteRecord.Post(); + int keyfield = Table.KeyFID; + if (keyfield == -1) keyfield = Table.Columns.Single(c => c.ColumnName == "Record ID#").ColumnId; + List lstQry = + _recordsToRemove.Select(recordId => String.Format("{{'{0}'.EQ.'{1}'}}", keyfield, (object)recordId)) + .ToList(); + //TODO: further optimization possible: sort and search through lstQry combining conjoining spans + int cnt = lstQry.Count; + for (int i = 0; i < cnt; i += 100) + { + int k = Math.Min(100, cnt - i); + String qry = String.Join(" OR ", lstQry.Skip(i).Take(k)); + var prBuild = new PurgeRecords.Builder(Application.Client.Ticket, Application.Token, + Application.Client.AccountDomain, Table.TableId); + prBuild.SetQuery(qry); + var xml = prBuild.Build().Post().CreateNavigator(); + int result = int.Parse(xml.SelectSingleNode("/qdbapi/errcode").Value); + if (result != 0) + { + string errmsg = xml.SelectSingleNode("/qdbapi/errtxt").Value; + throw new ApplicationException("Error in purgeRecords: '" + errmsg + "'"); + } + } } + _recordsToRemove.Clear(); } } -} +} \ No newline at end of file diff --git a/Intuit.QuickBase.Client/QTable.cs b/Intuit.QuickBase.Client/QTable.cs index 999f2cc..78f2ce4 100644 --- a/Intuit.QuickBase.Client/QTable.cs +++ b/Intuit.QuickBase.Client/QTable.cs @@ -5,8 +5,10 @@ * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/eclipse-1.0.php */ + using System; using System.Collections.Generic; +using System.Linq; using System.Xml.XPath; using Intuit.QuickBase.Core; @@ -41,21 +43,30 @@ private void CommonConstruction(QColumnFactoryBase columnFactory, QRecordFactory RecordFactory = recordFactory; Application = application; TableId = tableId; + KeyFID = -1; Records = new QRecordCollection(Application, this); Columns = new QColumnCollection(Application, this); } // Properties private IQApplication Application { get; set; } + public string TableId { get; private set; } + public string TableName { get; private set; } + public string RecordNames { get; private set; } + public QRecordCollection Records { get; private set; } + public QColumnCollection Columns { get; private set; } private QColumnFactoryBase ColumnFactory { get; set; } + private QRecordFactoryBase RecordFactory { get; set; } + public int KeyFID { get; private set; } + // Methods public void Clear() { @@ -111,7 +122,18 @@ public void Query() .SetFmt(true) .Build(); var xml = doQuery.Post().CreateNavigator(); + LoadColumns(xml); //Must be done each time, incase the schema changes do to another user + LoadRecords(xml); + } + public void Query(string options) + { + var doQuery = new DoQuery.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) + .SetCList("a") + .SetFmt(true) + .SetOptions(options) + .Build(); + var xml = doQuery.Post().CreateNavigator(); LoadColumns(xml); LoadRecords(xml); } @@ -125,7 +147,6 @@ public void Query(int[] clist) .SetFmt(true) .Build(); var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); LoadRecords(xml); } @@ -140,7 +161,6 @@ public void Query(int[] clist, string options) .SetFmt(true) .Build(); var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); LoadRecords(xml); } @@ -153,7 +173,19 @@ public void Query(Query query) .SetFmt(true) .Build(); var xml = doQuery.Post().CreateNavigator(); + LoadColumns(xml); + LoadRecords(xml); + } + public void Query(Query query, string options) + { + var doQuery = new DoQuery.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) + .SetQuery(query.ToString()) + .SetCList("a") + .SetOptions(options) + .SetFmt(true) + .Build(); + var xml = doQuery.Post().CreateNavigator(); LoadColumns(xml); LoadRecords(xml); } @@ -168,7 +200,6 @@ public void Query(Query query, int[] clist) .SetFmt(true) .Build(); var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); LoadRecords(xml); } @@ -185,7 +216,6 @@ public void Query(Query query, int[] clist, int[] slist) .SetFmt(true) .Build(); var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); LoadRecords(xml); } @@ -203,7 +233,6 @@ public void Query(Query query, int[] clist, int[] slist, string options) .SetFmt(true) .Build(); var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); LoadRecords(xml); } @@ -215,7 +244,18 @@ public void Query(int queryId) .SetFmt(true) .Build(); var xml = doQuery.Post().CreateNavigator(); + LoadColumns(xml); + LoadRecords(xml); + } + public void Query(int queryId, string options) + { + var doQuery = new DoQuery.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) + .SetQid(queryId) + .SetFmt(true) + .SetOptions(options) + .Build(); + var xml = doQuery.Post().CreateNavigator(); LoadColumns(xml); LoadRecords(xml); } @@ -254,12 +294,53 @@ public void PurgeRecords(int queryId) Records.Clear(); } + public void PurgeRecords(Query query) + { + var purge = new PurgeRecords.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) + .SetQuery(query.ToString()) + .Build(); + purge.Post(); + Records.Clear(); + } + public void AcceptChanges() { Records.RemoveRecords(); - foreach (var record in Records) + //optimize record uploads + List addList = Records.Where(record => record.RecordState == RecordState.New).ToList(); + List modList = Records.Where(record => record.RecordState == RecordState.Modified).ToList(); + int acnt = addList.Count; + int mcnt = modList.Count; + if (acnt + mcnt > 0) { - record.AcceptChanges(); + List csvLines = new List(acnt + mcnt); + String clist = String.Join(".", KeyFID == -1 ? Columns.Where(col => col.ColumnVirtual == false || col.ColumnName == "Record ID#").Select(col => col.ColumnId.ToString()) : Columns.Where(col => col.ColumnVirtual == false || col.ColumnId == KeyFID).Select(col => col.ColumnId.ToString())); + if (acnt > 0) + { + csvLines.AddRange(addList.Select(record => record.GetAsCSV(clist))); + } + if (mcnt > 0) + { + csvLines.AddRange(modList.Select(record => record.GetAsCSV(clist))); + } + var csvBuilder = new ImportFromCSV.Builder(Application.Client.Ticket, Application.Token, + Application.Client.AccountDomain, TableId, String.Join("\r\n", csvLines.ToArray())); + csvBuilder.SetCList(clist); + var csvUpload = csvBuilder.Build(); + + var xml = csvUpload.Post().CreateNavigator(); + + XPathNodeIterator xNodes = xml.Select("/qdbapi/rids/rid"); + //set records as in server now + foreach (IQRecord rec in addList) + { + xNodes.MoveNext(); + ((IQRecord_int)rec).ForceUpdateState(Int32.Parse(xNodes.Current.Value)); + } + foreach (IQRecord rec in modList) + { + ((IQRecord_int)rec).ForceUpdateState(); + } } } @@ -276,7 +357,7 @@ public override string ToString() internal void Load() { TableName = GetTableInfo().DbName; - LoadColumns(); + RefreshColumns(); } private void LoadRecords(XPathNavigator xml) @@ -290,7 +371,7 @@ private void LoadRecords(XPathNavigator xml) } } - private void LoadColumns() + public void RefreshColumns() { LoadColumns(GetTableSchema().CreateNavigator()); } @@ -298,6 +379,8 @@ private void LoadColumns() private void LoadColumns(XPathNavigator xml) { Columns.Clear(); + var keyFidNode = xml.SelectSingleNode("/qdbapi/table/original/key_fid"); + if (keyFidNode != null) { KeyFID = keyFidNode.ValueAsInt; } var columnNodes = xml.Select("/qdbapi/table/fields/field"); foreach (XPathNavigator columnNode in columnNodes) { @@ -306,7 +389,8 @@ private void LoadColumns(XPathNavigator xml) (FieldType)Enum.Parse(typeof(FieldType), columnNode.GetAttribute("field_type", String.Empty), true); var label = columnNode.SelectSingleNode("label").Value; - var col = ColumnFactory.CreateInstace(columnId, label, type); + bool virt = columnNode.GetAttribute("mode", String.Empty) == "virtual"; + var col = ColumnFactory.CreateInstace(columnId, label, type, virt); Columns.Add(col); } } @@ -318,20 +402,11 @@ private static string GetColumnList(ICollection clist) const int RECORDID_COLUMN_ID = 3; var columns = String.Empty; var columnList = new List(clist.Count + 1) { RECORDID_COLUMN_ID }; + columnList.AddRange(clist.Where(columnId => columnId != RECORDID_COLUMN_ID)); // Seed the list with the column ID of Record#ID - foreach (var columnId in clist) - { - if (columnId != RECORDID_COLUMN_ID) - { - columnList.Add(columnId); - } - } - foreach (var columnId in columnList) - { - columns += columnId + "."; - } + columns = columnList.Aggregate(columns, (current, columnId) => current + (columnId + ".")); return columns.TrimEnd('.'); } return "a"; @@ -339,12 +414,8 @@ private static string GetColumnList(ICollection clist) private static string GetSortList(IEnumerable slist) { - var solList = String.Empty; - foreach (var sol in slist) - { - solList += sol + "."; - } + var solList = slist.Aggregate(String.Empty, (current, sol) => current + (sol + ".")); return solList.TrimEnd('.'); } } -} +} \ No newline at end of file From 8cb7b7f648d3e55feb443bb70ae4e75ea175407f Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Wed, 8 Oct 2014 12:58:02 -0600 Subject: [PATCH 04/49] Handle lookup columns (identify them, and don't include them in uploads). --- Intuit.QuickBase.Client/IQColumn.cs | 1 + Intuit.QuickBase.Client/QColumn.cs | 4 +++- Intuit.QuickBase.Client/QColumnFactory.cs | 4 ++-- Intuit.QuickBase.Client/QColumnFactoryBase.cs | 2 +- Intuit.QuickBase.Client/QTable.cs | 6 ++++-- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Intuit.QuickBase.Client/IQColumn.cs b/Intuit.QuickBase.Client/IQColumn.cs index 4ce3bd6..4ec3fa7 100644 --- a/Intuit.QuickBase.Client/IQColumn.cs +++ b/Intuit.QuickBase.Client/IQColumn.cs @@ -15,6 +15,7 @@ public interface IQColumn string ColumnName { get; set; } FieldType ColumnType { get; set; } bool ColumnVirtual { get; set; } + bool ColumnLookup { get; set; } bool Equals(IQColumn column); bool Equals(object obj); int GetHashCode(); diff --git a/Intuit.QuickBase.Client/QColumn.cs b/Intuit.QuickBase.Client/QColumn.cs index 1aacf26..f6611b9 100644 --- a/Intuit.QuickBase.Client/QColumn.cs +++ b/Intuit.QuickBase.Client/QColumn.cs @@ -26,10 +26,11 @@ internal QColumn(int columnId, string columnName, FieldType columnType) ColumnId = columnId; } - internal QColumn(int columnId, string columnName, FieldType columnType, bool columnVirtual) + internal QColumn(int columnId, string columnName, FieldType columnType, bool columnVirtual, bool columnLookup) : this(columnName, columnType) { ColumnVirtual = columnVirtual; + ColumnLookup = columnLookup; ColumnId = columnId; } @@ -38,6 +39,7 @@ internal QColumn(int columnId, string columnName, FieldType columnType, bool col public string ColumnName { get; set; } public FieldType ColumnType { get; set; } public bool ColumnVirtual { get; set; } + public bool ColumnLookup { get; set; } // Methods public bool Equals(IQColumn column) diff --git a/Intuit.QuickBase.Client/QColumnFactory.cs b/Intuit.QuickBase.Client/QColumnFactory.cs index 6fc3132..9fefb31 100644 --- a/Intuit.QuickBase.Client/QColumnFactory.cs +++ b/Intuit.QuickBase.Client/QColumnFactory.cs @@ -24,9 +24,9 @@ internal static QColumnFactoryBase GetInstance() return _instance; } - internal override IQColumn CreateInstace(int columnId, string columnName, FieldType columnType, bool columnVirtual) + internal override IQColumn CreateInstace(int columnId, string columnName, FieldType columnType, bool columnVirtual, bool columnLookup) { - return new QColumn(columnId, columnName, columnType, columnVirtual); + return new QColumn(columnId, columnName, columnType, columnVirtual, columnLookup); } } } diff --git a/Intuit.QuickBase.Client/QColumnFactoryBase.cs b/Intuit.QuickBase.Client/QColumnFactoryBase.cs index 8cf0c6e..314d701 100644 --- a/Intuit.QuickBase.Client/QColumnFactoryBase.cs +++ b/Intuit.QuickBase.Client/QColumnFactoryBase.cs @@ -11,6 +11,6 @@ namespace Intuit.QuickBase.Client { internal abstract class QColumnFactoryBase { - internal abstract IQColumn CreateInstace(int columnId, string columnName, FieldType columnType, bool columnVirtual); + internal abstract IQColumn CreateInstace(int columnId, string columnName, FieldType columnType, bool columnVirtual, bool columnLookup); } } diff --git a/Intuit.QuickBase.Client/QTable.cs b/Intuit.QuickBase.Client/QTable.cs index 78f2ce4..2d979d0 100644 --- a/Intuit.QuickBase.Client/QTable.cs +++ b/Intuit.QuickBase.Client/QTable.cs @@ -314,7 +314,8 @@ public void AcceptChanges() if (acnt + mcnt > 0) { List csvLines = new List(acnt + mcnt); - String clist = String.Join(".", KeyFID == -1 ? Columns.Where(col => col.ColumnVirtual == false || col.ColumnName == "Record ID#").Select(col => col.ColumnId.ToString()) : Columns.Where(col => col.ColumnVirtual == false || col.ColumnId == KeyFID).Select(col => col.ColumnId.ToString())); + String clist = String.Join(".", KeyFID == -1 ? Columns.Where(col => (col.ColumnVirtual == false && col.ColumnLookup == false) || col.ColumnName == "Record ID#").Select(col => col.ColumnId.ToString()) + : Columns.Where(col => (col.ColumnVirtual == false && col.ColumnLookup == false) || col.ColumnId == KeyFID).Select(col => col.ColumnId.ToString())); if (acnt > 0) { csvLines.AddRange(addList.Select(record => record.GetAsCSV(clist))); @@ -390,7 +391,8 @@ private void LoadColumns(XPathNavigator xml) var label = columnNode.SelectSingleNode("label").Value; bool virt = columnNode.GetAttribute("mode", String.Empty) == "virtual"; - var col = ColumnFactory.CreateInstace(columnId, label, type, virt); + bool lookup = columnNode.GetAttribute("mode", String.Empty) == "lookup"; + var col = ColumnFactory.CreateInstace(columnId, label, type, virt, lookup); Columns.Add(col); } } From 8cee7a28a6e51e3154f417c59f24dee49dd0eabd Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Thu, 9 Oct 2014 16:23:11 -0600 Subject: [PATCH 05/49] Separate internal (QBformat) values from what an application can grab: make it so users don't have to know how QB represents time, etc. --- Intuit.QuickBase.Client/QField.cs | 40 +++++++++++++++++++++++++++--- Intuit.QuickBase.Client/QRecord.cs | 6 ++--- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/Intuit.QuickBase.Client/QField.cs b/Intuit.QuickBase.Client/QField.cs index 1118320..9a5dd81 100644 --- a/Intuit.QuickBase.Client/QField.cs +++ b/Intuit.QuickBase.Client/QField.cs @@ -6,12 +6,14 @@ * http://www.opensource.org/licenses/eclipse-1.0.php */ using System; +using System.IO; using Intuit.QuickBase.Core; namespace Intuit.QuickBase.Client { internal class QField { + private static readonly DateTime qbOffset = new DateTime(1970, 1, 1, 0, 0, 0, 0); // Instance fields private string _value; @@ -26,11 +28,17 @@ internal QField(int fieldId, string value, FieldType type, IQRecord record) FieldId = fieldId; Type = type; Record = record; // needs to be before Value. - Value = value; + _value = value; } // Properties internal int FieldId { get; private set; } + + internal string QBValue + { + get { return _value; } + } + internal string Value { get @@ -38,6 +46,8 @@ internal string Value switch (Type) { case FieldType.timestamp: + case FieldType.date: + case FieldType.timeofday: return ConvertQBMillisecondsToDateTime(_value).ToString(); default: return _value; @@ -49,7 +59,17 @@ internal string Value { Update = true; } - _value = value; + switch (Type) + { + case FieldType.timestamp: + case FieldType.date: + case FieldType.timeofday: + _value = ConvertDateTimeStringToQBMilliseconds(value); + break; + default: + _value = value; + break; + } } } internal FieldType Type { get; set; } @@ -84,8 +104,20 @@ public override string ToString() private static DateTime ConvertQBMillisecondsToDateTime(string milliseconds) { - var date = new DateTime(1970, 1, 1, 0, 0, 0, 0); - return new DateTime(date.Ticks + (Int64.Parse(milliseconds) * TimeSpan.TicksPerMillisecond)); + return new DateTime(qbOffset.Ticks + (Int64.Parse(milliseconds) * TimeSpan.TicksPerMillisecond)); + } + + private static string ConvertDateTimeStringToQBMilliseconds(string inDateStr) + { + DateTime inDate; + if (DateTime.TryParse(inDateStr, out inDate)) + { + return ((inDate.Ticks - qbOffset.Ticks)/TimeSpan.TicksPerMillisecond).ToString(); + } + else + { + throw new InvalidDataException(String.Format("Can't parse '{0}' into a date format", inDateStr)); + } } } } diff --git a/Intuit.QuickBase.Client/QRecord.cs b/Intuit.QuickBase.Client/QRecord.cs index 1a192c0..cd87150 100644 --- a/Intuit.QuickBase.Client/QRecord.cs +++ b/Intuit.QuickBase.Client/QRecord.cs @@ -121,7 +121,7 @@ public void AcceptChanges() { if (field.Update) { - IField qField = new Field(field.FieldId, field.Type, field.Value); + IField qField = new Field(field.FieldId, field.Type, field.QBValue); if(field.Type == FieldType.file) { qField.File = field.FullName; @@ -138,7 +138,7 @@ public void AcceptChanges() { foreach (var field in _fields) { - IField qField = new Field(field.FieldId, field.Type, field.Value); + IField qField = new Field(field.FieldId, field.Type, field.QBValue); if (field.Type == FieldType.file) { qField.File = field.FullName; @@ -169,7 +169,7 @@ public string GetAsCSV(string clist) else { if (field.Type == FieldType.file) throw new InvalidChoiceException(); - csvList.Add(CSVQuoter(field.Value)); + csvList.Add(CSVQuoter(field.QBValue)); } } return String.Join(",", csvList); From 1847a8c2ca38fd81f80763571b35f6b02b836982 Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Mon, 13 Oct 2014 14:17:32 -0600 Subject: [PATCH 06/49] Previous work on separating user view of data vs QBase view was flawed and incomplete. Fixed now and tested. --- Intuit.QuickBase.Client/QField.cs | 16 ++++++++++++++-- Intuit.QuickBase.Client/QRecord.cs | 29 ++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/Intuit.QuickBase.Client/QField.cs b/Intuit.QuickBase.Client/QField.cs index 9a5dd81..26874bd 100644 --- a/Intuit.QuickBase.Client/QField.cs +++ b/Intuit.QuickBase.Client/QField.cs @@ -23,12 +23,24 @@ internal QField(int fieldId) } // Constructors - internal QField(int fieldId, string value, FieldType type, IQRecord record) + internal QField(int fieldId, string value, FieldType type, IQRecord record) : this(fieldId, value, type, record, false) + { + } + + internal QField(int fieldId, string value, FieldType type, IQRecord record, bool QBinternal) { FieldId = fieldId; Type = type; Record = record; // needs to be before Value. - _value = value; + if (QBinternal) + { + _value = value; + } + else + { + Value = value; + Update = false; + } } // Properties diff --git a/Intuit.QuickBase.Client/QRecord.cs b/Intuit.QuickBase.Client/QRecord.cs index cd87150..e94e491 100644 --- a/Intuit.QuickBase.Client/QRecord.cs +++ b/Intuit.QuickBase.Client/QRecord.cs @@ -58,6 +58,21 @@ internal set } } + private void FieldLoad(int index, string value) + { + // Get field location with column index + var fieldIndex = _fields.IndexOf(new QField(Columns[index].ColumnId)); + + if (fieldIndex > -1) + { + SetExistingField(index, fieldIndex, value); + } + else + { + CreateNewField(index, value, true); + } + } + public string this[int index] { get @@ -77,7 +92,7 @@ public string this[int index] } else { - CreateNewField(index, value); + CreateNewField(index, value, false); } } } @@ -106,7 +121,7 @@ public string this[string columnName] } else { - CreateNewField(index, value); + CreateNewField(index, value, false); } } } @@ -205,11 +220,11 @@ private void FillRecord(XPathNavigator recordNode) if (fieldNode.HasChildren && fieldNode.MoveToChild("url", String.Empty)) { fieldNode.MoveToFirst(); - this[colIndex] = fieldNode.TypedValue as string; + FieldLoad(colIndex, fieldNode.TypedValue as string); } else { - this[colIndex] = fieldNode.TypedValue as string; + FieldLoad(colIndex, fieldNode.TypedValue as string); } if (fieldNode.GetAttribute("id", String.Empty).Equals("3")) @@ -263,11 +278,11 @@ public override string ToString() return RecordId.ToString(); } - private void CreateNewField(int index, string value) + private void CreateNewField(int index, string value, bool QBInternal) { if (Columns[index].ColumnType == FieldType.file && !IsOnServer) { - var field = new QField(Columns[index].ColumnId, Path.GetFileName(value), Columns[index].ColumnType, this) + var field = new QField(Columns[index].ColumnId, Path.GetFileName(value), Columns[index].ColumnType, this, QBInternal) { FullName = value }; @@ -275,7 +290,7 @@ private void CreateNewField(int index, string value) } else { - var field = new QField(Columns[index].ColumnId, value, Columns[index].ColumnType, this); + var field = new QField(Columns[index].ColumnId, value, Columns[index].ColumnType, this, QBInternal); _fields.Add(field); } } From b862b564cc1df0c96dd4e8966ca89d83673706db Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Mon, 27 Oct 2014 13:39:12 -0600 Subject: [PATCH 07/49] Convert all record results to the client to be a corresponding .NET type, add value checking on set, hide all QB conversions from end user, support additional QB types, start handling multiple choice fields properly. --- Intuit.QuickBase.Client/IQColumn.cs | 11 ++ Intuit.QuickBase.Client/IQRecord.cs | 4 +- Intuit.QuickBase.Client/IQTable.cs | 5 + .../Intuit.QuickBase.Client.csproj | 1 + Intuit.QuickBase.Client/QAddress.cs | 22 +++ Intuit.QuickBase.Client/QColumn.cs | 34 +++- Intuit.QuickBase.Client/QColumnFactory.cs | 4 +- Intuit.QuickBase.Client/QColumnFactoryBase.cs | 2 +- Intuit.QuickBase.Client/QField.cs | 183 +++++++++++++++--- Intuit.QuickBase.Client/QRecord.cs | 26 +-- Intuit.QuickBase.Client/QRecordCollection.cs | 4 +- Intuit.QuickBase.Client/QTable.cs | 76 +++++++- Intuit.QuickBase.Core/FieldType.cs | 55 +++++- 13 files changed, 363 insertions(+), 64 deletions(-) create mode 100644 Intuit.QuickBase.Client/QAddress.cs diff --git a/Intuit.QuickBase.Client/IQColumn.cs b/Intuit.QuickBase.Client/IQColumn.cs index 4ec3fa7..d7ae906 100644 --- a/Intuit.QuickBase.Client/IQColumn.cs +++ b/Intuit.QuickBase.Client/IQColumn.cs @@ -5,6 +5,8 @@ * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/eclipse-1.0.php */ + +using System.Collections.Generic; using Intuit.QuickBase.Core; namespace Intuit.QuickBase.Client @@ -15,10 +17,19 @@ public interface IQColumn string ColumnName { get; set; } FieldType ColumnType { get; set; } bool ColumnVirtual { get; set; } + bool IsHidden { get; set; } bool ColumnLookup { get; set; } + string CurrencySymbol { get; set; } bool Equals(IQColumn column); bool Equals(object obj); int GetHashCode(); string ToString(); + object[] GetChoices(); + } + + internal interface IQColumn_int + { + void AddChoice(object obj); + Dictionary GetComposites(); } } diff --git a/Intuit.QuickBase.Client/IQRecord.cs b/Intuit.QuickBase.Client/IQRecord.cs index 2b827e1..ec56035 100644 --- a/Intuit.QuickBase.Client/IQRecord.cs +++ b/Intuit.QuickBase.Client/IQRecord.cs @@ -12,8 +12,8 @@ public interface IQRecord int RecordId { get; } RecordState RecordState { get; } bool IsOnServer { get; } - string this[int index] { get; set; } - string this[string columnName] { get; set; } + object this[int index] { get; set; } + object this[string columnName] { get; set; } void AcceptChanges(); void DownloadFile(string columnName, string path, int versionId); void ChangeOwnerTo(string newOwner); diff --git a/Intuit.QuickBase.Client/IQTable.cs b/Intuit.QuickBase.Client/IQTable.cs index 020f001..0a24790 100644 --- a/Intuit.QuickBase.Client/IQTable.cs +++ b/Intuit.QuickBase.Client/IQTable.cs @@ -17,7 +17,12 @@ public interface IQTable QRecordCollection Records { get; } QColumnCollection Columns { get; } void Clear(); + string GenCsv(); string GenCsv(int queryId); + string GenCsv(Query query); + string GenHtml(string options = "", string clist = "a"); + string GenHtml(int queryId, string options = "", string clist = "a"); + string GenHtml(Query query, string options = "", string clist = "a"); XPathDocument GetTableSchema(); TableInfo GetTableInfo(); int GetServerRecordCount(); diff --git a/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj b/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj index 8909c43..da5dda9 100644 --- a/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj +++ b/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj @@ -72,6 +72,7 @@ + diff --git a/Intuit.QuickBase.Client/QAddress.cs b/Intuit.QuickBase.Client/QAddress.cs new file mode 100644 index 0000000..84cc8ac --- /dev/null +++ b/Intuit.QuickBase.Client/QAddress.cs @@ -0,0 +1,22 @@ +namespace Intuit.QuickBase.Client +{ + public class QAddress + { + public string Line1 { get; set; } + public string Line2 { get; set; } + public string City { get; set; } + public string Province { get; set; } + public string PostalCode { get; set; } + public string Country { get; set; } + + public QAddress(string line1, string line2, string city, string province, string postCode, string country) + { + Line1 = line1; + Line2 = line2; + City = city; + Province = province; + PostalCode = postCode; + Country = country; + } + } +} diff --git a/Intuit.QuickBase.Client/QColumn.cs b/Intuit.QuickBase.Client/QColumn.cs index f6611b9..df7f017 100644 --- a/Intuit.QuickBase.Client/QColumn.cs +++ b/Intuit.QuickBase.Client/QColumn.cs @@ -5,16 +5,22 @@ * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/eclipse-1.0.php */ + +using System.Collections.Generic; using Intuit.QuickBase.Core; namespace Intuit.QuickBase.Client { - public class QColumn : IQColumn + public class QColumn : IQColumn, IQColumn_int { // Constructors - internal QColumn() { } + internal QColumn() + { + choices = new List(); + composites = new Dictionary(); + } - public QColumn(string columnName, FieldType columnType) + public QColumn(string columnName, FieldType columnType) : this() { ColumnName = columnName; ColumnType = columnType; @@ -26,11 +32,12 @@ internal QColumn(int columnId, string columnName, FieldType columnType) ColumnId = columnId; } - internal QColumn(int columnId, string columnName, FieldType columnType, bool columnVirtual, bool columnLookup) + internal QColumn(int columnId, string columnName, FieldType columnType, bool columnVirtual, bool columnLookup, bool isHidden) : this(columnName, columnType) { ColumnVirtual = columnVirtual; ColumnLookup = columnLookup; + IsHidden = isHidden; ColumnId = columnId; } @@ -39,7 +46,11 @@ internal QColumn(int columnId, string columnName, FieldType columnType, bool col public string ColumnName { get; set; } public FieldType ColumnType { get; set; } public bool ColumnVirtual { get; set; } + public bool IsHidden { get; set; } public bool ColumnLookup { get; set; } + internal List choices; + internal Dictionary composites; + public string CurrencySymbol { get; set; } // Methods public bool Equals(IQColumn column) @@ -66,5 +77,20 @@ public override string ToString() { return ColumnName; } + + public object[] GetChoices() + { + return choices.ToArray(); + } + + public void AddChoice(object obj) + { + choices.Add(obj); + } + + public Dictionary GetComposites() + { + return composites; + } } } diff --git a/Intuit.QuickBase.Client/QColumnFactory.cs b/Intuit.QuickBase.Client/QColumnFactory.cs index 9fefb31..63ff22b 100644 --- a/Intuit.QuickBase.Client/QColumnFactory.cs +++ b/Intuit.QuickBase.Client/QColumnFactory.cs @@ -24,9 +24,9 @@ internal static QColumnFactoryBase GetInstance() return _instance; } - internal override IQColumn CreateInstace(int columnId, string columnName, FieldType columnType, bool columnVirtual, bool columnLookup) + internal override IQColumn CreateInstace(int columnId, string columnName, FieldType columnType, bool columnVirtual, bool columnLookup, bool ishidden) { - return new QColumn(columnId, columnName, columnType, columnVirtual, columnLookup); + return new QColumn(columnId, columnName, columnType, columnVirtual, columnLookup, ishidden); } } } diff --git a/Intuit.QuickBase.Client/QColumnFactoryBase.cs b/Intuit.QuickBase.Client/QColumnFactoryBase.cs index 314d701..2aa6f1f 100644 --- a/Intuit.QuickBase.Client/QColumnFactoryBase.cs +++ b/Intuit.QuickBase.Client/QColumnFactoryBase.cs @@ -11,6 +11,6 @@ namespace Intuit.QuickBase.Client { internal abstract class QColumnFactoryBase { - internal abstract IQColumn CreateInstace(int columnId, string columnName, FieldType columnType, bool columnVirtual, bool columnLookup); + internal abstract IQColumn CreateInstace(int columnId, string columnName, FieldType columnType, bool columnVirtual, bool columnLookup, bool isHidden); } } diff --git a/Intuit.QuickBase.Client/QField.cs b/Intuit.QuickBase.Client/QField.cs index 26874bd..0fb212a 100644 --- a/Intuit.QuickBase.Client/QField.cs +++ b/Intuit.QuickBase.Client/QField.cs @@ -6,6 +6,8 @@ * http://www.opensource.org/licenses/eclipse-1.0.php */ using System; +using System.CodeDom; +using System.Collections.Generic; using System.IO; using Intuit.QuickBase.Core; @@ -15,31 +17,31 @@ internal class QField { private static readonly DateTime qbOffset = new DateTime(1970, 1, 1, 0, 0, 0, 0); // Instance fields - private string _value; + private object _value; internal QField(int fieldId) - : this(fieldId, null, FieldType.empty, null) + : this(fieldId, null, FieldType.empty, null, null) { } // Constructors - internal QField(int fieldId, string value, FieldType type, IQRecord record) : this(fieldId, value, type, record, false) + internal QField(int fieldId, object value, FieldType type, IQRecord record, IQColumn column) : this(fieldId, value, type, record, column, false) { } - internal QField(int fieldId, string value, FieldType type, IQRecord record, bool QBinternal) + internal QField(int fieldId, object value, FieldType type, IQRecord record, IQColumn column, bool QBinternal) { FieldId = fieldId; Type = type; Record = record; // needs to be before Value. + Column = column; if (QBinternal) { - _value = value; + QBValue = (string)value; } else { Value = value; - Update = false; } } @@ -47,36 +49,56 @@ internal QField(int fieldId, string value, FieldType type, IQRecord record, bool internal int FieldId { get; private set; } internal string QBValue - { - get { return _value; } - } - - internal string Value { get { + if (_value == null) return String.Empty; switch (Type) { + case FieldType.address: + return string.Empty; case FieldType.timestamp: case FieldType.date: + return ConvertDateTimeToQBMilliseconds((DateTime)_value); case FieldType.timeofday: - return ConvertQBMillisecondsToDateTime(_value).ToString(); + return ConvertTimeSpanToQBMilliseconds((TimeSpan)_value); + case FieldType.checkbox: + return (bool)_value == true ? "1" : "0"; + case FieldType.percent: + return Math.Round((float) _value * 100.0, 6).ToString(); //Get around roundtrip bug in Quickbase default: - return _value; + return _value.ToString(); } } set { - if (_value != null) - { - Update = true; - } switch (Type) { - case FieldType.timestamp: + case FieldType.address: + // do nothing: child columns will fill this out + break; case FieldType.date: + _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDateTime(value).Date; + break; case FieldType.timeofday: - _value = ConvertDateTimeStringToQBMilliseconds(value); + _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : ConvertQBMillisecondsToDateTime(value).TimeOfDay; + break; + case FieldType.duration: + _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : TimeSpan.Parse(value); + break; + case FieldType.timestamp: + _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDateTime(value); + break; + case FieldType.checkbox: + _value = String.IsNullOrEmpty(value) ? new bool?() : (value == "1" || value == "true"); + break; + case FieldType.percent: + case FieldType.rating: + _value = String.IsNullOrEmpty(value) ? new float?() : float.Parse(value); + break; + case FieldType.@float: + case FieldType.currency: + _value = String.IsNullOrEmpty(value) ? new decimal?() : decimal.Parse(value); break; default: _value = value; @@ -84,8 +106,112 @@ internal string Value } } } + + internal object Value + { + get + { + switch (Type) + { + case FieldType.address: + Dictionary colDict = ((IQColumn_int) Column).GetComposites(); + return new QAddress( + (string)Record[colDict["street"]], + (string)Record[colDict["street2"]], + (string)Record[colDict["city"]], + (string)Record[colDict["region"]], + (string)Record[colDict["postal"]], + (string)Record[colDict["country"]] + ); + default: + return _value; + } + } + set + { + if (value == null) + { + if (_value != null) + { + _value = null; + Update = true; + } + } + else + { + if (_value == null || !_value.Equals(value)) + { + Update = true; + switch (Type) + { + case FieldType.address: + if (value.GetType() != typeof (QAddress)) + throw new ArgumentException("Can't supply type of " + value.GetType() + " to a " + + this.Type.ToString() + " field."); + Dictionary colDict = ((IQColumn_int) Column).GetComposites(); + Record[colDict["street"]] = ((QAddress) value).Line1; + Record[colDict["street2"]] = ((QAddress) value).Line2; + Record[colDict["city"]] = ((QAddress) value).City; + Record[colDict["region"]] = ((QAddress) value).Province; + Record[colDict["postal"]] = ((QAddress) value).PostalCode; + Record[colDict["country"]] = ((QAddress) value).Country; + break; + case FieldType.rating: + if (value.GetType() != typeof(float) || (float) value < 0 || (float) value > 5) + throw new ArgumentException("Invalid value for 'rating' fieldtype"); + _value = value; + break; + case FieldType.date: + if (value.GetType() != typeof(DateTime)) + throw new ArgumentException("Can't supply type of " + value.GetType() + " to a " + + this.Type.ToString() + " field."); + _value = ((DateTime) value).Date; + break; + case FieldType.timestamp: + if (value.GetType() != typeof(DateTime)) + throw new ArgumentException("Can't supply type of " + value.GetType() + " to a " + + this.Type.ToString() + " field."); + _value = value; + break; + case FieldType.duration: + case FieldType.timeofday: + if (value.GetType() != typeof(TimeSpan)) + throw new ArgumentException("Can't supply type of " + value.GetType() + " to a " + + this.Type.ToString() + " field."); + _value = value; + break; + case FieldType.@float: + case FieldType.currency: + decimal? val = value as decimal?; + Int32? val2 = value as Int32?; + if (val == null && val2 == null) + throw new ArgumentException("Can't supply type of " + value.GetType() + " to a " + + this.Type.ToString() + " field."); + if (val.HasValue) + _value = val.Value; + else + _value = val2.Value; + break; + case FieldType.checkbox: + if (value.GetType() != typeof(bool)) + throw new ArgumentException("Can't supply type of " + value.GetType() + " to a " + + this.Type.ToString() + " field."); + _value = value; + break; + default: + if (value.GetType() != typeof(string)) + throw new ArgumentException("Can't supply type of " + value.GetType() + " to a " + + this.Type.ToString() + " field."); + _value = value; + break; + } + } + } + } + } internal FieldType Type { get; set; } internal IQRecord Record { get; set; } + internal IQColumn Column { get; set; } internal string FullName { get; set; } internal bool Update { get; set; } @@ -111,7 +237,7 @@ public override int GetHashCode() public override string ToString() { - return Value; + return Value.ToString(); } private static DateTime ConvertQBMillisecondsToDateTime(string milliseconds) @@ -119,17 +245,14 @@ private static DateTime ConvertQBMillisecondsToDateTime(string milliseconds) return new DateTime(qbOffset.Ticks + (Int64.Parse(milliseconds) * TimeSpan.TicksPerMillisecond)); } - private static string ConvertDateTimeStringToQBMilliseconds(string inDateStr) + private static string ConvertDateTimeToQBMilliseconds(DateTime inDate) { - DateTime inDate; - if (DateTime.TryParse(inDateStr, out inDate)) - { - return ((inDate.Ticks - qbOffset.Ticks)/TimeSpan.TicksPerMillisecond).ToString(); - } - else - { - throw new InvalidDataException(String.Format("Can't parse '{0}' into a date format", inDateStr)); - } + return ((inDate.Ticks - qbOffset.Ticks)/TimeSpan.TicksPerMillisecond).ToString(); + } + + private static string ConvertTimeSpanToQBMilliseconds(TimeSpan inTime) + { + return (inTime.Ticks / TimeSpan.TicksPerMillisecond).ToString(); } } } diff --git a/Intuit.QuickBase.Client/QRecord.cs b/Intuit.QuickBase.Client/QRecord.cs index e94e491..57da626 100644 --- a/Intuit.QuickBase.Client/QRecord.cs +++ b/Intuit.QuickBase.Client/QRecord.cs @@ -73,7 +73,7 @@ private void FieldLoad(int index, string value) } } - public string this[int index] + public object this[int index] { get { @@ -97,7 +97,7 @@ public string this[int index] } } - public string this[string columnName] + public object this[string columnName] { get { @@ -192,8 +192,8 @@ public string GetAsCSV(string clist) private string CSVQuoter(string inStr) { - //if the string contains quote character(s), surround the string with quotes - if (inStr.Contains("\"")) + //if the string contains quote character(s), newlines or commas, surround the string with quotes + if (inStr.Contains("\"") || inStr.Contains(",") || inStr.Contains("\n") || inStr.Contains("\r")) return "\"" + inStr + "\""; else return inStr; @@ -240,7 +240,7 @@ public void DownloadFile(string columnName, string path, int versionId) { var index = GetColumnIndex(columnName); var field = _fields[_fields.IndexOf(new QField(Columns[index].ColumnId))]; - var fileName = field.Value; + string fileName = (string)field.Value; var fileToDownload = new DownloadFile(Application.Client.Ticket, Application.Client.AccountDomain, path, fileName, Table.TableId, RecordId, field.FieldId, versionId); @@ -278,29 +278,31 @@ public override string ToString() return RecordId.ToString(); } - private void CreateNewField(int index, string value, bool QBInternal) + private void CreateNewField(int index, object value, bool QBInternal) { if (Columns[index].ColumnType == FieldType.file && !IsOnServer) { - var field = new QField(Columns[index].ColumnId, Path.GetFileName(value), Columns[index].ColumnType, this, QBInternal) + string fileName = (string)value; + var field = new QField(Columns[index].ColumnId, Path.GetFileName(fileName), Columns[index].ColumnType, this, Columns[index], QBInternal) { - FullName = value + FullName = fileName }; _fields.Add(field); } else { - var field = new QField(Columns[index].ColumnId, value, Columns[index].ColumnType, this, QBInternal); + var field = new QField(Columns[index].ColumnId, value, Columns[index].ColumnType, this, Columns[index], QBInternal); _fields.Add(field); } } - private void SetExistingField(int index, int fieldIndex, string value) + private void SetExistingField(int index, int fieldIndex, object value) { if (Columns[index].ColumnType == FieldType.file) { - _fields[fieldIndex].Value = Path.GetFileName(value); - _fields[fieldIndex].FullName = value; + string fileName = (string) value; + _fields[fieldIndex].Value = Path.GetFileName(fileName); + _fields[fieldIndex].FullName = fileName; } else { diff --git a/Intuit.QuickBase.Client/QRecordCollection.cs b/Intuit.QuickBase.Client/QRecordCollection.cs index 62d9350..8712e6d 100644 --- a/Intuit.QuickBase.Client/QRecordCollection.cs +++ b/Intuit.QuickBase.Client/QRecordCollection.cs @@ -44,7 +44,7 @@ internal void RemoveRecords() { int keyfield = Table.KeyFID; if (keyfield == -1) keyfield = Table.Columns.Single(c => c.ColumnName == "Record ID#").ColumnId; - List lstQry = + List lstQry = _recordsToRemove.Select(recordId => String.Format("{{'{0}'.EQ.'{1}'}}", keyfield, (object)recordId)) .ToList(); //TODO: further optimization possible: sort and search through lstQry combining conjoining spans @@ -52,7 +52,7 @@ internal void RemoveRecords() for (int i = 0; i < cnt; i += 100) { int k = Math.Min(100, cnt - i); - String qry = String.Join(" OR ", lstQry.Skip(i).Take(k)); + string qry = String.Join(" OR ", lstQry.Skip(i).Take(k)); var prBuild = new PurgeRecords.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, Table.TableId); prBuild.SetQuery(qry); diff --git a/Intuit.QuickBase.Client/QTable.cs b/Intuit.QuickBase.Client/QTable.cs index 2d979d0..457e8e8 100644 --- a/Intuit.QuickBase.Client/QTable.cs +++ b/Intuit.QuickBase.Client/QTable.cs @@ -74,6 +74,15 @@ public void Clear() Columns.Clear(); } + public string GenCsv() + { + var genResultsTable = new GenResultsTable.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) + .SetOptions("csv") + .Build(); + var xml = genResultsTable.Post().CreateNavigator(); + return xml.SelectSingleNode("/response_data").Value; + } + public string GenCsv(int queryId) { var genResultsTable = new GenResultsTable.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) @@ -84,6 +93,48 @@ public string GenCsv(int queryId) return xml.SelectSingleNode("/response_data").Value; } + public string GenCsv(Query query) + { + var genResultsTable = new GenResultsTable.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) + .SetQuery(query.ToString()) + .SetOptions("csv") + .Build(); + var xml = genResultsTable.Post().CreateNavigator(); + return xml.SelectSingleNode("/response_data").Value; + } + + public string GenHtml(string options = "", string clist = "a") + { + var genResultsTable = new GenResultsTable.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) + .SetOptions(options) + .SetCList(clist) + .Build(); + var xml = genResultsTable.Post().CreateNavigator(); + return xml.SelectSingleNode("/response_data").Value; + } + + public string GenHtml(int queryId, string options = "", string clist = "a") + { + var genResultsTable = new GenResultsTable.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) + .SetQid(queryId) + .SetOptions(options) + .SetCList(clist) + .Build(); + var xml = genResultsTable.Post().CreateNavigator(); + return xml.SelectSingleNode("/response_data").Value; + } + + public string GenHtml(Query query, string options = "", string clist = "a") + { + var genResultsTable = new GenResultsTable.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) + .SetQuery(query.ToString()) + .SetOptions(options) + .SetCList(clist) + .Build(); + var xml = genResultsTable.Post().CreateNavigator(); + return xml.SelectSingleNode("/response_data").Value; + } + public XPathDocument GetTableSchema() { var tblSchema = new GetSchema(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId); @@ -389,10 +440,31 @@ private void LoadColumns(XPathNavigator xml) var type = (FieldType)Enum.Parse(typeof(FieldType), columnNode.GetAttribute("field_type", String.Empty), true); var label = columnNode.SelectSingleNode("label").Value; - + bool hidden = false; + var hidNode = columnNode.SelectSingleNode("appears_by_default"); + if (hidNode != null && hidNode.Value == "0") hidden = true; bool virt = columnNode.GetAttribute("mode", String.Empty) == "virtual"; bool lookup = columnNode.GetAttribute("mode", String.Empty) == "lookup"; - var col = ColumnFactory.CreateInstace(columnId, label, type, virt, lookup); + IQColumn col = ColumnFactory.CreateInstace(columnId, label, type, virt, lookup, hidden); + foreach (XPathNavigator choicenode in columnNode.Select("choices/choice")) + { + object value; + switch (type) + { + case FieldType.rating: + value = Int32.Parse(choicenode.Value); + break; + default: + value = choicenode.Value; + break; + } + ((IQColumn_int)col).AddChoice(value); + } + Dictionary colComposites = ((IQColumn_int)col).GetComposites(); + foreach (XPathNavigator compositenode in columnNode.Select("compositeFields/compositeField")) + { + colComposites.Add(compositenode.GetAttribute("key", String.Empty), Int32.Parse(compositenode.GetAttribute("id", String.Empty))); + } Columns.Add(col); } } diff --git a/Intuit.QuickBase.Core/FieldType.cs b/Intuit.QuickBase.Core/FieldType.cs index 5d3c176..f557ca4 100644 --- a/Intuit.QuickBase.Core/FieldType.cs +++ b/Intuit.QuickBase.Core/FieldType.cs @@ -43,11 +43,6 @@ public enum FieldType /// email, - /// - /// File Attachment - /// - file, - /// /// Float /// @@ -58,6 +53,11 @@ public enum FieldType /// currency, + /// + /// Percent + /// + percent, + /// /// Rating /// @@ -73,6 +73,11 @@ public enum FieldType /// text, + /// + /// DateTime + /// + timestamp, + /// /// Time Of Day /// @@ -83,13 +88,45 @@ public enum FieldType /// url, - // TODO: To be deleted. - timestamp, - recordid, + /// + /// UserID + /// userid, - percent, + + /// + /// Multi User Field + /// + multiuserid, + + /// + /// address + /// + address, + + /// + /// Record ID + /// + recordid, + + //TODO: not yet supported + /// + /// File Attachment + /// + file, + + /// + /// ICalendar entry + /// icalendarbutton, + + /// + /// VCard package + /// vcardbutton, + + /// + /// Project predecessor + /// predecessor } } \ No newline at end of file From 8e700e77602fd3a821bda2c36f5c9e46e50d393e Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Mon, 1 Dec 2014 09:54:26 -0700 Subject: [PATCH 08/49] Fix improperly implemented duration field --- Intuit.QuickBase.Client/QField.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Intuit.QuickBase.Client/QField.cs b/Intuit.QuickBase.Client/QField.cs index 0fb212a..28733d8 100644 --- a/Intuit.QuickBase.Client/QField.cs +++ b/Intuit.QuickBase.Client/QField.cs @@ -61,7 +61,8 @@ internal string QBValue case FieldType.date: return ConvertDateTimeToQBMilliseconds((DateTime)_value); case FieldType.timeofday: - return ConvertTimeSpanToQBMilliseconds((TimeSpan)_value); + case FieldType.duration: + return ConvertTimeSpanToMilliseconds((TimeSpan)_value); case FieldType.checkbox: return (bool)_value == true ? "1" : "0"; case FieldType.percent: @@ -81,10 +82,8 @@ internal string QBValue _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDateTime(value).Date; break; case FieldType.timeofday: - _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : ConvertQBMillisecondsToDateTime(value).TimeOfDay; - break; case FieldType.duration: - _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : TimeSpan.Parse(value); + _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : ConvertMillisecondsToTimeSpan(value); break; case FieldType.timestamp: _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDateTime(value); @@ -240,6 +239,12 @@ public override string ToString() return Value.ToString(); } + private static TimeSpan ConvertMillisecondsToTimeSpan(string milliseconds) + { + Int64 val = Int64.Parse(milliseconds); + return new TimeSpan(val * 10000); + } + private static DateTime ConvertQBMillisecondsToDateTime(string milliseconds) { return new DateTime(qbOffset.Ticks + (Int64.Parse(milliseconds) * TimeSpan.TicksPerMillisecond)); @@ -250,7 +255,7 @@ private static string ConvertDateTimeToQBMilliseconds(DateTime inDate) return ((inDate.Ticks - qbOffset.Ticks)/TimeSpan.TicksPerMillisecond).ToString(); } - private static string ConvertTimeSpanToQBMilliseconds(TimeSpan inTime) + private static string ConvertTimeSpanToMilliseconds(TimeSpan inTime) { return (inTime.Ticks / TimeSpan.TicksPerMillisecond).ToString(); } From 5ef21de7a701f1c327deb7d371f7390c7c55bb55 Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Wed, 8 Apr 2015 20:59:49 -0600 Subject: [PATCH 09/49] Fix datetime handling, fix column indexing for records not downloaded from the server, remove stubs for unit testing from Intuit that was not included in their source package, start to write my own unit tests. --- Intuit.QuickBase.Client/IQColumn.cs | 2 + Intuit.QuickBase.Client/IQRecord.cs | 3 +- Intuit.QuickBase.Client/QField.cs | 15 +-- Intuit.QuickBase.Client/QRecord.cs | 13 ++- Intuit.QuickBase.sln | 16 +-- Library/Rhino.Mocks.dll | Bin 292352 -> 0 bytes Library/nunit.framework.dll | Bin 131072 -> 0 bytes QBFunctionTest/Properties/AssemblyInfo.cs | 36 +++++++ QBFunctionTest/QBFunctionTest.csproj | 96 ++++++++++++++++++ QBFunctionTest/UnitTest1.cs | 14 +++ ...QBFunctionTest.csproj.FileListAbsolute.txt | 9 ++ 11 files changed, 179 insertions(+), 25 deletions(-) delete mode 100644 Library/Rhino.Mocks.dll delete mode 100644 Library/nunit.framework.dll create mode 100644 QBFunctionTest/Properties/AssemblyInfo.cs create mode 100644 QBFunctionTest/QBFunctionTest.csproj create mode 100644 QBFunctionTest/UnitTest1.cs create mode 100644 QBFunctionTest/obj/Debug/QBFunctionTest.csproj.FileListAbsolute.txt diff --git a/Intuit.QuickBase.Client/IQColumn.cs b/Intuit.QuickBase.Client/IQColumn.cs index d7ae906..bf8da9e 100644 --- a/Intuit.QuickBase.Client/IQColumn.cs +++ b/Intuit.QuickBase.Client/IQColumn.cs @@ -7,6 +7,8 @@ */ using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Security.AccessControl; using Intuit.QuickBase.Core; namespace Intuit.QuickBase.Client diff --git a/Intuit.QuickBase.Client/IQRecord.cs b/Intuit.QuickBase.Client/IQRecord.cs index ec56035..628ff16 100644 --- a/Intuit.QuickBase.Client/IQRecord.cs +++ b/Intuit.QuickBase.Client/IQRecord.cs @@ -27,6 +27,7 @@ public interface IQRecord internal interface IQRecord_int { void ForceUpdateState(int RecordId); - void ForceUpdateState(); + void ForceUpdateState(); + int GetColumnIndex(string colName); } } diff --git a/Intuit.QuickBase.Client/QField.cs b/Intuit.QuickBase.Client/QField.cs index 28733d8..0fb212a 100644 --- a/Intuit.QuickBase.Client/QField.cs +++ b/Intuit.QuickBase.Client/QField.cs @@ -61,8 +61,7 @@ internal string QBValue case FieldType.date: return ConvertDateTimeToQBMilliseconds((DateTime)_value); case FieldType.timeofday: - case FieldType.duration: - return ConvertTimeSpanToMilliseconds((TimeSpan)_value); + return ConvertTimeSpanToQBMilliseconds((TimeSpan)_value); case FieldType.checkbox: return (bool)_value == true ? "1" : "0"; case FieldType.percent: @@ -82,8 +81,10 @@ internal string QBValue _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDateTime(value).Date; break; case FieldType.timeofday: + _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : ConvertQBMillisecondsToDateTime(value).TimeOfDay; + break; case FieldType.duration: - _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : ConvertMillisecondsToTimeSpan(value); + _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : TimeSpan.Parse(value); break; case FieldType.timestamp: _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDateTime(value); @@ -239,12 +240,6 @@ public override string ToString() return Value.ToString(); } - private static TimeSpan ConvertMillisecondsToTimeSpan(string milliseconds) - { - Int64 val = Int64.Parse(milliseconds); - return new TimeSpan(val * 10000); - } - private static DateTime ConvertQBMillisecondsToDateTime(string milliseconds) { return new DateTime(qbOffset.Ticks + (Int64.Parse(milliseconds) * TimeSpan.TicksPerMillisecond)); @@ -255,7 +250,7 @@ private static string ConvertDateTimeToQBMilliseconds(DateTime inDate) return ((inDate.Ticks - qbOffset.Ticks)/TimeSpan.TicksPerMillisecond).ToString(); } - private static string ConvertTimeSpanToMilliseconds(TimeSpan inTime) + private static string ConvertTimeSpanToQBMilliseconds(TimeSpan inTime) { return (inTime.Ticks / TimeSpan.TicksPerMillisecond).ToString(); } diff --git a/Intuit.QuickBase.Client/QRecord.cs b/Intuit.QuickBase.Client/QRecord.cs index 57da626..bb18c48 100644 --- a/Intuit.QuickBase.Client/QRecord.cs +++ b/Intuit.QuickBase.Client/QRecord.cs @@ -104,8 +104,15 @@ public object this[string columnName] // Get column index var index = GetColumnIndex(columnName); - // Return field with column index - return _fields[index].Value; + // Get field location with column index + var fieldIndex = _fields.IndexOf(new QField(Columns[index].ColumnId)); + + if (fieldIndex > -1) + { + // Return field with column index + return _fields[fieldIndex].Value; + } + else throw new Exception("Can't get a nonexistant field (field not yet set"); } set { @@ -315,7 +322,7 @@ private void SetExistingField(int index, int fieldIndex, object value) } } - private int GetColumnIndex(string columnName) + public int GetColumnIndex(string columnName) { var index = Columns.IndexOf(new QColumn { diff --git a/Intuit.QuickBase.sln b/Intuit.QuickBase.sln index cce2908..444ff6d 100644 --- a/Intuit.QuickBase.sln +++ b/Intuit.QuickBase.sln @@ -11,9 +11,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intuit.QuickBase.Client", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intuit.QuickBase.Core", "Intuit.QuickBase.Core\Intuit.QuickBase.Core.csproj", "{72AE7ED2-1321-499E-8E0E-ECFD91B8C850}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intuit.QuickBase.UnitTests", "Intuit.QuickBase.UnitTests\Intuit.QuickBase.UnitTests.csproj", "{F5896BE7-8236-4A53-AACB-E6F33A436D04}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intuit.QuickBase.IntegrationTests", "Intuit.QuickBase.IntegrationTests\Intuit.QuickBase.IntegrationTests.csproj", "{D88A7B14-7A52-4A78-B51C-D33BA947F551}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QBFunctionTest", "QBFunctionTest\QBFunctionTest.csproj", "{0ECE8A75-198C-4DBA-83D8-E12CE882E6BC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -29,14 +27,10 @@ Global {72AE7ED2-1321-499E-8E0E-ECFD91B8C850}.Debug|Any CPU.Build.0 = Debug|Any CPU {72AE7ED2-1321-499E-8E0E-ECFD91B8C850}.Release|Any CPU.ActiveCfg = Release|Any CPU {72AE7ED2-1321-499E-8E0E-ECFD91B8C850}.Release|Any CPU.Build.0 = Release|Any CPU - {F5896BE7-8236-4A53-AACB-E6F33A436D04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F5896BE7-8236-4A53-AACB-E6F33A436D04}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F5896BE7-8236-4A53-AACB-E6F33A436D04}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F5896BE7-8236-4A53-AACB-E6F33A436D04}.Release|Any CPU.Build.0 = Release|Any CPU - {D88A7B14-7A52-4A78-B51C-D33BA947F551}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D88A7B14-7A52-4A78-B51C-D33BA947F551}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D88A7B14-7A52-4A78-B51C-D33BA947F551}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D88A7B14-7A52-4A78-B51C-D33BA947F551}.Release|Any CPU.Build.0 = Release|Any CPU + {0ECE8A75-198C-4DBA-83D8-E12CE882E6BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0ECE8A75-198C-4DBA-83D8-E12CE882E6BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0ECE8A75-198C-4DBA-83D8-E12CE882E6BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0ECE8A75-198C-4DBA-83D8-E12CE882E6BC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Library/Rhino.Mocks.dll b/Library/Rhino.Mocks.dll deleted file mode 100644 index 4b6904b6f85fa664619121048716ea1b4424a0dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 292352 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

~Jeb5Zrzbm5}ZMCI; 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¬FRo561NYpMkoo9Km9B! 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

jhJ2&)stU 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 diff --git a/QBFunctionTest/Properties/AssemblyInfo.cs b/QBFunctionTest/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c39ab15 --- /dev/null +++ b/QBFunctionTest/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("QBFunctionTest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("QBFunctionTest")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4ded4099-2ccc-46b5-8196-a3c531ab0a59")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/QBFunctionTest/QBFunctionTest.csproj b/QBFunctionTest/QBFunctionTest.csproj new file mode 100644 index 0000000..d717468 --- /dev/null +++ b/QBFunctionTest/QBFunctionTest.csproj @@ -0,0 +1,96 @@ + + + + Debug + AnyCPU + {0ECE8A75-198C-4DBA-83D8-E12CE882E6BC} + Library + Properties + QBFunctionTest + QBFunctionTest + v4.0 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + {f25380b0-b55a-4567-941e-b938723f6e07} + Intuit.QuickBase.Client + + + {72ae7ed2-1321-499e-8e0e-ecfd91b8c850} + Intuit.QuickBase.Core + + + + + + + False + + + False + + + False + + + False + + + + + + + + \ No newline at end of file diff --git a/QBFunctionTest/UnitTest1.cs b/QBFunctionTest/UnitTest1.cs new file mode 100644 index 0000000..3033668 --- /dev/null +++ b/QBFunctionTest/UnitTest1.cs @@ -0,0 +1,14 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace QBFunctionTest +{ + [TestClass] + public class UnitTest1 + { + [TestMethod] + public void TestMethod1() + { + } + } +} diff --git a/QBFunctionTest/obj/Debug/QBFunctionTest.csproj.FileListAbsolute.txt b/QBFunctionTest/obj/Debug/QBFunctionTest.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..d4105ca --- /dev/null +++ b/QBFunctionTest/obj/Debug/QBFunctionTest.csproj.FileListAbsolute.txt @@ -0,0 +1,9 @@ +C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\QBFunctionTest.dll +C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\QBFunctionTest.pdb +C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\Intuit.QuickBase.Client.dll +C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\Intuit.QuickBase.Core.dll +C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\Intuit.QuickBase.Client.pdb +C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\Intuit.QuickBase.Core.pdb +C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\obj\Debug\QBFunctionTest.csprojResolveAssemblyReference.cache +C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\obj\Debug\QBFunctionTest.dll +C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\obj\Debug\QBFunctionTest.pdb From 9d1b5f826b50dfa7fff8e396ceecad37a3b334e8 Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Fri, 10 Apr 2015 15:08:50 -0600 Subject: [PATCH 10/49] Fix handling of duration field --- Intuit.QuickBase.Client/QField.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Intuit.QuickBase.Client/QField.cs b/Intuit.QuickBase.Client/QField.cs index 0fb212a..96a77f7 100644 --- a/Intuit.QuickBase.Client/QField.cs +++ b/Intuit.QuickBase.Client/QField.cs @@ -62,6 +62,8 @@ internal string QBValue return ConvertDateTimeToQBMilliseconds((DateTime)_value); case FieldType.timeofday: return ConvertTimeSpanToQBMilliseconds((TimeSpan)_value); + case FieldType.duration: + return ((TimeSpan)_value).Milliseconds.ToString(); case FieldType.checkbox: return (bool)_value == true ? "1" : "0"; case FieldType.percent: @@ -84,7 +86,7 @@ internal string QBValue _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : ConvertQBMillisecondsToDateTime(value).TimeOfDay; break; case FieldType.duration: - _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : TimeSpan.Parse(value); + _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : TimeSpan.FromMilliseconds(Int64.Parse(value)); break; case FieldType.timestamp: _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDateTime(value); From 70fd3015876e9ecff0f21b662f4b4ab5f261d8d0 Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Fri, 18 Dec 2015 10:47:11 -0700 Subject: [PATCH 11/49] Fix DateTime handling so it properly round-trips from any local timezone. Also handle unset fields properly for records not yet sent to the server. --- Intuit.QuickBase.Client/QField.cs | 8 +++---- Intuit.QuickBase.Client/QRecord.cs | 21 ++++++++++++++----- ...QBFunctionTest.csproj.FileListAbsolute.txt | 9 -------- 3 files changed, 20 insertions(+), 18 deletions(-) delete mode 100644 QBFunctionTest/obj/Debug/QBFunctionTest.csproj.FileListAbsolute.txt diff --git a/Intuit.QuickBase.Client/QField.cs b/Intuit.QuickBase.Client/QField.cs index 96a77f7..a586585 100644 --- a/Intuit.QuickBase.Client/QField.cs +++ b/Intuit.QuickBase.Client/QField.cs @@ -15,7 +15,7 @@ namespace Intuit.QuickBase.Client { internal class QField { - private static readonly DateTime qbOffset = new DateTime(1970, 1, 1, 0, 0, 0, 0); + private static readonly DateTime qbTSOffset = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); // Instance fields private object _value; @@ -244,12 +244,12 @@ public override string ToString() private static DateTime ConvertQBMillisecondsToDateTime(string milliseconds) { - return new DateTime(qbOffset.Ticks + (Int64.Parse(milliseconds) * TimeSpan.TicksPerMillisecond)); + return qbTSOffset.AddMilliseconds(double.Parse(milliseconds)).ToLocalTime(); } - private static string ConvertDateTimeToQBMilliseconds(DateTime inDate) + private static string ConvertDateTimeToQBMilliseconds(DateTime inDT) { - return ((inDate.Ticks - qbOffset.Ticks)/TimeSpan.TicksPerMillisecond).ToString(); + return ((inDT.ToUniversalTime().Ticks - qbTSOffset.Ticks)/TimeSpan.TicksPerMillisecond).ToString(); } private static string ConvertTimeSpanToQBMilliseconds(TimeSpan inTime) diff --git a/Intuit.QuickBase.Client/QRecord.cs b/Intuit.QuickBase.Client/QRecord.cs index bb18c48..beb2c7d 100644 --- a/Intuit.QuickBase.Client/QRecord.cs +++ b/Intuit.QuickBase.Client/QRecord.cs @@ -77,8 +77,17 @@ public object this[int index] { get { + // Get field location with column index + var fieldIndex = _fields.IndexOf(new QField(Columns[index].ColumnId)); + + if (fieldIndex == -1) + { + //make null field + CreateNewField(index, null, false); + fieldIndex = _fields.IndexOf(new QField(Columns[index].ColumnId)); + } // Return field with column index - return _fields[index].Value; + return _fields[fieldIndex].Value; } set @@ -107,12 +116,14 @@ public object this[string columnName] // Get field location with column index var fieldIndex = _fields.IndexOf(new QField(Columns[index].ColumnId)); - if (fieldIndex > -1) + if (fieldIndex == -1) { - // Return field with column index - return _fields[fieldIndex].Value; + //make null field + CreateNewField(index, null, false); + fieldIndex = _fields.IndexOf(new QField(Columns[index].ColumnId)); } - else throw new Exception("Can't get a nonexistant field (field not yet set"); + // Return field with column index + return _fields[fieldIndex].Value; } set { diff --git a/QBFunctionTest/obj/Debug/QBFunctionTest.csproj.FileListAbsolute.txt b/QBFunctionTest/obj/Debug/QBFunctionTest.csproj.FileListAbsolute.txt deleted file mode 100644 index d4105ca..0000000 --- a/QBFunctionTest/obj/Debug/QBFunctionTest.csproj.FileListAbsolute.txt +++ /dev/null @@ -1,9 +0,0 @@ -C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\QBFunctionTest.dll -C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\QBFunctionTest.pdb -C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\Intuit.QuickBase.Client.dll -C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\Intuit.QuickBase.Core.dll -C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\Intuit.QuickBase.Client.pdb -C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\bin\Debug\Intuit.QuickBase.Core.pdb -C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\obj\Debug\QBFunctionTest.csprojResolveAssemblyReference.cache -C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\obj\Debug\QBFunctionTest.dll -C:\IPSUtilities\QuickBase-C-Sharp-SDK-master\QBFunctionTest\obj\Debug\QBFunctionTest.pdb From da0ee7934851f8b30007a5207b7fba0114d9b6cf Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Fri, 18 Dec 2015 13:58:27 -0700 Subject: [PATCH 12/49] Refix DateTime: it appears that with the functions we are using, the conversion must be asymetrical. More research needed as to why, but tested and working. --- .gitignore | 5 +++-- Intuit.QuickBase.Client/QField.cs | 9 ++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index b0daf6c..057fdb6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .svn -Intuit.QuickBase.Client/obj/Debug/Intuit.QuickBase.Client.csproj.FileListAbsolute.txt -Intuit.QuickBase.Core/obj/Debug/Intuit.QuickBase.Core.csproj.FileListAbsolute.txt +Intuit.QuickBase.Client/obj/ +Intuit.QuickBase.Core/obj/ +QBFunctionTest/obj/ diff --git a/Intuit.QuickBase.Client/QField.cs b/Intuit.QuickBase.Client/QField.cs index a586585..c40373e 100644 --- a/Intuit.QuickBase.Client/QField.cs +++ b/Intuit.QuickBase.Client/QField.cs @@ -249,7 +249,14 @@ private static DateTime ConvertQBMillisecondsToDateTime(string milliseconds) private static string ConvertDateTimeToQBMilliseconds(DateTime inDT) { - return ((inDT.ToUniversalTime().Ticks - qbTSOffset.Ticks)/TimeSpan.TicksPerMillisecond).ToString(); + //string msecs = ((inDT.ToUniversalTime().Ticks - qbTSOffset.Ticks) / TimeSpan.TicksPerMillisecond).ToString(); // this SHOULD work, why? + string msecs = ((inDT.Ticks - qbTSOffset.Ticks) / TimeSpan.TicksPerMillisecond).ToString(); + //DateTime check = ConvertQBMillisecondsToDateTime(msecs); + //if (!check.Equals(inDT)) + //{ + // Console.WriteLine("DateTime doesn't round trip?"); + //} + return msecs; } private static string ConvertTimeSpanToQBMilliseconds(TimeSpan inTime) From 4fa15be3392903e3902b1385795a22061435f67b Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Tue, 19 Jul 2016 11:54:36 -0600 Subject: [PATCH 13/49] Implement the beginnings of unit tests (table creation, round trip test of most value types), correct a few comments in the code, and using new unit tests, correct interpretation of some of the date/time types. --- .gitignore | 2 + Intuit.QuickBase.Client/QAddress.cs | 4 + Intuit.QuickBase.Client/QColumnCollection.cs | 1 + Intuit.QuickBase.Client/QField.cs | 26 ++-- Intuit.QuickBase.Client/QTable.cs | 2 +- .../Properties/Settings.Designer.cs | 71 ++++++++++ QBFunctionTest/Properties/Settings.settings | 21 +++ QBFunctionTest/QBFunctionTest.csproj | 12 ++ QBFunctionTest/UnitTest1.cs | 125 +++++++++++++++++- QBFunctionTest/app.config.example | 27 ++++ README.md | 5 +- 11 files changed, 280 insertions(+), 16 deletions(-) create mode 100644 QBFunctionTest/Properties/Settings.Designer.cs create mode 100644 QBFunctionTest/Properties/Settings.settings create mode 100644 QBFunctionTest/app.config.example diff --git a/.gitignore b/.gitignore index 057fdb6..2e57622 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ Intuit.QuickBase.Client/obj/ Intuit.QuickBase.Core/obj/ QBFunctionTest/obj/ +QBFunctionTest/app.config +TestResults/ diff --git a/Intuit.QuickBase.Client/QAddress.cs b/Intuit.QuickBase.Client/QAddress.cs index 84cc8ac..a09b40e 100644 --- a/Intuit.QuickBase.Client/QAddress.cs +++ b/Intuit.QuickBase.Client/QAddress.cs @@ -18,5 +18,9 @@ public QAddress(string line1, string line2, string city, string province, string PostalCode = postCode; Country = country; } + + public QAddress() + { + } } } diff --git a/Intuit.QuickBase.Client/QColumnCollection.cs b/Intuit.QuickBase.Client/QColumnCollection.cs index 95cd626..40c6a88 100644 --- a/Intuit.QuickBase.Client/QColumnCollection.cs +++ b/Intuit.QuickBase.Client/QColumnCollection.cs @@ -28,6 +28,7 @@ public QColumnCollection(IQApplication application, IQTable table) { var addCol = new AddField(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, Table.TableId, column.ColumnName, column.ColumnType); var xml = addCol.Post().CreateNavigator(); + //todo: need to put in error checking here var columnId = int.Parse(xml.SelectSingleNode("/qdbapi/fid").Value); column.ColumnId = columnId; } diff --git a/Intuit.QuickBase.Client/QField.cs b/Intuit.QuickBase.Client/QField.cs index c40373e..010fde2 100644 --- a/Intuit.QuickBase.Client/QField.cs +++ b/Intuit.QuickBase.Client/QField.cs @@ -61,9 +61,8 @@ internal string QBValue case FieldType.date: return ConvertDateTimeToQBMilliseconds((DateTime)_value); case FieldType.timeofday: - return ConvertTimeSpanToQBMilliseconds((TimeSpan)_value); case FieldType.duration: - return ((TimeSpan)_value).Milliseconds.ToString(); + return ((TimeSpan) _value).ToString(); case FieldType.checkbox: return (bool)_value == true ? "1" : "0"; case FieldType.percent: @@ -80,13 +79,13 @@ internal string QBValue // do nothing: child columns will fill this out break; case FieldType.date: - _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDateTime(value).Date; + _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDate(value); break; case FieldType.timeofday: - _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : ConvertQBMillisecondsToDateTime(value).TimeOfDay; + _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : ConvertQBMillisecondsToTime(value); break; case FieldType.duration: - _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : TimeSpan.FromMilliseconds(Int64.Parse(value)); + _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : TimeSpan.Parse(value); break; case FieldType.timestamp: _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDateTime(value); @@ -246,17 +245,18 @@ private static DateTime ConvertQBMillisecondsToDateTime(string milliseconds) { return qbTSOffset.AddMilliseconds(double.Parse(milliseconds)).ToLocalTime(); } + private static DateTime ConvertQBMillisecondsToDate(string milliseconds) + { + return qbTSOffset.AddMilliseconds(double.Parse(milliseconds)).Date; + } + private static TimeSpan ConvertQBMillisecondsToTime(string milliseconds) + { + return qbTSOffset.AddMilliseconds(double.Parse(milliseconds)).TimeOfDay; + } private static string ConvertDateTimeToQBMilliseconds(DateTime inDT) { - //string msecs = ((inDT.ToUniversalTime().Ticks - qbTSOffset.Ticks) / TimeSpan.TicksPerMillisecond).ToString(); // this SHOULD work, why? - string msecs = ((inDT.Ticks - qbTSOffset.Ticks) / TimeSpan.TicksPerMillisecond).ToString(); - //DateTime check = ConvertQBMillisecondsToDateTime(msecs); - //if (!check.Equals(inDT)) - //{ - // Console.WriteLine("DateTime doesn't round trip?"); - //} - return msecs; + return ((inDT.Ticks - qbTSOffset.Ticks) / TimeSpan.TicksPerMillisecond).ToString(); } private static string ConvertTimeSpanToQBMilliseconds(TimeSpan inTime) diff --git a/Intuit.QuickBase.Client/QTable.cs b/Intuit.QuickBase.Client/QTable.cs index 457e8e8..adb3782 100644 --- a/Intuit.QuickBase.Client/QTable.cs +++ b/Intuit.QuickBase.Client/QTable.cs @@ -173,7 +173,7 @@ public void Query() .SetFmt(true) .Build(); var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); //Must be done each time, incase the schema changes do to another user + LoadColumns(xml); //Must be done each time, incase the schema changes due to another user, or from a previous query that has a difering subset of columns LoadRecords(xml); } diff --git a/QBFunctionTest/Properties/Settings.Designer.cs b/QBFunctionTest/Properties/Settings.Designer.cs new file mode 100644 index 0000000..dfbbebb --- /dev/null +++ b/QBFunctionTest/Properties/Settings.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace QBFunctionTest.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("***REMOVED***")] + public string qbUser { + get { + return ((string)(this["qbUser"])); + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("***REMOVED***")] + public string qbPass { + get { + return ((string)(this["qbPass"])); + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("***REMOVED***")] + public string qbAppToken { + get { + return ((string)(this["qbAppToken"])); + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("***REMOVED***")] + public string qbSiteURL { + get { + return ((string)(this["qbSiteURL"])); + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("***REMOVED***")] + public string qbAppDBID { + get { + return ((string)(this["qbAppDBID"])); + } + } + } +} diff --git a/QBFunctionTest/Properties/Settings.settings b/QBFunctionTest/Properties/Settings.settings new file mode 100644 index 0000000..420ac0c --- /dev/null +++ b/QBFunctionTest/Properties/Settings.settings @@ -0,0 +1,21 @@ + + + + + + ***REMOVED*** + + + ***REMOVED*** + + + ***REMOVED*** + + + ***REMOVED*** + + + ***REMOVED*** + + + \ No newline at end of file diff --git a/QBFunctionTest/QBFunctionTest.csproj b/QBFunctionTest/QBFunctionTest.csproj index d717468..d9f023a 100644 --- a/QBFunctionTest/QBFunctionTest.csproj +++ b/QBFunctionTest/QBFunctionTest.csproj @@ -53,6 +53,11 @@ + + True + True + Settings.settings + @@ -66,6 +71,13 @@ Intuit.QuickBase.Core + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + diff --git a/QBFunctionTest/UnitTest1.cs b/QBFunctionTest/UnitTest1.cs index 3033668..9695fe9 100644 --- a/QBFunctionTest/UnitTest1.cs +++ b/QBFunctionTest/UnitTest1.cs @@ -1,14 +1,137 @@ using System; +using System.Collections.Generic; +using System.Linq; +using Intuit.QuickBase.Client; +using Intuit.QuickBase.Core; using Microsoft.VisualStudio.TestTools.UnitTesting; +using QBFunctionTest.Properties; namespace QBFunctionTest { [TestClass] public class UnitTest1 { + private IQApplication qbApp; + + public void InitConnection() + { + var client = QuickBase.Login(Settings.Default.qbUser, Settings.Default.qbPass, Settings.Default.qbSiteURL); + qbApp = client.Connect(Settings.Default.qbAppDBID, Settings.Default.qbAppToken); + + } + + class TestRecord + { + public string textVal; + public decimal floatVal; + public bool checkboxVal; + public DateTime dateVal; + public DateTime timeStampVal; + public TimeSpan timeOfDayVal; + public QAddress addressVal; + public decimal currencyVal; + public TimeSpan durationVal; + public string emailVal; + public string phoneVal; + public decimal percentVal; + + public TestRecord() + { + addressVal = new QAddress(); + } + public void SetupTestValues() + { + textVal = "Test string #1"; + floatVal = (decimal)3452.54; + checkboxVal = true; + dateVal = new DateTime(2015, 04, 15); + timeStampVal = new DateTime(1970, 02, 28, 23, 55, 00, DateTimeKind.Local); + timeOfDayVal = new DateTime(2000, 1, 1, 12, 34, 56).TimeOfDay; + durationVal = new TimeSpan(3, 4, 5, 6); + addressVal.Line1 = "1313 Mockingbird Ln"; + addressVal.City = "Culver City"; + addressVal.Province = "CA"; + addressVal.PostalCode = "90120"; + addressVal.Country = "USA"; + } + } + [TestMethod] - public void TestMethod1() + public void BasicCreationAndRoundTripTest() { + InitConnection(); + List appsLst = qbApp.GrantedDBs(); + foreach (var app in appsLst) + { + foreach (var tab in app.GrantedTables) + { + if (tab.Name == "APITestApp: APITestTable") + { + IQTable tbl = qbApp.GetTable(tab.Dbid); + qbApp.DeleteTable(tbl); + break; + } + } + } + + IQTable testTable = qbApp.NewTable("APITestTable", "dummyRec"); + testTable.Columns.Add(new QColumn("TextTest", FieldType.text)); + testTable.Columns.Add(new QColumn("FloatTest", FieldType.@float)); + testTable.Columns.Add(new QColumn("CheckboxTest", FieldType.checkbox)); + testTable.Columns.Add(new QColumn("DateTest", FieldType.date)); + testTable.Columns.Add(new QColumn("TimeStampTest", FieldType.timestamp)); + testTable.Columns.Add(new QColumn("TimeOfDayTest", FieldType.timeofday)); + testTable.Columns.Add(new QColumn("DurationTest", FieldType.duration)); + //testTable.Columns.Add(new QColumn("AddressTest", FieldType.address)); + //testTable.Columns.Add(new QColumn("CurrencyTest", FieldType.currency)); + //testTable.Columns.Add(new QColumn("EmailTest", FieldType.email)); + //testTable.Columns.Add(new QColumn("PhoneTest", FieldType.phone)); + //testTable.Columns.Add(new QColumn("PercentTest", FieldType.percent)); + + TestRecord exemplar = new TestRecord(); + exemplar.SetupTestValues(); + + IQRecord inRec = testTable.NewRecord(); + inRec["TextTest"] = exemplar.textVal; + inRec["FloatTest"] = exemplar.floatVal; + inRec["CheckboxTest"] = exemplar.checkboxVal; + inRec["DateTest"] = exemplar.dateVal; + inRec["TimeStampTest"] = exemplar.timeStampVal; + inRec["TimeOfDayTest"] = exemplar.timeOfDayVal; + //inRec["DurationTest"] = exemplar.durationVal; + //inRec["AddressTest"] = exemplar.addressVal; + + Assert.AreEqual(exemplar.textVal, inRec["TextTest"], "Strings setter fails"); + Assert.AreEqual(exemplar.floatVal, inRec["FloatTest"], "Floats setter fails"); + Assert.AreEqual(exemplar.checkboxVal, inRec["CheckboxTest"], "Checkboxes setter fails"); + Assert.AreEqual(exemplar.dateVal, inRec["DateTest"], "Dates setter fails"); + Assert.AreEqual(exemplar.timeStampVal, inRec["TimeStampTest"], "TimeStamps setter fails"); + Assert.AreEqual(exemplar.timeOfDayVal, inRec["TimeOfDayTest"], "TimeOfDays setter fails"); + //Assert.AreEqual(exemplar.durationVal, inRec["DurationTest"], "Durations setter fails"); + + testTable.Records.Add(inRec); + testTable.AcceptChanges(); + + Assert.AreEqual(exemplar.textVal, inRec["TextTest"], "Strings wrong post upload"); + Assert.AreEqual(exemplar.floatVal, inRec["FloatTest"], "Floats wrong post upload"); + Assert.AreEqual(exemplar.checkboxVal, inRec["CheckboxTest"], "Checkboxes wrong post upload"); + Assert.AreEqual(exemplar.dateVal, inRec["DateTest"], "Dates wrong post upload"); + Assert.AreEqual(exemplar.timeStampVal, inRec["TimeStampTest"], "TimeStamps wrong post upload"); + Assert.AreEqual(exemplar.timeOfDayVal, inRec["TimeOfDayTest"], "TimeOfDays wrong post upload"); + //Assert.AreEqual(exemplar.durationVal, inRec["DurationTest"], "Durations wrong post upload"); + + testTable.Records.Clear(); + testTable.Query(); + + IQRecord outRec = testTable.Records[0]; + Assert.AreEqual(exemplar.textVal, outRec["TextTest"], "Strings don't roundtrip"); + Assert.AreEqual(exemplar.floatVal, outRec["FloatTest"], "Floats don't roundtrip"); + Assert.AreEqual(exemplar.checkboxVal, outRec["CheckboxTest"], "Checkboxes don't roundtrip"); + Assert.AreEqual(exemplar.dateVal, outRec["DateTest"], "Dates don't roundtrip"); + Assert.AreEqual(exemplar.timeStampVal, outRec["TimeStampTest"], "TimeStamps don't roundtrip"); + Assert.AreEqual(exemplar.timeOfDayVal, outRec["TimeOfDayTest"], "TimeOfDays don't roundtrip"); + //Assert.AreEqual(exemplar.durationVal, outRec["DurationTest"], "Durations don't roundtrip"); + } } } diff --git a/QBFunctionTest/app.config.example b/QBFunctionTest/app.config.example new file mode 100644 index 0000000..2d1adba --- /dev/null +++ b/QBFunctionTest/app.config.example @@ -0,0 +1,27 @@ + + + + +

+ + + + + + user@example.com + + + VeryStrongPassword1234!@#$ + + + apptokenfromqbgoeshere + + + example.quickbase.com + + + appdatabaseidfromqbgoeshere + + + + \ No newline at end of file diff --git a/README.md b/README.md index 51797f8..9cae0fc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ QuickBase-C--SDK ================ -C# wrapper for Intuit QuickBase HTTP APIs \ No newline at end of file +C# wrapper for Intuit QuickBase HTTP APIs + +In order to compile and run the unit tests, you will need to copy QBFunctionTest/app.config.example to +QBFunctionTest/app.config and put values for your site into it. From d997a59dbfcdb20b8a486ba0f7a9c5c145f35bd5 Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Wed, 17 Aug 2016 21:00:22 -0600 Subject: [PATCH 14/49] Start getting file uploads to work, make sure testable values round trip properly. --- Intuit.QuickBase.Client/IQRecord.cs | 1 + Intuit.QuickBase.Client/QField.cs | 13 +++++---- Intuit.QuickBase.Client/QRecord.cs | 15 +++++++++++ QBFunctionTest/UnitTest1.cs | 41 +++++++++++++++++++++-------- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/Intuit.QuickBase.Client/IQRecord.cs b/Intuit.QuickBase.Client/IQRecord.cs index 628ff16..3809c3c 100644 --- a/Intuit.QuickBase.Client/IQRecord.cs +++ b/Intuit.QuickBase.Client/IQRecord.cs @@ -15,6 +15,7 @@ public interface IQRecord object this[int index] { get; set; } object this[string columnName] { get; set; } void AcceptChanges(); + void UploadFile(string columnName, string filePath); void DownloadFile(string columnName, string path, int versionId); void ChangeOwnerTo(string newOwner); string GetAsCSV(string clist); diff --git a/Intuit.QuickBase.Client/QField.cs b/Intuit.QuickBase.Client/QField.cs index 010fde2..8a95a88 100644 --- a/Intuit.QuickBase.Client/QField.cs +++ b/Intuit.QuickBase.Client/QField.cs @@ -62,11 +62,9 @@ internal string QBValue return ConvertDateTimeToQBMilliseconds((DateTime)_value); case FieldType.timeofday: case FieldType.duration: - return ((TimeSpan) _value).ToString(); + return ((TimeSpan)_value).ToString(); case FieldType.checkbox: return (bool)_value == true ? "1" : "0"; - case FieldType.percent: - return Math.Round((float) _value * 100.0, 6).ToString(); //Get around roundtrip bug in Quickbase default: return _value.ToString(); } @@ -82,10 +80,8 @@ internal string QBValue _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDate(value); break; case FieldType.timeofday: - _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : ConvertQBMillisecondsToTime(value); - break; case FieldType.duration: - _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : TimeSpan.Parse(value); + _value = String.IsNullOrEmpty(value) ? new TimeSpan?() : ConvertQBMillisecondsToTime(value); break; case FieldType.timestamp: _value = String.IsNullOrEmpty(value) ? new DateTime?() : ConvertQBMillisecondsToDateTime(value); @@ -93,10 +89,12 @@ internal string QBValue case FieldType.checkbox: _value = String.IsNullOrEmpty(value) ? new bool?() : (value == "1" || value == "true"); break; - case FieldType.percent: case FieldType.rating: _value = String.IsNullOrEmpty(value) ? new float?() : float.Parse(value); break; + case FieldType.percent: + _value = String.IsNullOrEmpty(value) ? new decimal?() : decimal.Parse(value) * 100; //get around roundtrip bug + break; case FieldType.@float: case FieldType.currency: _value = String.IsNullOrEmpty(value) ? new decimal?() : decimal.Parse(value); @@ -183,6 +181,7 @@ internal object Value break; case FieldType.@float: case FieldType.currency: + case FieldType.percent: decimal? val = value as decimal?; Int32? val2 = value as Int32?; if (val == null && val2 == null) diff --git a/Intuit.QuickBase.Client/QRecord.cs b/Intuit.QuickBase.Client/QRecord.cs index beb2c7d..f755a55 100644 --- a/Intuit.QuickBase.Client/QRecord.cs +++ b/Intuit.QuickBase.Client/QRecord.cs @@ -254,6 +254,20 @@ private void FillRecord(XPathNavigator recordNode) RecordState = RecordState.Unchanged; } + public void UploadFile(string columnName, string filePath) + { + // create new field with columnName + var index = GetColumnIndex(columnName); + CreateNewField(index, columnName, false); + + // change type to file + Columns[index].ColumnType = FieldType.file; + + // Get field location with column index + var fieldIndex = _fields.IndexOf(new QField(Columns[index].ColumnId)); + SetExistingField(index, fieldIndex, filePath); + } + public void DownloadFile(string columnName, string path, int versionId) { var index = GetColumnIndex(columnName); @@ -296,6 +310,7 @@ public override string ToString() return RecordId.ToString(); } + //value 'QBInternal' is passed into the QField, and specifies if the column exists inside QB's internal dataformat, or is .Net datatype private void CreateNewField(int index, object value, bool QBInternal) { if (Columns[index].ColumnType == FieldType.file && !IsOnServer) diff --git a/QBFunctionTest/UnitTest1.cs b/QBFunctionTest/UnitTest1.cs index 9695fe9..c2ed039 100644 --- a/QBFunctionTest/UnitTest1.cs +++ b/QBFunctionTest/UnitTest1.cs @@ -42,17 +42,21 @@ public TestRecord() public void SetupTestValues() { textVal = "Test string #1"; - floatVal = (decimal)3452.54; + floatVal = 3452.54m; checkboxVal = true; dateVal = new DateTime(2015, 04, 15); timeStampVal = new DateTime(1970, 02, 28, 23, 55, 00, DateTimeKind.Local); timeOfDayVal = new DateTime(2000, 1, 1, 12, 34, 56).TimeOfDay; - durationVal = new TimeSpan(3, 4, 5, 6); + durationVal = new TimeSpan(0, 4, 5, 6); addressVal.Line1 = "1313 Mockingbird Ln"; addressVal.City = "Culver City"; addressVal.Province = "CA"; addressVal.PostalCode = "90120"; addressVal.Country = "USA"; + currencyVal = 50.50m; + emailVal = "test@example.com"; + phoneVal = "(303) 555-1212"; + percentVal = 95.5m; } } @@ -83,10 +87,10 @@ public void BasicCreationAndRoundTripTest() testTable.Columns.Add(new QColumn("TimeOfDayTest", FieldType.timeofday)); testTable.Columns.Add(new QColumn("DurationTest", FieldType.duration)); //testTable.Columns.Add(new QColumn("AddressTest", FieldType.address)); - //testTable.Columns.Add(new QColumn("CurrencyTest", FieldType.currency)); - //testTable.Columns.Add(new QColumn("EmailTest", FieldType.email)); - //testTable.Columns.Add(new QColumn("PhoneTest", FieldType.phone)); - //testTable.Columns.Add(new QColumn("PercentTest", FieldType.percent)); + testTable.Columns.Add(new QColumn("CurrencyTest", FieldType.currency)); + testTable.Columns.Add(new QColumn("PercentTest", FieldType.percent)); + testTable.Columns.Add(new QColumn("EmailTest", FieldType.email)); + testTable.Columns.Add(new QColumn("PhoneTest", FieldType.phone)); TestRecord exemplar = new TestRecord(); exemplar.SetupTestValues(); @@ -98,8 +102,12 @@ public void BasicCreationAndRoundTripTest() inRec["DateTest"] = exemplar.dateVal; inRec["TimeStampTest"] = exemplar.timeStampVal; inRec["TimeOfDayTest"] = exemplar.timeOfDayVal; - //inRec["DurationTest"] = exemplar.durationVal; + inRec["DurationTest"] = exemplar.durationVal; //inRec["AddressTest"] = exemplar.addressVal; + inRec["CurrencyTest"] = exemplar.currencyVal; + inRec["PercentTest"] = exemplar.percentVal; + inRec["EmailTest"] = exemplar.emailVal; + inRec["PhoneTest"] = exemplar.phoneVal; Assert.AreEqual(exemplar.textVal, inRec["TextTest"], "Strings setter fails"); Assert.AreEqual(exemplar.floatVal, inRec["FloatTest"], "Floats setter fails"); @@ -107,7 +115,11 @@ public void BasicCreationAndRoundTripTest() Assert.AreEqual(exemplar.dateVal, inRec["DateTest"], "Dates setter fails"); Assert.AreEqual(exemplar.timeStampVal, inRec["TimeStampTest"], "TimeStamps setter fails"); Assert.AreEqual(exemplar.timeOfDayVal, inRec["TimeOfDayTest"], "TimeOfDays setter fails"); - //Assert.AreEqual(exemplar.durationVal, inRec["DurationTest"], "Durations setter fails"); + Assert.AreEqual(exemplar.durationVal, inRec["DurationTest"], "Durations setter fails"); + Assert.AreEqual(exemplar.currencyVal, inRec["CurrencyTest"], "Currency setter fails"); + Assert.AreEqual(exemplar.percentVal, inRec["PercentTest"], "Percent setter fails"); + Assert.AreEqual(exemplar.emailVal, inRec["EmailTest"], "Email setter fails"); + Assert.AreEqual(exemplar.phoneVal, inRec["PhoneTest"], "Phone setter fails"); testTable.Records.Add(inRec); testTable.AcceptChanges(); @@ -118,7 +130,11 @@ public void BasicCreationAndRoundTripTest() Assert.AreEqual(exemplar.dateVal, inRec["DateTest"], "Dates wrong post upload"); Assert.AreEqual(exemplar.timeStampVal, inRec["TimeStampTest"], "TimeStamps wrong post upload"); Assert.AreEqual(exemplar.timeOfDayVal, inRec["TimeOfDayTest"], "TimeOfDays wrong post upload"); - //Assert.AreEqual(exemplar.durationVal, inRec["DurationTest"], "Durations wrong post upload"); + Assert.AreEqual(exemplar.durationVal, inRec["DurationTest"], "Durations wrong post upload"); + Assert.AreEqual(exemplar.currencyVal, inRec["CurrencyTest"], "Currency wrong post upload"); + Assert.AreEqual(exemplar.percentVal, inRec["PercentTest"], "Percent wrong post upload"); + Assert.AreEqual(exemplar.emailVal, inRec["EmailTest"], "Email wrong post upload"); + Assert.AreEqual(exemplar.phoneVal, inRec["PhoneTest"], "Phone wrong post upload"); testTable.Records.Clear(); testTable.Query(); @@ -130,8 +146,11 @@ public void BasicCreationAndRoundTripTest() Assert.AreEqual(exemplar.dateVal, outRec["DateTest"], "Dates don't roundtrip"); Assert.AreEqual(exemplar.timeStampVal, outRec["TimeStampTest"], "TimeStamps don't roundtrip"); Assert.AreEqual(exemplar.timeOfDayVal, outRec["TimeOfDayTest"], "TimeOfDays don't roundtrip"); - //Assert.AreEqual(exemplar.durationVal, outRec["DurationTest"], "Durations don't roundtrip"); - + Assert.AreEqual(exemplar.durationVal, outRec["DurationTest"], "Durations don't roundtrip"); + Assert.AreEqual(exemplar.currencyVal, outRec["CurrencyTest"], "Currencies don't roundtrip"); + Assert.AreEqual(exemplar.percentVal, outRec["PercentTest"], "Percents don't roundtrip"); + Assert.AreEqual(exemplar.emailVal, outRec["EmailTest"], "Emails don't roundtrip"); + Assert.AreEqual(exemplar.phoneVal, outRec["PhoneTest"], "Phones don't roundtrip"); } } } From 5dcac93337d51a5e8fda0309c4ba3bbaf0a460a5 Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Mon, 29 Aug 2016 23:25:34 -0600 Subject: [PATCH 15/49] Fix updating a field to actually check before marking a record dirty, properly XMLquote username and passwords --- Intuit.QuickBase.Client/QRecord.cs | 17 ++++-- .../Payload/AuthenticatePayload.cs | 10 ++++ QBFunctionTest/UnitTest1.cs | 53 ++++++++++++++++++- 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/Intuit.QuickBase.Client/QRecord.cs b/Intuit.QuickBase.Client/QRecord.cs index f755a55..7b6e30f 100644 --- a/Intuit.QuickBase.Client/QRecord.cs +++ b/Intuit.QuickBase.Client/QRecord.cs @@ -336,16 +336,23 @@ private void SetExistingField(int index, int fieldIndex, object value) string fileName = (string) value; _fields[fieldIndex].Value = Path.GetFileName(fileName); _fields[fieldIndex].FullName = fileName; + if (RecordState != RecordState.New) + { + RecordState = RecordState.Modified; + } } else { - _fields[fieldIndex].Value = value; + if (!_fields[fieldIndex].Value.Equals(value)) + { + _fields[fieldIndex].Value = value; + if (RecordState != RecordState.New) + { + RecordState = RecordState.Modified; + } + } } - if (RecordState != RecordState.New) - { - RecordState = RecordState.Modified; - } } public int GetColumnIndex(string columnName) diff --git a/Intuit.QuickBase.Core/Payload/AuthenticatePayload.cs b/Intuit.QuickBase.Core/Payload/AuthenticatePayload.cs index f3b10a1..dc33eab 100644 --- a/Intuit.QuickBase.Core/Payload/AuthenticatePayload.cs +++ b/Intuit.QuickBase.Core/Payload/AuthenticatePayload.cs @@ -7,6 +7,8 @@ */ using System; using System.Text; +using System.Xml; +using System.Xml.Linq; namespace Intuit.QuickBase.Core.Payload { @@ -62,11 +64,19 @@ private int Hours internal override string GetXmlPayload() { +#if FALSE var sb = new StringBuilder(); sb.Append(String.Format("{0}{1}", Username, Password)); sb.Append(Hours > 0 ? String.Format("{0}", Hours) : String.Empty); return sb.ToString(); +#else + var sb = new StringBuilder(); + sb.Append(new XElement("username", Username)); + sb.Append(new XElement("password", Password)); + if (Hours > 0) sb.Append(new XElement("hours", Hours)); + return sb.ToString(); +#endif } } } diff --git a/QBFunctionTest/UnitTest1.cs b/QBFunctionTest/UnitTest1.cs index c2ed039..807057e 100644 --- a/QBFunctionTest/UnitTest1.cs +++ b/QBFunctionTest/UnitTest1.cs @@ -58,6 +58,27 @@ public void SetupTestValues() phoneVal = "(303) 555-1212"; percentVal = 95.5m; } + + public void Setup2ndValues() + { + textVal = "Test string #2 & an ampersand"; + floatVal = 1234.56m; + checkboxVal = false; + dateVal = new DateTime(2010, 01, 12); + timeStampVal = new DateTime(1971, 03, 24, 23, 55, 00, DateTimeKind.Local); + timeOfDayVal = new DateTime(2002, 2, 2, 23, 45, 56).TimeOfDay; + durationVal = new TimeSpan(0, 1, 2, 3); + addressVal.Line1 = "1313 Mockingbird Ln"; + addressVal.City = "Culver City"; + addressVal.Province = "CA"; + addressVal.PostalCode = "90120"; + addressVal.Country = "USA"; + currencyVal = 25.25m; + emailVal = "test2@example.com"; + phoneVal = "(719) 555-1212"; + percentVal = 95.5m; + } + } [TestMethod] @@ -86,7 +107,6 @@ public void BasicCreationAndRoundTripTest() testTable.Columns.Add(new QColumn("TimeStampTest", FieldType.timestamp)); testTable.Columns.Add(new QColumn("TimeOfDayTest", FieldType.timeofday)); testTable.Columns.Add(new QColumn("DurationTest", FieldType.duration)); - //testTable.Columns.Add(new QColumn("AddressTest", FieldType.address)); testTable.Columns.Add(new QColumn("CurrencyTest", FieldType.currency)); testTable.Columns.Add(new QColumn("PercentTest", FieldType.percent)); testTable.Columns.Add(new QColumn("EmailTest", FieldType.email)); @@ -103,7 +123,6 @@ public void BasicCreationAndRoundTripTest() inRec["TimeStampTest"] = exemplar.timeStampVal; inRec["TimeOfDayTest"] = exemplar.timeOfDayVal; inRec["DurationTest"] = exemplar.durationVal; - //inRec["AddressTest"] = exemplar.addressVal; inRec["CurrencyTest"] = exemplar.currencyVal; inRec["PercentTest"] = exemplar.percentVal; inRec["EmailTest"] = exemplar.emailVal; @@ -151,6 +170,36 @@ public void BasicCreationAndRoundTripTest() Assert.AreEqual(exemplar.percentVal, outRec["PercentTest"], "Percents don't roundtrip"); Assert.AreEqual(exemplar.emailVal, outRec["EmailTest"], "Emails don't roundtrip"); Assert.AreEqual(exemplar.phoneVal, outRec["PhoneTest"], "Phones don't roundtrip"); + + exemplar.Setup2ndValues(); + outRec["TextTest"] = exemplar.textVal; + outRec["FloatTest"] = exemplar.floatVal; + outRec["CheckboxTest"] = exemplar.checkboxVal; + outRec["DateTest"] = exemplar.dateVal; + outRec["TimeStampTest"] = exemplar.timeStampVal; + outRec["TimeOfDayTest"] = exemplar.timeOfDayVal; + outRec["DurationTest"] = exemplar.durationVal; + outRec["CurrencyTest"] = exemplar.currencyVal; + outRec["PercentTest"] = exemplar.percentVal; + outRec["EmailTest"] = exemplar.emailVal; + outRec["PhoneTest"] = exemplar.phoneVal; + + testTable.AcceptChanges(); + testTable.Query(); + + IQRecord outRec2 = testTable.Records[0]; + Assert.AreEqual(exemplar.textVal, outRec2["TextTest"], "Strings don't update"); + Assert.AreEqual(exemplar.floatVal, outRec2["FloatTest"], "Floats don't update"); + Assert.AreEqual(exemplar.checkboxVal, outRec2["CheckboxTest"], "Checkboxes don't update"); + Assert.AreEqual(exemplar.dateVal, outRec2["DateTest"], "Dates don't update"); + Assert.AreEqual(exemplar.timeStampVal, outRec2["TimeStampTest"], "TimeStamps don't update"); + Assert.AreEqual(exemplar.timeOfDayVal, outRec2["TimeOfDayTest"], "TimeOfDays don't update"); + Assert.AreEqual(exemplar.durationVal, outRec2["DurationTest"], "Durations don't update"); + Assert.AreEqual(exemplar.currencyVal, outRec2["CurrencyTest"], "Currencies don't update"); + Assert.AreEqual(exemplar.percentVal, outRec2["PercentTest"], "Percents don't update"); + Assert.AreEqual(exemplar.emailVal, outRec2["EmailTest"], "Emails don't update"); + Assert.AreEqual(exemplar.phoneVal, outRec2["PhoneTest"], "Phones don't update"); + } } } From 246c59e6a616475a1375affd65885cebf2884ecc Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Tue, 30 Aug 2016 09:01:38 -0600 Subject: [PATCH 16/49] Remove dead code changed by last patch --- Intuit.QuickBase.Core/Payload/AuthenticatePayload.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Intuit.QuickBase.Core/Payload/AuthenticatePayload.cs b/Intuit.QuickBase.Core/Payload/AuthenticatePayload.cs index dc33eab..d33b4f1 100644 --- a/Intuit.QuickBase.Core/Payload/AuthenticatePayload.cs +++ b/Intuit.QuickBase.Core/Payload/AuthenticatePayload.cs @@ -64,19 +64,11 @@ private int Hours internal override string GetXmlPayload() { -#if FALSE - var sb = new StringBuilder(); - sb.Append(String.Format("{0}{1}", - Username, Password)); - sb.Append(Hours > 0 ? String.Format("{0}", Hours) : String.Empty); - return sb.ToString(); -#else var sb = new StringBuilder(); sb.Append(new XElement("username", Username)); sb.Append(new XElement("password", Password)); if (Hours > 0) sb.Append(new XElement("hours", Hours)); return sb.ToString(); -#endif } } } From 0e954bdb921a2aa413e44a737abca8acdb7e90dc Mon Sep 17 00:00:00 2001 From: Jareth Hein Date: Wed, 5 Oct 2016 09:05:14 -0600 Subject: [PATCH 17/49] Remove a lot of 'homegrown' xml formation/creation and use System.Xml to avoid problems with invalid entities, etc. Should refactor soon to remove a lot of the ToString calls. Also shut off genCSV uploads for tables with file columns. --- .gitignore | 5 +- .../Intuit.QuickBase.Client.csproj | 1 + Intuit.QuickBase.Client/QRecord.cs | 2 +- Intuit.QuickBase.Client/QTable.cs | 77 ++++++++++--------- Intuit.QuickBase.Core/DoQuery.cs | 5 ++ Intuit.QuickBase.Core/Field.cs | 12 +-- Intuit.QuickBase.Core/Http.cs | 6 +- .../Intuit.QuickBase.Core.csproj | 6 ++ .../Payload/AddFieldPayload.cs | 6 +- .../Payload/AddRecordPayload.cs | 18 +++-- .../Payload/AddReplaceDBPagePayload.cs | 9 ++- .../Payload/AddUserToRolePayload.cs | 7 +- .../Payload/ApplicationTicket.cs | 4 +- .../Payload/ApplicationToken.cs | 4 +- .../Payload/ChangeRecordOwnerPayload.cs | 7 +- .../Payload/ChangeUserRolePayload.cs | 9 ++- .../Payload/CloneDatabasePayload.cs | 12 +-- .../Payload/CreateDatabasePayload.cs | 10 ++- .../Payload/CreateTablePayload.cs | 5 +- .../Payload/DeleteFieldPayload.cs | 3 +- .../Payload/DeleteRecordPayload.cs | 3 +- .../Payload/DoQueryCountPayload.cs | 7 +- .../Payload/DoQueryPayload.cs | 24 ++++-- .../Payload/EditRecordPayload.cs | 23 +++--- .../Payload/FieldChoicesPayload.cs | 5 +- .../Payload/FindDbByNamePayload.cs | 3 +- .../Payload/GetDBPagePayload.cs | 3 +- .../Payload/GetDBvarPayload.cs | 3 +- .../Payload/GetRecordAsHtmlPayload.cs | 5 +- .../Payload/GetRecordInfoPayload.cs | 3 +- .../Payload/GetUserInfoPayload.cs | 3 +- .../Payload/GetUserRolePayload.cs | 3 +- .../Payload/GrantDBsPayload.cs | 7 +- .../Payload/ImportFromCSVPayload.cs | 7 +- .../Payload/ProvisionUserPayload.cs | 8 +- .../Payload/PurgeRecordsPayload.cs | 7 +- .../Payload/RemoveUserFromRolePayload.cs | 7 +- .../Payload/RenameAppPayload.cs | 3 +- .../Payload/RunImportPayload.cs | 3 +- .../Payload/SendInvitationPayload.cs | 7 +- .../Payload/SetDBvarPayload.cs | 7 +- Intuit.QuickBase.Core/Payload/WrapPayload.cs | 9 ++- QBFunctionTest/UnitTest1.cs | 28 +++---- 43 files changed, 232 insertions(+), 154 deletions(-) diff --git a/.gitignore b/.gitignore index 2e57622..26e9074 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,8 @@ Intuit.QuickBase.Client/obj/ Intuit.QuickBase.Core/obj/ QBFunctionTest/obj/ -QBFunctionTest/app.config +QBFunctionTest/*.config TestResults/ +*.CodeAnalysisLog.xml +*.ruleset +*.lastcodeanalysissucceeded diff --git a/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj b/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj index da5dda9..249aea5 100644 --- a/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj +++ b/Intuit.QuickBase.Client/Intuit.QuickBase.Client.csproj @@ -32,6 +32,7 @@ DEBUG;TRACE prompt 4 + true pdbonly diff --git a/Intuit.QuickBase.Client/QRecord.cs b/Intuit.QuickBase.Client/QRecord.cs index 7b6e30f..ae5278d 100644 --- a/Intuit.QuickBase.Client/QRecord.cs +++ b/Intuit.QuickBase.Client/QRecord.cs @@ -201,7 +201,7 @@ public string GetAsCSV(string clist) } else { - if (field.Type == FieldType.file) throw new InvalidChoiceException(); + if (field.Type == FieldType.file) throw new InvalidChoiceException(); //Can't upload a file via CSV upload csvList.Add(CSVQuoter(field.QBValue)); } } diff --git a/Intuit.QuickBase.Client/QTable.cs b/Intuit.QuickBase.Client/QTable.cs index adb3782..0bf3859 100644 --- a/Intuit.QuickBase.Client/QTable.cs +++ b/Intuit.QuickBase.Client/QTable.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Xml.XPath; using Intuit.QuickBase.Core; +using Intuit.QuickBase.Core.Exceptions; namespace Intuit.QuickBase.Client { @@ -166,15 +167,30 @@ public int GetServerRecordCount() return int.Parse(xml.SelectSingleNode("/qdbapi/num_records").Value); } + private void _doQuery(DoQuery qry) + { + XPathNavigator xml; + Records.Clear(); + try + { + xml = qry.Post().CreateNavigator(); + } + catch (ViewTooLargeException ex) + { + //split into smaller queries automagically eventually + throw; + } + LoadColumns(xml); //Must be done each time, incase the schema changes due to another user, or from a previous query that has a differing subset of columns + LoadRecords(xml); + } + public void Query() { var doQuery = new DoQuery.Builder(Application.Client.Ticket, Application.Token, Application.Client.AccountDomain, TableId) .SetCList("a") .SetFmt(true) .Build(); - var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); //Must be done each time, incase the schema changes due to another user, or from a previous query that has a difering subset of columns - LoadRecords(xml); + _doQuery(doQuery); } public void Query(string options) @@ -184,9 +200,7 @@ public void Query(string options) .SetFmt(true) .SetOptions(options) .Build(); - var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); - LoadRecords(xml); + _doQuery(doQuery); } public void Query(int[] clist) @@ -197,9 +211,7 @@ public void Query(int[] clist) .SetCList(colList) .SetFmt(true) .Build(); - var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); - LoadRecords(xml); + _doQuery(doQuery); } public void Query(int[] clist, string options) @@ -211,9 +223,7 @@ public void Query(int[] clist, string options) .SetOptions(options) .SetFmt(true) .Build(); - var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); - LoadRecords(xml); + _doQuery(doQuery); } public void Query(Query query) @@ -223,9 +233,7 @@ public void Query(Query query) .SetCList("a") .SetFmt(true) .Build(); - var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); - LoadRecords(xml); + _doQuery(doQuery); } public void Query(Query query, string options) @@ -236,9 +244,7 @@ public void Query(Query query, string options) .SetOptions(options) .SetFmt(true) .Build(); - var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); - LoadRecords(xml); + _doQuery(doQuery); } public void Query(Query query, int[] clist) @@ -250,9 +256,7 @@ public void Query(Query query, int[] clist) .SetCList(colList) .SetFmt(true) .Build(); - var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); - LoadRecords(xml); + _doQuery(doQuery); } public void Query(Query query, int[] clist, int[] slist) @@ -266,9 +270,7 @@ public void Query(Query query, int[] clist, int[] slist) .SetSList(solList) .SetFmt(true) .Build(); - var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); - LoadRecords(xml); + _doQuery(doQuery); } public void Query(Query query, int[] clist, int[] slist, string options) @@ -283,9 +285,7 @@ public void Query(Query query, int[] clist, int[] slist, string options) .SetOptions(options) .SetFmt(true) .Build(); - var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); - LoadRecords(xml); + _doQuery(doQuery); } public void Query(int queryId) @@ -294,9 +294,7 @@ public void Query(int queryId) .SetQid(queryId) .SetFmt(true) .Build(); - var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); - LoadRecords(xml); + _doQuery(doQuery); } public void Query(int queryId, string options) @@ -306,9 +304,7 @@ public void Query(int queryId, string options) .SetFmt(true) .SetOptions(options) .Build(); - var xml = doQuery.Post().CreateNavigator(); - LoadColumns(xml); - LoadRecords(xml); + _doQuery(doQuery); } public int QueryCount(Query query) @@ -362,7 +358,10 @@ public void AcceptChanges() List modList = Records.Where(record => record.RecordState == RecordState.Modified).ToList(); int acnt = addList.Count; int mcnt = modList.Count; - if (acnt + mcnt > 0) + bool hasFileColumn = false; + foreach (var col in Columns) + if (col.ColumnType == FieldType.file) hasFileColumn = true; + if (acnt + mcnt > 5 && !hasFileColumn) // if greater than 5 and no file-type columns involved, use csv upload method for reducing API calls { List csvLines = new List(acnt + mcnt); String clist = String.Join(".", KeyFID == -1 ? Columns.Where(col => (col.ColumnVirtual == false && col.ColumnLookup == false) || col.ColumnName == "Record ID#").Select(col => col.ColumnId.ToString()) @@ -387,13 +386,20 @@ public void AcceptChanges() foreach (IQRecord rec in addList) { xNodes.MoveNext(); - ((IQRecord_int)rec).ForceUpdateState(Int32.Parse(xNodes.Current.Value)); + ((IQRecord_int)rec).ForceUpdateState(Int32.Parse(xNodes.Current.Value)); //set in-memory recordid to new server value } foreach (IQRecord rec in modList) { ((IQRecord_int)rec).ForceUpdateState(); } } + else + { + foreach (IQRecord rec in addList) + rec.AcceptChanges(); + foreach (IQRecord rec in modList) + rec.AcceptChanges(); + } } public IQRecord NewRecord() @@ -414,7 +420,6 @@ internal void Load() private void LoadRecords(XPathNavigator xml) { - Records.Clear(); var recordNodes = xml.Select("/qdbapi/table/records/record"); foreach (XPathNavigator recordNode in recordNodes) { diff --git a/Intuit.QuickBase.Core/DoQuery.cs b/Intuit.QuickBase.Core/DoQuery.cs index 109b620..212df4c 100644 --- a/Intuit.QuickBase.Core/DoQuery.cs +++ b/Intuit.QuickBase.Core/DoQuery.cs @@ -131,6 +131,11 @@ private DoQuery(Builder builder) _uri = new QUriDbid(builder.AccountDomain, builder.Dbid); } + internal string Options + { + get { return (DoQueryPayload)_doQueryPayload.Options; } + } + public string XmlPayload { get diff --git a/Intuit.QuickBase.Core/Field.cs b/Intuit.QuickBase.Core/Field.cs index ad32115..38a262a 100644 --- a/Intuit.QuickBase.Core/Field.cs +++ b/Intuit.QuickBase.Core/Field.cs @@ -50,7 +50,7 @@ public string Value { get { - return EncodeSpecialCharacters(_value); + return _value; } private set { @@ -73,15 +73,5 @@ public string File _file = value; } } - - private static string EncodeSpecialCharacters(string strLine) - { - strLine = Regex.Replace(strLine, "&(?!amp;)", "&"); - strLine = Regex.Replace(strLine, "<", "<"); - strLine = Regex.Replace(strLine, ">", ">"); - strLine = Regex.Replace(strLine, "\"", """); - strLine = Regex.Replace(strLine, "'", "'"); - return strLine; - } } } \ No newline at end of file diff --git a/Intuit.QuickBase.Core/Http.cs b/Intuit.QuickBase.Core/Http.cs index 5f0107f..942fe8c 100644 --- a/Intuit.QuickBase.Core/Http.cs +++ b/Intuit.QuickBase.Core/Http.cs @@ -47,8 +47,7 @@ internal void GetFile(DownloadFile downloadFile) BinaryReader br = null; BinaryWriter bw = null; WebResponse response = null; - Stream responseStream = null; - + try { // Request @@ -63,7 +62,7 @@ internal void GetFile(DownloadFile downloadFile) // Response response = request.GetResponse(); - responseStream = response.GetResponseStream(); + var responseStream = response.GetResponseStream(); // Write file if (!Directory.Exists(downloadFile.Path)) @@ -79,7 +78,6 @@ internal void GetFile(DownloadFile downloadFile) { if (bw != null) bw.Close(); if (br != null) br.Close(); - if (responseStream != null) responseStream.Close(); if (response != null) response.Close(); } } diff --git a/Intuit.QuickBase.Core/Intuit.QuickBase.Core.csproj b/Intuit.QuickBase.Core/Intuit.QuickBase.Core.csproj index 571a9b1..2d9c9ef 100644 --- a/Intuit.QuickBase.Core/Intuit.QuickBase.Core.csproj +++ b/Intuit.QuickBase.Core/Intuit.QuickBase.Core.csproj @@ -32,6 +32,8 @@ DEBUG;TRACE prompt 4 + true + Intuit.QuickBase.Core.ruleset pdbonly @@ -40,6 +42,7 @@ TRACE prompt 4 + Intuit.QuickBase.Core.ruleset @@ -211,6 +214,9 @@ + + +