/// <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> * /// Locks current record. * /// </summary> * public void LockRecord() * { * if(!this.IsDatabaseOpen){ * throw new Exception("Database isn't open, please open database first !"); * } * * } */ /* * /// <summary> * /// Unlocks current record. * /// </summary> * public void UnlockRecord() * { * if(!this.IsDatabaseOpen){ * throw new Exception("Database isn't open, please open database first !"); * } * * } */ /// <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 (!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); }
/// <summary> /// Appends new record to table. /// </summary> public void AppendRecord(object[] values) { if (!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 (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)); StoreDataToDataPages(m_DataPageDataAreaSize, record, dataPages); if (unlock) { UnlockTable(); } }
/// <summary> /// Appends new record to table. /// </summary> public void AppendRecord(object[] values) { if (!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 (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(); } }
/* /// <summary> /// Locks current record. /// </summary> public void LockRecord() { if(!this.IsDatabaseOpen){ throw new Exception("Database isn't open, please open database first !"); } } */ /* /// <summary> /// Unlocks current record. /// </summary> public void UnlockRecord() { if(!this.IsDatabaseOpen){ throw new Exception("Database isn't open, please open database first !"); } } */ /// <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 (!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; }