/// <summary>
        /// Gets or sets specified data column value.
        /// </summary>
        /// <param name="columnIndex">Zero based column index.</param>
        /// <returns></returns>
        public object this[int columnIndex]
        {
            /* Fixed record structure:
             *      1 byte     - specified is row is used or free space
             *                   u - used
             *                   f - free space
             *      x bytes    - columns data
             *      2 bytes    - CRLF
             */

            get{
                if (columnIndex < 0)
                {
                    throw new Exception("The columnIndex can't be negative value !");
                }
                if (columnIndex > m_ColumnCount)
                {
                    throw new Exception("The columnIndex out of columns count !");
                }

                return(ConvertFromInternalData(m_ColumnDataTypes[columnIndex], m_RowData, m_ColumnDataStartOffsets[columnIndex], m_ColumnDataSizes[columnIndex]));
            }

            set{
                if (columnIndex < 0)
                {
                    throw new Exception("The columnIndex can't be negative value !");
                }
                if (columnIndex > m_ColumnCount)
                {
                    throw new Exception("The columnIndex out of columns count !");
                }

                byte[] val = LDB_Record.ConvertToInternalData(m_pOwnerDb.Columns[columnIndex], value);
                // Check that value won't exceed maximum cloumn allowed size
                if (val.Length > m_ColumnDataSizes[columnIndex])
                {
                    throw new Exception("Value exceeds maximum allowed value for column '" + m_pOwnerDb.Columns[columnIndex].ColumnName + "' !");
                }

                // TODO: String, string must be char(0) terminated and padded to column length
                if (m_ColumnDataTypes[columnIndex] == LDB_DataType.String)
                {
                    throw new Exception("TODO: String not implemented !");
                }

                // Update value in database file
                m_pOwnerDb.WriteToFile(m_Pointer + m_ColumnDataStartOffsets[columnIndex], val, 0, val.Length);

                // Update value in buffer
                Array.Copy(val, 0, m_RowData, m_ColumnDataStartOffsets[columnIndex], val.Length);
            }
        }
        /// <summary>
        /// Updates this record values.
        /// </summary>
        /// <param name="rowValues">Row new values.</param>
        private void UpdateRecord(object[] rowValues)
        {
            bool unlock = true;

            // Table is already locked, don't lock it
            if (m_pOwnerDb.TableLocked)
            {
                unlock = false;
            }
            else
            {
                m_pOwnerDb.LockTable(15);
            }

            // Create new record
            byte[] rowData = LDB_Record.CreateRecord(m_pOwnerDb, rowValues);

            DataPage[] dataPages = this.DataPages;
            // Clear old data ?? do we need that
            //	for(int i=0;i<dataPages.Length;i++){
            //		dataPages[i].Data = new byte[1000];
            //	}

            // We haven't enough room to store row, get needed data pages
            if ((int)Math.Ceiling(rowData.Length / (double)m_pOwnerDb.DataPageDataAreaSize) > dataPages.Length)
            {
                int        dataPagesNeeded     = (int)Math.Ceiling(rowData.Length / (double)m_pOwnerDb.DataPageDataAreaSize) - dataPages.Length;
                DataPage[] additionalDataPages = m_pOwnerDb.GetDataPages(dataPages[dataPages.Length - 1].Pointer, dataPagesNeeded);

                // Append new data pages to existing data pages chain
                dataPages[dataPages.Length - 1].NextDataPagePointer = additionalDataPages[0].Pointer;

                DataPage[] newVal = new DataPage[dataPages.Length + additionalDataPages.Length];
                Array.Copy(dataPages, 0, newVal, 0, dataPages.Length);
                Array.Copy(additionalDataPages, 0, newVal, dataPages.Length, additionalDataPages.Length);
                dataPages = newVal;
            }

            // Store new record
            DbFile.StoreDataToDataPages(m_pOwnerDb.DataPageDataAreaSize, rowData, dataPages);

            // Update row info
            ParseRowInfo();

            if (unlock)
            {
                m_pOwnerDb.UnlockTable();
            }
        }
Example #3
0
/*
 *              /// <summary>
 *              /// Locks current record.
 *              /// </summary>
 *              public void LockRecord()
 *              {
 *                      if(!this.IsDatabaseOpen){
 *                              throw new Exception("Database isn't open, please open database first !");
 *                      }
 *
 *              }
 */
        #endregion

        #region method UnlockRecord

/*
 *              /// <summary>
 *              /// Unlocks current record.
 *              /// </summary>
 *              public void UnlockRecord()
 *              {
 *                      if(!this.IsDatabaseOpen){
 *                              throw new Exception("Database isn't open, please open database first !");
 *                      }
 *
 *              }
 */
        #endregion


        #region method NextRecord

        /// <summary>
        /// Gets next record. Returns true if end of file reached and there are no more records.
        /// </summary>
        /// <returns>Returns true if end of file reached and there are no more records.</returns>
        public bool NextRecord()
        {
            if (!this.IsDatabaseOpen)
            {
                throw new Exception("Database isn't open, please open database first !");
            }

            //--- Find next record ---------------------------------------------------//
            long nextRowStartOffset = 0;

            if (m_pCurrentRecord == null)
            {
                nextRowStartOffset = m_DatapagesStartOffset;
            }
            else
            {
                nextRowStartOffset = m_pCurrentRecord.DataPage.Pointer + m_DataPageDataAreaSize + 33;
            }

            while (true)
            {
                if (m_FileLength > nextRowStartOffset)
                {
                    DataPage dataPage = new DataPage(m_DataPageDataAreaSize, this, nextRowStartOffset);

                    // We want datapage with used space
                    if (dataPage.Used && dataPage.OwnerDataPagePointer < 1)
                    {
                        m_pCurrentRecord = new LDB_Record(this, dataPage);
                        break;
                    }
                }
                else
                {
                    return(true);
                }

                nextRowStartOffset += m_DataPageDataAreaSize + 33;
            }
            //-------------------------------------------------------------------------//

            return(false);
        }
Example #4
0
        /// <summary>
        /// Appends new record to table.
        /// </summary>
        public void AppendRecord(object[] values)
        {
            if (!this.IsDatabaseOpen)
            {
                throw new Exception("Database isn't open, please open database first !");
            }
            if (m_pColumns.Count != values.Length)
            {
                throw new Exception("Each column must have corresponding value !");
            }

            bool unlock = true;

            // Table is already locked, don't lock it
            if (this.TableLocked)
            {
                unlock = false;
            }
            else
            {
                LockTable(15);
            }

            // Construct record data
            byte[] record = LDB_Record.CreateRecord(this, values);

            // Get free data pages
            DataPage[] dataPages = GetDataPages(0, (int)Math.Ceiling(record.Length / (double)m_DataPageDataAreaSize));

            DbFile.StoreDataToDataPages(m_DataPageDataAreaSize, record, dataPages);

            if (unlock)
            {
                UnlockTable();
            }
        }
        /// <summary>
        /// Appends new record to table.
        /// </summary>
        public void AppendRecord(object[] values)
        {
            if (!this.IsDatabaseOpen)
            {
                throw new Exception("Database isn't open, please open database first !");
            }
            if (m_pColumns.Count != values.Length)
            {
                throw new Exception("Each column must have corresponding value !");
            }

            bool unlock = true;

            // Table is already locked, don't lock it
            if (this.TableLocked)
            {
                unlock = false;
            }
            else
            {
                LockTable(15);
            }

            /* Fixed record structure:
             *  1 byte     - specified is row is used or free space
             *               u - used
             *               f - free space
             *  x bytes    - columns data
             *  2 bytes    - CRLF
             */

            int rowLength = 1 + 2;

            for (int i = 0; i < m_pColumns.Count; i++)
            {
                rowLength += m_pColumns[i].ColumnSize;
            }

            int position = 1;

            byte[] record = new byte[rowLength];
            record[0]             = (int)'u';
            record[rowLength - 2] = (int)'\r';
            record[rowLength - 1] = (int)'\n';
            for (int i = 0; i < values.Length; i++)
            {
                byte[] columnData = LDB_Record.ConvertToInternalData(m_pColumns[i], values[i]);
                // Check that column won't exceed maximum length.
                if (columnData.Length > m_pColumns[i].ColumnSize)
                {
                    throw new Exception("Column '" + m_pColumns[i] + "' exceeds maximum value length !");
                }

                Array.Copy(columnData, 0, record, position, columnData.Length);
                position += columnData.Length;
            }

            // Find free row
            byte[] freeRowsBuffer = new byte[4];
            ReadFromFile(52, freeRowsBuffer, 0, freeRowsBuffer.Length);
            int freeRows = ldb_Utils.ByteToInt(freeRowsBuffer, 0);

            // There are plenty free rows, find first

            if (freeRows > 100)
            {
                //--- Find free record ---------------------------------------------------//
                long nextRowStartOffset = m_RowsStartOffset;
                long rowOffset          = 0;

                byte[] rowData = new byte[m_RowLength];
                while (true)
                {
                    ReadFromFile(nextRowStartOffset, rowData, 0, m_RowLength);

                    // We want used row
                    if (rowData[0] == 'f')
                    {
                        rowOffset = nextRowStartOffset;
                        break;
                    }

                    nextRowStartOffset += m_RowLength;
                }
                //-------------------------------------------------------------------------//

                // Write new record to file
                WriteToFile(rowOffset, record, 0, record.Length);

                // Update free rows count
                WriteToFile(52, ldb_Utils.IntToByte(freeRows - 1), 0, 4);
            }
            // There are few empty rows, just append it
            else
            {
                AppendToFile(record, 0, record.Length);
            }

            if (unlock)
            {
                UnlockTable();
            }
        }
Example #6
0
        /// <summary>
        /// Gets next record. Returns true if end of file reached and there are no more records.
        /// </summary>
        /// <returns>Returns true if end of file reached and there are no more records.</returns>
        public bool NextRecord()
        {
            if(!this.IsDatabaseOpen){
                throw new Exception("Database isn't open, please open database first !");
            }

            //--- Find next record ---------------------------------------------------//
            long nextRowStartOffset = 0;
            if(m_pCurrentRecord == null){
                nextRowStartOffset = m_DatapagesStartOffset;
            }
            else{
                nextRowStartOffset = m_pCurrentRecord.DataPage.Pointer + m_DataPageDataAreaSize + 33;
            }

            while(true){
                if(m_FileLength > nextRowStartOffset){
                    DataPage dataPage = new DataPage(m_DataPageDataAreaSize,this,nextRowStartOffset);

                    // We want datapage with used space
                    if(dataPage.Used && dataPage.OwnerDataPagePointer < 1){
                        m_pCurrentRecord = new LDB_Record(this,dataPage);
                        break;
                    }
                }
                else{
                    return true;
                }

                nextRowStartOffset += m_DataPageDataAreaSize + 33;
            }
            //-------------------------------------------------------------------------//

            return false;
        }