private static bool ParseNodeTableColumn(
IList<TSqlParserToken> tokens,
ref int nextToken,
ref WNodeTableColumn result,
ref int farestError)
{
var currentToken = nextToken;
var firstToken = nextToken;
var lastToken = nextToken;
var metaDataStr = "";
// Quoted identifier is an expression inside a pair of brackets [ ... ]
if (!ReadToken(tokens, TSqlTokenType.QuotedIdentifier, ref metaDataStr, ref currentToken, ref farestError))
return false;
Identifier columnName = null;
if (!ParseIdentifier(tokens, ref currentToken, ref columnName, ref farestError))
return false;
WDataTypeReference dataType = null;
if (!ParseDataType(tokens, ref currentToken, ref dataType, ref farestError))
return false;
HashSet<string> metaDataFields = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"columnrole",
"reference",
"attributes"
};
metaDataStr = '{' + metaDataStr.Substring(1, metaDataStr.Length - 2) + '}';
var metaStrToken = tokens[firstToken];
var tokenErrorKey = "";
List<AnnotationToken> annotationTokens = LexicalAnalyzer.Tokenize(metaDataStr, ref tokenErrorKey);
if (annotationTokens == null)
{
throw new SyntaxErrorException(metaStrToken.Line, tokenErrorKey);
}
int startToken = 0, fareastError = -1;
NestedObject nestedObj = null;
ParseNestedObject(annotationTokens, ref startToken, ref nestedObj, ref fareastError);
if (nestedObj == null || nestedObj.GetType() != typeof(CollectionObject))
{
throw new SyntaxErrorException(metaStrToken.Line, annotationTokens[1].value);
}
CollectionObject annotationObj = nestedObj as CollectionObject;
var invalidFields = annotationObj.Collection.Where(e => !metaDataFields.Contains(e.Key)).Select(e=>e.Key).ToList();
if (invalidFields.Count > 0)
{
var invalidFieldsStr = new StringBuilder();
foreach (var field in invalidFields)
{
invalidFieldsStr.AppendFormat("'{0}' ", field);
}
throw new SyntaxErrorException(metaStrToken.Line, invalidFields.First(),
string.Format("Invalid metadata field(s): {0}", invalidFieldsStr));
}
if (annotationObj.Collection.ContainsKey("columnrole"))
{
StringObject roleValue = annotationObj.Collection["columnrole"] as StringObject;
if (string.Equals(roleValue.Value, "edge", StringComparison.OrdinalIgnoreCase))
{
if (!annotationObj.Collection.ContainsKey("reference"))
{
throw new SyntaxErrorException(metaStrToken.Line, "edge", "No edge reference");
}
StringObject refValue = annotationObj.Collection["reference"] as StringObject;
var refTableName = new WSchemaObjectName(new Identifier { Value = refValue.Value });
var attributeList = new List<Tuple<Identifier, WEdgeAttributeType>>();
if (annotationObj.Collection.ContainsKey("attributes"))
{
CollectionObject attributeCollection = annotationObj.Collection["attributes"] as CollectionObject;
foreach (string propName in attributeCollection.Collection.Keys)
{
StringObject propValue = attributeCollection.Collection[propName] as StringObject;
attributeList.Add(new Tuple<Identifier, WEdgeAttributeType>(
new Identifier { Value = propName },
(WEdgeAttributeType)Enum.Parse(typeof(WEdgeAttributeType), propValue.Value, true)
));
}
}
result = new WGraphTableEdgeColumn
{
ColumnName = columnName,
DataType = dataType,
TableReference = new WNamedTableReference { TableObjectName = refTableName },
Attributes = attributeList,
FirstTokenIndex = firstToken,
LastTokenIndex = currentToken - 1,
};
}
else if (string.Equals(roleValue.Value, "property", StringComparison.OrdinalIgnoreCase))
{
if (annotationObj.Collection.Count > 1)
{
var invalidName =
annotationObj.Collection.Where(e => e.Key.ToLower() != "columnrole")
.Select(e => e.Key);
var sb = new StringBuilder();
foreach (var name in invalidName)
{
sb.AppendFormat("'{0}' ",name);
}
throw new SyntaxErrorException(metaStrToken.Line, "columnrole",
string.Format("Invalid metadata field(s): {0}", sb));
}
result = new WGraphTablePropertyColumn
{
ColumnName = columnName,
DataType = dataType,
FirstTokenIndex = firstToken,
LastTokenIndex = currentToken - 1,
};
}
else if (string.Equals(roleValue.Value, "nodeid", StringComparison.OrdinalIgnoreCase))
{
if (annotationObj.Collection.Count > 1)
{
var invalidName =
annotationObj.Collection.Where(e => e.Key.ToLower() != "columnrole")
.Select(e => e.Key);
var sb = new StringBuilder();
foreach (var name in invalidName)
{
sb.AppendFormat("'{0}' ", name);
}
throw new SyntaxErrorException(metaStrToken.Line, "columnrole",
string.Format("Invalid metadata field(s): {0}", sb));
}
result = new WGraphTableNodeIdColumn
{
ColumnName = columnName,
DataType = dataType,
FirstTokenIndex = firstToken,
LastTokenIndex = currentToken - 1,
};
}
else
{
throw new SyntaxErrorException(metaStrToken.Line, "columnrole", "Invalid column role");
}
}
else
{
throw new SyntaxErrorException(metaStrToken.Line, annotationTokens[1].value, "Invalid metadata Field"); ;
}
nextToken = currentToken;
return true;
}