code: func (db *Storage) CreateTables(ctxt Context) error {
  	ctxt = debugContext(ctxt)
  	var buf bytes.Buffer
  	for _, t := range db.types {
  		buf.Reset()
  		if t.fts4 {
  			fmt.Fprintf(&buf, "create virtual table %q using fts4", t.name)
  		} else {
  			fmt.Fprintf(&buf, "create table %q", t.name)
  		}
  
  		fmt.Fprintf(&buf, " (")
  		sep := ""
  		for _, col := range t.fields {
  			if t.fts4 && col.rowid {
  				continue // fts4 rowid is implicit
  			}
  			fmt.Fprintf(&buf, "%s%q %s", sep, col.name, col.dbtype)
  			sep = ","
  		}
  		if len(t.keys) > 0 && t.rowid == nil {
  			fmt.Fprintf(&buf, ", unique (")
  			for i, col := range t.keys {
  				if i > 0 {
  					fmt.Fprintf(&buf, ", ")
  				}
  				fmt.Fprintf(&buf, "%q", col.name)
  			}
  			fmt.Fprintf(&buf, ") on conflict replace")
  		}
  		fmt.Fprintf(&buf, ")")
  
  		if _, err := ctxt.Exec(buf.String()); err != nil {
  			return fmt.Errorf("creating table %s [%s]: %v", t.name, buf.String(), err)
  		}
  	}
  
  	return nil
  }
docs: // NOTE: All these %q should really be a custom quoting mechanism
  // that emits sqlite3-double-quoted escapes, but since we don't expect
  // to see double quotes or backslashes in the names, using %q is fine.
  // CreateTables creates the tables to hold the registered types.
  // It only needs to be called when creating a new database.
  // Each table is named for the type it stores, in the form "full/import/path.TypeName".