diff --git a/umbraco.Test/DocumentTest.cs b/umbraco.Test/DocumentTest.cs index b2eef67c39..c2ec6e5c9e 100644 --- a/umbraco.Test/DocumentTest.cs +++ b/umbraco.Test/DocumentTest.cs @@ -38,7 +38,7 @@ namespace umbraco.Test ///and then deletes it. /// [TestMethod()] - public void MakeNewTest() + public void Document_MakeNewTest() { //System.Diagnostics.Debugger.Break(); string Name = "TEST-" + Guid.NewGuid().ToString("N"); @@ -56,7 +56,7 @@ namespace umbraco.Test /// lookup the root docs to do the test. /// [TestMethod()] - public void CopyTest() + public void Document_CopyTest() { //System.Diagnostics.Debugger.Break(); Document target = new Document(GetExistingNodeId()); @@ -88,11 +88,11 @@ namespace umbraco.Test /// Tests copying by relating nodes, then deleting /// [TestMethod()] - public void CopyAndRelateTest() + public void Document_CopyAndRelateTest() { //System.Diagnostics.Debugger.Break(); Document target = new Document(GetExistingNodeId()); - int parentId = target.Parent.Id; + int parentId = target.Level == 1 ? -1 : target.Parent.Id; bool RelateToOrignal = true; //get children ids @@ -100,7 +100,7 @@ namespace umbraco.Test target.Copy(parentId, m_User, RelateToOrignal); - Assert.AreEqual(childrenIds.Count() + 1, target.Parent.ChildCount); + Assert.AreEqual(childrenIds.Count() + 1, target.Level == 1 ? Document.GetRootDocuments().Count() : target.Parent.ChildCount); Document parent = new Document(parentId); //get the children difference which should be the new node @@ -117,7 +117,7 @@ namespace umbraco.Test ///Create a new document, create preview xml for it, then delete it /// [TestMethod()] - public void ToPreviewXmlTest() + public void Document_ToPreviewXmlTest() { //System.Diagnostics.Debugger.Break(); string Name = "TEST-" + Guid.NewGuid().ToString("N"); @@ -140,7 +140,7 @@ namespace umbraco.Test /// Run test to create a node, publish it and delete it. This will test the versioning too. /// [TestMethod()] - public void MakeNewAndPublishTest() + public void Document_MakeNewAndPublishTest() { //System.Diagnostics.Debugger.Break(); string Name = "TEST-" + Guid.NewGuid().ToString("N"); @@ -164,7 +164,7 @@ namespace umbraco.Test ///A test that creates a new document, publishes it, unpublishes it and finally deletes it /// [TestMethod()] - public void PublishThenUnPublishTest() + public void Document_PublishThenUnPublishTest() { //System.Diagnostics.Debugger.Break(); string Name = "TEST-" + Guid.NewGuid().ToString("N"); @@ -192,7 +192,7 @@ namespace umbraco.Test ///A test that makes a new document, updates some properties, saves and publishes the document, then rolls the document back and finally deletes it. /// [TestMethod()] - public void SaveAndPublishThenRollBackTest() + public void Document_SaveAndPublishThenRollBackTest() { //System.Diagnostics.Debugger.Break(); @@ -209,6 +209,8 @@ namespace umbraco.Test var versionCount = actual.GetVersions().Count(); //save + //wait a sec so that there's a time delay between the update time and version time + Thread.Sleep(1000); actual.Save(); Assert.IsTrue(actual.HasPendingChanges()); @@ -238,7 +240,7 @@ namespace umbraco.Test ///them as children of each other to ensure the deletion occurs correctly. /// [TestMethod()] - public void DeleteAllDocsByDocumentTypeTest() + public void Document_DeleteAllDocsByDocumentTypeTest() { //System.Diagnostics.Debugger.Break(); @@ -298,7 +300,7 @@ namespace umbraco.Test /// then move it to the second one and finally delete everything that was created. /// [TestMethod] - public void MoveTest() + public void Document_MoveTest() { //first need to document type that allows other types of document types to exist underneath it DocumentType parent = null; @@ -343,7 +345,7 @@ namespace umbraco.Test /// This will find an existing node, copy it to the same parent, delete the copied node and restore it, then finally completley remove it. /// [TestMethod] - public void UndeleteTest() + public void Document_UndeleteTest() { //find existing content var doc = new Document(GetExistingNodeId()); @@ -371,7 +373,7 @@ namespace umbraco.Test /// This method will create 20 content nodes, send them to the recycle bin and then empty the recycle bin /// [TestMethod] - public void EmptyRecycleBinTest() + public void Document_EmptyRecycleBinTest() { var docList = new List(); var total = 20; diff --git a/umbraco.Test/DocumentTypeTest.cs b/umbraco.Test/DocumentTypeTest.cs new file mode 100644 index 0000000000..fe95eddd56 --- /dev/null +++ b/umbraco.Test/DocumentTypeTest.cs @@ -0,0 +1,757 @@ +using umbraco.cms.businesslogic.web; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using umbraco.BusinessLogic; +using System.Xml; +using System.Linq; +using umbraco.cms.businesslogic.template; +using umbraco.cms.businesslogic.datatype; +using System.Data.SqlClient; + +namespace umbraco.Test +{ + + + /// + /// Tests DocumentType apis. + /// + /// + /// After each test is run, any document type created is removed + /// + [TestClass()] + public class DocumentTypeTest + { + + /// + ///A test for creating a new document type + /// + [TestMethod()] + public void DocumentType_MakeNewTest() + { + var dt = DocumentType.MakeNew(m_User, "TEST" + Guid.NewGuid().ToString("N")); + Assert.IsTrue(dt.Id > 0); + Assert.AreEqual(DateTime.Now.Date, dt.CreateDateTime.Date); + + DeleteDocType(dt); + } + + /// + /// Tests adding every type of property to a new document type on a new tab, then delete the tab, then the document type + /// + [TestMethod()] + public void DocumentType_AddPropertiesToTabThenDeleteItTest() + { + //System.Diagnostics.Debugger.Break(); + + var dt = DocumentType.MakeNew(m_User, "TEST" + Guid.NewGuid().ToString("N")); + Assert.IsTrue(dt.Id > 0); + Assert.AreEqual(DateTime.Now.Date, dt.CreateDateTime.Date); + + //allow itself to be created under itself + dt.AllowedChildContentTypeIDs = new int[] { dt.Id }; + //create a tab + dt.AddVirtualTab("TEST"); + + //test the tab + var tabs = dt.getVirtualTabs.ToList(); + Assert.AreEqual(1, tabs.Count); + + //create a property + var allDataTypes = DataTypeDefinition.GetAll().ToList(); //get all definitions + var i = 0; + foreach (var dataType in allDataTypes) + { + //add a property type of the first type found in the list + dt.AddPropertyType(dataType, "testProperty" + (++i).ToString(), "Test Property" + i.ToString()); + //test the prop + var prop = dt.getPropertyType("testProperty" + i.ToString()); + Assert.IsTrue(prop.Id > 0); + Assert.AreEqual("Test Property" + i.ToString(), prop.Name); + //put the properties to the tab + dt.SetTabOnPropertyType(prop, tabs[0].Id); + //re-get the property since data is cached in the object + prop = dt.getPropertyType("testProperty" + i.ToString()); + Assert.AreEqual(tabs[0].Id, prop.TabId); + } + + //now we need to delete the tab + dt.DeleteVirtualTab(tabs[0].Id); + + dt.delete(); + } + + /// + ///A test for GetAll + /// + [TestMethod()] + public void DocumentType_GetAllTest() + { + //check with sql that it's the correct number of children + var ids = new List(); + using (var reader = Application.SqlHelper.ExecuteReader(DocumentType.m_SQLOptimizedGetAll, + Application.SqlHelper.CreateParameter("@nodeObjectType", DocumentType._objectType))) + { + while (reader.Read()) + { + ids.Add(reader.Get("id")); + } + } + + var all = DocumentType.GetAllAsList(); + + Assert.AreEqual(ids.Distinct().Count(), all.Count); + } + + /// + ///A test for HasChildren + /// + [TestMethod()] + public void DocumentType_HasChildrenTest() + { + //System.Diagnostics.Debugger.Break(); + + var dt1 = DocumentType.MakeNew(m_User, "TEST" + Guid.NewGuid().ToString("N")); + + Assert.IsTrue(dt1.Id > 0); + Assert.AreEqual(DateTime.Now.Date, dt1.CreateDateTime.Date); + Assert.IsFalse(dt1.HasChildren); + + var dt2 = DocumentType.MakeNew(m_User, "TEST" + Guid.NewGuid().ToString("N")); + + Assert.IsTrue(dt2.Id > 0); + Assert.AreEqual(DateTime.Now.Date, dt2.CreateDateTime.Date); + Assert.IsFalse(dt2.HasChildren); + + dt2.MasterContentType = dt1.Id; + dt2.Save(); + + //unfortunately this won't work! because the HasChildren property is cached + //Assert.IsTrue(dt1.HasChildren); + var reloaded = new DocumentType(dt1.Id); + Assert.IsTrue(reloaded.HasChildren); + + var hasError = false; + try + { + DeleteDocType(dt1); + } + catch (ArgumentException) + { + hasError = true; + } + Assert.IsTrue(hasError); + + DeleteDocType(dt2); + DeleteDocType(dt1); + } + + #region Tests to write + ///// + /////A test for allowedTemplates + ///// + //[TestMethod()] + //public void allowedTemplatesTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // DocumentType target = new DocumentType(id); // TODO: Initialize to an appropriate value + // Template[] expected = null; // TODO: Initialize to an appropriate value + // Template[] actual; + // target.allowedTemplates = expected; + // actual = target.allowedTemplates; + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for DefaultTemplate + ///// + //[TestMethod()] + //public void DefaultTemplateTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // DocumentType target = new DocumentType(id); // TODO: Initialize to an appropriate value + // int expected = 0; // TODO: Initialize to an appropriate value + // int actual; + // target.DefaultTemplate = expected; + // actual = target.DefaultTemplate; + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + + ///// + /////A test for ToXml + ///// + //[TestMethod()] + //public void ToXmlTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // DocumentType target = new DocumentType(id); // TODO: Initialize to an appropriate value + // XmlDocument xd = null; // TODO: Initialize to an appropriate value + // XmlElement expected = null; // TODO: Initialize to an appropriate value + // XmlElement actual; + // actual = target.ToXml(xd); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for Save + ///// + //[TestMethod()] + //public void SaveTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // DocumentType target = new DocumentType(id); // TODO: Initialize to an appropriate value + // target.Save(); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + ///// + /////A test for RemoveDefaultTemplate + ///// + //[TestMethod()] + //public void RemoveDefaultTemplateTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // DocumentType target = new DocumentType(id); // TODO: Initialize to an appropriate value + // target.RemoveDefaultTemplate(); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + + + ///// + /////A test for HasTemplate + ///// + //[TestMethod()] + //public void HasTemplateTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // DocumentType target = new DocumentType(id); // TODO: Initialize to an appropriate value + // bool expected = false; // TODO: Initialize to an appropriate value + // bool actual; + // actual = target.HasTemplate(); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for GetByAlias + ///// + //[TestMethod()] + //public void GetByAliasTest() + //{ + // string Alias = string.Empty; // TODO: Initialize to an appropriate value + // DocumentType expected = null; // TODO: Initialize to an appropriate value + // DocumentType actual; + // actual = DocumentType.GetByAlias(Alias); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for GetAllAsList + ///// + //[TestMethod()] + //public void GetAllAsListTest() + //{ + // List expected = null; // TODO: Initialize to an appropriate value + // List actual; + // actual = DocumentType.GetAllAsList(); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for GenerateDtd + ///// + //[TestMethod()] + //public void GenerateDtdTest() + //{ + // string expected = string.Empty; // TODO: Initialize to an appropriate value + // string actual; + // actual = DocumentType.GenerateDtd(); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for delete + ///// + //[TestMethod()] + //public void deleteTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // DocumentType target = new DocumentType(id); // TODO: Initialize to an appropriate value + // target.delete(); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + ///// + /////A test for clearTemplates + ///// + //[TestMethod()] + //public void clearTemplatesTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // DocumentType target = new DocumentType(id); // TODO: Initialize to an appropriate value + // target.clearTemplates(); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + ///// + /////A test for Thumbnail + ///// + //[TestMethod()] + //public void ThumbnailTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // string expected = string.Empty; // TODO: Initialize to an appropriate value + // string actual; + // target.Thumbnail = expected; + // actual = target.Thumbnail; + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for Text + ///// + //[TestMethod()] + //public void TextTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // string expected = string.Empty; // TODO: Initialize to an appropriate value + // string actual; + // target.Text = expected; + // actual = target.Text; + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for PropertyTypes + ///// + //[TestMethod()] + //public void PropertyTypesTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // List actual; + // actual = target.PropertyTypes; + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for MasterContentType + ///// + //[TestMethod()] + //public void MasterContentTypeTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // int expected = 0; // TODO: Initialize to an appropriate value + // int actual; + // target.MasterContentType = expected; + // actual = target.MasterContentType; + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for IconUrl + ///// + //[TestMethod()] + //public void IconUrlTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // string expected = string.Empty; // TODO: Initialize to an appropriate value + // string actual; + // target.IconUrl = expected; + // actual = target.IconUrl; + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for getVirtualTabs + ///// + //[TestMethod()] + //public void getVirtualTabsTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // ContentType.TabI[] actual; + // actual = target.getVirtualTabs; + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for Description + ///// + //[TestMethod()] + //public void DescriptionTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // string expected = string.Empty; // TODO: Initialize to an appropriate value + // string actual; + // target.Description = expected; + // actual = target.Description; + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for AllowedChildContentTypeIDs + ///// + //[TestMethod()] + //public void AllowedChildContentTypeIDsTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // int[] expected = null; // TODO: Initialize to an appropriate value + // int[] actual; + // target.AllowedChildContentTypeIDs = expected; + // actual = target.AllowedChildContentTypeIDs; + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for Alias + ///// + //[TestMethod()] + //public void AliasTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // string expected = string.Empty; // TODO: Initialize to an appropriate value + // string actual; + // target.Alias = expected; + // actual = target.Alias; + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for SetTabSortOrder + ///// + //[TestMethod()] + //public void SetTabSortOrderTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // int tabId = 0; // TODO: Initialize to an appropriate value + // int sortOrder = 0; // TODO: Initialize to an appropriate value + // target.SetTabSortOrder(tabId, sortOrder); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + ///// + /////A test for SetTabOnPropertyType + ///// + //[TestMethod()] + //public void SetTabOnPropertyTypeTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // PropertyType pt = null; // TODO: Initialize to an appropriate value + // int TabId = 0; // TODO: Initialize to an appropriate value + // target.SetTabOnPropertyType(pt, TabId); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + ///// + /////A test for SetTabName + ///// + //[TestMethod()] + //public void SetTabNameTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // int tabId = 0; // TODO: Initialize to an appropriate value + // string Caption = string.Empty; // TODO: Initialize to an appropriate value + // target.SetTabName(tabId, Caption); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + ///// + /////A test for Save + ///// + //[TestMethod()] + //public void SaveTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // target.Save(); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + ///// + /////A test for removePropertyTypeFromTab + ///// + //[TestMethod()] + //public void removePropertyTypeFromTabTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // PropertyType pt = null; // TODO: Initialize to an appropriate value + // target.removePropertyTypeFromTab(pt); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + ///// + /////A test for getTabIdFromPropertyType + ///// + //[TestMethod()] + //public void getTabIdFromPropertyTypeTest() + //{ + // PropertyType pt = null; // TODO: Initialize to an appropriate value + // int expected = 0; // TODO: Initialize to an appropriate value + // int actual; + // actual = ContentType.getTabIdFromPropertyType(pt); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for GetRawText + ///// + //[TestMethod()] + //public void GetRawTextTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // string expected = string.Empty; // TODO: Initialize to an appropriate value + // string actual; + // actual = target.GetRawText(); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for getPropertyType + ///// + //[TestMethod()] + //public void getPropertyTypeTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // string alias = string.Empty; // TODO: Initialize to an appropriate value + // PropertyType expected = null; // TODO: Initialize to an appropriate value + // PropertyType actual; + // actual = target.getPropertyType(alias); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for GetContentType + ///// + //[TestMethod()] + //public void GetContentTypeTest() + //{ + // int id = 0; // TODO: Initialize to an appropriate value + // ContentType expected = null; // TODO: Initialize to an appropriate value + // ContentType actual; + // actual = ContentType.GetContentType(id); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for GetByAlias + ///// + //[TestMethod()] + //public void GetByAliasTest() + //{ + // string Alias = string.Empty; // TODO: Initialize to an appropriate value + // ContentType expected = null; // TODO: Initialize to an appropriate value + // ContentType actual; + // actual = ContentType.GetByAlias(Alias); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for GetAll + ///// + //[TestMethod()] + //public void GetAllTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // ContentType[] expected = null; // TODO: Initialize to an appropriate value + // ContentType[] actual; + // actual = target.GetAll(); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for FlushTabCache + ///// + //[TestMethod()] + //public void FlushTabCacheTest() + //{ + // int TabId = 0; // TODO: Initialize to an appropriate value + // int ContentTypeId = 0; // TODO: Initialize to an appropriate value + // ContentType.FlushTabCache(TabId, ContentTypeId); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + ///// + /////A test for delete + ///// + //[TestMethod()] + //public void deleteTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // target.delete(); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + ///// + /////A test for AddVirtualTab + ///// + //[TestMethod()] + //public void AddVirtualTabTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // string Caption = string.Empty; // TODO: Initialize to an appropriate value + // int expected = 0; // TODO: Initialize to an appropriate value + // int actual; + // actual = target.AddVirtualTab(Caption); + // Assert.AreEqual(expected, actual); + // Assert.Inconclusive("Verify the correctness of this test method."); + //} + + ///// + /////A test for AddPropertyType + ///// + //[TestMethod()] + //public void AddPropertyTypeTest() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); // TODO: Initialize to an appropriate value + // DataTypeDefinition dt = null; // TODO: Initialize to an appropriate value + // string Alias = string.Empty; // TODO: Initialize to an appropriate value + // string Name = string.Empty; // TODO: Initialize to an appropriate value + // target.AddPropertyType(dt, Alias, Name); + // Assert.Inconclusive("A method that does not return a value cannot be verified."); + //} + + ///// + /////A test for ContentType Constructor + ///// + //[TestMethod()] + //public void ContentTypeConstructorTest2() + //{ + // int id = 0; // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); + // Assert.Inconclusive("TODO: Implement code to verify target"); + //} + + ///// + /////A test for ContentType Constructor + ///// + //[TestMethod()] + //public void ContentTypeConstructorTest1() + //{ + // Guid id = new Guid(); // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id); + // Assert.Inconclusive("TODO: Implement code to verify target"); + //} + + ///// + /////A test for ContentType Constructor + ///// + //[TestMethod()] + //public void ContentTypeConstructorTest() + //{ + // int id = 0; // TODO: Initialize to an appropriate value + // bool noSetup = false; // TODO: Initialize to an appropriate value + // ContentType target = new ContentType(id, noSetup); + // Assert.Inconclusive("TODO: Implement code to verify target"); + //} + #endregion + + #region Private properties and methods + + private User m_User = new User(0); + + private void DeleteDocType(DocumentType dt) + { + var id = dt.Id; + + dt.delete(); + + //check with sql that it is gone + var count = Application.SqlHelper.ExecuteScalar("SELECT COUNT(*) FROM umbracoNode WHERE id=@id", + Application.SqlHelper.CreateParameter("@id", id)); + + Assert.AreEqual(0, count); + } + + #endregion + + #region Test context + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + #endregion + + #region Initialize and cleanup + // + //You can use the following additional attributes as you write your tests: + // + //Use ClassInitialize to run code before running the first test in the class + //[ClassInitialize()] + //public static void MyClassInitialize(TestContext testContext) + //{ + //} + // + //Use ClassCleanup to run code after all tests in a class have run + //[ClassCleanup()] + //public static void MyClassCleanup() + //{ + //} + // + //Use TestInitialize to run code before running each test + //[TestInitialize()] + //public void MyTestInitialize() + //{ + //} + // + //Use TestCleanup to run code after each test has run + //[TestCleanup()] + //public void MyTestCleanup() + //{ + //} + // + #endregion + + } +} diff --git a/umbraco.Test/umbraco.Test.csproj b/umbraco.Test/umbraco.Test.csproj index ecbfcdf873..8a59fd8f3f 100644 --- a/umbraco.Test/umbraco.Test.csproj +++ b/umbraco.Test/umbraco.Test.csproj @@ -115,6 +115,7 @@ + diff --git a/umbraco/cms/businesslogic/CMSNode.cs b/umbraco/cms/businesslogic/CMSNode.cs index ad43abcca8..be208fd0ad 100644 --- a/umbraco/cms/businesslogic/CMSNode.cs +++ b/umbraco/cms/businesslogic/CMSNode.cs @@ -513,7 +513,8 @@ order by level,sortOrder"; { if (!_hasChildrenInitialized) { - int tmpChildrenCount = SqlHelper.ExecuteScalar("select count(id) from umbracoNode where ParentId = " + _id); + int tmpChildrenCount = SqlHelper.ExecuteScalar("select count(id) from umbracoNode where ParentId = @id", + SqlHelper.CreateParameter("@id", Id)); HasChildren = (tmpChildrenCount > 0); } return _hasChildren; diff --git a/umbraco/cms/businesslogic/ContentType.cs b/umbraco/cms/businesslogic/ContentType.cs index 4006521184..d894946860 100644 --- a/umbraco/cms/businesslogic/ContentType.cs +++ b/umbraco/cms/businesslogic/ContentType.cs @@ -85,12 +85,16 @@ namespace umbraco.cms.businesslogic #endregion - #region Constants + #region Constants and static members + private const string m_SQLOptimizedGetAll = @" SELECT id, createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text, masterContentType,Alias,icon,thumbnail,description FROM umbracoNode INNER JOIN cmsContentType ON umbracoNode.id = cmsContentType.nodeId - WHERE nodeObjectType = @nodeObjectType"; + WHERE nodeObjectType = @nodeObjectType"; + + private static readonly object m_Locker = new object(); + #endregion #region Static Methods @@ -104,8 +108,15 @@ namespace umbraco.cms.businesslogic { if (HttpRuntime.Cache[string.Format("UmbracoContentType{0}", id.ToString())] == null) { - ContentType ct = new ContentType(id); - HttpRuntime.Cache.Insert(string.Format("UmbracoContentType{0}", id.ToString()), ct); + lock (m_Locker) + { + //double check + if (HttpRuntime.Cache[string.Format("UmbracoContentType{0}", id.ToString())] == null) + { + ContentType ct = new ContentType(id); + HttpRuntime.Cache.Insert(string.Format("UmbracoContentType{0}", id.ToString()), ct); + } + } } return (ContentType)HttpRuntime.Cache[string.Format("UmbracoContentType{0}", id.ToString())]; } @@ -297,7 +308,8 @@ namespace umbraco.cms.businesslogic { get { - string cacheKey = "ContentType_PropertyTypes_Content:" + this.Id; + string cacheKey = GetPropertiesCacheKey(); + return Cache.GetCacheItem>(cacheKey, propertyTypesCacheSyncLock, TimeSpan.FromMinutes(15), delegate @@ -380,6 +392,7 @@ namespace umbraco.cms.businesslogic set { m_masterContentType = value; + SqlHelper.ExecuteNonQuery("update cmsContentType set masterContentType = @masterContentType where nodeId = @nodeId", SqlHelper.CreateParameter("@masterContentType", value), SqlHelper.CreateParameter("@nodeId", Id)); @@ -469,9 +482,7 @@ namespace umbraco.cms.businesslogic /// /// The list of all ContentTypes public ContentType[] GetAll() - { - //write optimized sql for this! - + { var contentTypes = new List(); using (IRecordsReader dr = @@ -520,17 +531,14 @@ namespace umbraco.cms.businesslogic /// /// Adding a PropertyType to a Tab, the Tabs are primarily used for making the /// editing interface more userfriendly. - /// /// /// The PropertyType /// The Id of the Tab public void SetTabOnPropertyType(PropertyType pt, int TabId) - { - SqlHelper.ExecuteNonQuery( - "update cmsPropertyType set tabId = " + TabId.ToString() + " where id = " + - pt.Id.ToString()); - - // Remove from cache + { + // This is essentially just a wrapper for the property + pt.TabId = TabId; + //flush the content type cache, the the tab cache (why so much cache?! argh!) FlushFromCache(Id); foreach (TabI t in getVirtualTabs.ToList()) FlushTabCache(t.Id, pt.ContentTypeId); @@ -541,10 +549,8 @@ namespace umbraco.cms.businesslogic /// /// The PropertyType which should be freed from its tab public void removePropertyTypeFromTab(PropertyType pt) - { - SqlHelper.ExecuteNonQuery( - "update cmsPropertyType set tabId = NULL where id = " + pt.Id.ToString()); - + { + pt.TabId = 0; //this will set to null in the database. // Remove from cache FlushFromCache(Id); } @@ -578,8 +584,17 @@ namespace umbraco.cms.businesslogic /// The Id of the Tab to be deleted. public void DeleteVirtualTab(int id) { - SqlHelper.ExecuteNonQuery( - "Update cmsPropertyType set tabId = NULL where tabId =" + id); + //set each property on the tab to have a tab id of zero + this.getVirtualTabs.ToList() + .Where(x => x.Id == id) + .Single() + .PropertyTypes + .ToList() + .ForEach(x => + { + x.TabId = 0; + }); + SqlHelper.ExecuteNonQuery("delete from cmsTab where id =" + id); // Remove from cache @@ -687,6 +702,19 @@ namespace umbraco.cms.businesslogic #region Protected Methods + protected void PopulateContentTypeNodeFromReader(IRecordsReader dr) + { + _alias = dr.GetString("Alias"); + _iconurl = dr.GetString("icon"); + if (!dr.IsNull("masterContentType")) + m_masterContentType = dr.GetInt("masterContentType"); + + if (!dr.IsNull("thumbnail")) + _thumbnail = dr.GetString("thumbnail"); + if (!dr.IsNull("description")) + _description = dr.GetString("description"); + } + /// /// Set up the internal data of the ContentType /// @@ -725,18 +753,27 @@ namespace umbraco.cms.businesslogic protected void FlushFromCache(int Id) { if (HttpRuntime.Cache[string.Format("UmbracoContentType{0}", Id.ToString())] != null) - HttpRuntime.Cache.Remove(string.Format("UmbracoContentType{0}", Id.ToString())); + { + lock (m_Locker) + { + //double check + if (HttpRuntime.Cache[string.Format("UmbracoContentType{0}", Id.ToString())] != null) + { + HttpRuntime.Cache.Remove(string.Format("UmbracoContentType{0}", Id.ToString())); + } + } + } - if (HttpRuntime.Cache[string.Format("ContentType_PropertyTypes_Content:{0}", Id.ToString())] != null) - HttpRuntime.Cache.Remove(string.Format("ContentType_PropertyTypes_Content:{0}", Id.ToString())); + string cacheKey = GetPropertiesCacheKey(); + Cache.ClearCacheItem(cacheKey); ClearVirtualTabs(); } protected void FlushAllFromCache() { - cache.Cache.ClearCacheByKeySearch("UmbracoContentType"); - cache.Cache.ClearCacheByKeySearch("ContentType_PropertyTypes_Content"); + Cache.ClearCacheByKeySearch("UmbracoContentType"); + Cache.ClearCacheByKeySearch("ContentType_PropertyTypes_Content"); ClearVirtualTabs(); } @@ -745,6 +782,15 @@ namespace umbraco.cms.businesslogic #region Private Methods + /// + /// The cache key used to cache the properties for the content type + /// + /// + private string GetPropertiesCacheKey() + { + return "ContentType_PropertyTypes_Content:" + this.Id; + } + /// /// Clears the locally loaded tabs which forces them to be reloaded next time they requested /// @@ -795,19 +841,6 @@ namespace umbraco.cms.businesslogic m_VirtualTabs.Sort((a, b) => a.SortOrder.CompareTo(b.SortOrder)); } - private void PopulateContentTypeNodeFromReader(IRecordsReader dr) - { - _alias = dr.GetString("Alias"); - _iconurl = dr.GetString("icon"); - if (!dr.IsNull("masterContentType")) - m_masterContentType = dr.GetInt("masterContentType"); - - if (!dr.IsNull("thumbnail")) - _thumbnail = dr.GetString("thumbnail"); - if (!dr.IsNull("description")) - _description = dr.GetString("description"); - } - private void populateMasterContentTypes(PropertyType pt, int docTypeId) { foreach (web.DocumentType docType in web.DocumentType.GetAllAsList()) diff --git a/umbraco/cms/businesslogic/cache/Cache.cs b/umbraco/cms/businesslogic/cache/Cache.cs index 694117619a..886830cc12 100644 --- a/umbraco/cms/businesslogic/cache/Cache.cs +++ b/umbraco/cms/businesslogic/cache/Cache.cs @@ -9,6 +9,8 @@ namespace umbraco.cms.businesslogic.cache public class Cache { + public static readonly object m_Locker = new object(); + /// /// Clears everything in umbraco's runtime cache, which means that not only /// umbraco content is removed, but also other cache items from pages running in @@ -35,8 +37,15 @@ namespace umbraco.cms.businesslogic.cache { if (System.Web.HttpRuntime.Cache[Key] != null) { - System.Web.HttpRuntime.Cache.Remove(Key); - System.Web.HttpContext.Current.Trace.Warn("Cache", "Item " + Key + " removed from cache"); + lock (m_Locker) + { + //check again + if (System.Web.HttpRuntime.Cache[Key] != null) + { + System.Web.HttpRuntime.Cache.Remove(Key); + System.Web.HttpContext.Current.Trace.Warn("Cache", "Item " + Key + " removed from cache"); + } + } } } @@ -54,10 +63,20 @@ namespace umbraco.cms.businesslogic.cache if (c != null) { System.Collections.IDictionaryEnumerator cacheEnumerator = c.GetEnumerator(); - while ( cacheEnumerator.MoveNext() ) - if (cacheEnumerator.Key != null && c[cacheEnumerator.Key.ToString()] != null && c[cacheEnumerator.Key.ToString()].GetType() != null && c[cacheEnumerator.Key.ToString()].GetType().ToString() == TypeName) - c.Remove(cacheEnumerator.Key.ToString()); - + while (cacheEnumerator.MoveNext()) + { + if (cacheEnumerator.Key != null && c[cacheEnumerator.Key.ToString()] != null && c[cacheEnumerator.Key.ToString()].GetType() != null && c[cacheEnumerator.Key.ToString()].GetType().ToString() == TypeName) + { + lock (m_Locker) + { + //check again + if (cacheEnumerator.Key != null && c[cacheEnumerator.Key.ToString()] != null && c[cacheEnumerator.Key.ToString()].GetType() != null && c[cacheEnumerator.Key.ToString()].GetType().ToString() == TypeName) + { + c.Remove(cacheEnumerator.Key.ToString()); + } + } + } + } } } catch (Exception CacheE) diff --git a/umbraco/cms/businesslogic/propertytype/propertytype.cs b/umbraco/cms/businesslogic/propertytype/propertytype.cs index 659252d353..92ecdb8222 100644 --- a/umbraco/cms/businesslogic/propertytype/propertytype.cs +++ b/umbraco/cms/businesslogic/propertytype/propertytype.cs @@ -88,6 +88,13 @@ namespace umbraco.cms.businesslogic.propertytype get { return _id; } } + /// + /// Setting the tab id is not meant to be used directly in code. Use the ContentType SetTabOnPropertyType method instead + /// as that will handle all of the caching properly, this will not. + /// + /// + /// Setting the tab id to a negative value will actually set the value to NULL in the database + /// public int TabId { get { return _tabId; } @@ -95,8 +102,15 @@ namespace umbraco.cms.businesslogic.propertytype { _tabId = value; this.InvalidateCache(); + object tabId = value; + if (value < 1) + { + tabId = DBNull.Value; + } + SqlHelper.ExecuteNonQuery( "Update cmsPropertyType set tabId = @tabId where id = @id", - SqlHelper.CreateParameter("@tabId", value), SqlHelper.CreateParameter("@id", this.Id)); + SqlHelper.CreateParameter("@tabId", tabId), + SqlHelper.CreateParameter("@id", this.Id)); } } @@ -325,7 +339,7 @@ namespace umbraco.cms.businesslogic.propertytype protected virtual void FlushCache() { // clear local cache - cache.Cache.ClearCacheItem(GetCacheKey(Id)); + Cache.ClearCacheItem(GetCacheKey(Id)); // clear cache in contentype Cache.ClearCacheItem("ContentType_PropertyTypes_Content:" + this._contenttypeid.ToString()); diff --git a/umbraco/cms/businesslogic/web/DocumentType.cs b/umbraco/cms/businesslogic/web/DocumentType.cs index add0d51285..980a1d42c4 100644 --- a/umbraco/cms/businesslogic/web/DocumentType.cs +++ b/umbraco/cms/businesslogic/web/DocumentType.cs @@ -8,6 +8,9 @@ using umbraco.BusinessLogic; using umbraco.cms.businesslogic.propertytype; using umbraco.DataLayer; using System.Collections.Generic; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Umbraco.Test")] namespace umbraco.cms.businesslogic.web { @@ -22,16 +25,23 @@ namespace umbraco.cms.businesslogic.web public DocumentType(Guid id) : base(id) { } - //public DocumentType(bool useOptimizedMode, int id) - // : base(useOptimizedMode, id) - //{ - - //} + public DocumentType(int id, bool noSetup) : base(id, noSetup) { } #endregion #region Constants and Static members - public static Guid _objectType = new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"); + + public static Guid _objectType = new Guid("a2cb7800-f571-4787-9638-bc48539a0efb"); + + internal const string m_SQLOptimizedGetAll = @" + SELECT id, createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text, + masterContentType,Alias,icon,thumbnail,description, + templateNodeId, IsDefault + FROM umbracoNode + INNER JOIN cmsContentType ON umbracoNode.id = cmsContentType.nodeId + LEFT OUTER JOIN cmsDocumentType ON cmsContentType.nodeId = cmsDocumentType.contentTypeNodeId + WHERE nodeObjectType = @nodeObjectType"; + #endregion #region Private Members @@ -138,16 +148,40 @@ namespace umbraco.cms.businesslogic.web } public static List GetAllAsList() - { - List retVal = new List(); - Guid[] Ids = getAllUniquesFromObjectType(_objectType); - for (int i = 0; i < Ids.Length; i++) + { + + var documentTypes = new List(); + + using (IRecordsReader dr = + SqlHelper.ExecuteReader(m_SQLOptimizedGetAll, SqlHelper.CreateParameter("@nodeObjectType", DocumentType._objectType))) { - retVal.Add(new DocumentType(Ids[i])); + while (dr.Read()) + { + //check if the document id has already been added + if (documentTypes.Where(x => x.Id == dr.Get("id")).Count() == 0) + { + //create the DocumentType object without setting up + DocumentType dt = new DocumentType(dr.Get("id"), true); + //populate it's CMSNode properties + dt.PopulateCMSNodeFromReader(dr); + //populate it's ContentType properties + dt.PopulateContentTypeNodeFromReader(dr); + //populate from it's DocumentType properties + dt.PopulateDocumentTypeNodeFromReader(dr); + + documentTypes.Add(dt); + } + else + { + //we've already created the document type with this id, so we'll add the rest of it's templates to itself + var dt = documentTypes.Where(x => x.Id == dr.Get("id")).Single(); + dt.PopulateDocumentTypeNodeFromReader(dr); + } + } } - retVal.Sort(delegate(DocumentType dt1, DocumentType dt2) { return dt1.Text.CompareTo(dt2.Text); }); - return retVal; + return documentTypes.OrderBy(x => x.Text).ToList(); + } #endregion @@ -212,6 +246,10 @@ namespace umbraco.cms.businesslogic.web #region Public Methods + /// + /// + /// + /// Throws an exception if trying to delete a document type that is assigned as a master document type public override void delete() { DeleteEventArgs e = new DeleteEventArgs(); @@ -349,27 +387,34 @@ namespace umbraco.cms.businesslogic.web #region Protected Methods + protected void PopulateDocumentTypeNodeFromReader(IRecordsReader dr) + { + if (!dr.IsNull("templateNodeId")) + { + _templateIds.Add(dr.GetInt("templateNodeId")); + if (!dr.IsNull("IsDefault")) + { + if (dr.GetBoolean("IsDefault")) + { + _defaultTemplate = dr.GetInt("templateNodeId"); + } + } + } + } + protected override void setupNode() { base.setupNode(); - if (SqlHelper.ExecuteScalar("select count(TemplateNodeId) as tmp from cmsDocumentType where contentTypeNodeId =" + Id) > 0) + using (IRecordsReader dr = SqlHelper.ExecuteReader("Select templateNodeId, IsDefault from cmsDocumentType where contentTypeNodeId = @id", + SqlHelper.CreateParameter("@id", Id))) { - IRecordsReader dr = - SqlHelper.ExecuteReader( - "Select templateNodeId, IsDefault from cmsDocumentType where contentTypeNodeId =" + - Id); while (dr.Read()) { - if (template.Template.IsNode(dr.GetInt("templateNodeId"))) - { - _templateIds.Add(dr.GetInt("templateNodeId")); - if (dr.GetBoolean("IsDefault")) - _defaultTemplate = dr.GetInt("templateNodeId"); - } + PopulateDocumentTypeNodeFromReader(dr); } - dr.Close(); } + } #endregion diff --git a/umbraco/datalayer/SqlHelpers/MySql/Sql/KeysIndexesAndConstraints.sql b/umbraco/datalayer/SqlHelpers/MySql/Sql/KeysIndexesAndConstraints.sql new file mode 100644 index 0000000000..bda1eba2f2 --- /dev/null +++ b/umbraco/datalayer/SqlHelpers/MySql/Sql/KeysIndexesAndConstraints.sql @@ -0,0 +1,12 @@ +/* + +THIS IS A TEMPORARY FILE USED TO STORE THE SCRIPTS TO CREATE FOREIGN KEYS, UNIQUE CONSTRAINTS AND INDEXES FOR PERFORMANCE REASONS. +THIS WILL BE MERGED INTO THE INSTALL SCRIPTS AND WILL BE CREATED AS A SEPERATE STANDALONE UPGRADE SCRIPT FOR OLDER VERSIONS. +THIS FILE EXISTS HERE CURRENTLY BECAUSE A FULL DATA LAYER TEST SUITE NEEDS TO BE CREATED TO ENSURE THAT THESE CONSTRAINTS ARE +NOT GOING TO BREAK UMBRACO. + +*/ + +/* Create missing indexes and primary keys */ +CREATE INDEX IX_Icon ON cmsContentType(nodeId, icon) +; \ No newline at end of file diff --git a/umbraco/datalayer/SqlHelpers/MySql/Sql/Total.sql b/umbraco/datalayer/SqlHelpers/MySql/Sql/Total.sql index 285d0b9352..421a8ac931 100644 --- a/umbraco/datalayer/SqlHelpers/MySql/Sql/Total.sql +++ b/umbraco/datalayer/SqlHelpers/MySql/Sql/Total.sql @@ -812,4 +812,14 @@ ALTER TABLE umbraconode MODIFY COLUMN id INTEGER NOT NULL AUTO_INCREMENT; /* Add the mediaRecycleBin tree type */ INSERT IGNORE INTO umbracoAppTree (treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType) VALUES (0, 0, 0, 'media', 'mediaRecycleBin', 'RecycleBin', 'folder.gif', 'folder_o.gif', 'umbraco', 'cms.presentation.Trees.MediaRecycleBin') -; \ No newline at end of file +; + +CREATE TABLE cmsPreviewXml( + nodeId int NOT NULL, + versionId CHAR(36) NOT NULL, + timestamp datetime NOT NULL, + xml LONGTEXT NOT NULL) +; +ALTER TABLE cmsPreviewXml ADD CONSTRAINT PK_cmsContentPreviewXml PRIMARY KEY CLUSTERED (nodeId, versionId) +; + diff --git a/umbraco/datalayer/SqlHelpers/MySql/Sql/Version4_Upgrade.sql b/umbraco/datalayer/SqlHelpers/MySql/Sql/Version4_Upgrade.sql index 82f4074136..de86df9560 100644 --- a/umbraco/datalayer/SqlHelpers/MySql/Sql/Version4_Upgrade.sql +++ b/umbraco/datalayer/SqlHelpers/MySql/Sql/Version4_Upgrade.sql @@ -1,16 +1,10 @@ /******************************************************************************************* - - - - - - Umbraco database installation script for SQL Server (upgrade from Umbraco 4.0.x) -IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT + IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT - Database version: 4.1.0.0 + Database version: 4.1.0.2 Please increment this version number if ANY change is made to this script, so compatibility with scripts for other database systems can be verified easily. @@ -26,21 +20,13 @@ IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT * you have documented the code change in this script; * you have incremented the version number in this script. -IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT - - - - - - + IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT ********************************************************************************************/ - - +/* INSERT NEW MEDIA RECYCLE BIN NODE */ /* remove auto increment so we can insert identity */ ALTER TABLE umbraconode MODIFY COLUMN id INTEGER NOT NULL; -/* INSERT NEW MEDIA RECYCLE BIN NODE */ INSERT INTO umbracoNode (id, trashed, parentID, nodeUser, level, path, sortOrder, uniqueID, text, nodeObjectType, createDate) VALUES (-21, 0, -1, 0, 0, '-1,-21', 0, 'BF7C7CBC-952F-4518-97A2-69E9C7B33842', 'Recycle Bin', 'CF3D8E34-1C1C-41e9-AE56-878B57B32113', '2009/08/28 00:28:28.920') ; @@ -50,3 +36,13 @@ ALTER TABLE umbraconode MODIFY COLUMN id INTEGER NOT NULL AUTO_INCREMENT; INSERT IGNORE INTO umbracoAppTree (treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType) VALUES (0, 0, 0, 'media', 'mediaRecycleBin', 'RecycleBin', 'folder.gif', 'folder_o.gif', 'umbraco', 'cms.presentation.Trees.MediaRecycleBin') ; + +CREATE TABLE cmsPreviewXml( + nodeId int NOT NULL, + versionId CHAR(36) NOT NULL, + timestamp datetime NOT NULL, + xml LONGTEXT NOT NULL) +; +ALTER TABLE cmsPreviewXml ADD CONSTRAINT PK_cmsContentPreviewXml PRIMARY KEY CLUSTERED (nodeId, versionId) +; + diff --git a/umbraco/datalayer/SqlHelpers/SqlServer/Sql/KeysIndexesAndConstraints.sql b/umbraco/datalayer/SqlHelpers/SqlServer/Sql/KeysIndexesAndConstraints.sql new file mode 100644 index 0000000000..2385f998af --- /dev/null +++ b/umbraco/datalayer/SqlHelpers/SqlServer/Sql/KeysIndexesAndConstraints.sql @@ -0,0 +1,500 @@ +/* + +THIS IS A TEMPORARY FILE USED TO STORE THE SCRIPTS TO CREATE FOREIGN KEYS, UNIQUE CONSTRAINTS AND INDEXES FOR PERFORMANCE REASONS. +THIS WILL BE MERGED INTO THE INSTALL SCRIPTS AND WILL BE CREATED AS A SEPERATE STANDALONE UPGRADE SCRIPT FOR OLDER VERSIONS. +THIS FILE EXISTS HERE CURRENTLY BECAUSE A FULL DATA LAYER TEST SUITE NEEDS TO BE CREATED TO ENSURE THAT THESE CONSTRAINTS ARE +NOT GOING TO BREAK UMBRACO. + +*/ + +/* Create missing indexes and primary keys */ +CREATE NONCLUSTERED INDEX [IX_Icon] ON CMSContenttype(nodeId, Icon) +; + +ALTER TABLE dbo.cmsContentType ADD CONSTRAINT + IX_cmsContentType UNIQUE NONCLUSTERED + ( + nodeId + ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +; + +ALTER TABLE dbo.cmsContent ADD CONSTRAINT + IX_cmsContent UNIQUE NONCLUSTERED + ( + nodeId + ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + + +ALTER TABLE dbo.cmsContentVersion ADD CONSTRAINT + FK_cmsContentVersion_cmsContent FOREIGN KEY + ( + ContentId + ) REFERENCES dbo.cmsContent + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsMember ADD CONSTRAINT + PK_cmsMember PRIMARY KEY CLUSTERED + ( + nodeId + ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +; + +ALTER TABLE dbo.cmsMember ADD CONSTRAINT + FK_cmsMember_cmsContent FOREIGN KEY + ( + nodeId + ) REFERENCES dbo.cmsContent + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsMember ADD CONSTRAINT + FK_cmsMember_umbracoNode FOREIGN KEY + ( + nodeId + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsStylesheet ADD CONSTRAINT + PK_cmsStylesheet PRIMARY KEY CLUSTERED + ( + nodeId + ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +; + +ALTER TABLE dbo.cmsStylesheetProperty ADD CONSTRAINT + PK_cmsStylesheetProperty PRIMARY KEY CLUSTERED + ( + nodeId + ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +; + +ALTER TABLE dbo.cmsStylesheetProperty ADD CONSTRAINT + FK_cmsStylesheetProperty_umbracoNode FOREIGN KEY + ( + nodeId + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsStylesheet ADD CONSTRAINT + FK_cmsStylesheet_umbracoNode FOREIGN KEY + ( + nodeId + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsContentXml ADD CONSTRAINT + FK_cmsContentXml_cmsContent FOREIGN KEY + ( + nodeId + ) REFERENCES dbo.cmsContent + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsDataType ADD CONSTRAINT + IX_cmsDataType UNIQUE NONCLUSTERED + ( + nodeId + ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +; + +/* +We need to remove any data type that doesn't exist in umbracoNode as these shouldn't actually exist +I think they must be left over from how Umbraco used to show the types of data types registered instead +of using reflection. Here are the data types in the cmsDataType table that are not in umbracoNode: + +12 -91 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Nvarchar +22 -44 A3776494-0574-4D93-B7DE-EFDFDEC6F2D1 Ntext +23 -128 A52C7C1C-C330-476E-8605-D63D3B84B6A6 Nvarchar +24 -129 928639ED-9C73-4028-920C-1E55DBB68783 Nvarchar +25 -130 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Nvarchar +26 -131 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Nvarchar +27 -132 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Nvarchar +28 -133 6C738306-4C17-4D88-B9BD-6546F3771597 Ntext +29 -134 928639ED-9C73-4028-920C-1E55DBB68783 Nvarchar +30 -50 AAF99BB2-DBBE-444D-A296-185076BF0484 Date +39 1042 5E9B75AE-FACE-41C8-B47E-5F4B0FD82F83 Ntext +40 1043 5E9B75AE-FACE-41C8-B47E-5F4B0FD82F83 Ntext +41 1044 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Ntext +42 1045 A74EA9C9-8E18-4D2A-8CF6-73C6206C5DA6 Ntext +47 1194 D15E1281-E456-4B24-AA86-1DDA3E4299D5 Ntext + +*/ +DELETE FROM cmsDataType WHERE nodeId NOT IN (SELECT id FROM umbracoNode) + +ALTER TABLE dbo.cmsDataType ADD CONSTRAINT + FK_cmsDataType_umbracoNode FOREIGN KEY + ( + nodeId + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +/* Need to remove any data type prevalues that aren't related to a data type */ +DELETE FROM cmsDataTypePreValues WHERE dataTypeNodeID NOT IN (SELECT nodeId FROM cmsDataType) +; + +ALTER TABLE dbo.cmsDataTypePreValues ADD CONSTRAINT + FK_cmsDataTypePreValues_cmsDataType FOREIGN KEY + ( + datatypeNodeId + ) REFERENCES dbo.cmsDataType + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsDocument ADD CONSTRAINT + FK_cmsDocument_cmsContent FOREIGN KEY + ( + nodeId + ) REFERENCES dbo.cmsContent + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsDocumentType ADD CONSTRAINT + FK_cmsDocumentType_cmsContentType FOREIGN KEY + ( + contentTypeNodeId + ) REFERENCES dbo.cmsContentType + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsDocumentType ADD CONSTRAINT + FK_cmsDocumentType_umbracoNode FOREIGN KEY + ( + contentTypeNodeId + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsMacroProperty ADD CONSTRAINT + FK_cmsMacroProperty_cmsMacro FOREIGN KEY + ( + macro + ) REFERENCES dbo.cmsMacro + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsMemberType ADD CONSTRAINT + FK_cmsMemberType_cmsContentType FOREIGN KEY + ( + NodeId + ) REFERENCES dbo.cmsContentType + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsMemberType ADD CONSTRAINT + FK_cmsMemberType_umbracoNode FOREIGN KEY + ( + NodeId + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsMember2MemberGroup ADD CONSTRAINT + FK_cmsMember2MemberGroup_cmsMember FOREIGN KEY + ( + Member + ) REFERENCES dbo.cmsMember + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsDocument ADD CONSTRAINT + IX_cmsDocument UNIQUE NONCLUSTERED + ( + nodeId, + versionId + ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +; + +ALTER TABLE dbo.cmsPropertyData ADD CONSTRAINT + FK_cmsPropertyData_cmsPropertyType FOREIGN KEY + ( + propertytypeid + ) REFERENCES dbo.cmsPropertyType + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsPropertyType ADD CONSTRAINT + FK_cmsPropertyType_cmsContentType FOREIGN KEY + ( + contentTypeId + ) REFERENCES dbo.cmsContentType + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsPropertyType ADD CONSTRAINT + FK_cmsPropertyType_cmsDataType FOREIGN KEY + ( + dataTypeId + ) REFERENCES dbo.cmsDataType + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsTab ADD CONSTRAINT + FK_cmsTab_cmsContentType FOREIGN KEY + ( + contenttypeNodeId + ) REFERENCES dbo.cmsContentType + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsTemplate ADD CONSTRAINT + IX_cmsTemplate UNIQUE NONCLUSTERED + ( + nodeId + ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +; + +ALTER TABLE dbo.cmsDocument ADD CONSTRAINT + FK_cmsDocument_cmsTemplate FOREIGN KEY + ( + templateId + ) REFERENCES dbo.cmsTemplate + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.umbracoDomains ADD CONSTRAINT + FK_umbracoDomains_umbracoNode FOREIGN KEY + ( + domainRootStructureID + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsDictionary ADD CONSTRAINT + IX_cmsDictionary UNIQUE NONCLUSTERED + ( + id + ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +; + +ALTER TABLE dbo.cmsLanguageText ADD CONSTRAINT + FK_cmsLanguageText_cmsDictionary FOREIGN KEY + ( + UniqueId + ) REFERENCES dbo.cmsDictionary + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.umbracoUser2NodeNotify ADD CONSTRAINT + FK_umbracoUser2NodeNotify_umbracoUser FOREIGN KEY + ( + userId + ) REFERENCES dbo.umbracoUser + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.umbracoUser2NodeNotify ADD CONSTRAINT + FK_umbracoUser2NodeNotify_umbracoNode FOREIGN KEY + ( + nodeId + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.umbracoUser2NodePermission ADD CONSTRAINT + FK_umbracoUser2NodePermission_umbracoUser FOREIGN KEY + ( + userId + ) REFERENCES dbo.umbracoUser + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.umbracoUser2NodePermission ADD CONSTRAINT + FK_umbracoUser2NodePermission_umbracoNode FOREIGN KEY + ( + nodeId + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsTask ADD CONSTRAINT + FK_cmsTask_umbracoUser FOREIGN KEY + ( + parentUserId + ) REFERENCES dbo.umbracoUser + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsTask ADD CONSTRAINT + FK_cmsTask_umbracoUser1 FOREIGN KEY + ( + userId + ) REFERENCES dbo.umbracoUser + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsTask ADD CONSTRAINT + FK_cmsTask_umbracoNode FOREIGN KEY + ( + nodeId + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsDictionary ADD CONSTRAINT + FK_cmsDictionary_cmsDictionary FOREIGN KEY + ( + parent + ) REFERENCES dbo.cmsDictionary + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +CREATE NONCLUSTERED INDEX IX_umbracoLog ON dbo.umbracoLog + ( + NodeId + ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +; + +ALTER TABLE dbo.umbracoRelation ADD CONSTRAINT + FK_umbracoRelation_umbracoRelationType FOREIGN KEY + ( + relType + ) REFERENCES dbo.umbracoRelationType + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.umbracoRelation ADD CONSTRAINT + FK_umbracoRelation_umbracoNode FOREIGN KEY + ( + parentId + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.umbracoRelation ADD CONSTRAINT + FK_umbracoRelation_umbracoNode1 FOREIGN KEY + ( + childId + ) REFERENCES dbo.umbracoNode + ( + id + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +/* need to remove any content restrictions that don't exist in cmsContent */ + +DELETE FROM cmsContentTypeAllowedContentType WHERE id NOT IN (SELECT nodeId FROM cmsContentType) +DELETE FROM cmsContentTypeAllowedContentType WHERE Allowedid NOT IN (SELECT nodeId FROM cmsContentType) + +ALTER TABLE dbo.cmsContentTypeAllowedContentType ADD CONSTRAINT + FK_cmsContentTypeAllowedContentType_cmsContentType FOREIGN KEY + ( + Id + ) REFERENCES dbo.cmsContentType + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; + +ALTER TABLE dbo.cmsContentTypeAllowedContentType ADD CONSTRAINT + FK_cmsContentTypeAllowedContentType_cmsContentType1 FOREIGN KEY + ( + AllowedId + ) REFERENCES dbo.cmsContentType + ( + nodeId + ) ON UPDATE NO ACTION + ON DELETE NO ACTION +; \ No newline at end of file diff --git a/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Version4_Upgrade.sql b/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Version4_Upgrade.sql index b490aa6f64..fc37ce8b33 100644 --- a/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Version4_Upgrade.sql +++ b/umbraco/datalayer/SqlHelpers/SqlServer/Sql/Version4_Upgrade.sql @@ -1,14 +1,10 @@ - -/******************************************************************************************* - - - +/******************************************************************************************* Umbraco database installation script for SQL Server (upgrade from Umbraco 4.0.x) -IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT + IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT - Database version: 4.1.0.0 + Database version: 4.1.0.2 Please increment this version number if ANY change is made to this script, so compatibility with scripts for other database systems can be verified easily. @@ -24,13 +20,7 @@ IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT * you have documented the code change in this script; * you have incremented the version number in this script. -IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT - - - - - - + IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT ********************************************************************************************/ diff --git a/umbraco/datalayer/umbraco.datalayer.csproj b/umbraco/datalayer/umbraco.datalayer.csproj index b6c7d7d988..0dba75bc49 100644 --- a/umbraco/datalayer/umbraco.datalayer.csproj +++ b/umbraco/datalayer/umbraco.datalayer.csproj @@ -139,8 +139,10 @@ + +