public SelectFrom ( string table ) : string | ||
table | string | The table. |
return | string |
/// <summary> /// Gets all the Log Entries, sorted by date/time (oldest to newest). /// </summary> /// <returns>The Log Entries.</returns> public LogEntry[] GetLogEntries() { ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("Log", new string[] { "DateTime", "EntryType", "User", "Message", "Wiki" }); query = queryBuilder.OrderBy(query, new string[] { "DateTime" }, new Ordering[] { Ordering.Asc }); DbCommand command = builder.GetCommand(connString, query, new List <Parameter>()); DbDataReader reader = ExecuteReader(command); if (reader != null) { List <LogEntry> result = new List <LogEntry>(100); while (reader.Read()) { result.Add(new LogEntry(EntryTypeFromChar((reader["EntryType"] as string)[0]), new DateTime(((DateTime)reader["DateTime"]).Ticks, DateTimeKind.Utc), reader["Message"] as string, reader["User"] as string, reader["Wiki"] as string)); } CloseReader(command, reader); return(result.ToArray()); } else { return(null); } }
public override string[] List() { ICommandBuilder builder = _sqlStorageProviderUtility.GetCommandBuilder2(); DbConnection connection = builder.GetConnection(_connString); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("SearchIndex", new string[] { "Name" }); query = queryBuilder.Where(query, "Wiki", WhereOperator.Equals, "Wiki"); query = queryBuilder.OrderBy(query, new[] { "Name" }, new[] { Ordering.Asc }); List <Parameter> parameters = new List <Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Wiki", _wiki)); DbCommand command = builder.GetCommand(connection, query, parameters); DbDataReader reader = _sqlStorageProviderUtility.ExecuteReader(command); List <string> result = new List <string>(20); if (reader != null) { while (reader.Read()) { result.Add(reader["Name"] as string); } _sqlStorageProviderUtility.CloseReader(command, reader); } return(result.ToArray()); }
/// <summary> /// Retrieves a plugin's assembly. /// </summary> /// <param name="filename">The file name of the assembly.</param> /// <returns>The assembly content, or <c>null</c>.</returns> /// <exception cref="ArgumentNullException">If <b>filename</b> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <b>filename</b> is empty.</exception> public byte[] RetrievePluginAssembly(string filename) { if (filename == null) { throw new ArgumentNullException("filename"); } if (filename.Length == 0) { throw new ArgumentException("Filename cannot be empty", "filename"); } ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("PluginAssembly", new string[] { "Assembly" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); List <Parameter> parameters = new List <Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Name", filename)); DbCommand command = builder.GetCommand(connString, query, parameters); DbDataReader reader = ExecuteReader(command); if (reader != null) { byte[] result = null; if (reader.Read()) { result = GetBinaryColumn(reader, "Assembly", MaxAssemblySize); } CloseReader(command, reader); return(result); } else { return(null); } }
/// <summary> /// Determines whether this instance is locked. /// </summary> /// <returns><c>true</c> if this instance is locked; otherwise, <c>false</c>.</returns> public override bool IsLocked() { ICommandBuilder builder = _sqlStorageProviderUtility.GetCommandBuilder2(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("SearchIndexLock"); query = queryBuilder.Where(query, "Wiki", WhereOperator.Equals, "Wiki"); query = queryBuilder.AndWhere(query, "Name", WhereOperator.Equals, "Name"); List <Parameter> parameters = new List <Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Wiki", _wiki)); parameters.Add(new Parameter(ParameterType.String, "Name", _name)); DbCommand command = builder.GetCommand(_connString, query, parameters); DbDataReader reader = _sqlStorageProviderUtility.ExecuteReader(command); if (reader != null) { string result = null; if (reader.Read()) { result = reader["Value"] as string; } _sqlStorageProviderUtility.CloseReader(command, reader); return(result == "locked"); } else { return(false); } }
/// <summary> /// Get last time a file has been modified. /// </summary> /// <param name="name">The name of the file.</param> /// <returns>Last modified time.</returns> public override long FileModified(string name) { ICommandBuilder builder = _sqlStorageProviderUtility.GetCommandBuilder2(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("SearchIndex", new string[] { "LastModified" }); query = queryBuilder.Where(query, "Wiki", WhereOperator.Equals, "Wiki"); query = queryBuilder.AndWhere(query, "Name", WhereOperator.Equals, "Name"); List <Parameter> parameters = new List <Parameter>(3); parameters.Add(new Parameter(ParameterType.String, "Wiki", _wiki)); parameters.Add(new Parameter(ParameterType.String, "Name", name)); DbCommand command = builder.GetCommand(_connString, query, parameters); DbDataReader reader = _sqlStorageProviderUtility.ExecuteReader(command); if (reader != null) { long lastModified = 0; if (reader.Read()) { lastModified = ((DateTime)reader["LastModified"]).Ticks; } _sqlStorageProviderUtility.CloseReader(command, reader); return(lastModified); } else { return(0); } }
/// <summary> /// Reduces the size of the Log to the specified size (or less). /// </summary> /// <param name="size">The size to shrink the log to (in bytes).</param> private void CutLog(int size) { ICommandBuilder builder = GetCommandBuilder(); DbConnection connection = builder.GetConnection(connString); DbTransaction transaction = BeginTransaction(connection); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectCountFrom("Log"); DbCommand command = builder.GetCommand(transaction, query, new List <Parameter>()); int rows = ExecuteScalar <int>(command, -1, false); if (rows == -1) { RollbackTransaction(transaction); return; } int estimatedSize = rows * EstimatedLogEntrySize; if (size < estimatedSize) { int difference = estimatedSize - size; int entriesToDelete = difference / EstimatedLogEntrySize; // Add 10% to avoid 1-by-1 deletion when adding new entries entriesToDelete += entriesToDelete / 10; if (entriesToDelete > 0) { // This code is not optimized, but it surely works in most DBMS query = queryBuilder.SelectFrom("Log", new string[] { "Id" }); query = queryBuilder.OrderBy(query, new string[] { "Id" }, new Ordering[] { Ordering.Asc }); command = builder.GetCommand(transaction, query, new List <Parameter>()); DbDataReader reader = ExecuteReader(command); List <int> ids = new List <int>(entriesToDelete); if (reader != null) { while (reader.Read() && ids.Count < entriesToDelete) { ids.Add((int)reader["Id"]); } CloseReader(reader); } if (ids.Count > 0) { // Given that the IDs to delete can be many, the query is split in many chunks, each one deleting 50 items // This works-around the problem of too many parameters in a RPC call of SQL Server // See also CutRecentChangesIfNecessary for (int chunk = 0; chunk <= ids.Count / MaxParametersInQuery; chunk++) { query = queryBuilder.DeleteFrom("Log"); List <string> parms = new List <string>(MaxParametersInQuery); List <Parameter> parameters = new List <Parameter>(MaxParametersInQuery); for (int i = chunk * MaxParametersInQuery; i < Math.Min(ids.Count, (chunk + 1) * MaxParametersInQuery); i++) { parms.Add("P" + i.ToString()); parameters.Add(new Parameter(ParameterType.Int32, parms[parms.Count - 1], ids[i])); } query = queryBuilder.WhereIn(query, "Id", parms.ToArray()); command = builder.GetCommand(transaction, query, parameters); if (ExecuteNonQuery(command, false) < 0) { RollbackTransaction(transaction); return; } } } CommitTransaction(transaction); } } }
/// <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> /// Gets a meta-data item's content. /// </summary> /// <param name="item">The item.</param> /// <param name="tag">The tag that specifies the context (usually the namespace).</param> /// <returns>The content.</returns> public string GetMetaDataItem(MetaDataItem item, string tag) { if(tag == null) tag = ""; ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("MetaDataItem", new string[] { "Data" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); query = queryBuilder.AndWhere(query, "Tag", WhereOperator.Equals, "Tag"); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name", item.ToString())); parameters.Add(new Parameter(ParameterType.String, "Tag", tag)); DbCommand command = builder.GetCommand(connString, query, parameters); string value = ExecuteScalar<string>(command, ""); return value; }
/// <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> /// Gets all the Pages in a namespace. /// </summary> /// <param name="connection">A database connection.</param> /// <param name="nspace">The namespace (<c>null</c> for the root).</param> /// <returns>All the Pages in the namespace. The array is not sorted.</returns> private PageInfo[] GetPages(DbConnection connection, NamespaceInfo nspace) { string nspaceName = nspace != null ? nspace.Name : ""; ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("Page"); query = queryBuilder.Where(query, "Namespace", WhereOperator.Equals, "Namespace"); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspaceName)); query = queryBuilder.OrderBy(query, new[] { "Name" }, new[] { Ordering.Asc }); DbCommand command = builder.GetCommand(connection, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { List<PageInfo> result = new List<PageInfo>(100); while(reader.Read()) { result.Add(new PageInfo(NameTools.GetFullName(reader["Namespace"] as string, reader["Name"] as string), this, (DateTime)reader["CreationDateTime"])); } CloseReader(reader); return result.ToArray(); } else return null; }
/// <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> /// Retrieves a plugin's assembly. /// </summary> /// <param name="filename">The file name of the assembly.</param> /// <returns>The assembly content, or <c>null</c>.</returns> /// <exception cref="ArgumentNullException">If <b>filename</b> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <b>filename</b> is empty.</exception> public byte[] RetrievePluginAssembly(string filename) { if(filename == null) throw new ArgumentNullException("filename"); if(filename.Length == 0) throw new ArgumentException("Filename cannot be empty", "filename"); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("PluginAssembly", new string[] { "Assembly" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Name", filename)); DbCommand command = builder.GetCommand(connString, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { byte[] result = null; if(reader.Read()) { result = GetBinaryColumn(reader, "Assembly", MaxAssemblySize); } CloseReader(command, reader); return result; } else return null; }
/// <summary> /// Adds a new Message to a Page. /// </summary> /// <param name="page">The Page.</param> /// <param name="username">The Username.</param> /// <param name="subject">The Subject.</param> /// <param name="dateTime">The Date/Time.</param> /// <param name="body">The Body.</param> /// <param name="parent">The Parent Message ID, or -1.</param> /// <returns>True if the Message is added successfully.</returns> /// <exception cref="ArgumentNullException">If <paramref name="page"/>, <paramref name="username"/>, <paramref name="subject"/> or <paramref name="body"/> are <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="username"/> or <paramref name="subject"/> are empty.</exception> /// <exception cref="ArgumentOutOfRangeException">If <paramref name="parent"/> is less than -1.</exception> public bool AddMessage(PageInfo page, string username, string subject, DateTime dateTime, string body, int parent) { if(page == null) throw new ArgumentNullException("page"); if(username == null) throw new ArgumentNullException("username"); if(username.Length == 0) throw new ArgumentException("Username cannot be empty", "username"); if(subject == null) throw new ArgumentNullException("subject"); if(subject.Length == 0) throw new ArgumentException("Subject cannot be empty", "subject"); if(body == null) throw new ArgumentNullException("body"); // body can be empty if(parent < -1) throw new ArgumentOutOfRangeException("parent", "Invalid Parent Message ID"); string nspace, name; NameTools.ExpandFullName(page.FullName, out nspace, out name); if(nspace == null) nspace = ""; ICommandBuilder builder = GetCommandBuilder(); DbConnection connection = builder.GetConnection(connString); DbTransaction transaction = BeginTransaction(connection); if(parent != -1 && FindMessage(GetMessages(transaction, page), parent) == null) { RollbackTransaction(transaction); return false; } QueryBuilder queryBuilder = new QueryBuilder(builder); short freeId = -1; string query = queryBuilder.SelectFrom("Message", new string[] { "Id" }); query = queryBuilder.Where(query, "Page", WhereOperator.Equals, "Page"); query = queryBuilder.AndWhere(query, "Namespace", WhereOperator.Equals, "Namespace"); query = queryBuilder.OrderBy(query, new string[] { "Id" }, new Ordering[] { Ordering.Desc }); 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(transaction, query, parameters); freeId = ExecuteScalar<short>(command, -1, false); if(freeId == -1) freeId = 0; else freeId++; query = queryBuilder.InsertInto("Message", new string[] { "Page", "Namespace", "Id", "Parent", "Username", "Subject", "DateTime", "Body" }, new string[] { "Page", "Namespace", "Id", "Parent", "Username", "Subject", "DateTime", "Body" }); parameters = new List<Parameter>(8); parameters.Add(new Parameter(ParameterType.String, "Page", name)); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspace)); parameters.Add(new Parameter(ParameterType.Int16, "Id", freeId)); if(parent != -1) parameters.Add(new Parameter(ParameterType.Int16, "Parent", parent)); else parameters.Add(new Parameter(ParameterType.Int16, "Parent", DBNull.Value)); parameters.Add(new Parameter(ParameterType.String, "Username", username)); parameters.Add(new Parameter(ParameterType.String, "Subject", subject)); parameters.Add(new Parameter(ParameterType.DateTime, "DateTime", dateTime)); parameters.Add(new Parameter(ParameterType.String, "Body", body)); command = builder.GetCommand(transaction, query, parameters); int rows = ExecuteNonQuery(command, false); if(rows == 1) { IndexMessage(page, freeId, subject, dateTime, body, transaction); CommitTransaction(transaction); return true; } else { RollbackTransaction(transaction); return false; } }
/// <summary> /// Gets the recent changes of the Wiki. /// </summary> /// <returns>The recent Changes, oldest to newest.</returns> public RecentChange[] GetRecentChanges() { ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("RecentChange", new string[] { "Page", "Title", "MessageSubject", "DateTime", "User", "Change", "Description" }); query = queryBuilder.OrderBy(query, new string[] { "DateTime" }, new Ordering[] { Ordering.Asc }); DbCommand command = builder.GetCommand(connString, query, new List<Parameter>()); DbDataReader reader = ExecuteReader(command); if(reader != null) { List<RecentChange> result = new List<RecentChange>(100); while(reader.Read()) { result.Add(new RecentChange(reader["Page"] as string, reader["Title"] as string, GetNullableColumn<string>(reader, "MessageSubject", ""), (DateTime)reader["DateTime"], reader["User"] as string, RecentChangeFromChar(((string)reader["Change"])[0]), GetNullableColumn<string>(reader, "Description", ""))); } CloseReader(command, reader); return result.ToArray(); } else return null; }
/// <summary> /// Retrieves the value of a Setting. /// </summary> /// <param name="name">The name of the Setting.</param> /// <returns>The value of the Setting, or null.</returns> /// <exception cref="ArgumentNullException">If <b>name</b> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <b>name</b> is empty.</exception> public string GetSetting(string name) { if(name == null) throw new ArgumentNullException("name"); if(name.Length == 0) throw new ArgumentException("Name cannot be empty", "name"); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("Setting"); 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(connString, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { string result = null; if(reader.Read()) { result = reader["Value"] as string; } CloseReader(command, reader); // HACK: this allows to correctly initialize a fully SQL-based wiki instance without any user intervention if(string.IsNullOrEmpty(result)) { if(name == "DefaultUsersProvider") result = DefaultUsersStorageProvider; if(name == "DefaultPagesProvider") result = DefaultPagesStorageProvider; if(name == "DefaultFilesProvider") result = DefaultFilesStorageProvider; } return result; } else return null; }
/// <summary> /// Gets the status of a plugin. /// </summary> /// <param name="typeName">The Type name of the plugin.</param> /// <returns>The status (<c>false</c> for disabled, <c>true</c> for enabled), or <c>true</c> if no status is found.</returns> /// <exception cref="ArgumentNullException">If <b>typeName</b> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <b>typeName</b> is empty.</exception> public bool GetPluginStatus(string typeName) { if(typeName == null) throw new ArgumentNullException("typeName"); if(typeName.Length == 0) throw new ArgumentException("Type Name cannot be empty", "typeName"); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("PluginStatus", new string[] { "Enabled" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Name", typeName)); DbCommand command = builder.GetCommand(connString, query, parameters); DbDataReader reader = ExecuteReader(command); bool? enabled = null; if(reader != null && reader.Read()) { if(!IsDBNull(reader, "Enabled")) enabled = (bool)reader["Enabled"]; } CloseReader(command, reader); if(enabled.HasValue) return enabled.Value; else { if(typeName == "ScrewTurn.Wiki.UsersStorageProvider" || typeName == "ScrewTurn.Wiki.PagesStorageProvider" || typeName == "ScrewTurn.Wiki.FilesStorageProvider") return false; else return true; } }
/// <summary> /// Gets the configuration of a plugin. /// </summary> /// <param name="typeName">The Type name of the plugin.</param> /// <returns>The plugin configuration, or <b>String.Empty</b>.</returns> /// <exception cref="ArgumentNullException">If <b>typeName</b> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <b>typeName</b> is empty.</exception> public string GetPluginConfiguration(string typeName) { if(typeName == null) throw new ArgumentNullException("typeName"); if(typeName.Length == 0) throw new ArgumentException("Type Name cannot be empty", "typeName"); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("PluginStatus", new string[] { "Configuration" }); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "Name"); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Name", typeName)); DbCommand command = builder.GetCommand(connString, query, parameters); string result = ExecuteScalar<string>(command, ""); return result; }
/// <summary> /// Gets the outgoing links of a page. /// </summary> /// <param name="page">The full name of the page.</param> /// <returns>The outgoing links.</returns> /// <exception cref="ArgumentNullException">If <b>page</b> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <b>page</b> is empty.</exception> public string[] GetOutgoingLinks(string page) { if(page == null) throw new ArgumentNullException("page"); if(page.Length == 0) throw new ArgumentException("Page cannot be empty", "page"); ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("OutgoingLink", new string[] { "Destination" }); query = queryBuilder.Where(query, "Source", WhereOperator.Equals, "Source"); query = queryBuilder.OrderBy(query, new[] { "Destination" }, new[] { Ordering.Asc }); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Source", page)); DbCommand command = builder.GetCommand(connString, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { List<string> result = new List<string>(20); while(reader.Read()) { result.Add(reader["Destination"] as string); } CloseReader(command, reader); return result.ToArray(); } else return null; }
/// <summary> /// Gets a namespace. /// </summary> /// <param name="connection">A database connection.</param> /// <param name="name">The name of the namespace (cannot be <c>null</c> or empty).</param> /// <returns>The <see cref="T:NamespaceInfo" />, or <c>null</c> if no namespace is found.</returns> private NamespaceInfo GetNamespace(DbConnection connection, string name) { ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); // select ... from Namespace left join Page on Namespace.DefaultPage = Page.Name where Namespace.Name = <name> and (Namespace.DefaultPage is null or Page.Namespace = <name>) string query = queryBuilder.SelectFrom("Namespace", "Page", "DefaultPage", "Name", Join.LeftJoin, new string[] { "Name", "DefaultPage" }, new string[] { "CreationDateTime" }); query = queryBuilder.Where(query, "Namespace", "Name", WhereOperator.Equals, "Name1"); query = queryBuilder.AndWhere(query, "Namespace", "DefaultPage", WhereOperator.IsNull, null, true, false); query = queryBuilder.OrWhere(query, "Page", "Namespace", WhereOperator.Equals, "Name2", false, true); List<Parameter> parameters = new List<Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Name1", name)); parameters.Add(new Parameter(ParameterType.String, "Name2", name)); DbCommand command = builder.GetCommand(connection, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { NamespaceInfo result = null; if(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"]); result = new NamespaceInfo(realName, this, defaultPage); } CloseReader(reader); return result; } else return null; }
/// <summary> /// Deletes all data associated to a document. /// </summary> /// <param name="document">The document.</param> /// <param name="state">A state object passed from the index (can be <c>null</c> or a <see cref="T:DbTransaction" />).</param> private void DeleteDataForDocument(IDocument document, object state) { // 1. Delete all data related to a document // 2. Delete all words that have no more mappings ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.DeleteFrom("IndexDocument"); query = queryBuilder.Where(query, "Name", WhereOperator.Equals, "DocName"); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "DocName", document.Name)); string subQuery = queryBuilder.SelectFrom("IndexWordMapping", new string[] { "Word" }); subQuery = queryBuilder.GroupBy(subQuery, new string[] { "Word" }); string query2 = queryBuilder.DeleteFrom("IndexWord"); query2 = queryBuilder.WhereNotInSubquery(query2, "IndexWord", "Id", subQuery); query = queryBuilder.AppendForBatch(query, query2); DbCommand command = null; if(state != null) command = builder.GetCommand((DbTransaction)state, query, parameters); else command = builder.GetCommand(connString, query, parameters); // Close only if state is null ExecuteNonQuery(command, state == null); }
/// <summary> /// Gets a page. /// </summary> /// <param name="connection">A database connection.</param> /// <param name="fullName">The full name of the page.</param> /// <returns>The <see cref="T:PageInfo" />, or <c>null</c> if no page is found.</returns> private PageInfo GetPage(DbConnection connection, string fullName) { string nspace, name; NameTools.ExpandFullName(fullName, out nspace, out name); if(nspace == null) nspace = ""; ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("Page"); 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); DbDataReader reader = ExecuteReader(command); if(reader != null) { PageInfo result = null; if(reader.Read()) { result = new PageInfo(NameTools.GetFullName(reader["Namespace"] as string, reader["Name"] as string), this, (DateTime)reader["CreationDateTime"]); } CloseReader(reader); return result; } else return null; }
/// <summary> /// Gets the Backup/Revision numbers of a Page. /// </summary> /// <param name="connection">A database connection.</param> /// <param name="page">The Page to get the Backups of.</param> /// <returns>The Backup/Revision numbers.</returns> private int[] GetBackups(DbConnection connection, PageInfo page) { if(GetPage(connection, page.FullName) == null) { return null; } string name, nspace; NameTools.ExpandFullName(page.FullName, out nspace, out name); if(nspace == null) nspace = ""; ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("PageContent", new string[] { "Revision" }); query = queryBuilder.Where(query, "Page", WhereOperator.Equals, "Page"); query = queryBuilder.AndWhere(query, "Namespace", WhereOperator.Equals, "Namespace"); query = queryBuilder.AndWhere(query, "Revision", WhereOperator.GreaterThanOrEqualTo, "Revision"); query = queryBuilder.OrderBy(query, new[] { "Revision" }, new[] { Ordering.Asc }); 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, "Revision", FirstRevision)); DbCommand command = builder.GetCommand(connection, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { List<int> result = new List<int>(100); while(reader.Read()) { result.Add((short)reader["Revision"]); } CloseReader(reader); return result.ToArray(); } else return null; }
/// <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> /// 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> /// 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 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> /// 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> /// 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> /// Gets all the Categories in a namespace. /// </summary> /// <param name="connection">A database connection.</param> /// <param name="nspace">The namespace.</param> /// <returns>All the Categories in the namespace. The array is not sorted.</returns> private CategoryInfo[] GetCategories(DbConnection connection, NamespaceInfo nspace) { string nspaceName = nspace != null ? nspace.Name : ""; ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); 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, "Category", "Namespace", WhereOperator.Equals, "Namespace"); query = queryBuilder.OrderBy(query, new string[] { "Category_Name", "CategoryBinding_Page" }, new Ordering[] { Ordering.Asc, Ordering.Asc }); List<Parameter> parameters = new List<Parameter>(1); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspaceName)); DbCommand command = builder.GetCommand(connection, 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(reader); if(result.Count > 0) result[result.Count - 1].Pages = pages.ToArray(); return result.ToArray(); } else return null; }
/// <summary> /// Retrieves the value of a Setting. /// </summary> /// <param name="name">The name of the Setting.</param> /// <returns>The value of the Setting, or null.</returns> /// <exception cref="ArgumentNullException">If <b>name</b> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <b>name</b> is empty.</exception> public string GetSetting(string name) { if (name == null) { throw new ArgumentNullException("name"); } if (name.Length == 0) { throw new ArgumentException("Name cannot be empty", "name"); } ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("GlobalSetting"); 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(connString, query, parameters); DbDataReader reader = ExecuteReader(command); if (reader != null) { string result = null; if (reader.Read()) { result = reader["Value"] as string; } CloseReader(command, reader); // HACK: this allows to correctly initialize a fully SQL-based wiki instance without any user intervention if (string.IsNullOrEmpty(result)) { if (name == "DefaultUsersProvider") { result = DefaultUsersStorageProvider; } if (name == "DefaultPagesProvider") { result = DefaultPagesStorageProvider; } if (name == "DefaultFilesProvider") { result = DefaultFilesStorageProvider; } } return(result); } 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 a category. /// </summary> /// <param name="connection">A database connection.</param> /// <param name="fullName">The full name of the category.</param> /// <returns>The <see cref="T:CategoryInfo" />, or <c>null</c> if no category is found.</returns> private CategoryInfo GetCategory(DbConnection connection, string fullName) { string nspace = null; string name = null; NameTools.ExpandFullName(fullName, out nspace, out name); if(nspace == null) nspace = ""; ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); 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, "Category", "Namespace", WhereOperator.Equals, "Namespace"); query = queryBuilder.AndWhere(query, "Category", "Name", WhereOperator.Equals, "Name"); List<Parameter> parameters = new List<Parameter>(3); parameters.Add(new Parameter(ParameterType.String, "Namespace", nspace)); parameters.Add(new Parameter(ParameterType.String, "Name", name)); DbCommand command = builder.GetCommand(connection, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { CategoryInfo result = null; List<string> pages = new List<string>(50); while(reader.Read()) { if(result == null) result = new CategoryInfo(NameTools.GetFullName(reader["Category_Namespace"] as string, reader["Category_Name"] as string), this); if(!IsDBNull(reader, "CategoryBinding_Page")) { pages.Add(NameTools.GetFullName(reader["Category_Namespace"] as string, reader["CategoryBinding_Page"] as string)); } } CloseReader(reader); if(result != null) result.Pages = pages.ToArray(); return result; } else return null; }
/// <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 the content of a specific revision of a page. /// </summary> /// <param name="transaction">A database transaction.</param> /// <param name="page">The page.</param> /// <param name="revision">The revision.</param> /// <returns>The content.</returns> private PageContent GetContent(DbTransaction transaction, PageInfo page, int revision) { // Internal version to work with GetContent, GetBackupContent, GetDraft ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string name, nspace; NameTools.ExpandFullName(page.FullName, out nspace, out name); if(nspace == null) nspace = ""; string query = queryBuilder.SelectFrom("PageContent", "PageKeyword", new string[] { "Page", "Namespace", "Revision" }, new string[] { "Page", "Namespace", "Revision" }, Join.LeftJoin, new string[] { "Title", "User", "LastModified", "Comment", "Content", "Description" }, new string[] { "Keyword" }); query = queryBuilder.Where(query, "PageContent", "Page", WhereOperator.Equals, "Page"); query = queryBuilder.AndWhere(query, "PageContent", "Namespace", WhereOperator.Equals, "Namespace"); query = queryBuilder.AndWhere(query, "PageContent", "Revision", WhereOperator.Equals, "Revision"); 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, "Revision", (short)revision)); DbCommand command = builder.GetCommand(transaction, query, parameters); DbDataReader reader = ExecuteReader(command); if(reader != null) { PageContent result = null; string title = null, user = null, comment = null, content = null, description = null; DateTime dateTime = DateTime.MinValue; List<string> keywords = new List<string>(10); while(reader.Read()) { if(title == null) { title = reader["PageContent_Title"] as string; user = reader["PageContent_User"] as string; dateTime = (DateTime)reader["PageContent_LastModified"]; comment = GetNullableColumn<string>(reader, "PageContent_Comment", ""); content = reader["PageContent_Content"] as string; description = GetNullableColumn<string>(reader, "PageContent_Description", null); } if(!IsDBNull(reader, "PageKeyword_Keyword")) { keywords.Add(reader["PageKeyword_Keyword"] as string); } } if(title != null) { result = new PageContent(page, title, user, dateTime, comment, content, keywords.ToArray(), description); } CloseReader(reader); return result; } else return null; }
/// <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> /// Gets a free element ID from the database. /// </summary> /// <param name="element">The element type.</param> /// <param name="transaction">The current database transaction.</param> /// <returns>The free element ID.</returns> private uint GetFreeElementId(IndexElementType element, DbTransaction transaction) { if(element == IndexElementType.Occurrences) throw new ArgumentException("Element cannot be Occurrences", "element"); string table = element == IndexElementType.Documents ? "IndexDocument" : "IndexWord"; ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom(table, new string[] { "Id" }); query = queryBuilder.OrderBy(query, new string[] { "Id" }, new Ordering[] { Ordering.Desc }); DbCommand command = builder.GetCommand(transaction, query, new List<Parameter>()); int id = ExecuteScalar<int>(command, -1, false); if(id == -1) return 0; else return (uint)id + 1; }
/// <summary> /// Gets the Page Messages. /// </summary> /// <param name="connection">A database connection.</param> /// <param name="page">The Page.</param> /// <returns>The list of the <b>first-level</b> Messages, containing the replies properly nested, sorted by date/time.</returns> private Message[] GetMessages(DbConnection connection, PageInfo page) { if(GetPage(connection, page.FullName) == null) return null; // 1. Load all messages in memory in a dictionary id->message // 2. Build tree using ParentID string nspace, name; NameTools.ExpandFullName(page.FullName, out nspace, out name); if(nspace == null) nspace = ""; ICommandBuilder builder = GetCommandBuilder(); QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("Message", new string[] { "Id", "Parent", "Username", "Subject", "DateTime", "Body" }); query = queryBuilder.Where(query, "Page", WhereOperator.Equals, "Page"); query = queryBuilder.AndWhere(query, "Namespace", WhereOperator.Equals, "Namespace"); query = queryBuilder.OrderBy(query, new string[] { "DateTime", "Id" }, new Ordering[] { Ordering.Asc, Ordering.Asc }); 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); DbDataReader reader = ExecuteReader(command); if(reader != null) { Dictionary<short, Message> allMessages = new Dictionary<short, Message>(50); List<short> ids = new List<short>(50); List<short?> parents = new List<short?>(50); while(reader.Read()) { Message msg = new Message((short)reader["Id"], reader["Username"] as string, reader["Subject"] as string, (DateTime)reader["DateTime"], reader["Body"] as string); ids.Add((short)msg.ID); // Import from V2: parent = -1, otherwise null if(!IsDBNull(reader, "Parent")) { short par = (short)reader["Parent"]; if(par >= 0) parents.Add(par); else parents.Add(null); } else parents.Add(null); allMessages.Add((short)msg.ID, msg); } CloseReader(reader); // Add messages to their parents and build the top-level messages list List<Message> result = new List<Message>(20); for(int i = 0; i < ids.Count; i++) { short? currentParent = parents[i]; short currentId = ids[i]; if(currentParent.HasValue) { List<Message> replies = new List<Message>(allMessages[currentParent.Value].Replies); replies.Add(allMessages[currentId]); allMessages[currentParent.Value].Replies = replies.ToArray(); } else result.Add(allMessages[currentId]); } return result.ToArray(); } else return null; }
/// <summary> /// Initializes a new instance of the <see cref="SqlIndexInput"/> class. /// </summary> /// <param name="sqlServerDirectory">The Sql Server Directory object.</param> /// <param name="sqlStorageProviderUtility">The SQL storage provider utility.</param> /// <param name="connString">The connection string.</param> /// <param name="wiki">The wiki.</param> /// <param name="name">The name of the file.</param> public SqlIndexInput(SqlDirectory sqlServerDirectory, ISqlStorageProviderUtility sqlStorageProviderUtility, string connString, string wiki, string name) { _sqlServerDirectory = sqlServerDirectory; _sqlStorageProviderUtility = sqlStorageProviderUtility; bool fFileNeeded = false; if (!CacheDirectory.FileExists(name)) { fFileNeeded = true; } if (name.Contains("segments")) { fFileNeeded = true; } if (fFileNeeded) { StreamOutput fileStream = _sqlServerDirectory.CreateCachedOutputAsStream(name); ICommandBuilder builder = _sqlStorageProviderUtility.GetCommandBuilder2(); DbConnection connection = builder.GetConnection(connString); DbTransaction transaction = _sqlStorageProviderUtility.BeginTransaction(connection); if (!FileExists(transaction, wiki, name)) { _sqlStorageProviderUtility.RollbackTransaction(transaction); _sqlStorageProviderUtility.CloseDbConnection(connection); throw new FileNotFoundException(); } QueryBuilder queryBuilder = new QueryBuilder(builder); string query = queryBuilder.SelectFrom("SearchIndex", new string[] { "Size", "Data" }); query = queryBuilder.Where(query, "Wiki", WhereOperator.Equals, "Wiki"); query = queryBuilder.AndWhere(query, "Name", WhereOperator.Equals, "Name"); List <Parameter> parameters = new List <Parameter>(2); parameters.Add(new Parameter(ParameterType.String, "Wiki", wiki)); parameters.Add(new Parameter(ParameterType.String, "Name", name)); DbCommand command = builder.GetCommand(transaction, query, parameters); DbDataReader reader = _sqlStorageProviderUtility.ExecuteReader(command); if (reader != null) { bool done = false; if (reader.Read()) { int read = _sqlStorageProviderUtility.ReadBinaryColumn(reader, "Data", fileStream); done = (long)read == (long)reader["Size"]; } _sqlStorageProviderUtility.CloseReader(reader); if (!done) { _sqlStorageProviderUtility.RollbackTransaction(transaction); } _sqlStorageProviderUtility.CommitTransaction(transaction); } else { _sqlStorageProviderUtility.RollbackTransaction(transaction); } fileStream.Flush(); fileStream.Close(); // and open it as an input _indexInput = CacheDirectory.OpenInput(name); } else { _indexInput = CacheDirectory.OpenInput(name); } }