/// <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> /// 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(); } }