private List<Column> getFileSchema() throws DdlException {
        if (fileStatuses.isEmpty()) {
            return Lists.newArrayList();
        }
        TNetworkAddress address;
        List<Long> nodeIds = GlobalStateMgr.getCurrentState().getNodeMgr().getClusterInfo().getBackendIds(true);
        if (RunMode.isSharedDataMode()) {
            nodeIds.addAll(GlobalStateMgr.getCurrentState().getNodeMgr().getClusterInfo().getComputeNodeIds(true));
        }
        if (nodeIds.isEmpty()) {
            if (RunMode.isSharedNothingMode()) {
                throw new DdlException("Failed to send proxy request. No alive backends");
            } else {
                throw new DdlException("Failed to send proxy request. No alive backends or compute nodes");
            }
        }

        Collections.shuffle(nodeIds);
        ComputeNode node = GlobalStateMgr.getCurrentState().getNodeMgr().getClusterInfo().getBackendOrComputeNode(nodeIds.get(0));
        address = new TNetworkAddress(node.getHost(), node.getBrpcPort());

        PGetFileSchemaResult result;
        try {
            PGetFileSchemaRequest request = getGetFileSchemaRequest(fileStatuses);
            Future<PGetFileSchemaResult> future = BackendServiceClient.getInstance().getFileSchema(address, request);
            result = future.get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new DdlException("failed to get file schema", e);
        } catch (Exception e) {
            throw new DdlException("failed to get file schema: " + e.getMessage());
        }

        if (TStatusCode.findByValue(result.status.statusCode) != TStatusCode.OK) {
            throw new DdlException("failed to get file schema, path: " + path + ", error: " + result.status.errorMsgs);
        }

        List<Column> columns = new ArrayList<>();
        for (PSlotDescriptor slot : result.schema) {
            columns.add(new Column(slot.colName, Type.fromProtobuf(slot.slotType), true));
        }
        return columns;
    }
@Test
    public void testGetFileSchema(@Mocked GlobalStateMgr globalStateMgr,
                                  @Mocked SystemInfoService systemInfoService) throws Exception {
        new Expectations() {
            {
                globalStateMgr.getCurrentState().getNodeMgr().getClusterInfo();
                result = systemInfoService;
                minTimes = 0;

                systemInfoService.getBackendIds(anyBoolean);
                result = new ArrayList<>();
                minTimes = 0;
            }
        };

        TableFunctionTable t = new TableFunctionTable(newProperties());

        Method method = TableFunctionTable.class.getDeclaredMethod("getFileSchema", null);
        method.setAccessible(true);

        try {
            method.invoke(t, null);
        } catch (Exception e) {
            Assert.assertTrue(e.getCause().getMessage().contains("Failed to send proxy request. No alive backends"));
        }

        new MockUp<RunMode>() {
            @Mock
            public RunMode getCurrentRunMode() {
                return RunMode.SHARED_DATA;
            }
        };

        try {
            method.invoke(t, null);
        } catch (Exception e) {
            Assert.assertTrue(e.getCause().getMessage().
                    contains("Failed to send proxy request. No alive backends or compute nodes"));
        }

        Backend backend = new Backend(1L, "192.168.1.1", 9050);
        backend.setBrpcPort(8050);

        List<Long> nodeList = new ArrayList<>();
        nodeList.add(1L);

        new Expectations() {
            {
                systemInfoService.getBackendIds(anyBoolean);
                result = nodeList;
                minTimes = 0;

                systemInfoService.getComputeNodeIds(anyBoolean);
                result = new ArrayList<>();
                minTimes = 0;

                systemInfoService.getBackendOrComputeNode(anyLong);
                result = backend;
                minTimes = 0;
            }
        };

        try {
            method.invoke(t, null);
        } catch (Exception e) {
            Assert.assertFalse(false);
        }
    }