/// <summary> /// Removes a Navigation Path. /// </summary> /// <param name="connection">A database connection.</param> /// <param name="path">The navigation path to remove.</param> /// <returns><c>true</c> if the path is removed, <c>false</c> otherwise.</returns> private bool RemoveNavigationPath(DbConnection connection, NavigationPath path) { string nspace, name; NameTools.ExpandFullName(path.FullName, out nspace, out name); if(nspace == null) nspace = ""; ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.DeleteFrom("NavigationPath"); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Namespace", WhereOperator.Equals, "Namespace"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name", name)); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspace)); DbCommand command = builder.GetCommand(connection, query, parameters); int rows = ExecuteNonQuery(command, false); return rows > 0; }
/// <summary> /// Retrieves a Page Attachment. /// </summary> /// <param name="pageInfo">The Page Info that owns the Attachment.</param> /// <param name="name">The name of the Attachment, for example "myfile.jpg".</param> /// <param name="destinationStream">A Stream object used as <b>destination</b> of a byte stream, /// i.e. the method writes to the Stream the file content.</param> /// <param name="countHit">A value indicating whether or not to count this retrieval in the statistics.</param> /// <returns><c>true</c> if the Attachment is retrieved, <c>false</c> otherwise.</returns> /// <exception cref="ArgumentNullException">If <paramref name="pageInfo"/>, <paramref name="name"/> or <paramref name="destinationStream"/> are <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="name"/> is empty or if <paramref name="destinationStream"/> does not support writing, /// or if the page does not have attachments or if the attachment does not exist.</exception> public bool RetrievePageAttachment(PageInfo pageInfo, string name, System.IO.Stream destinationStream, bool countHit) { if(pageInfo == null) throw new ArgumentNullException("pageInfo"); if(name == null) throw new ArgumentNullException("name"); if(name.Length == 0) throw new ArgumentException("Name cannot be empty", "name"); if(destinationStream == null) throw new ArgumentNullException("destinationStream"); if(!destinationStream.CanWrite) throw new ArgumentException("Cannot write into Destination Stream", "destinationStream"); ICommandBuilder builder = GetCommandBuilder(); DbConnection connection = builder.GetConnection(connString); DbTransaction transaction = BeginTransaction(connection); if(!AttachmentExists(transaction, pageInfo, name)) { RollbackTransaction(transaction); throw new ArgumentException("Attachment does not exist", "name"); } QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("Attachment", new string[] { "Size", "Data" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Page", WhereOperator.Equals, "Page"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name", name)); parameters.Add(new Parameter(ParameterType.String, "Page", pageInfo.FullName)); DbCommand command = builder.GetCommand(transaction, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { bool done = false; if(reader.Read()) { int read = ReadBinaryColumn(reader, "Data", destinationStream); done = (long)read == (long)reader["Size"]; } CloseReader(reader); if(!done) { RollbackTransaction(transaction); return false; } } else { RollbackTransaction(transaction); return false; } if(countHit) { // Update download count query = queryBuilder.UpdateIncrement("Attachment", "Downloads", 1); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Page", WhereOperator.Equals, "Page"); parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name", name)); parameters.Add(new Parameter(ParameterType.String, "Page", pageInfo.FullName)); command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); if(rows != 1) { RollbackTransaction(transaction); return false; } } CommitTransaction(transaction); return true; }
/// <summary> /// Sets the number of times a page attachment was retrieved. /// </summary> /// <param name="pageInfo">The page.</param> /// <param name="name">The name of the attachment.</param> /// <param name="count">The count to set.</param> /// <exception cref="ArgumentNullException">If <paramref name="pageInfo"/> or <paramref name="name"/> are <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="name"/> is empty.</exception> /// <exception cref="ArgumentOutOfRangeException">If <paramref name="count"/> is less than zero.</exception> public void SetPageAttachmentRetrievalCount(PageInfo pageInfo, string name, int count) { if(pageInfo == null) throw new ArgumentNullException("pageInfo"); if(name == null) throw new ArgumentNullException("name"); if(name.Length == 0) throw new ArgumentException("Name cannot be empty"); if(count < 0) throw new ArgumentOutOfRangeException("Count must be greater than or equal to zero", "count"); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.Update("Attachment", new string[] { "Downloads" }, new string[] { "Downloads" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Page", WhereOperator.Equals, "Page"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name", name)); parameters.Add(new Parameter(ParameterType.String, "Page", pageInfo.FullName)); parameters.Add(new Parameter(ParameterType.Int32, "Downloads", count)); DbCommand command = builder.GetCommand(connString, query, parameters); ExecuteNonQuery(command); }
/// <summary> /// Lists the Files in the specified Directory. /// </summary> /// <param name="directory">The full directory name, for example "/my/directory". Null, empty or "/" for the root directory.</param> /// <returns>The list of Files in the directory.</returns> /// <exception cref="ArgumentException">If <paramref name="directory"/> does not exist.</exception> public string[] ListFiles(string directory) { directory = PrepareDirectory(directory); ICommandBuilder builder = GetCommandBuilder(); DbConnection connection = builder.GetConnection(connString); if(!DirectoryExists(connection, directory)) { CloseConnection(connection); throw new ArgumentException("Directory does not exist", "directory"); } QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("File", new string[] { "Name" }); query = queryBuilder.Where(query, "Directory", WhereOperator.Equals, "Directory"); query = queryBuilder.OrderBy(query, new [] { "Name" }, new[] { Ordering.Asc }); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Directory", directory)); DbCommand command = builder.GetCommand(connection, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { List<string> result = new List<string>(20); while(reader.Read()) { result.Add(directory + reader["Name"] as string); } CloseReader(command, reader); return result.ToArray(); } else return null; }
/// <summary> /// Renames or moves a File. /// </summary> /// <param name="oldFullName">The old full name of the File.</param> /// <param name="newFullName">The new full name of the File.</param> /// <returns><c>true</c> if the File is renamed, <c>false</c> otherwise.</returns> /// <exception cref="ArgumentNullException">If <paramref name="oldFullName"/> or <paramref name="newFullName"/> are <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="oldFullName"/> or <paramref name="newFullName"/> are empty, or if the old file does not exist, or if the new file already exist.</exception> public bool RenameFile(string oldFullName, string newFullName) { if(oldFullName == null) throw new ArgumentNullException("oldFullName"); if(oldFullName.Length == 0) throw new ArgumentException("Old Full Name cannot be empty", "oldFullName"); if(newFullName == null) throw new ArgumentNullException("newFullName"); if(newFullName.Length == 0) throw new ArgumentException("New Full Name cannot be empty", "newFullName"); ICommandBuilder builder = GetCommandBuilder(); DbConnection connection = builder.GetConnection(connString); DbTransaction transaction = BeginTransaction(connection); QueryBuilder queryBuilder = new QueryBuilder(builder); if(!FileExists(transaction, oldFullName)) { RollbackTransaction(transaction); throw new ArgumentException("File does not exist", "oldFullName"); } if(FileExists(transaction, newFullName)) { RollbackTransaction(transaction); throw new ArgumentException("File already exists", "newFullPath"); } string oldDirectory, newDirectory, oldFilename, newFilename; SplitFileFullName(oldFullName, out oldDirectory, out oldFilename); SplitFileFullName(newFullName, out newDirectory, out newFilename); string query = queryBuilder.Update("File", new string[] { "Name" }, new string[] { "NewName" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "OldName"); query = queryBuilder.AndWhere(query, "Directory", WhereOperator.Equals, "OldDirectory"); List<Parameter> parameters = new List<Parameter>(3); parameters.Add(new Parameter(ParameterType.String, "NewName", newFilename)); parameters.Add(new Parameter(ParameterType.String, "OldName", oldFilename)); parameters.Add(new Parameter(ParameterType.String, "OldDirectory", oldDirectory)); DbCommand command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); if(rows == 1) CommitTransaction(transaction); else RollbackTransaction(transaction); return rows == 1; }
/// <summary> /// Renames or moves a Directory. /// </summary> /// <param name="transaction">The current transaction to use.</param> /// <param name="oldFullPath">The old full path of the Directory.</param> /// <param name="newFullPath">The new full path of the Directory.</param> /// <returns><c>true</c> if the Directory is renamed, <c>false</c> otherwise.</returns> private bool RenameDirectory(DbTransaction transaction, string oldFullPath, string newFullPath) { string[] directories = ListDirectories(transaction, oldFullPath); foreach(string dir in directories) { string trimmed = dir.Trim('/'); string name = trimmed.Substring(trimmed.LastIndexOf("/") + 1); string newFullPathSub = PrepareDirectory(newFullPath + name); RenameDirectory(dir, newFullPathSub); } ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.Update("Directory", new string[] { "FullPath" }, new string[] { "NewDirectory1" }); query = queryBuilder.Where(query, "FullPath", WhereOperator.Equals, "OldDirectory1"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "NewDirectory1", newFullPath)); parameters.Add(new Parameter(ParameterType.String, "OldDirectory1", oldFullPath)); DbCommand command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); return rows > 0; }
/// <summary> /// Gets the details of a page attachment. /// </summary> /// <param name="pageInfo">The page that owns the attachment.</param> /// <param name="name">The name of the attachment, for example "myfile.jpg".</param> /// <returns>The details of the attachment, or <c>null</c> if the attachment does not exist.</returns> /// <exception cref="ArgumentNullException">If <paramref name="pageInfo"/> or <paramref name="name"/> are <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="name"/> is empty.</exception> public FileDetails GetPageAttachmentDetails(PageInfo pageInfo, string name) { if(pageInfo == null) throw new ArgumentNullException("pageInfo"); if(name == null) throw new ArgumentNullException("name"); if(name.Length == 0) throw new ArgumentException("Name cannot be empty"); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("Attachment", new string[] { "Size", "Downloads", "LastModified" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Page", WhereOperator.Equals, "Page"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name", name)); parameters.Add(new Parameter(ParameterType.String, "Page", pageInfo.FullName)); DbCommand command = builder.GetCommand(connString, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { FileDetails details = null; if(reader.Read()) { details = new FileDetails((long)reader["Size"], (DateTime)reader["LastModified"], (int)reader["Downloads"]); } CloseReader(command, reader); return details; } else return null; }
/// <summary> /// Gets all the categories of a page. /// </summary> /// <param name="page">The page.</param> /// <returns>The categories, sorted by name.</returns> /// <exception cref="ArgumentNullException">If <paramref name="page"/> is <c>null</c>.</exception> public CategoryInfo[] GetCategoriesForPage(PageInfo page) { if(page == null) throw new ArgumentNullException("page"); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string nspace, pageName; NameTools.ExpandFullName(page.FullName, out nspace, out pageName); if(nspace == null) nspace = ""; string query = queryBuilder.SelectFrom("Category", "CategoryBinding", new string[] { "Name", "Namespace" }, new string[] { "Category", "Namespace" }, Join.LeftJoin, new string[] { "Name", "Namespace" }, new string[] { "Page" }); query = queryBuilder.Where(query, "CategoryBinding", "Namespace", WhereOperator.Equals, "Namespace"); query = queryBuilder.AndWhere(query, "CategoryBinding", "Page", WhereOperator.Equals, "Page"); query = queryBuilder.OrderBy(query, new[] { "Category_Name" }, new[] { Ordering.Asc }); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspace)); parameters.Add(new Parameter(ParameterType.String, "Page", pageName)); DbCommand command = builder.GetCommand(connString, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { List<CategoryInfo> result = new List<CategoryInfo>(20); List<string> pages = new List<string>(50); string prevName = "|||"; string name = null; while(reader.Read()) { name = reader["Category_Name"] as string; if(name != prevName) { if(prevName != "|||") { result[result.Count - 1].Pages = pages.ToArray(); pages.Clear(); } result.Add(new CategoryInfo(NameTools.GetFullName(reader["Category_Namespace"] as string, name), this)); } prevName = name; if(!IsDBNull(reader, "CategoryBinding_Page")) { pages.Add(NameTools.GetFullName(reader["Category_Namespace"] as string, reader["CategoryBinding_Page"] as string)); } } CloseReader(command, reader); if(result.Count > 0) result[result.Count - 1].Pages = pages.ToArray(); return result.ToArray(); } else return null; }
/// <summary> /// Gets the total number of Messages in a Page Discussion. /// </summary> /// <param name="page">The Page.</param> /// <returns>The number of messages.</returns> /// <exception cref="ArgumentNullException">If <paramref name="page"/> is <c>null</c>.</exception> public int GetMessageCount(PageInfo page) { if(page == null) throw new ArgumentNullException("page"); ICommandBuilder builder = GetCommandBuilder(); DbConnection connection = builder.GetConnection(connString); if(GetPage(connection, page.FullName) == null) { CloseConnection(connection); return -1; } string nspace, name; NameTools.ExpandFullName(page.FullName, out nspace, out name); if(nspace == null) nspace = ""; QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectCountFrom("Message"); query = queryBuilder.Where(query, "Page", WhereOperator.Equals, "Page"); query = queryBuilder.AndWhere(query, "Namespace", WhereOperator.Equals, "Namespace"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Page", name)); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspace)); DbCommand command = builder.GetCommand(connection, query, parameters); int count = ExecuteScalar<int>(command, 0); return count; }
/// <summary> /// Tries to load all data related to a word from the database. /// </summary> /// <param name="text">The word text.</param> /// <param name="word">The returned word.</param> /// <param name="connection">An open database connection.</param> /// <returns><c>true</c> if the word is found, <c>false</c> otherwise.</returns> private bool TryFindWord(string text, out Word word, DbConnection connection) { // 1. Find word - if not found, return // 2. Read all raw word mappings // 3. Read all documents (unique) // 4. Build result data structure ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("IndexWord", new string[] { "Id" }); query = queryBuilder.Where(query, "Text", WhereOperator.Equals, "Text"); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Text", text)); DbCommand command = builder.GetCommand(connection, query, parameters); int wordId = ExecuteScalar<int>(command, -1, false); if(wordId == -1) { word = null; return false; } // Read all raw mappings query = queryBuilder.SelectFrom("IndexWordMapping"); query = queryBuilder.Where(query, "Word", WhereOperator.Equals, "WordId"); parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.Int32, "WordId", wordId)); command = builder.GetCommand(connection, query, parameters); DbDataReader reader = ExecuteReader(command, false); List<DumpedWordMapping> mappings = new List<DumpedWordMapping>(2048); while(reader != null && reader.Read()) { mappings.Add(new DumpedWordMapping((uint)wordId, (uint)(int)reader["Document"], (ushort)(short)reader["FirstCharIndex"], (ushort)(short)reader["WordIndex"], (byte)reader["Location"])); } CloseReader(reader); if(mappings.Count == 0) { word = null; return false; } // Find all documents query = queryBuilder.SelectFrom("IndexDocument"); query = queryBuilder.Where(query, "Id", WhereOperator.Equals, "DocId"); parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.Int32, "DocId", 0)); Dictionary<uint, IDocument> documents = new Dictionary<uint, IDocument>(64); foreach(DumpedWordMapping map in mappings) { uint docId = map.DocumentID; if(documents.ContainsKey(docId)) continue; parameters[0].Value = (int)docId; command = builder.GetCommand(connection, query, parameters); reader = ExecuteReader(command, false); if(reader != null && reader.Read()) { DumpedDocument dumpedDoc = new DumpedDocument(docId, reader["Name"] as string, reader["Title"] as string, reader["TypeTag"] as string, (DateTime)reader["DateTime"]); IDocument document = BuildDocument(dumpedDoc); if(document != null) documents.Add(docId, document); } CloseReader(reader); } OccurrenceDictionary occurrences = new OccurrenceDictionary(mappings.Count); foreach(DumpedWordMapping map in mappings) { if(!occurrences.ContainsKey(documents[map.DocumentID])) { occurrences.Add(documents[map.DocumentID], new SortedBasicWordInfoSet(2)); } occurrences[documents[map.DocumentID]].Add(new BasicWordInfo( map.FirstCharIndex, map.WordIndex, WordLocation.GetInstance(map.Location))); } word = new Word((uint)wordId, text, occurrences); return true; }
/// <summary> /// Deletes the Backups of a Page, up to a specified revision. /// </summary> /// <param name="page">The Page to delete the backups of.</param> /// <param name="revision">The newest revision to delete (newer revision are kept) o -1 to delete all the Backups.</param> /// <returns><c>true</c> if the deletion succeeded, <c>false</c> otherwise.</returns> /// <exception cref="ArgumentNullException">If <paramref name="page"/> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException">If <paramref name="revision"/> is less than -1.</exception> public bool DeleteBackups(PageInfo page, int revision) { if(page == null) throw new ArgumentNullException("page"); if(revision < -1) throw new ArgumentOutOfRangeException("revision", "Invalid Revision"); // 1. Retrieve target content (revision-1 = first kept revision) // 2. Replace the current content (delete, store) // 3. Delete all older revisions up to the specified on (included) "N-m...N" // 4. Re-number remaining revisions starting from FirstRevision (zero) to revision-1 (don't re-number revs -1, -100) ICommandBuilder builder = GetCommandBuilder(); DbConnection connection = builder.GetConnection(connString); DbTransaction transaction = BeginTransaction(connection); if(GetPage(transaction, page.FullName) == null) { RollbackTransaction(transaction); return false; } int[] baks = GetBackups(transaction, page); if(baks.Length > 0 && revision > baks[baks.Length - 1]) { RollbackTransaction(transaction); return true; } string nspace, name; NameTools.ExpandFullName(page.FullName, out nspace, out name); if(nspace == null) nspace = ""; QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.DeleteFrom("PageContent"); query = queryBuilder.Where(query, "Page", WhereOperator.Equals, "Page"); query = queryBuilder.AndWhere(query, "Namespace", WhereOperator.Equals, "Namespace"); if(revision != -1) query = queryBuilder.AndWhere(query, "Revision", WhereOperator.LessThanOrEqualTo, "Revision"); query = queryBuilder.AndWhere(query, "Revision", WhereOperator.GreaterThanOrEqualTo, "FirstRevision"); List<Parameter> parameters = new List<Parameter>(4); parameters.Add(new Parameter(ParameterType.String, "Page", name)); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspace)); if(revision != -1) parameters.Add(new Parameter(ParameterType.Int16, "Revision", revision)); parameters.Add(new Parameter(ParameterType.Int16, "FirstRevision", FirstRevision)); DbCommand command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); if(rows == -1) { RollbackTransaction(transaction); return false; } if(revision != -1) { int revisionDelta = revision + 1; query = queryBuilder.UpdateIncrement("PageContent", "Revision", -revisionDelta); query = queryBuilder.Where(query, "Page", WhereOperator.Equals, "Page"); query = queryBuilder.AndWhere(query, "Namespace", WhereOperator.Equals, "Namespace"); query = queryBuilder.AndWhere(query, "Revision", WhereOperator.GreaterThanOrEqualTo, "FirstRevision"); parameters = new List<Parameter>(3); parameters.Add(new Parameter(ParameterType.String, "Page", name)); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspace)); parameters.Add(new Parameter(ParameterType.Int16, "FirstRevision", FirstRevision)); command = builder.GetCommand(transaction, query, parameters); rows = ExecuteNonQuery(command, false); if(rows > 0) CommitTransaction(transaction); else RollbackTransaction(transaction); return rows >= 0; } else { CommitTransaction(transaction); return true; } }
/// <summary> /// Stores the content for a revision. /// </summary> /// <param name="transaction">A database transaction.</param> /// <param name="content">The content.</param> /// <param name="revision">The revision.</param> /// <returns><c>true</c> if the content is stored, <c>false</c> otherwise.</returns> private bool SetContent(DbTransaction transaction, PageContent content, int revision) { string name, nspace; NameTools.ExpandFullName(content.PageInfo.FullName, out nspace, out name); if(nspace == null) nspace = ""; ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.InsertInto("PageContent", new string[] { "Page", "Namespace", "Revision", "Title", "User", "LastModified", "Comment", "Content", "Description" }, new string[] { "Page", "Namespace", "Revision", "Title", "User", "LastModified", "Comment", "Content", "Description" }); List<Parameter> parameters = new List<Parameter>(9); parameters.Add(new Parameter(ParameterType.String, "Page", name)); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspace)); parameters.Add(new Parameter(ParameterType.Int16, "Revision", revision)); parameters.Add(new Parameter(ParameterType.String, "Title", content.Title)); parameters.Add(new Parameter(ParameterType.String, "User", content.User)); parameters.Add(new Parameter(ParameterType.DateTime, "LastModified", content.LastModified)); if(!string.IsNullOrEmpty(content.Comment)) parameters.Add(new Parameter(ParameterType.String, "Comment", content.Comment)); else parameters.Add(new Parameter(ParameterType.String, "Comment", DBNull.Value)); parameters.Add(new Parameter(ParameterType.String, "Content", content.Content)); if(!string.IsNullOrEmpty(content.Description)) parameters.Add(new Parameter(ParameterType.String, "Description", content.Description)); else parameters.Add(new Parameter(ParameterType.String, "Description", DBNull.Value)); DbCommand command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); if(rows != 1) return false; if(content.Keywords.Length > 0) { parameters = new List<Parameter>(content.Keywords.Length * 4); string fullQuery = ""; int count = 0; string countString; foreach(string kw in content.Keywords) { countString = count.ToString(); query = queryBuilder.InsertInto("PageKeyword", new string[] { "Page", "Namespace", "Revision", "Keyword" }, new string[] { "Page" + countString, "Namespace" + countString, "Revision" + countString, "Keyword" + countString }); fullQuery = queryBuilder.AppendForBatch(fullQuery, query); parameters.Add(new Parameter(ParameterType.String, "Page" + countString, name)); parameters.Add(new Parameter(ParameterType.String, "Namespace" + countString, nspace)); parameters.Add(new Parameter(ParameterType.Int16, "Revision" + countString, revision)); parameters.Add(new Parameter(ParameterType.String, "Keyword" + countString, kw)); count++; } command = builder.GetCommand(transaction, fullQuery, parameters); rows = ExecuteNonQuery(command, false); return rows == content.Keywords.Length; } else return true; }
/// <summary> /// Saves data for a new document. /// </summary> /// <param name="document">The document.</param> /// <param name="content">The content words.</param> /// <param name="title">The title words.</param> /// <param name="keywords">The keywords.</param> /// <param name="state">A state object passed from the index (can be <c>null</c> or a <see cref="T:DbTransaction" />).</param> /// <returns>The number of stored occurrences.</returns> private int SaveDataForDocument(IDocument document, WordInfo[] content, WordInfo[] title, WordInfo[] keywords, object state) { // 1. Insert document // 2. Insert all new words // 3. Load all word IDs // 4. Insert mappings // On error, return without rolling back if state != null, rollback otherwise // On completion, commit if state == null ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); DbTransaction transaction = null; if(state != null) transaction = (DbTransaction)state; else { DbConnection connection = builder.GetConnection(connString); transaction = BeginTransaction(connection); } uint freeDocumentId = GetFreeElementId(IndexElementType.Documents, transaction); uint freeWordId = GetFreeElementId(IndexElementType.Words, transaction); // Insert the document string query = queryBuilder.InsertInto("IndexDocument", new string[] { "Id", "Name", "Title", "TypeTag", "DateTime" }, new string[] { "Id", "Name", "Title", "TypeTag", "DateTime" }); List<Parameter> parameters = new List<Parameter>(5); parameters.Add(new Parameter(ParameterType.Int32, "Id", (int)freeDocumentId)); parameters.Add(new Parameter(ParameterType.String, "Name", document.Name)); parameters.Add(new Parameter(ParameterType.String, "Title", document.Title)); parameters.Add(new Parameter(ParameterType.String, "TypeTag", document.TypeTag)); parameters.Add(new Parameter(ParameterType.DateTime, "DateTime", document.DateTime)); DbCommand command = builder.GetCommand(transaction, query, parameters); if(ExecuteNonQuery(command, false) != 1) { if(state == null) RollbackTransaction(transaction); return -1; } document.ID = freeDocumentId; List<WordInfo> allWords = new List<WordInfo>(content.Length + title.Length + keywords.Length); allWords.AddRange(content); allWords.AddRange(title); allWords.AddRange(keywords); List<WordInfo> existingWords = new List<WordInfo>(allWords.Count / 2); Dictionary<string, uint> wordIds = new Dictionary<string, uint>(1024); // Try to blindly insert all words (assumed to be lowercase and clean from diacritics) query = queryBuilder.InsertInto("IndexWord", new string[] { "Id", "Text" }, new string[] { "Id", "Text" }); parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.Int32, "Id", 0)); parameters.Add(new Parameter(ParameterType.String, "Text", "")); foreach(WordInfo word in allWords) { parameters[0].Value = (int)freeWordId; parameters[1].Value = word.Text; command = builder.GetCommand(transaction, query, parameters); if(ExecuteNonQuery(command, false, false) == 1) { wordIds.Add(word.Text, freeWordId); freeWordId++; } else { existingWords.Add(word); } } // Load IDs of all existing words query = queryBuilder.SelectFrom("IndexWord", new string[] { "Id" }); query = queryBuilder.Where(query, "Text", WhereOperator.Equals, "Text"); parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Text", "")); foreach(WordInfo word in existingWords) { parameters[0].Value = word.Text; command = builder.GetCommand(transaction, query, parameters); int id = ExecuteScalar<int>(command, -1, false); if(id == -1) { if(state == null) RollbackTransaction(transaction); return -1; } if(!wordIds.ContainsKey(word.Text)) { wordIds.Add(word.Text, (uint)id); } else if(wordIds[word.Text] != (uint)id) throw new InvalidOperationException("Word ID mismatch"); } // Insert all mappings query = queryBuilder.InsertInto("IndexWordMapping", new string[] { "Word", "Document", "FirstCharIndex", "WordIndex", "Location" }, new string[] { "Word", "Document", "FirstCharIndex", "WordIndex", "Location" }); parameters = new List<Parameter>(5); parameters.Add(new Parameter(ParameterType.Int32, "Word", 0)); parameters.Add(new Parameter(ParameterType.Int32, "Document", (int)freeDocumentId)); parameters.Add(new Parameter(ParameterType.Int16, "FirstCharIndex", 0)); parameters.Add(new Parameter(ParameterType.Int16, "WordIndex", 0)); parameters.Add(new Parameter(ParameterType.Byte, "Location", 0)); foreach(WordInfo word in allWords) { parameters[0].Value = (int)wordIds[word.Text]; parameters[1].Value = (int)freeDocumentId; parameters[2].Value = (short)word.FirstCharIndex; parameters[3].Value = (short)word.WordIndex; parameters[4].Value = word.Location.Location; command = builder.GetCommand(transaction, query, parameters); if(ExecuteNonQuery(command, false) != 1) { if(state == null) RollbackTransaction(transaction); return -1; } } if(state == null) CommitTransaction(transaction); return allWords.Count; }
/// <summary> /// Removes a new Snippet. /// </summary> /// <param name="connection">A database connection.</param> /// <param name="name">The Name of the Snippet to remove.</param> /// <returns><c>true</c> if the snippet is removed, <c>false</c> otherwise.</returns> private bool RemoveSnippet(DbConnection connection, string name) { ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.DeleteFrom("Snippet"); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Name", name)); DbCommand command = builder.GetCommand(connection, query, parameters); int rows = ExecuteNonQuery(command, false); return rows == 1; }
/// <summary> /// Deletes a File. /// </summary> /// <param name="fullName">The full name of the File.</param> /// <returns><c>true</c> if the File is deleted, <c>false</c> otherwise.</returns> /// <exception cref="ArgumentNullException">If <paramref name="fullName"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="fullName"/> is empty or it does not exist.</exception> public bool DeleteFile(string fullName) { if(fullName == null) throw new ArgumentNullException("fullName"); if(fullName.Length == 0) throw new ArgumentException("Full Name cannot be empty", "fullName"); ICommandBuilder builder = GetCommandBuilder(); DbConnection connection = builder.GetConnection(connString); DbTransaction transaction = BeginTransaction(connection); if(!FileExists(transaction, fullName)) { RollbackTransaction(transaction); throw new ArgumentException("File does not exist", "fullName"); } QueryBuilder queryBuilder = new QueryBuilder(builder); string directory, filename; SplitFileFullName(fullName, out directory, out filename); string query = queryBuilder.DeleteFrom("File"); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Directory", WhereOperator.Equals, "Directory"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name", filename)); parameters.Add(new Parameter(ParameterType.String, "Directory", directory)); DbCommand command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); if(rows == 1) CommitTransaction(transaction); else RollbackTransaction(transaction); return rows == 1; }
/// <summary> /// Gets all the sub-namespaces. /// </summary> /// <returns>The sub-namespaces, sorted by name.</returns> public NamespaceInfo[] GetNamespaces() { ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); // select ... from Namespace left join Page on Namespace.DefaultPage = Page.Name where Namespace.Name <> '' and (Namespace.DefaultPage is null or Page.Namespace <> '') string query = queryBuilder.SelectFrom("Namespace", "Page", "DefaultPage", "Name", Join.LeftJoin, new string[] { "Name", "DefaultPage" }, new string[] { "CreationDateTime" }); query = queryBuilder.Where(query, "Namespace", "Name", WhereOperator.NotEquals, "Empty1"); query = queryBuilder.AndWhere(query, "Namespace", "DefaultPage", WhereOperator.IsNull, null, true, false); query = queryBuilder.OrWhere(query, "Page", "Namespace", WhereOperator.NotEquals, "Empty2", false, true); query = queryBuilder.OrderBy(query, new[] { "Namespace_Name" }, new[] { Ordering.Asc }); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Empty1", "")); parameters.Add(new Parameter(ParameterType.String, "Empty2", "")); DbCommand command = builder.GetCommand(connString, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { List<NamespaceInfo> result = new List<NamespaceInfo>(10); while(reader.Read()) { string realName = reader["Namespace_Name"] as string; string page = GetNullableColumn<string>(reader, "Namespace_DefaultPage", null); PageInfo defaultPage = string.IsNullOrEmpty(page) ? null : new PageInfo(NameTools.GetFullName(realName, page), this, (DateTime)reader["Page_CreationDateTime"]); // The query returns duplicate entries if the main page of two or more namespaces have the same name if(result.Find(n => { return n.Name.Equals(realName); }) == null) { result.Add(new NamespaceInfo(realName, this, defaultPage)); } } CloseReader(command, reader); return result.ToArray(); } else return null; }
/// <summary> /// Returns the names of the Attachments of a Page. /// </summary> /// <param name="connection">A database connection.</param> /// <param name="pageInfo">The Page Info object that owns the Attachments.</param> /// <returns>The names, or an empty list.</returns> private string[] ListPageAttachments(DbConnection connection, PageInfo pageInfo) { ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("Attachment", new string[] { "Name" }); query = queryBuilder.Where(query, "Page", WhereOperator.Equals, "Page"); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Page", pageInfo.FullName)); query = queryBuilder.OrderBy(query, new[] { "Name" }, new[] { Ordering.Asc }); DbCommand command = builder.GetCommand(connection, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { List<string> result = new List<string>(10); while(reader.Read()) { result.Add(reader["Name"] as string); } CloseReader(reader); return result.ToArray(); } else return null; }
/// <summary> /// Gets all the Navigation Paths in a Namespace. /// </summary> /// <param name="nspace">The Namespace.</param> /// <returns>All the Navigation Paths, sorted by name.</returns> public NavigationPath[] GetNavigationPaths(NamespaceInfo nspace) { string nspaceName = nspace != null ? nspace.Name : ""; ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("NavigationPath", new string[] { "Name", "Namespace", "Page" }); query = queryBuilder.Where(query, "Namespace", WhereOperator.Equals, "Namespace"); query = queryBuilder.OrderBy(query, new string[] { "Namespace", "Name", "Number" }, new Ordering[] { Ordering.Asc, Ordering.Asc, Ordering.Asc }); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspaceName)); DbCommand command = builder.GetCommand(connString, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { List<NavigationPath> result = new List<NavigationPath>(10); string prevName = "|||"; string name; string actualNamespace = ""; List<string> pages = new List<string>(10); while(reader.Read()) { name = reader["Name"] as string; if(name != prevName) { actualNamespace = reader["Namespace"] as string; if(prevName != "|||") { result[result.Count - 1].Pages = pages.ToArray(); pages.Clear(); } result.Add(new NavigationPath(NameTools.GetFullName(actualNamespace, name), this)); } prevName = name; pages.Add(NameTools.GetFullName(actualNamespace, reader["Page"] as string)); } if(result.Count > 0) { result[result.Count - 1].Pages = pages.ToArray(); } CloseReader(command, reader); return result.ToArray(); } else return null; }
/// <summary> /// Gets the details of a file. /// </summary> /// <param name="fullName">The full name of the file.</param> /// <returns>The details, or <c>null</c> if the file does not exist.</returns> /// <exception cref="ArgumentNullException">If <paramref name="fullName"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="fullName"/> is empty.</exception> public FileDetails GetFileDetails(string fullName) { if(fullName == null) throw new ArgumentNullException("fullName"); if(fullName.Length == 0) throw new ArgumentException("Full Name cannot be empty", "fullName"); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string directory, filename; SplitFileFullName(fullName, out directory, out filename); string query = queryBuilder.SelectFrom("File", new string[] { "Size", "Downloads", "LastModified" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Directory", WhereOperator.Equals, "Directory"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name", filename)); parameters.Add(new Parameter(ParameterType.String, "Directory", directory)); DbCommand command = builder.GetCommand(connString, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { FileDetails details = null; if(reader.Read()) { details = new FileDetails((long)reader["Size"], (DateTime)reader["LastModified"], (int)reader["Downloads"]); } CloseReader(command, reader); return details; } else return null; }
/// <summary> /// Determines whether a page attachment exists. /// </summary> /// <param name="transaction">A database transaction.</param> /// <param name="page">The page.</param> /// <param name="name">The attachment.</param> /// <returns><c>true</c> if the attachment exists, <c>false</c> otherwise.</returns> private bool AttachmentExists(DbTransaction transaction, PageInfo page, string name) { ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectCountFrom("Attachment"); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Page", WhereOperator.Equals, "Page"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name", name)); parameters.Add(new Parameter(ParameterType.String, "Page", page.FullName)); DbCommand command = builder.GetCommand(transaction, query, parameters); int count = ExecuteScalar<int>(command, -1, false); return count == 1; }
/// <summary> /// The the names of the pages with attachments. /// </summary> /// <returns>The names of the pages with attachments.</returns> public string[] GetPagesWithAttachments() { ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("Attachment", new string[] { "Page" }); query = queryBuilder.GroupBy(query, new[] { "Page" }); query = queryBuilder.OrderBy(query, new[] { "Page" }, new[] { Ordering.Asc }); DbCommand command = builder.GetCommand(connString, query, new List<Parameter>()); DbDataReader reader = ExecuteReader(command); if(reader != null) { List<string> result = new List<string>(100); while(reader.Read()) { result.Add(reader["Page"] as string); } CloseReader(command, reader); return result.ToArray(); } else return null; }
/// <summary> /// Deletes a directory and all its contents. /// </summary> /// <param name="transaction">The current transaction to use.</param> /// <param name="fullPath">The full path of the directory.</param> /// <returns><c>true</c> if the directory is deleted, <c>false</c> otherwise.</returns> private bool DeleteDirectory(DbTransaction transaction, string fullPath) { string[] dirs = ListDirectories(transaction, fullPath); foreach(string dir in dirs) { if(!DeleteDirectory(transaction, dir)) { return false; } } ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.DeleteFrom("Directory"); query = queryBuilder.Where(query, "FullPath", WhereOperator.Equals, "FullPath"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "FullPath", fullPath)); DbCommand command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); return rows > 0; }
/// <summary> /// Notifies the Provider that a Page has been renamed. /// </summary> /// <param name="oldPage">The old Page Info object.</param> /// <param name="newPage">The new Page Info object.</param> /// <exception cref="ArgumentNullException">If <paramref name="oldPage"/> or <paramref name="newPage"/> are <c>null</c>.</exception> /// <exception cref="ArgumentException">If the new page is already in use.</exception> public void NotifyPageRenaming(PageInfo oldPage, PageInfo newPage) { if(oldPage == null) throw new ArgumentNullException("oldPage"); if(newPage == null) throw new ArgumentNullException("newPage"); ICommandBuilder builder = GetCommandBuilder(); DbConnection connection = builder.GetConnection(connString); DbTransaction transaction = BeginTransaction(connection); if(ListPageAttachments(transaction, newPage).Length > 0) { RollbackTransaction(transaction); throw new ArgumentException("New Page already exists", "newPage"); } QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.Update("Attachment", new string[] { "Page" }, new string[] { "NewPage" }); query = queryBuilder.Where(query, "Page", WhereOperator.Equals, "OldPage"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "NewPage", newPage.FullName)); parameters.Add(new Parameter(ParameterType.String, "OldPage", oldPage.FullName)); DbCommand command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); if(rows != -1) CommitTransaction(transaction); else RollbackTransaction(transaction); }
/// <summary> /// Determines whether a directory exists. /// </summary> /// <param name="transaction">A database transaction.</param> /// <param name="directory">The directory, for example "/my/directory".</param> /// <returns><c>true</c> if the directory exists, <c>false</c> otherwise.</returns> /// <remarks>The root directory always exists.</remarks> private bool DirectoryExists(DbTransaction transaction, string directory) { directory = PrepareDirectory(directory); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectCountFrom("Directory"); query = queryBuilder.Where(query, "FullPath", WhereOperator.Equals, "FullPath"); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "FullPath", directory)); DbCommand command = builder.GetCommand(transaction, query, parameters); int count = ExecuteScalar<int>(command, -1, false); return count == 1; }
/// <summary> /// Renames a Page Attachment. /// </summary> /// <param name="pageInfo">The Page Info that owns the Attachment.</param> /// <param name="oldName">The old name of the Attachment.</param> /// <param name="newName">The new name of the Attachment.</param> /// <returns><c>true</c> if the Attachment is renamed, false otherwise.</returns> /// <exception cref="ArgumentNullException">If <paramref name="pageInfo"/>, <paramref name="oldName"/> or <paramref name="newName"/> are <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="pageInfo"/>, <paramref name="oldName"/> or <paramref name="newName"/> are empty, /// or if the page or old attachment do not exist, or the new attachment name already exists.</exception> public bool RenamePageAttachment(PageInfo pageInfo, string oldName, string newName) { if(pageInfo == null) throw new ArgumentNullException("pageInfo"); if(oldName == null) throw new ArgumentNullException("oldName"); if(oldName.Length == 0) throw new ArgumentException("Old Name cannot be empty", "oldName"); if(newName == null) throw new ArgumentNullException("newName"); if(newName.Length == 0) throw new ArgumentException("New Name cannot be empty", "newName"); ICommandBuilder builder = GetCommandBuilder(); DbConnection connection = builder.GetConnection(connString); DbTransaction transaction = BeginTransaction(connection); if(!AttachmentExists(transaction, pageInfo, oldName)) { RollbackTransaction(transaction); throw new ArgumentException("Attachment does not exist", "name"); } if(AttachmentExists(transaction, pageInfo, newName)) { RollbackTransaction(transaction); throw new ArgumentException("Attachment already exists", "name"); } QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.Update("Attachment", new string[] { "Name" }, new string[] { "NewName" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "OldName"); query = queryBuilder.AndWhere(query, "Page", WhereOperator.Equals, "Page"); List<Parameter> parameters = new List<Parameter>(3); parameters.Add(new Parameter(ParameterType.String, "NewName", newName)); parameters.Add(new Parameter(ParameterType.String, "OldName", oldName)); parameters.Add(new Parameter(ParameterType.String, "Page", pageInfo.FullName)); DbCommand command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); if(rows == 1) CommitTransaction(transaction); else RollbackTransaction(transaction); return rows == 1; }
/// <summary> /// Determines whether a file exists. /// </summary> /// <param name="transaction">A database transaction.</param> /// <param name="fullName">The file full name, for example "/file.txt" or "/directory/file.txt".</param> /// <returns><c>true</c> if the file exists, <c>false</c> otherwise.</returns> private bool FileExists(DbTransaction transaction, string fullName) { string directory, file; SplitFileFullName(fullName, out directory, out file); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectCountFrom("File"); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Directory", WhereOperator.Equals, "Directory"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name", file)); parameters.Add(new Parameter(ParameterType.String, "Directory", directory)); DbCommand command = builder.GetCommand(transaction, query, parameters); int count = ExecuteScalar<int>(command, -1, false); return count == 1; }
/// <summary> /// Sets the number of times a file was retrieved. /// </summary> /// <param name="fullName">The full name of the file.</param> /// <param name="count">The count to set.</param> /// <exception cref="ArgumentNullException">If <paramref name="fullName"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="fullName"/> is empty.</exception> /// <exception cref="ArgumentOutOfRangeException">If <paramref name="count"/> is less than zero.</exception> public void SetFileRetrievalCount(string fullName, int count) { if(fullName == null) throw new ArgumentNullException("fullName"); if(fullName.Length == 0) throw new ArgumentException("Full Name cannot be empty", "fullName"); if(count < 0) throw new ArgumentOutOfRangeException("count", "Count must be greater than or equal to zero"); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string directory, filename; SplitFileFullName(fullName, out directory, out filename); string query = queryBuilder.Update("File", new string[] { "Downloads" }, new string[] { "Downloads" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Directory", WhereOperator.Equals, "Directory"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name", filename)); parameters.Add(new Parameter(ParameterType.String, "Directory", directory)); parameters.Add(new Parameter(ParameterType.Int32, "Downloads", count)); DbCommand command = builder.GetCommand(connString, query, parameters); ExecuteNonQuery(command); }
/// <summary> /// Lists the Directories in the specified directory. /// </summary> /// <param name="transaction">A database transaction.</param> /// <param name="directory">The full directory name, for example "/my/directory". Null, empty or "/" for the root directory.</param> /// <returns>The list of Directories in the Directory.</returns> private string[] ListDirectories(DbTransaction transaction, string directory) { directory = PrepareDirectory(directory); ICommandBuilder builder = GetCommandBuilder(); if(!DirectoryExists(transaction, directory)) { RollbackTransaction(transaction); throw new ArgumentException("Directory does not exist", "directory"); } QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("Directory", new string[] { "FullPath" }); query = queryBuilder.Where(query, "Parent", WhereOperator.Equals, "Parent"); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Parent", directory)); query = queryBuilder.OrderBy(query, new[] { "FullPath" }, new[] { Ordering.Asc }); DbCommand command = builder.GetCommand(transaction, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { List<string> result = new List<string>(20); while(reader.Read()) { result.Add(reader["FullPath"] as string); } CloseReader(reader); return result.ToArray(); } else return null; }
/// <summary> /// Stores a Page Attachment. /// </summary> /// <param name="pageInfo">The Page Info that owns the Attachment.</param> /// <param name="name">The name of the Attachment, for example "myfile.jpg".</param> /// <param name="sourceStream">A Stream object used as <b>source</b> of a byte stream, /// i.e. the method reads from the Stream and stores the content properly.</param> /// <param name="overwrite"><c>true</c> to overwrite an existing Attachment.</param> /// <returns><c>true</c> if the Attachment is stored, <c>false</c> otherwise.</returns> /// <remarks>If <b>overwrite</b> is <c>false</c> and Attachment already exists, the method returns <c>false</c>.</remarks> /// <exception cref="ArgumentNullException">If <paramref name="pageInfo"/>, <paramref name="name"/> or <paramref name="sourceStream"/> are <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="name"/> is empty or if <paramref name="sourceStream"/> does not support reading.</exception> public bool StorePageAttachment(PageInfo pageInfo, string name, System.IO.Stream sourceStream, bool overwrite) { if(pageInfo == null) throw new ArgumentNullException("pageInfo"); if(name == null) throw new ArgumentNullException("name"); if(name.Length == 0) throw new ArgumentException("Name cannot be empty", "name"); if(sourceStream == null) throw new ArgumentNullException("sourceStream"); if(!sourceStream.CanRead) throw new ArgumentException("Cannot read from Source Stream", "sourceStream"); ICommandBuilder builder = GetCommandBuilder(); DbConnection connection = builder.GetConnection(connString); DbTransaction transaction = BeginTransaction(connection); bool attachmentExists = AttachmentExists(transaction, pageInfo, name); if(attachmentExists && !overwrite) { RollbackTransaction(transaction); return false; } // To achieve decent performance, an UPDATE query is issued if the attachment exists, // otherwise an INSERT query is issued QueryBuilder queryBuilder = new QueryBuilder(builder); string query; List<Parameter> parameters; byte[] attachmentData = null; int size = Tools.ReadStream(sourceStream, ref attachmentData, MaxFileSize); if(size < 0) { RollbackTransaction(transaction); throw new ArgumentException("Source Stream contains too much data", "sourceStream"); } if(attachmentExists) { query = queryBuilder.Update("Attachment", new string[] { "Size", "LastModified", "Data" }, new string[] { "Size", "LastModified", "Data" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Page", WhereOperator.Equals, "Page"); parameters = new List<Parameter>(5); parameters.Add(new Parameter(ParameterType.Int64, "Size", (long)size)); parameters.Add(new Parameter(ParameterType.DateTime, "LastModified", DateTime.Now)); parameters.Add(new Parameter(ParameterType.ByteArray, "Data", attachmentData)); parameters.Add(new Parameter(ParameterType.String, "Name", name)); parameters.Add(new Parameter(ParameterType.String, "Page", pageInfo.FullName)); } else { query = queryBuilder.InsertInto("Attachment", new string[] { "Name", "Page", "Size", "Downloads", "LastModified", "Data" }, new string[] { "Name", "Page", "Size", "Downloads", "LastModified", "Data" }); parameters = new List<Parameter>(6); parameters.Add(new Parameter(ParameterType.String, "Name", name)); parameters.Add(new Parameter(ParameterType.String, "Page", pageInfo.FullName)); parameters.Add(new Parameter(ParameterType.Int64, "Size", (long)size)); parameters.Add(new Parameter(ParameterType.Int32, "Downloads", 0)); parameters.Add(new Parameter(ParameterType.DateTime, "LastModified", DateTime.Now)); parameters.Add(new Parameter(ParameterType.ByteArray, "Data", attachmentData)); } DbCommand command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); if(rows == 1) CommitTransaction(transaction); else RollbackTransaction(transaction); return rows == 1; }
/// <summary> /// Removes a Message. /// </summary> /// <param name="transaction">A database transaction.</param> /// <param name="page">The Page.</param> /// <param name="id">The ID of the Message to remove.</param> /// <param name="removeReplies">A value specifying whether or not to remove the replies.</param> /// <returns>True if the Message is removed successfully.</returns> private bool RemoveMessage(DbTransaction transaction, PageInfo page, int id, bool removeReplies) { string nspace, name; NameTools.ExpandFullName(page.FullName, out nspace, out name); if(nspace == null) nspace = ""; Message[] messages = GetMessages(transaction, page); if(messages == null) return false; Message message = FindMessage(messages, id); if(message == null) return false; Message parent = FindAnchestor(messages, id); int parentId = parent != null ? parent.ID : -1; UnindexMessage(page, message.ID, message.Subject, message.DateTime, message.Body, transaction); if(removeReplies) { // Recursively remove all replies BEFORE removing parent (depth-first) foreach(Message reply in message.Replies) { if(!RemoveMessage(transaction, page, reply.ID, true)) return false; } } // Remove this message ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.DeleteFrom("Message"); query = queryBuilder.Where(query, "Page", WhereOperator.Equals, "Page"); query = queryBuilder.AndWhere(query, "Namespace", WhereOperator.Equals, "Namespace"); query = queryBuilder.AndWhere(query, "Id", WhereOperator.Equals, "Id"); List<Parameter> parameters = new List<Parameter>(3); parameters.Add(new Parameter(ParameterType.String, "Page", name)); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspace)); parameters.Add(new Parameter(ParameterType.Int16, "Id", (short)id)); DbCommand command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); if(!removeReplies && rows == 1) { // Update replies' parent id query = queryBuilder.Update("Message", new string[] { "Parent" }, new string[] { "NewParent" }); query = queryBuilder.Where(query, "Page", WhereOperator.Equals, "Page"); query = queryBuilder.AndWhere(query, "Namespace", WhereOperator.Equals, "Namespace"); query = queryBuilder.AndWhere(query, "Parent", WhereOperator.Equals, "OldParent"); parameters = new List<Parameter>(4); if(parentId != -1) parameters.Add(new Parameter(ParameterType.Int16, "NewParent", parentId)); else parameters.Add(new Parameter(ParameterType.Int16, "NewParent", DBNull.Value)); parameters.Add(new Parameter(ParameterType.String, "Page", name)); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspace)); parameters.Add(new Parameter(ParameterType.Int16, "OldParent", (short)id)); command = builder.GetCommand(transaction, query, parameters); rows = ExecuteNonQuery(command, false); } return rows > 0; }