Esempio n. 1
0
// 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
}
Esempio n. 2
0
// 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
}