未验证 提交 01b1885c 编写于 作者: A Andrey Pechkurov 提交者: GitHub

fix(sql): treat zero char as empty string literal (#1550)

上级 b8cbf29a
...@@ -419,7 +419,7 @@ public class FunctionParser implements PostOrderTreeTraversalAlgo.Visitor { ...@@ -419,7 +419,7 @@ public class FunctionParser implements PostOrderTreeTraversalAlgo.Visitor {
if (len == 2) { if (len == 2) {
// empty // empty
return CharConstant.ZERO; return StrConstant.EMPTY;
} }
return new StrConstant(tok); return new StrConstant(tok);
} }
......
...@@ -34,6 +34,7 @@ import io.questdb.griffin.SqlExecutionContext; ...@@ -34,6 +34,7 @@ import io.questdb.griffin.SqlExecutionContext;
import io.questdb.griffin.engine.functions.BooleanFunction; import io.questdb.griffin.engine.functions.BooleanFunction;
import io.questdb.griffin.engine.functions.UnaryFunction; import io.questdb.griffin.engine.functions.UnaryFunction;
import io.questdb.griffin.engine.functions.constants.BooleanConstant; import io.questdb.griffin.engine.functions.constants.BooleanConstant;
import io.questdb.griffin.engine.functions.constants.CharConstant;
import io.questdb.std.IntHashSet; import io.questdb.std.IntHashSet;
import io.questdb.std.IntList; import io.questdb.std.IntList;
import io.questdb.std.ObjList; import io.questdb.std.ObjList;
...@@ -64,6 +65,12 @@ public class InCharFunctionFactory implements FunctionFactory { ...@@ -64,6 +65,12 @@ public class InCharFunctionFactory implements FunctionFactory {
Function func = args.getQuick(i); Function func = args.getQuick(i);
if (ColumnType.isChar(func.getType())) { if (ColumnType.isChar(func.getType())) {
set.add(func.getChar(null)); set.add(func.getChar(null));
} else if (ColumnType.isString(func.getType())) {
// Implicitly cast empty string literal ('') to zero char
if (func.getStrLen(null) != 0) {
throw SqlException.$(argPositions.getQuick(i), "CHAR constant expected");
}
set.add(CharConstant.ZERO.getChar(null));
} else { } else {
throw SqlException.$(argPositions.getQuick(i), "CHAR constant expected"); throw SqlException.$(argPositions.getQuick(i), "CHAR constant expected");
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* *
******************************************************************************/ ******************************************************************************/
package io.questdb.griffin.engine.functions.eq; package io.questdb.griffin.engine.functions.conditional;
import io.questdb.cairo.CairoConfiguration; import io.questdb.cairo.CairoConfiguration;
import io.questdb.cairo.sql.Function; import io.questdb.cairo.sql.Function;
...@@ -34,7 +34,7 @@ import io.questdb.griffin.engine.functions.CharFunction; ...@@ -34,7 +34,7 @@ import io.questdb.griffin.engine.functions.CharFunction;
import io.questdb.std.IntList; import io.questdb.std.IntList;
import io.questdb.std.ObjList; import io.questdb.std.ObjList;
public class NullIfCharCharFunctionFactory implements FunctionFactory { public class NullIfCharFunctionFactory implements FunctionFactory {
@Override @Override
public String getSignature() { public String getSignature() {
return "nullif(AA)"; return "nullif(AA)";
...@@ -42,7 +42,6 @@ public class NullIfCharCharFunctionFactory implements FunctionFactory { ...@@ -42,7 +42,6 @@ public class NullIfCharCharFunctionFactory implements FunctionFactory {
@Override @Override
public Function newInstance(int position, ObjList<Function> args, IntList argPositions, CairoConfiguration configuration, SqlExecutionContext sqlExecutionContext) { public Function newInstance(int position, ObjList<Function> args, IntList argPositions, CairoConfiguration configuration, SqlExecutionContext sqlExecutionContext) {
Function chrFunc1 = args.getQuick(0); Function chrFunc1 = args.getQuick(0);
Function chrFunc2 = args.getQuick(1); Function chrFunc2 = args.getQuick(1);
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* *
******************************************************************************/ ******************************************************************************/
package io.questdb.griffin.engine.functions.catalogue; package io.questdb.griffin.engine.functions.conditional;
import io.questdb.cairo.CairoConfiguration; import io.questdb.cairo.CairoConfiguration;
import io.questdb.cairo.sql.Function; import io.questdb.cairo.sql.Function;
...@@ -70,7 +70,7 @@ public class NullIfIFunctionFactory implements FunctionFactory { ...@@ -70,7 +70,7 @@ public class NullIfIFunctionFactory implements FunctionFactory {
@Override @Override
public int getInt(Record rec) { public int getInt(Record rec) {
final int val = value.getInt(rec); final int val = value.getInt(rec);
return val != Numbers.INT_NaN ? val : replacement; return val == replacement ? Numbers.INT_NaN : val;
} }
} }
} }
...@@ -22,33 +22,81 @@ ...@@ -22,33 +22,81 @@
* *
******************************************************************************/ ******************************************************************************/
package io.questdb.griffin.engine.functions.str; package io.questdb.griffin.engine.functions.conditional;
import io.questdb.cairo.CairoConfiguration;
import io.questdb.cairo.sql.Function;
import io.questdb.cairo.sql.Record;
import io.questdb.griffin.FunctionFactory; import io.questdb.griffin.FunctionFactory;
import io.questdb.griffin.SqlException; import io.questdb.griffin.SqlExecutionContext;
import io.questdb.griffin.engine.AbstractFunctionFactoryTest; import io.questdb.griffin.engine.functions.BinaryFunction;
import org.junit.Test; import io.questdb.griffin.engine.functions.StrFunction;
import io.questdb.std.Chars;
import io.questdb.std.IntList;
import io.questdb.std.ObjList;
public class LengthSymbolVFunctionFactoryTest extends AbstractFunctionFactoryTest { public class NullIfStrFunctionFactory implements FunctionFactory {
@Override
@Test public String getSignature() {
public void testEmpty() throws SqlException { return "nullif(SS)";
call("").andAssert(0);
} }
@Test @Override
public void testNull() throws SqlException { public Function newInstance(
call((Object) null).andAssert(-1); int position,
ObjList<Function> args,
IntList argPositions,
CairoConfiguration configuration,
SqlExecutionContext sqlExecutionContext
) {
Function strFunc1 = args.getQuick(0);
Function strFunc2 = args.getQuick(1);
return new Func(strFunc1, strFunc2);
} }
@Test private static class Func extends StrFunction implements BinaryFunction {
public void testSimple() throws SqlException { private final Function strFunc1;
call("xyz").andAssert(3); private final Function strFunc2;
}
@Override public Func(Function strFunc1, Function strFunc2) {
protected FunctionFactory getFunctionFactory() { this.strFunc1 = strFunc1;
return new LengthSymbolFunctionFactory(); this.strFunc2 = strFunc2;
} }
@Override
public Function getLeft() {
return strFunc1;
}
@Override
public Function getRight() {
return strFunc2;
}
} @Override
\ No newline at end of file public CharSequence getStr(Record rec) {
CharSequence cs1 = strFunc1.getStr(rec);
if (cs1 == null) {
return null;
}
CharSequence cs2 = strFunc2.getStr(rec);
if (cs2 == null) {
return null;
}
return Chars.equals(cs1, cs2) ? null : cs1;
}
@Override
public CharSequence getStrB(Record rec) {
CharSequence cs1 = strFunc1.getStrB(rec);
if (cs1 == null) {
return null;
}
CharSequence cs2 = strFunc2.getStrB(rec);
if (cs2 == null) {
return null;
}
return Chars.equals(cs1, cs2) ? null : cs1;
}
}
}
...@@ -31,6 +31,7 @@ import io.questdb.std.Chars; ...@@ -31,6 +31,7 @@ import io.questdb.std.Chars;
public class StrConstant extends StrFunction implements ConstantFunction { public class StrConstant extends StrFunction implements ConstantFunction {
public static final StrConstant NULL = new StrConstant(null); public static final StrConstant NULL = new StrConstant(null);
public static final StrConstant EMPTY = new StrConstant("");
private final String value; private final String value;
private final int length; private final int length;
......
...@@ -126,7 +126,9 @@ open module io.questdb { ...@@ -126,7 +126,9 @@ open module io.questdb {
io.questdb.griffin.engine.functions.eq.EqStrGeoHashFunctionFactory, io.questdb.griffin.engine.functions.eq.EqStrGeoHashFunctionFactory,
//nullif //nullif
io.questdb.griffin.engine.functions.eq.NullIfCharCharFunctionFactory, io.questdb.griffin.engine.functions.conditional.NullIfCharFunctionFactory,
io.questdb.griffin.engine.functions.conditional.NullIfIFunctionFactory,
io.questdb.griffin.engine.functions.conditional.NullIfStrFunctionFactory,
// '<' operator // '<' operator
io.questdb.griffin.engine.functions.lt.LtDoubleVVFunctionFactory, io.questdb.griffin.engine.functions.lt.LtDoubleVVFunctionFactory,
...@@ -542,7 +544,6 @@ open module io.questdb { ...@@ -542,7 +544,6 @@ open module io.questdb {
io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetPartKeyDefFunctionFactory, io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetPartKeyDefFunctionFactory,
io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetSITExprFunctionFactory, io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetSITExprFunctionFactory,
io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetSIExprFunctionFactory, io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetSIExprFunctionFactory,
io.questdb.griffin.engine.functions.catalogue.NullIfIFunctionFactory,
io.questdb.griffin.engine.functions.catalogue.FormatTypeFunctionFactory, io.questdb.griffin.engine.functions.catalogue.FormatTypeFunctionFactory,
io.questdb.griffin.engine.functions.catalogue.ProcCatalogueFunctionFactory, io.questdb.griffin.engine.functions.catalogue.ProcCatalogueFunctionFactory,
io.questdb.griffin.engine.functions.catalogue.RangeCatalogueFunctionFactory, io.questdb.griffin.engine.functions.catalogue.RangeCatalogueFunctionFactory,
......
...@@ -58,8 +58,10 @@ io.questdb.griffin.engine.functions.eq.EqGeoHashGeoHashFunctionFactory ...@@ -58,8 +58,10 @@ io.questdb.griffin.engine.functions.eq.EqGeoHashGeoHashFunctionFactory
io.questdb.griffin.engine.functions.eq.EqGeoHashStrFunctionFactory io.questdb.griffin.engine.functions.eq.EqGeoHashStrFunctionFactory
io.questdb.griffin.engine.functions.eq.EqStrGeoHashFunctionFactory io.questdb.griffin.engine.functions.eq.EqStrGeoHashFunctionFactory
#nullif # nullif
io.questdb.griffin.engine.functions.eq.NullIfCharCharFunctionFactory io.questdb.griffin.engine.functions.conditional.NullIfCharFunctionFactory
io.questdb.griffin.engine.functions.conditional.NullIfStrFunctionFactory
io.questdb.griffin.engine.functions.conditional.NullIfIFunctionFactory
# '<' operator # '<' operator
io.questdb.griffin.engine.functions.lt.LtDoubleVVFunctionFactory io.questdb.griffin.engine.functions.lt.LtDoubleVVFunctionFactory
...@@ -520,7 +522,6 @@ io.questdb.griffin.engine.functions.catalogue.CurrentSchemaFunctionFactory ...@@ -520,7 +522,6 @@ io.questdb.griffin.engine.functions.catalogue.CurrentSchemaFunctionFactory
io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetPartKeyDefFunctionFactory io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetPartKeyDefFunctionFactory
io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetSIExprFunctionFactory io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetSIExprFunctionFactory
io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetSITExprFunctionFactory io.questdb.griffin.engine.functions.catalogue.PrefixedPgGetSITExprFunctionFactory
io.questdb.griffin.engine.functions.catalogue.NullIfIFunctionFactory
io.questdb.griffin.engine.functions.catalogue.FormatTypeFunctionFactory io.questdb.griffin.engine.functions.catalogue.FormatTypeFunctionFactory
io.questdb.griffin.engine.functions.catalogue.ProcCatalogueFunctionFactory io.questdb.griffin.engine.functions.catalogue.ProcCatalogueFunctionFactory
io.questdb.griffin.engine.functions.catalogue.RangeCatalogueFunctionFactory io.questdb.griffin.engine.functions.catalogue.RangeCatalogueFunctionFactory
......
...@@ -3062,10 +3062,10 @@ nodejs code: ...@@ -3062,10 +3062,10 @@ nodejs code:
"qdb", null, null, null "qdb", null, null, null
)) { )) {
assertResultSet( assertResultSet(
"TABLE_CAT[VARCHAR],TABLE_SCHEM[VARCHAR],TABLE_NAME[VARCHAR],TABLE_TYPE[VARCHAR],REMARKS[VARCHAR],TYPE_CAT[CHAR],TYPE_SCHEM[CHAR],TYPE_NAME[CHAR],SELF_REFERENCING_COL_NAME[CHAR],REF_GENERATION[CHAR]\n" + "TABLE_CAT[VARCHAR],TABLE_SCHEM[VARCHAR],TABLE_NAME[VARCHAR],TABLE_TYPE[VARCHAR],REMARKS[VARCHAR],TYPE_CAT[VARCHAR],TYPE_SCHEM[VARCHAR],TYPE_NAME[VARCHAR],SELF_REFERENCING_COL_NAME[VARCHAR],REF_GENERATION[VARCHAR]\n" +
"pg_catalog,pg_catalog,pg_class,SYSTEM TABLE,null,null,null,null,null,null\n" + "pg_catalog,pg_catalog,pg_class,SYSTEM TABLE,null,,,,,\n" +
"public,public,test,TABLE,null,null,null,null,null,null\n" + "public,public,test,TABLE,null,,,,,\n" +
"public,public,test2,TABLE,null,null,null,null,null,null\n", "public,public,test2,TABLE,null,,,,,\n",
sink, sink,
rs rs
); );
......
...@@ -1385,31 +1385,6 @@ public class CastTest extends AbstractGriffinTest { ...@@ -1385,31 +1385,6 @@ public class CastTest extends AbstractGriffinTest {
); );
} }
@Test
public void testCharToStrConstZero() throws Exception {
assertQuery(
"a\n",
"select a from tab",
"create table tab (a string)",
null,
"insert into tab select cast('' as string) from long_sequence(10)",
"a\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n",
true,
true,
true
);
}
@Test @Test
public void testCharToStrSort() throws Exception { public void testCharToStrSort() throws Exception {
assertQuery( assertQuery(
...@@ -4574,6 +4549,31 @@ public class CastTest extends AbstractGriffinTest { ...@@ -4574,6 +4549,31 @@ public class CastTest extends AbstractGriffinTest {
); );
} }
@Test
public void testStrConstZeroToChar() throws Exception {
assertQuery(
"a\n",
"select a from tab",
"create table tab (a char)",
null,
"insert into tab select cast('' as char) from long_sequence(10)",
"a\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n",
true,
true,
true
);
}
@Test @Test
public void testStrToDate() throws Exception { public void testStrToDate() throws Exception {
assertQuery( assertQuery(
......
/*******************************************************************************
* ___ _ ____ ____
* / _ \ _ _ ___ ___| |_| _ \| __ )
* | | | | | | |/ _ \/ __| __| | | | _ \
* | |_| | |_| | __/\__ \ |_| |_| | |_) |
* \__\_\\__,_|\___||___/\__|____/|____/
*
* Copyright (c) 2014-2019 Appsicle
* Copyright (c) 2019-2022 QuestDB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package io.questdb.griffin.engine.functions.conditional;
import io.questdb.griffin.AbstractGriffinTest;
import org.junit.Test;
public class NullIfFunctionFactoryTest extends AbstractGriffinTest {
@Test
public void testStrSimple() throws Exception {
assertQuery(
"str1\tstr2\tnullif\n" +
"cat\tcat\t\n" +
"dog\t\t\n" +
"\t\t\n" +
"\tdog\t\n" +
"cat\tdog\tcat\n" +
"dog\t\t\n" +
"dog\tdog\t\n" +
"dog\tcat\tdog\n" +
"cat\tdog\tcat\n" +
"cat\tdog\tcat\n",
"select str1,str2,nullif(str1,str2) from x",
"create table x as (" +
"select rnd_str('cat','dog',NULL) as str1\n" +
", rnd_str('cat','dog',NULL) as str2\n" +
"from long_sequence(10)" +
")",
null,
true,
false,
true
);
}
@Test
public void testCharSimple() throws Exception {
assertQuery(
"ch1\tch2\tnullif\n" +
"V\tT\tV\n" +
"J\tW\tJ\n" +
"C\tP\tC\n" +
"S\tW\tS\n" +
"H\tY\tH\n" +
"R\tX\tR\n" +
"P\tE\tP\n" +
"H\tN\tH\n" +
"R\tX\tR\n" +
"G\tZ\tG\n" +
"S\tX\tS\n" +
"U\tX\tU\n" +
"I\tB\tI\n" +
"B\tT\tB\n" +
"G\tP\tG\n" +
"G\tW\tG\n" +
"F\tF\t\n" +
"Y\tU\tY\n" +
"D\tE\tD\n" +
"Y\tY\t\n",
"select ch1,ch2,nullif(ch1,ch2) from x",
"create table x as (" +
"select rnd_char() as ch1\n" +
", rnd_char() as ch2\n" +
"from long_sequence(20)" +
")",
null,
true,
false,
true
);
}
@Test
public void testIntSimple() throws Exception {
assertQuery(
"int\tnullif\n" +
"4\t4\n" +
"2\t2\n" +
"5\tNaN\n" +
"2\t2\n" +
"4\t4\n",
"select int,nullif(int,5) from x",
"create table x as (" +
"select rnd_int(1,5,0) as int\n" +
"from long_sequence(5)" +
")",
null,
true,
false,
true
);
}
@Test
public void testIntConstNull() throws Exception {
assertQuery(
"nullif1\tnullif2\n" +
"NaN\t5\n",
"select nullif(null,5) nullif1, nullif(5,null) nullif2",
null,
null,
true,
false,
true
);
}
}
...@@ -22,27 +22,84 @@ ...@@ -22,27 +22,84 @@
* *
******************************************************************************/ ******************************************************************************/
package io.questdb.griffin.engine.functions.eq; package io.questdb.griffin.engine.functions.str;
import io.questdb.griffin.FunctionFactory; import io.questdb.griffin.AbstractGriffinTest;
import io.questdb.griffin.SqlException;
import io.questdb.griffin.engine.AbstractFunctionFactoryTest;
import org.junit.Test; import org.junit.Test;
public class NullIfCharCharFunctionFactoryTest extends AbstractFunctionFactoryTest { public class LengthFunctionFactoryTest extends AbstractGriffinTest {
@Test @Test
public void testNullIfWhenDifferent() throws SqlException { public void testStrSimple() throws Exception {
call('A', 'B').andAssert('A'); assertQuery(
"str\tlength\n" +
"abc\t3\n" +
"\t0\n" +
"x\t1\n" +
"\t-1\n" +
"x\t1\n",
"select str,length(str) from x",
"create table x as (" +
"select rnd_str('abc','x','',NULL) as str\n" +
"from long_sequence(5)" +
")",
null,
true,
false,
true
);
} }
@Test @Test
public void testNullIfWhenEquals() throws SqlException { public void testSymbolSimple() throws Exception {
call('A', 'A').andAssert(Character.MIN_VALUE); assertQuery(
"sym\tlength\n" +
"WC\t2\n" +
"\t-1\n" +
"EH\t2\n" +
"\t-1\n" +
"EH\t2\n" +
"SWH\t3\n" +
"T\t1\n" +
"T\t1\n" +
"T\t1\n" +
"\t-1\n",
"select sym,length(sym) from x",
"create table x as (" +
"select rnd_symbol(5,1,3,5) as sym\n" +
"from long_sequence(10)" +
")",
null,
true,
false,
true
);
} }
@Override @Test
protected FunctionFactory getFunctionFactory() { public void testBinSimple() throws Exception {
return new NullIfCharCharFunctionFactory(); assertQuery(
"bin\tlength\n" +
"00000000 41 1d\t2\n" +
"00000000 8a 17 fa d8\t4\n" +
"00000000 ce f1\t2\n" +
"\t-1\n" +
"00000000 91\t1\n" +
"00000000 db f3 04 1b\t4\n" +
"00000000 de a0\t2\n" +
"\t-1\n" +
"00000000 15 68\t2\n" +
"00000000 af 19 c4 95\t4\n",
"select bin,length(bin) from x",
"create table x as (" +
"select rnd_bin(1,5,5) as bin\n" +
"from long_sequence(10)" +
")",
null,
true,
false,
true
);
} }
}
\ No newline at end of file }
...@@ -30,7 +30,7 @@ import org.junit.Test; ...@@ -30,7 +30,7 @@ import org.junit.Test;
public class StrPosFunctionFactoryTest extends AbstractGriffinTest { public class StrPosFunctionFactoryTest extends AbstractGriffinTest {
@Test @Test
public void testVarStr() throws Exception { public void testStrVar() throws Exception {
assertQuery( assertQuery(
"substr\tstr\tstrpos\n" + "substr\tstr\tstrpos\n" +
"XYZ\tABC XYZ XYZ\t5\n" + "XYZ\tABC XYZ XYZ\t5\n" +
...@@ -62,7 +62,7 @@ public class StrPosFunctionFactoryTest extends AbstractGriffinTest { ...@@ -62,7 +62,7 @@ public class StrPosFunctionFactoryTest extends AbstractGriffinTest {
} }
@Test @Test
public void testVarStrConstSubstr() throws Exception { public void testStrVarConst() throws Exception {
assertQuery( assertQuery(
"str\tstrpos\n" + "str\tstrpos\n" +
"ABC XYZ XYZ\t5\n" + "ABC XYZ XYZ\t5\n" +
...@@ -83,7 +83,7 @@ public class StrPosFunctionFactoryTest extends AbstractGriffinTest { ...@@ -83,7 +83,7 @@ public class StrPosFunctionFactoryTest extends AbstractGriffinTest {
} }
@Test @Test
public void testVarChar() throws Exception { public void testCharVar() throws Exception {
assertQuery( assertQuery(
"substr\tstr\tstrpos\n" + "substr\tstr\tstrpos\n" +
"T\tTEST\t1\n" + "T\tTEST\t1\n" +
...@@ -115,7 +115,7 @@ public class StrPosFunctionFactoryTest extends AbstractGriffinTest { ...@@ -115,7 +115,7 @@ public class StrPosFunctionFactoryTest extends AbstractGriffinTest {
} }
@Test @Test
public void testVarCharConstSubstr() throws Exception { public void testCharVarConst() throws Exception {
assertQuery( assertQuery(
"str\tstrpos\n" + "str\tstrpos\n" +
"ABC XYZ XYZ\t3\n" + "ABC XYZ XYZ\t3\n" +
...@@ -153,8 +153,7 @@ public class StrPosFunctionFactoryTest extends AbstractGriffinTest { ...@@ -153,8 +153,7 @@ public class StrPosFunctionFactoryTest extends AbstractGriffinTest {
public void testConstantEmptyString() throws Exception { public void testConstantEmptyString() throws Exception {
assertQuery( assertQuery(
"pos1\tpos2\tpos3\n" + "pos1\tpos2\tpos3\n" +
// TODO(puzpuzpuz): fix the empty string literal, so that the result is "0\t1\t1\n" "0\t1\t1\n",
"NaN\tNaN\tNaN\n",
"select strpos('','a') pos1, strpos('a',cast('' as string)) pos2, strpos('','') pos3", "select strpos('','a') pos1, strpos('a',cast('' as string)) pos2, strpos('','') pos3",
null, null,
null, null,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册