Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parser for type declaration. #2950

Merged
merged 11 commits into from
Feb 5, 2019
4 changes: 2 additions & 2 deletions dgraph/cmd/bulk/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ func readSchema(filename string) []*pb.SchemaUpdate {
buf, err := ioutil.ReadAll(r)
x.Check(err)

initialSchema, err := schema.Parse(string(buf))
result, err := schema.Parse(string(buf))
x.Check(err)
return initialSchema
return result.Schemas
}

func findDataFiles(dir string, ext string) []string {
Expand Down
4 changes: 2 additions & 2 deletions edgraph/access_ee.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,11 +462,11 @@ func authorizeAlter(ctx context.Context, op *api.Operation) error {
return nil
}

updates, err := schema.Parse(op.Schema)
result, err := schema.Parse(op.Schema)
if err != nil {
return err
}
for _, update := range updates {
for _, update := range result.Schemas {
if err := authorizePredicate(groupIds, update.Predicate, acl.Modify); err != nil {
return status.Error(codes.PermissionDenied,
fmt.Sprintf("unauthorized to alter the predicate: %v", err))
Expand Down
6 changes: 3 additions & 3 deletions edgraph/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,13 @@ func (s *Server) Alter(ctx context.Context, op *api.Operation) (*api.Payload, er
return empty, err
}

updates, err := schema.Parse(op.Schema)
result, err := schema.Parse(op.Schema)
if err != nil {
return empty, err
}
glog.Infof("Got schema: %+v\n", updates)
glog.Infof("Got schema: %+v\n", result.Schemas)
// TODO: Maybe add some checks about the schema.
m.Schema = updates
m.Schema = result.Schemas
_, err = query.ApplyMutations(ctx, m)
return empty, err
}
Expand Down
Binary file added git-branch-cleanup
Binary file not shown.
12 changes: 11 additions & 1 deletion protos/pb.proto
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ message Posting {
UID = 7;
PASSWORD = 8;
STRING = 9;

OBJECT = 10;
}
ValType val_type = 3;
enum PostingType {
Expand Down Expand Up @@ -338,11 +338,21 @@ message SchemaUpdate {
bool upsert = 8;
bool lang = 9;

// Fields required for type system.
bool non_nullable = 10;
bool non_nullable_list = 11;
string object_type_name = 12;

// Deleted field:
reserved 7;
reserved "explicit";
}

message TypeUpdate {
string type_name = 1;
repeated SchemaUpdate fields = 2;
}

// Bulk loader proto.
message MapEntry {
bytes key = 1;
Expand Down
839 changes: 603 additions & 236 deletions protos/pb/pb.pb.go

Large diffs are not rendered by default.

143 changes: 136 additions & 7 deletions schema/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ func ParseBytes(s []byte, gid uint32) (rerr error) {
reset()
}
pstate.DeleteAll()
updates, err := Parse(string(s))
result, err := Parse(string(s))
if err != nil {
return err
}

for _, update := range updates {
for _, update := range result.Schemas {
State().Set(update.Predicate, *update)
}
State().Set("_predicate_", pb.SchemaUpdate{
Expand Down Expand Up @@ -295,9 +295,129 @@ func resolveTokenizers(updates []*pb.SchemaUpdate) error {
return nil
}

func parseTypeDeclaration(it *lex.ItemIterator) (*pb.TypeUpdate, error) {
// Iterator is currently on the token corresponding to the keyword type.
// Call Next to land on the type name.
it.Next()
typeUpdate := &pb.TypeUpdate{TypeName: it.Item().Val}

// Call next again to skip the { character.
it.Next()

var fields []*pb.SchemaUpdate
for {
item := it.Item()
switch item.Typ {
case itemRightCurl:
it.Next()
if it.Item().Typ != itemNewLine {
return nil, x.Errorf("Expected new line after type declaration. Got %v",
it.Item().Val)
}

typeUpdate.Fields = fields
return typeUpdate, nil
case itemText:
field, err := parseTypeField(it)
if err != nil {
return nil, err
}
fields = append(fields, field)
default:
it.Next()
}
}
}

func parseTypeField(it *lex.ItemIterator) (*pb.SchemaUpdate, error) {
field := &pb.SchemaUpdate{Predicate: it.Item().Val}
var list bool

it.Next()
if it.Item().Typ != itemColon {
return nil, x.Errorf("Missing colon in type declaration. Got %v", it.Item().Val)
}

it.Next()
if it.Item().Typ == itemLeftSquare {
list = true
it.Next()
}

if it.Item().Typ != itemText {
return nil, x.Errorf("Missing field type in type declaration. Got %v", it.Item().Val)
}
field.ValueType = getType(it.Item().Val)
if field.ValueType == pb.Posting_OBJECT {
field.ObjectTypeName = it.Item().Val
}

it.Next()
if it.Item().Typ == itemExclamationMark {
field.NonNullable = true
it.Next()
}

if list {
if it.Item().Typ != itemRightSquare {
return nil, x.Errorf("Expected matching square bracket. Got %v", it.Item().Val)
}
field.List = true
it.Next()

if it.Item().Typ == itemExclamationMark {
field.NonNullableList = true
it.Next()
}
}

if it.Item().Typ != itemNewLine {
return nil, x.Errorf("Expected new line after field declaration. Got %v", it.Item().Val)
}

it.Next()
return field, nil
}

func getType(typeName string) pb.Posting_ValType {
typ, ok := types.TypeForName(strings.ToLower(typeName))
if ok {
return pb.Posting_ValType(typ)
}

return pb.Posting_OBJECT
}

// SchemasAndTypes represents the parsed schema and type updates.
type SchemasAndTypes struct {
Schemas []*pb.SchemaUpdate
Types []*pb.TypeUpdate
}

func isTypeDeclaration(item lex.Item, it *lex.ItemIterator) bool {
if item.Val != "type" {
return false
}

nextItems, err := it.Peek(2)
switch {
case err != nil || len(nextItems) != 2:
return false

case nextItems[0].Typ != itemText:
return false

case nextItems[1].Typ != itemLeftCurl:
return false
}

return true
}

// Parse parses a schema string and returns the schema representation for it.
func Parse(s string) ([]*pb.SchemaUpdate, error) {
var schemas []*pb.SchemaUpdate
func Parse(s string) (*SchemasAndTypes, error) {
var result SchemasAndTypes

l := lex.NewLexer(s)
l.Run(lexText)
if err := l.ValidateResult(); err != nil {
Expand All @@ -308,17 +428,26 @@ func Parse(s string) ([]*pb.SchemaUpdate, error) {
item := it.Item()
switch item.Typ {
case lex.ItemEOF:
if err := resolveTokenizers(schemas); err != nil {
if err := resolveTokenizers(result.Schemas); err != nil {
return nil, x.Wrapf(err, "failed to enrich schema")
}
return schemas, nil
return &result, nil

case itemText:
if isTypeDeclaration(item, it) {
typeUpdate, err := parseTypeDeclaration(it)
if err != nil {
return nil, err
}
result.Types = append(result.Types, typeUpdate)
continue
}

schema, err := parseScalarPair(it, item.Val)
if err != nil {
return nil, err
}
schemas = append(schemas, schema)
result.Schemas = append(result.Schemas, schema)
case itemNewLine:
// pass empty line

Expand Down
Loading