3636import io .questdb .griffin .model .IntervalUtils ;
3737import io .questdb .griffin .model .QueryColumn ;
3838import io .questdb .griffin .model .QueryModel ;
39- import io .questdb .std .CharSequenceHashSet ;
4039import io .questdb .std .Chars ;
4140import io .questdb .std .GenericLexer ;
4241import io .questdb .std .Long256 ;
4342import io .questdb .std .Long256Acceptor ;
4443import io .questdb .std .Long256FromCharSequenceDecoder ;
4544import io .questdb .std .Long256Impl ;
45+ import io .questdb .std .LowerCaseCharSequenceHashSet ;
4646import io .questdb .std .LowerCaseCharSequenceObjHashMap ;
4747import io .questdb .std .Numbers ;
4848import io .questdb .std .NumericException ;
6565
6666public class SqlUtil {
6767
68- static final CharSequenceHashSet disallowedAliases = new CharSequenceHashSet ();
68+ static final LowerCaseCharSequenceHashSet disallowedAliases = new LowerCaseCharSequenceHashSet ();
6969 private static final DateFormat [] DATE_FORMATS_FOR_TIMESTAMP ;
7070 private static final int DATE_FORMATS_FOR_TIMESTAMP_SIZE ;
7171 private static final ThreadLocal <Long256ConstantFactory > LONG256_FACTORY = new ThreadLocal <>(Long256ConstantFactory ::new );
@@ -96,23 +96,28 @@ public static CharSequence createExprColumnAlias(
9696 boolean nonLiteral
9797 ) {
9898 // We need to wrap disallowed aliases with double quotes to avoid later conflicts.
99- final boolean quote = nonLiteral && !Chars .isDoubleQuoted (base ) && (
100- Chars .indexOf (base , '.' ) > -1 || disallowedAliases .contains (base )
101- );
99+ final int baseLen = base .length ();
100+ final int indexOfDot = Chars .indexOfLastUnquoted (base , '.' );
101+ final boolean prefixedLiteral = !nonLiteral && indexOfDot > -1 && indexOfDot < baseLen - 1 ;
102+ boolean quote = nonLiteral
103+ ? !Chars .isDoubleQuoted (base ) && (indexOfDot > -1 || disallowedAliases .contains (base ))
104+ : indexOfDot > -1 && disallowedAliases .contains (base , indexOfDot + 1 , base .length ());
102105
103- int len = base .length ();
104106 // early exit for simple cases
105- if (!quote && aliasToColumnMap .excludes (base ) && len > 0 && len <= maxLength && base .charAt (len - 1 ) != ' ' ) {
107+ if (!prefixedLiteral && !quote && aliasToColumnMap .excludes (base )
108+ && baseLen > 0 && baseLen <= maxLength && base .charAt (baseLen - 1 ) != ' ' ) {
106109 return base ;
107110 }
108111
112+ final int start = prefixedLiteral ? indexOfDot + 1 : 0 ;
113+ int len = baseLen - start ;
109114 final CharacterStoreEntry entry = store .newEntry ();
110115 final int entryLen = entry .length ();
111116 if (quote ) {
112117 entry .put ('"' );
113118 len += 2 ;
114119 }
115- entry .put (base );
120+ entry .put (base , start , baseLen );
116121
117122 int sequence = 1 ;
118123 int seqSize = 0 ;
@@ -123,8 +128,8 @@ public static CharSequence createExprColumnAlias(
123128 len = Math .min (len , maxLength - seqSize - (quote ? 1 : 0 ));
124129
125130 // We don't want the alias to finish with a space.
126- if (!quote && len > 0 && base .charAt (len - 1 ) == ' ' ) {
127- final int lastSpace = Chars .lastIndexOfDifferent (base , 0 , len , ' ' );
131+ if (!quote && len > 0 && base .charAt (start + len - 1 ) == ' ' ) {
132+ final int lastSpace = Chars .lastIndexOfDifferent (base , start , start + len , ' ' ) - start ;
128133 if (lastSpace > 0 ) {
129134 len = lastSpace + 1 ;
130135 }
@@ -153,22 +158,8 @@ public static long dateToTimestamp(long millis) {
153158 }
154159
155160 public static long expectMicros (CharSequence tok , int position ) throws SqlException {
156- int k = -1 ;
157-
158161 final int len = tok .length ();
159-
160- // look for end of digits
161- for (int i = 0 ; i < len ; i ++) {
162- char c = tok .charAt (i );
163- if (c < '0' || c > '9' ) {
164- k = i ;
165- break ;
166- }
167- }
168-
169- if (k == -1 ) {
170- throw SqlException .$ (position + len , "expected interval qualifier in " ).put (tok );
171- }
162+ final int k = findEndOfDigitsPos (tok , len , position );
172163
173164 try {
174165 long interval = Numbers .parseLong (tok , 0 , k );
@@ -223,22 +214,8 @@ public static long expectMicros(CharSequence tok, int position) throws SqlExcept
223214 }
224215
225216 public static long expectSeconds (CharSequence tok , int position ) throws SqlException {
226- int k = -1 ;
227-
228217 final int len = tok .length ();
229-
230- // look for end of digits
231- for (int i = 0 ; i < len ; i ++) {
232- char c = tok .charAt (i );
233- if (c < '0' || c > '9' ) {
234- k = i ;
235- break ;
236- }
237- }
238-
239- if (k == -1 ) {
240- throw SqlException .$ (position + len , "expected interval qualifier in " ).put (tok );
241- }
218+ final int k = findEndOfDigitsPos (tok , len , position );
242219
243220 try {
244221 long interval = Numbers .parseLong (tok , 0 , k );
@@ -1075,6 +1052,23 @@ public static short toPersistedTypeTag(@NotNull CharSequence tok, int tokPositio
10751052 throw SqlException .$ (tokPosition , "non-persisted type: " ).put (tok );
10761053 }
10771054
1055+ private static int findEndOfDigitsPos (CharSequence tok , int tokLen , int tokPosition ) throws SqlException {
1056+ int k = -1 ;
1057+ // look for end of digits
1058+ for (int i = 0 ; i < tokLen ; i ++) {
1059+ char c = tok .charAt (i );
1060+ if (c < '0' || c > '9' ) {
1061+ k = i ;
1062+ break ;
1063+ }
1064+ }
1065+
1066+ if (k == -1 ) {
1067+ throw SqlException .$ (tokPosition + tokLen , "expected interval qualifier in " ).put (tok );
1068+ }
1069+ return k ;
1070+ }
1071+
10781072 private static long implicitCastStrVarcharAsDate0 (CharSequence value , int columnType ) {
10791073 assert columnType == ColumnType .VARCHAR || columnType == ColumnType .STRING ;
10801074 try {
0 commit comments