public String toJson(String srcTxFilePath) {
        TxFileStruct tx = new TxFileStruct();

        try (Path path = new Path().put(srcTxFilePath)) {
            if (!ff.exists(path.$())) {
                System.err.printf("file does not exist: %s%n", srcTxFilePath);
                return null;
            }
            try (MemoryMR roTxMem = Vm.getCMRInstance(ff, path.$(), ff.length(path.$()), MemoryTag.MMAP_DEFAULT)) {
                roTxMem.growToFileSize();
                final long version = roTxMem.getLong(TX_BASE_OFFSET_VERSION_64);
                final boolean isA = (version & 1L) == 0L;
                final long baseOffset = isA ? roTxMem.getInt(TX_BASE_OFFSET_A_32) : roTxMem.getInt(TX_BASE_OFFSET_B_32);
                final int symbolsSize = isA ? roTxMem.getInt(TX_BASE_OFFSET_SYMBOLS_SIZE_A_32) : roTxMem.getInt(TX_BASE_OFFSET_SYMBOLS_SIZE_B_32);
                final int partitionSegmentSize = isA ? roTxMem.getInt(TX_BASE_OFFSET_PARTITIONS_SIZE_A_32) : roTxMem.getInt(TX_BASE_OFFSET_PARTITIONS_SIZE_B_32);

                tx.TX_OFFSET_TXN = roTxMem.getLong(baseOffset + TX_OFFSET_TXN_64);
                tx.TX_OFFSET_TRANSIENT_ROW_COUNT = roTxMem.getLong(baseOffset + TX_OFFSET_TRANSIENT_ROW_COUNT_64);
                tx.TX_OFFSET_FIXED_ROW_COUNT = roTxMem.getLong(baseOffset + TX_OFFSET_FIXED_ROW_COUNT_64);
                tx.TX_OFFSET_MIN_TIMESTAMP = roTxMem.getLong(baseOffset + TX_OFFSET_MIN_TIMESTAMP_64);
                tx.TX_OFFSET_MAX_TIMESTAMP = roTxMem.getLong(baseOffset + TX_OFFSET_MAX_TIMESTAMP_64);
                tx.TX_OFFSET_DATA_VERSION = roTxMem.getLong(baseOffset + TX_OFFSET_DATA_VERSION_64);
                tx.TX_OFFSET_STRUCT_VERSION = roTxMem.getLong(baseOffset + TX_OFFSET_STRUCT_VERSION_64);
                tx.TX_OFFSET_MAP_WRITER_COUNT = roTxMem.getInt(baseOffset + TX_OFFSET_MAP_WRITER_COUNT_32); // symbolColumnCount
                tx.TX_OFFSET_PARTITION_TABLE_VERSION = roTxMem.getLong(baseOffset + TX_OFFSET_PARTITION_TABLE_VERSION_64);
                tx.TX_OFFSET_COLUMN_VERSION = roTxMem.getLong(baseOffset + TX_OFFSET_COLUMN_VERSION_64);
                tx.TX_OFFSET_LAG_ROW_COUNT = roTxMem.getInt(baseOffset + TX_OFFSET_LAG_ROW_COUNT_32);
                tx.TX_OFFSET_LAG_TXN_COUNT = roTxMem.getInt(baseOffset + TX_OFFSET_LAG_TXN_COUNT_32);
                tx.TX_OFFSET_TRUNCATE_VERSION = roTxMem.getLong(baseOffset + TX_OFFSET_TRUNCATE_VERSION_64);
                tx.TX_OFFSET_LAG_MIN_TIMESTAMP = roTxMem.getLong(baseOffset + TX_OFFSET_LAG_MIN_TIMESTAMP_64);
                tx.TX_OFFSET_LAG_MAX_TIMESTAMP = roTxMem.getLong(baseOffset + TX_OFFSET_LAG_MAX_TIMESTAMP_64);
                tx.TX_OFFSET_CHECKSUM = roTxMem.getInt(baseOffset + TX_OFFSET_LAG_MAX_TIMESTAMP_64);
                tx.TX_OFFSET_SEQ_TXN = roTxMem.getLong(baseOffset + TX_OFFSET_SEQ_TXN_64);

                final int symbolColumnCount = symbolsSize / Long.BYTES;
                tx.SYMBOLS = new ArrayList<>(symbolColumnCount);
                long offset = baseOffset + TX_OFFSET_MAP_WRITER_COUNT_32 + Integer.BYTES;
                final long maxOffsetSymbols = offset + symbolsSize;
                while (offset + 3 < Math.min(roTxMem.size(), maxOffsetSymbols)) {
                    TxFileStruct.SymbolInfo symbol = new TxFileStruct.SymbolInfo();
                    tx.SYMBOLS.add(symbol);
                    symbol.COUNT = roTxMem.getInt(offset);
                    offset += Integer.BYTES;
                    if (offset + 3 < roTxMem.size()) {
                        symbol.UNCOMMITTED_COUNT = roTxMem.getInt(offset);
                        offset += Integer.BYTES;
                    }
                }

                final int txAttachedPartitionsCount = partitionSegmentSize / LONGS_PER_TX_ATTACHED_PARTITION / Long.BYTES;
                tx.ATTACHED_PARTITIONS_COUNT = txAttachedPartitionsCount;
                tx.ATTACHED_PARTITIONS = new ArrayList<>(txAttachedPartitionsCount);
                final long partitionTableOffset = TableUtils.getPartitionTableSizeOffset(tx.TX_OFFSET_MAP_WRITER_COUNT);
                offset = baseOffset + getPartitionTableIndexOffset(partitionTableOffset, 0);
                final long maxOffsetPartitions = offset + partitionSegmentSize;
                while (offset + 7 < Math.min(roTxMem.size(), maxOffsetPartitions)) {
                    TxFileStruct.AttachedPartition partition = new TxFileStruct.AttachedPartition();
                    tx.ATTACHED_PARTITIONS.add(partition);
                    partition.TS = roTxMem.getLong(offset);
                    offset += Long.BYTES;
                    if (offset + 7 < roTxMem.size()) {
                        long maskedSize = roTxMem.getLong(offset);
                        partition.MASK = (maskedSize & TxReader.PARTITION_FLAGS_MASK) >>> 44;
                        partition.SIZE = maskedSize & TxReader.PARTITION_SIZE_MASK;
                        offset += Long.BYTES;
                    }
                    if (offset + 7 < roTxMem.size()) {
                        partition.NAME_TX = roTxMem.getLong(offset);
                        offset += Long.BYTES;
                    }
                    if (offset + 7 < roTxMem.size()) {
                        partition.DATA_TX = roTxMem.getLong(offset);
                        offset += Long.BYTES;
                    }
                }
            }
        }
        return GSON.toJson(tx);
    }
@Test
    public void testPartitionedDailyWithTruncate() throws SqlException {
        String createTableSql = "create table xxx as (" +
                "select " +
                "rnd_symbol('A', 'B', 'C') as sym1," +
                "rnd_symbol(4,4,4,2) as sym2," +
                "x," +
                "timestamp_sequence(0, 1000000000000) ts " +
                "from long_sequence(10)" +
                ") timestamp(ts) PARTITION BY DAY";

        engine.ddl(createTableSql, sqlExecutionContext);

        TxSerializer serializer = new TxSerializer();
        String txPath = root.toString() + Files.SEPARATOR + "xxx" + Files.SEPARATOR + "_txn";
        String json = serializer.toJson(txPath);
        Assert.assertTrue(json.contains("\"TX_OFFSET_TRUNCATE_VERSION\": 0"));

        engine.ddl("truncate table xxx", sqlExecutionContext);
        json = serializer.toJson(txPath);
        Assert.assertTrue(json.contains("\"TX_OFFSET_TRUNCATE_VERSION\": 1"));
    }