2222import org .apache .iotdb .common .rpc .thrift .TSStatus ;
2323import org .apache .iotdb .commons .conf .IoTDBConstant ;
2424import org .apache .iotdb .commons .exception .IllegalPathException ;
25+ import org .apache .iotdb .commons .exception .IoTDBException ;
26+ import org .apache .iotdb .commons .exception .IoTDBRuntimeException ;
2527import org .apache .iotdb .commons .exception .pipe .PipeRuntimeOutOfMemoryCriticalException ;
2628import org .apache .iotdb .commons .log .LoggerPeriodicalLogReducer ;
2729import org .apache .iotdb .commons .path .PartialPath ;
7375import org .apache .iotdb .db .queryengine .plan .Coordinator ;
7476import org .apache .iotdb .db .queryengine .plan .analyze .ClusterPartitionFetcher ;
7577import org .apache .iotdb .db .queryengine .plan .analyze .schema .ClusterSchemaFetcher ;
78+ import org .apache .iotdb .db .queryengine .plan .execution .config .ConfigTaskResult ;
7679import org .apache .iotdb .db .queryengine .plan .execution .config .executor .ClusterConfigTaskExecutor ;
80+ import org .apache .iotdb .db .queryengine .plan .execution .config .metadata .DatabaseSchemaTask ;
7781import org .apache .iotdb .db .queryengine .plan .planner .plan .node .metedata .write .view .AlterLogicalViewNode ;
7882import org .apache .iotdb .db .queryengine .plan .statement .Statement ;
7983import org .apache .iotdb .db .queryengine .plan .statement .StatementType ;
96100import org .apache .iotdb .service .rpc .thrift .TPipeTransferReq ;
97101import org .apache .iotdb .service .rpc .thrift .TPipeTransferResp ;
98102
103+ import com .google .common .util .concurrent .ListenableFuture ;
99104import org .apache .tsfile .utils .Pair ;
100105import org .slf4j .Logger ;
101106import org .slf4j .LoggerFactory ;
112117import java .util .Objects ;
113118import java .util .Optional ;
114119import java .util .Set ;
120+ import java .util .concurrent .ConcurrentHashMap ;
121+ import java .util .concurrent .ExecutionException ;
115122import java .util .concurrent .atomic .AtomicLong ;
116123import java .util .concurrent .atomic .AtomicReference ;
117124import java .util .stream .Collectors ;
@@ -153,6 +160,15 @@ public class IoTDBDataNodeReceiver extends IoTDBFileReceiver {
153160 private static final SessionManager SESSION_MANAGER = SessionManager .getInstance ();
154161
155162 private PipeMemoryBlock allocatedMemoryBlock ;
163+ private final Set <String > autoCreatedTreeDatabases = ConcurrentHashMap .newKeySet ();
164+ private final Set <String > conflictedTreeDatabases = ConcurrentHashMap .newKeySet ();
165+
166+ private enum TreeDatabaseCreationResult {
167+ SKIPPED ,
168+ CREATED_OR_EXISTED ,
169+ CONFLICTED
170+ }
171+
156172 private final List <PipeMemoryBlock > allocatedSliceMemoryBlocks = new ArrayList <>();
157173
158174 static {
@@ -1045,6 +1061,11 @@ private TSStatus executeStatement(final Statement statement) {
10451061 return RpcUtils .getStatus (status .getCode (), status .getMessage ());
10461062 }
10471063
1064+ if (autoCreateTreeDatabaseIfNecessary (getTreeDatabaseName (statement ))
1065+ == TreeDatabaseCreationResult .CONFLICTED ) {
1066+ clearTreeDatabaseName (statement );
1067+ }
1068+
10481069 return Coordinator .getInstance ()
10491070 .executeForTreeModel (
10501071 shouldMarkAsPipeRequest .get () ? new PipeEnrichedStatement (statement ) : statement ,
@@ -1059,6 +1080,91 @@ private TSStatus executeStatement(final Statement statement) {
10591080 .status ;
10601081 }
10611082
1083+ private TreeDatabaseCreationResult autoCreateTreeDatabaseIfNecessary (final String database ) {
1084+ if (database == null
1085+ || LoadTsFileStatement .getDatabaseLevelByTreeDatabase (database ) == null
1086+ || !IoTDBDescriptor .getInstance ().getConfig ().isAutoCreateSchemaEnabled ()) {
1087+ return TreeDatabaseCreationResult .SKIPPED ;
1088+ }
1089+ if (autoCreatedTreeDatabases .contains (database )) {
1090+ return TreeDatabaseCreationResult .CREATED_OR_EXISTED ;
1091+ }
1092+ if (conflictedTreeDatabases .contains (database )) {
1093+ return TreeDatabaseCreationResult .CONFLICTED ;
1094+ }
1095+
1096+ try {
1097+ final DatabaseSchemaStatement statement =
1098+ new DatabaseSchemaStatement (DatabaseSchemaStatement .DatabaseSchemaStatementType .CREATE );
1099+ statement .setDatabasePath (new PartialPath (database ));
1100+ statement .setEnablePrintExceptionLog (false );
1101+
1102+ final TSStatus permissionStatus = statement .checkPermissionBeforeProcess (username );
1103+ if (permissionStatus .getCode () != TSStatusCode .SUCCESS_STATUS .getStatusCode ()) {
1104+ throw new PipeException (permissionStatus .getMessage ());
1105+ }
1106+
1107+ final DatabaseSchemaTask task = new DatabaseSchemaTask (statement );
1108+ final ListenableFuture <ConfigTaskResult > future =
1109+ task .execute (ClusterConfigTaskExecutor .getInstance ());
1110+ final ConfigTaskResult result = future .get ();
1111+ final int statusCode = result .getStatusCode ().getStatusCode ();
1112+ if (statusCode == TSStatusCode .SUCCESS_STATUS .getStatusCode ()
1113+ || statusCode == TSStatusCode .DATABASE_ALREADY_EXISTS .getStatusCode ()) {
1114+ autoCreatedTreeDatabases .add (database );
1115+ return TreeDatabaseCreationResult .CREATED_OR_EXISTED ;
1116+ }
1117+ if (statusCode == TSStatusCode .DATABASE_CONFLICT .getStatusCode ()) {
1118+ conflictedTreeDatabases .add (database );
1119+ return TreeDatabaseCreationResult .CONFLICTED ;
1120+ }
1121+ throw new PipeException (
1122+ String .format (
1123+ "Auto create tree database failed: %s, status: %s" ,
1124+ database , result .getStatus () == null ? result .getStatusCode () : result .getStatus ()));
1125+ } catch (final IllegalPathException e ) {
1126+ throw new PipeException (String .format ("Illegal tree database %s." , database ), e );
1127+ } catch (final ExecutionException | InterruptedException e ) {
1128+ if (e instanceof InterruptedException ) {
1129+ Thread .currentThread ().interrupt ();
1130+ }
1131+ final Throwable rootCause = getRootCause (e );
1132+ final int errorCode ;
1133+ if (rootCause instanceof IoTDBException ) {
1134+ errorCode = ((IoTDBException ) rootCause ).getErrorCode ();
1135+ } else if (rootCause instanceof IoTDBRuntimeException ) {
1136+ errorCode = ((IoTDBRuntimeException ) rootCause ).getErrorCode ();
1137+ } else {
1138+ errorCode = TSStatusCode .INTERNAL_SERVER_ERROR .getStatusCode ();
1139+ }
1140+ if (errorCode == TSStatusCode .DATABASE_ALREADY_EXISTS .getStatusCode ()) {
1141+ autoCreatedTreeDatabases .add (database );
1142+ return TreeDatabaseCreationResult .CREATED_OR_EXISTED ;
1143+ }
1144+ if (errorCode == TSStatusCode .DATABASE_CONFLICT .getStatusCode ()) {
1145+ conflictedTreeDatabases .add (database );
1146+ return TreeDatabaseCreationResult .CONFLICTED ;
1147+ }
1148+ throw new PipeException ("Auto create tree database failed because " + e .getMessage (), e );
1149+ }
1150+ }
1151+
1152+ private String getTreeDatabaseName (final Statement statement ) {
1153+ if (statement instanceof LoadTsFileStatement ) {
1154+ return ((LoadTsFileStatement ) statement ).getDatabase ();
1155+ }
1156+ return null ;
1157+ }
1158+
1159+ static void clearTreeDatabaseName (final Statement statement ) {
1160+ if (statement instanceof LoadTsFileStatement ) {
1161+ final LoadTsFileStatement loadTsFileStatement = (LoadTsFileStatement ) statement ;
1162+ loadTsFileStatement .setDatabase (null );
1163+ loadTsFileStatement .setDatabaseLevel (
1164+ IoTDBDescriptor .getInstance ().getConfig ().getDefaultDatabaseLevel ());
1165+ }
1166+ }
1167+
10621168 @ Override
10631169 protected TSStatus login () {
10641170 final IClientSession session = SESSION_MANAGER .getCurrSession ();
0 commit comments