in core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java [4188:4408]
public SQLDataType parseDataType(boolean restrict) {
if (lexer.keepSourceLocation) {
lexer.computeRowAndColumn();
}
int sourceLine = lexer.getPosLine(), sourceColumn = lexer.getPosColumn();
Token token = lexer.token;
if (token == Token.DEFAULT || token == Token.NOT || token == Token.NULL) {
return null;
}
if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {
return parseArrayDataType();
}
if (lexer.identifierEquals(FnvHash.Constants.MAP)) {
lexer.nextToken();
if (lexer.token == Token.LPAREN) { // presto
lexer.nextToken();
SQLDataType keyType = parseDataType();
accept(Token.COMMA);
SQLDataType valueType = parseDataType();
accept(Token.RPAREN);
return new SQLMapDataType(keyType, valueType, dbType);
}
accept(Token.LT);
SQLDataType keyType = parseDataType();
accept(Token.COMMA);
SQLDataType valueType = parseDataType();
if (lexer.token == Token.GTGT) {
lexer.token = Token.GT;
} else {
accept(Token.GT);
}
return new SQLMapDataType(keyType, valueType, dbType);
}
if (lexer.identifierEquals(FnvHash.Constants.STRUCT)) {
return parseDataTypeStruct();
} else if (lexer.token == Token.TABLE) {
lexer.nextToken();
SQLTableDataType table = new SQLTableDataType();
accept(Token.LPAREN);
for (; ; ) {
SQLColumnDefinition column;
if (lexer.token == Token.STAR) {
lexer.nextToken();
column = new SQLColumnDefinition();
column.setName("*");
accept(Token.ANY);
} else {
column = this.parseColumn();
}
column.setParent(table);
table.getColumns().add(column);
if (lexer.token == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
return table;
} else if (lexer.identifierEquals(FnvHash.Constants.ROW) || lexer.token == Token.ROW) {
lexer.nextToken();
return parseDataTypeRow();
} else if (lexer.identifierEquals(FnvHash.Constants.NESTED)) {
SQLDataType dataType = parseDataTypeNested();
if (dataType != null) {
return dataType;
}
}
if (lexer.identifierEquals(FnvHash.Constants.UNIONTYPE)) {
lexer.nextToken();
accept(Token.LT);
SQLUnionDataType unionType = new SQLUnionDataType();
for (; ; ) {
SQLDataType item = this.parseDataType();
unionType.add(item);
if (lexer.token == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.GT);
return unionType;
}
if (lexer.identifierEquals(FnvHash.Constants.GENERATED)
|| lexer.identifierEquals(FnvHash.Constants.RENAME)) {
return null;
}
SQLName typeExpr = name();
final long typeNameHashCode = typeExpr.nameHashCode64();
StringBuilder typeName = new StringBuilder(typeExpr.toString());
if (typeNameHashCode == FnvHash.Constants.LONG
&& lexer.identifierEquals(FnvHash.Constants.BYTE)) {
parseDataTypeByte(typeName);
} else if (typeNameHashCode == FnvHash.Constants.DOUBLE) {
parseDataTypeDouble(typeName);
parseDataTypePrecision(typeName);
}
if (typeNameHashCode == FnvHash.Constants.UNSIGNED) {
if (lexer.token == Token.IDENTIFIER) {
typeName.append(' ').append(lexer.stringVal());
lexer.nextToken();
}
} else if (typeNameHashCode == FnvHash.Constants.SIGNED) {
if (lexer.token == Token.IDENTIFIER) {
typeName.append(' ').append(lexer.stringVal());
lexer.nextToken();
}
} else if (isCharType(typeNameHashCode)) {
SQLCharacterDataType charType = new SQLCharacterDataType(typeName.toString());
//for ads
if (lexer.token == Token.LBRACKET) {
SQLArrayDataType arrayDataType = new SQLArrayDataType(charType, dbType);
lexer.nextToken();
accept(Token.RBRACKET);
arrayDataType.putAttribute("ads.arrayDataType", Boolean.TRUE);
return arrayDataType;
}
if (lexer.token == Token.LPAREN) {
lexer.nextToken();
if (typeNameHashCode == FnvHash.Constants.ENUM) {
exprList(charType.getArguments(), charType);
} else {
SQLExpr arg = this.expr();
arg.setParent(charType);
charType.addArgument(arg);
}
accept(Token.RPAREN);
}
charType = (SQLCharacterDataType) parseCharTypeRest(charType);
if (lexer.token == Token.HINT) {
List<SQLCommentHint> hints = this.parseHints();
charType.setHints(hints);
}
if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {
return parseDataTypeRest(charType);
} else if (lexer.token == Token.LBRACKET) {
return parseDataTypeRest(charType);
}
return charType;
} else if (typeNameHashCode == FnvHash.Constants.DATE) {
return parseDataTypeRest(parseDataTypeDate(typeName, sourceLine, sourceColumn));
}
if ("national".equalsIgnoreCase(typeName.toString()) &&
(lexer.identifierEquals(FnvHash.Constants.CHAR)
|| lexer.identifierEquals(FnvHash.Constants.VARCHAR))) {
typeName.append(' ').append(lexer.stringVal());
lexer.nextToken();
SQLCharacterDataType charType = new SQLCharacterDataType(typeName.toString());
if (lexer.token == Token.LPAREN) {
lexer.nextToken();
SQLExpr arg = this.expr();
arg.setParent(charType);
charType.addArgument(arg);
accept(Token.RPAREN);
}
charType = (SQLCharacterDataType) parseCharTypeRest(charType);
if (lexer.token == Token.HINT) {
List<SQLCommentHint> hints = this.parseHints();
charType.setHints(hints);
}
if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {
return parseDataTypeRest(charType);
}
return charType;
}
if ("character".equalsIgnoreCase(typeName.toString()) && "varying".equalsIgnoreCase(lexer.stringVal())) {
typeName.append(' ').append(lexer.stringVal());
lexer.nextToken();
}
parseDataTypeComplex(typeName);
SQLDataType dataType = new SQLDataTypeImpl(typeName.toString());
dataType.setDbType(dbType);
//for ads
if (lexer.token == Token.LBRACKET) {
dataType = new SQLArrayDataType(dataType, dbType);
lexer.nextToken();
if (lexer.token == Token.LITERAL_INT) {
SQLExpr arg = this.expr();
arg.setParent(dataType);
dataType.getArguments().add(arg);
}
accept(Token.RBRACKET);
dataType.putAttribute("ads.arrayDataType", Boolean.TRUE);
}
dataType.setSource(sourceLine, sourceColumn);
return parseDataTypeRest(dataType);
}