Where() public method

Applies a WHERE clause to a query.
public Where ( string query, string column, WhereOperator op, string parameter ) : string
query string The query.
column string The column subject of the WHERE clause.
op WhereOperator The operator.
parameter string The name of the parameter for the WHERE clause.
return string
Ejemplo n.º 1
0
        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());
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Releases the lock.
        /// </summary>
        public override void Release()
        {
            ICommandBuilder builder     = _sqlStorageProviderUtility.GetCommandBuilder2();
            DbConnection    connection  = builder.GetConnection(_connString);
            DbTransaction   transaction = _sqlStorageProviderUtility.BeginTransaction(connection);

            QueryBuilder queryBuilder = new QueryBuilder(builder);

            string query = queryBuilder.DeleteFrom("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(transaction, query, parameters);

            int rows = _sqlStorageProviderUtility.ExecuteNonQuery(command, false);

            if (rows == 1)
            {
                _sqlStorageProviderUtility.CommitTransaction(transaction);
            }
            else
            {
                _sqlStorageProviderUtility.RollbackTransaction(transaction);
            }
        }
Ejemplo n.º 3
0
        public override void RenameFile(string from, string to)
        {
            ICommandBuilder builder     = _sqlStorageProviderUtility.GetCommandBuilder2();
            DbConnection    connection  = builder.GetConnection(_connString);
            DbTransaction   transaction = _sqlStorageProviderUtility.BeginTransaction(connection);

            QueryBuilder queryBuilder = new QueryBuilder(builder);

            if (!FileExists(transaction, from))
            {
                _sqlStorageProviderUtility.RollbackTransaction(transaction);
                throw new ArgumentException("File does not exist", "from");
            }
            if (FileExists(transaction, to))
            {
                _sqlStorageProviderUtility.RollbackTransaction(transaction);
                throw new ArgumentException("File already exists", "to");
            }

            string query = queryBuilder.Update("SearchIndex", new string[] { "Name" }, new string[] { "NewName" });

            query = queryBuilder.Where(query, "Wiki", WhereOperator.Equals, "Wiki");
            query = queryBuilder.AndWhere(query, "Name", WhereOperator.Equals, "OldName");

            List <Parameter> parameters = new List <Parameter>(3);

            parameters.Add(new Parameter(ParameterType.String, "Wiki", _wiki));
            parameters.Add(new Parameter(ParameterType.String, "NewName", to));
            parameters.Add(new Parameter(ParameterType.String, "OldName", from));

            DbCommand command = builder.GetCommand(transaction, query, parameters);

            int rows = _sqlStorageProviderUtility.ExecuteNonQuery(command, false);

            if (rows != 1)
            {
                _sqlStorageProviderUtility.RollbackTransaction(transaction);
            }
            else
            {
                _sqlStorageProviderUtility.CommitTransaction(transaction);

                // we delete and force a redownload, since we can't do this in an atomic way
                if (_cacheDirectory.FileExists(from))
                {
                    _cacheDirectory.DeleteFile(from);
                }

                // drop old cached data as it's wrong now
                if (_cacheDirectory.FileExists(from + ".blob"))
                {
                    _cacheDirectory.DeleteFile(from + ".blob");
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Obtains the lock.
        /// </summary>
        /// <returns><c>true</c> if the lock has been obtained, <c>false</c> otherwise.</returns>
        public override bool Obtain()
        {
            ICommandBuilder builder     = _sqlStorageProviderUtility.GetCommandBuilder2();
            DbConnection    connection  = builder.GetConnection(_connString);
            DbTransaction   transaction = _sqlStorageProviderUtility.BeginTransaction(connection);

            QueryBuilder queryBuilder = new QueryBuilder(builder);

            string query = queryBuilder.DeleteFrom("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(transaction, query, parameters);

            int rows = _sqlStorageProviderUtility.ExecuteNonQuery(command, false);

            if (rows != 0)
            {
                _sqlStorageProviderUtility.RollbackTransaction(transaction);
                return(false);                // Deletion command failed (0 is the only accepted value)
            }

            query = queryBuilder.InsertInto("SearchIndexLock",
                                            new string[] { "wiki", "Name", "Value" }, new string[] { "Wiki", "Name", "Value" });
            parameters = new List <Parameter>(3);
            parameters.Add(new Parameter(ParameterType.String, "Wiki", _wiki));
            parameters.Add(new Parameter(ParameterType.String, "Name", _name));
            parameters.Add(new Parameter(ParameterType.String, "Value", "locked"));

            command = builder.GetCommand(transaction, query, parameters);

            rows = _sqlStorageProviderUtility.ExecuteNonQuery(command, false);

            if (rows == 1)
            {
                _sqlStorageProviderUtility.CommitTransaction(transaction);
            }
            else
            {
                _sqlStorageProviderUtility.RollbackTransaction(transaction);
            }

            return(rows == 1);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Deletes a file.
        /// </summary>
        /// <param name="name">The name of the file to be deleted.</param>
        public override void DeleteFile(string name)
        {
            ICommandBuilder builder     = _sqlStorageProviderUtility.GetCommandBuilder2();
            DbConnection    connection  = builder.GetConnection(_connString);
            DbTransaction   transaction = _sqlStorageProviderUtility.BeginTransaction(connection);

            if (!FileExists(transaction, name))
            {
                _sqlStorageProviderUtility.RollbackTransaction(transaction);
                return;
            }

            QueryBuilder queryBuilder = new QueryBuilder(builder);

            string query = queryBuilder.DeleteFrom("SearchIndex");

            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);

            int rows = _sqlStorageProviderUtility.ExecuteNonQuery(command, false);

            if (rows != 1)
            {
                _sqlStorageProviderUtility.RollbackTransaction(transaction);
            }
            else
            {
                _sqlStorageProviderUtility.CommitTransaction(transaction);

                if (_cacheDirectory.FileExists(name + ".blob"))
                {
                    _cacheDirectory.DeleteFile(name + ".blob");
                }

                if (_cacheDirectory.FileExists(name))
                {
                    _cacheDirectory.DeleteFile(name);
                }
            }
        }
Ejemplo n.º 6
0
        /// <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);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Removes a plugin's assembly.
        /// </summary>
        /// <param name="connection">A database connection.</param>
        /// <param name="filename">The file name of the assembly to remove, such as "Assembly.dll".</param>
        /// <returns><c>true</c> if the assembly is removed, <c>false</c> otherwise.</returns>
        private bool DeletePluginAssembly(DbConnection connection, string filename)
        {
            ICommandBuilder builder      = GetCommandBuilder();
            QueryBuilder    queryBuilder = new QueryBuilder(builder);

            string query = queryBuilder.DeleteFrom("PluginAssembly");

            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(connection, query, parameters);

            int rows = ExecuteNonQuery(command, false);

            return(rows == 1);
        }
Ejemplo n.º 8
0
        private bool FileExists(DbTransaction transaction, string name)
        {
            ICommandBuilder builder      = _sqlStorageProviderUtility.GetCommandBuilder2();
            QueryBuilder    queryBuilder = new QueryBuilder(builder);

            string query = queryBuilder.SelectCountFrom("SearchIndex");

            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);

            int count = _sqlStorageProviderUtility.ExecuteScalar <int>(command, -1, false);

            return(count == 1);
        }
Ejemplo n.º 9
0
        /// <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);
            }
        }
Ejemplo n.º 10
0
        /// <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>
        /// Removes a Category.
        /// </summary>
        /// <param name="transaction">A database transaction.</param>
        /// <param name="category">The Category to remove.</param>
        /// <returns>True if the Category has been removed successfully.</returns>
        private bool RemoveCategory(DbTransaction transaction, CategoryInfo category)
        {
            string nspace = null;
            string name = null;
            NameTools.ExpandFullName(category.FullName, out nspace, out name);
            if(nspace == null) nspace = "";

            ICommandBuilder builder = GetCommandBuilder();
            QueryBuilder queryBuilder = new QueryBuilder(builder);

            string query = queryBuilder.DeleteFrom("Category");
            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(transaction, query, parameters);

            int rows = ExecuteNonQuery(command, false);

            return rows > 0;
        }
        /// <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 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>
        /// 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>
        /// 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>
        /// 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 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>
        /// 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 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>
        /// 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 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>
        /// 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>
        /// 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>
        /// 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>
        /// 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>
        /// 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>
        /// 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>
        /// 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>
        /// 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>
        /// 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>
        /// 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>
        /// 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>
        /// 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;
        }
        /// <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;
        }
Ejemplo n.º 35
0
        /// <summary>
        /// Stores the value of a Setting.
        /// </summary>
        /// <param name="name">The name of the Setting.</param>
        /// <param name="value">The value of the Setting. Value cannot contain CR and LF characters, which will be removed.</param>
        /// <returns>True if the Setting is stored, false otherwise.</returns>
        /// <remarks>This method stores the Value immediately.</remarks>
        public bool SetSetting(string name, string value)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            if (name.Length == 0)
            {
                throw new ArgumentException("Name cannot be empty", "name");
            }

            // 1. Delete old value, if any
            // 2. Store new value

            // Nulls are converted to empty strings
            if (value == null)
            {
                value = "";
            }

            ICommandBuilder builder     = GetCommandBuilder();
            DbConnection    connection  = builder.GetConnection(connString);
            DbTransaction   transaction = BeginTransaction(connection);

            QueryBuilder queryBuilder = new QueryBuilder(builder);

            string query = queryBuilder.DeleteFrom("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(transaction, query, parameters);

            int rows = ExecuteNonQuery(command, false);

            if (rows == -1)
            {
                RollbackTransaction(transaction);
                return(false);                // Deletion command failed (0-1 are OK)
            }

            query = queryBuilder.InsertInto("GlobalSetting",
                                            new string[] { "Name", "Value" }, new string[] { "Name", "Value" });
            parameters = new List <Parameter>(2);
            parameters.Add(new Parameter(ParameterType.String, "Name", name));
            parameters.Add(new Parameter(ParameterType.String, "Value", value));

            command = builder.GetCommand(transaction, query, parameters);

            rows = ExecuteNonQuery(command, false);

            if (rows == 1)
            {
                CommitTransaction(transaction);
            }
            else
            {
                RollbackTransaction(transaction);
            }

            return(rows == 1);
        }
        /// <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>
        /// 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>
        /// 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>
        /// 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;
        }
Ejemplo n.º 40
0
        /// <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>
        /// 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;
        }
Ejemplo n.º 42
0
        /// <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);
            }
        }
        /// <summary>
        /// Binds a Page with one or more Categories.
        /// </summary>
        /// <param name="connection">A database connection.</param>
        /// <param name="page">The Page to bind.</param>
        /// <param name="categories">The Categories to bind the Page with.</param>
        /// <returns>True if the binding succeeded.</returns>
        /// <remarks>After a successful operation, the Page is bound with all and only the categories passed as argument.</remarks>
        private bool RebindPage(DbConnection connection, PageInfo page, string[] categories)
        {
            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.DeleteFrom("CategoryBinding");
            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 rows = ExecuteNonQuery(command, false);

            if(rows < 0) return false;

            if(categories.Length > 0) {
                string finalQuery = "";
                parameters = new List<Parameter>(categories.Length * 3);
                int count = 0;
                string countString;

                foreach(string cat in categories) {
                    countString = count.ToString();

                    query = queryBuilder.InsertInto("CategoryBinding", new string[] { "Namespace", "Category", "Page" },
                        new string[] { "Namespace" + countString, "Category" + countString, "Page" + countString });
                    finalQuery = queryBuilder.AppendForBatch(finalQuery, query);

                    parameters.Add(new Parameter(ParameterType.String, "Namespace" + countString, nspace));
                    parameters.Add(new Parameter(ParameterType.String, "Category" + countString, NameTools.GetLocalName(cat)));
                    parameters.Add(new Parameter(ParameterType.String, "Page" + countString, name));

                    count++;
                }

                command = builder.GetCommand(connection, finalQuery, parameters);

                rows = ExecuteNonQuery(command, false);

                return rows == categories.Length;
            }
            else return true;
        }