Repository: genjidb/genji (go)

Issue:
Define and filter forbidden characters on identifiers
A few packages (`index`, `engine/*`, ...) use special characters as separators when they build keys (example: https://github.com/asdine/genji/blob/master/index/index.go#L98-L106).
Currently, we don't prevent users to use these separators in their documents, which can cause problems.
Define these characters somewhere and make sure to return an error if they are used

Pull request description:
Add prefix to table stores
This PR adds a prefix to every created table store. It also fixes a panic when decoding a tableInfo.
Fixes #73

Patch:
diff --git a/database/config.go b/database/config.go
index fc58dea2..d1e451e3 100644
--- a/database/config.go
+++ b/database/config.go
@@ -14,6 +14,8 @@ import (
 	"github.com/genjidb/genji/index"
 )
 
+const storePrefix = 't'
+
 // FieldConstraint describes constraints on a particular field.
 type FieldConstraint struct {
 	Path         document.ValuePath
@@ -134,7 +136,7 @@ func (ti *TableInfo) ScanDocument(d document.Document) error {
 	ti.FieldConstraints = make([]FieldConstraint, l)
 
 	err = ar.Iterate(func(i int, value document.Value) error {
-		return ti.FieldConstraints[i].ScanDocument(v.V.(document.Document))
+		return ti.FieldConstraints[i].ScanDocument(value.V.(document.Document))
 	})
 	if err != nil {
 		return err
@@ -333,17 +335,19 @@ func (t *tableInfoStore) GetTableInfo() map[string]TableInfo {
 }
 
 // generateStoreID generates an ID used as a key to reference a table.
-// The first 4 bytes represent the timestamp in second and the last-2 bytes are
+// The first byte contains the prefix used for table stores.
+// The next 4 bytes represent the timestamp in second and the last 2 bytes are
 // randomly generated.
 func (t *tableInfoStore) generateStoreID() []byte {
 	t.mu.RLock()
 	defer t.mu.RUnlock()
 
 	var found bool = true
-	var id [6]byte
+	var id [7]byte
 	for found {
-		binary.BigEndian.PutUint32(id[:], uint32(time.Now().Unix()))
-		if _, err := rand.Reader.Read(id[4:]); err != nil {
+		id[0] = storePrefix
+		binary.BigEndian.PutUint32(id[1:], uint32(time.Now().Unix()))
+		if _, err := rand.Reader.Read(id[5:]); err != nil {
 			panic(fmt.Errorf("cannot generate random number: %v;", err))
 		}
 


Test patch:
diff --git a/database/config_test.go b/database/config_test.go
index f2744c46..393266b4 100644
--- a/database/config_test.go
+++ b/database/config_test.go
@@ -8,6 +8,20 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
+func TestTableInfo(t *testing.T) {
+	info := &TableInfo{
+		FieldConstraints: []FieldConstraint{
+			{Path: []string{"k"}, Type: document.DoubleValue, IsPrimaryKey: true},
+		},
+	}
+
+	doc := info.ToDocument()
+
+	var res TableInfo
+	err := res.ScanDocument(doc)
+	require.NoError(t, err)
+}
+
 func TestTableInfoStore(t *testing.T) {
 	t.Run("ok", func(t *testing.T) {
 		ng := memoryengine.NewEngine()