private PLStartSymbol recognizeStartSymbol(Collection<Integer> sourceCache) {
        if (sourceCache.size() > MAX_PL_PATTEN_TYPE_SIZE) {
            return null;
        }
        int[] cacheTokenTypeArray = sourceCache.stream().mapToInt(i -> i).toArray();
        for (int i = 0; i < ALL_PL_START_PATTERNS.length; i++) {
            int[] pattern = ALL_PL_START_PATTERNS[i];
            if (Arrays.equals(pattern, cacheTokenTypeArray)) {
                return INDEX_2_START_SYMBOL.get(i);
            }
        }
        return PLStartSymbol.UNKNOWN;
    }
<pre>
sub PL block start rule is different from the first PL block start
cache token types are stored in a queue because when we run into a new symbol,
we always add to the tail of queue and try to remove head of queue when it it full

when trying to match ALL_PL_START_PATTERNS, we always try to match the longer start pattern,
for example, match `create type body` but not `create type`
</pre>
chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/SqlSplitter.java