// Creates a new table. func (db *Database) Create(name string) (*table.Table, int) { var newTable *table.Table _, exists := db.Tables[name] if exists { return nil, st.TableAlreadyExists } if len(name) > constant.MaxTableNameLength { return nil, st.TableNameTooLong } // Create table files and directories. tablefilemanager.Create(db.Path, name) // Open the table var status int newTable, status = table.Open(db.Path, name) if status == st.OK { // Add default columns for columnName, length := range constant.DatabaseColumns() { status = newTable.Add(columnName, length) if status != st.OK { return nil, status } } db.Tables[name] = newTable } return newTable, st.OK }
// Rebuild data file, get rid off removed rows, optionally leaves space for a new column. func (table *Table) RebuildDataFile(name string, length int) int { // Create a temporary table named by an accurate timestamp. tempName := strconv.Itoa(time.Now().Nanosecond()) // tempName := strconv.Itoa(time.Nanosecond) tablefilemanager.Create(table.Path, tempName) var tempTable *Table tempTable, status := Open(table.Path, tempName) if status != st.OK { return status } // Put all columns of this table to the temporary table. for _, column := range table.ColumnsInOrder { tempTable.Add(column.Name, column.Length) } // Add the new column into the table as well. if name != "" { tempTable.Add(name, length) } var numberOfRows int numberOfRows, status = table.NumberOfRows() if status != st.OK { return status } var everFailed bool if name == "" { // If no new column, simply copy rows from this table to the temp table. for i := 0; i < numberOfRows; i++ { row, ret := table.Read(i) if ret != st.OK { everFailed = true } if row["~del"] != "y" { tempTable.Insert(row) } } } else { // If adding new column, not only copy rows from this table to the temporary one. // Also leave space for the new column's values. for i := 0; i < numberOfRows; i++ { row, ret := table.Read(i) if ret != st.OK { everFailed = true } if row["~del"] != "y" { row[name] = "" tempTable.Insert(row) } } } // Flush all the changes made to temporary table. status = tempTable.Flush() if everFailed || status != st.OK { return st.FailedToCopyCertainRows } // Delete the old table (one that is rebuilt), and rename the temporary // table to the name of the rebuilt table. status = tablefilemanager.Delete(table.Path, table.Name) if status == st.OK { status = tablefilemanager.Rename(table.Path, tempName, table.Name) if status == st.OK { // Files have been changed, thus re-open file handles. return table.OpenFiles() } } return st.OK }