Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
jobily
Questdb
提交
8c5576d9
Q
Questdb
项目概览
jobily
/
Questdb
11 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
Questdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
8c5576d9
编写于
11月 09, 2021
作者:
A
Andrey Pechkurov
提交者:
GitHub
11月 09, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore(sql): improve strpos function (#1535)
上级
4c99a2e8
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
246 addition
and
67 deletion
+246
-67
benchmarks/src/main/java/org/questdb/StrPosBenchmark.java
benchmarks/src/main/java/org/questdb/StrPosBenchmark.java
+43
-12
core/src/main/java/io/questdb/griffin/engine/functions/str/StrPosCharFunctionFactory.java
...iffin/engine/functions/str/StrPosCharFunctionFactory.java
+54
-15
core/src/main/java/io/questdb/griffin/engine/functions/str/StrPosFunctionFactory.java
...b/griffin/engine/functions/str/StrPosFunctionFactory.java
+61
-26
core/src/test/java/io/questdb/griffin/engine/functions/str/StrPosFunctionFactoryTest.java
...iffin/engine/functions/str/StrPosFunctionFactoryTest.java
+88
-14
未找到文件。
benchmarks/src/main/java/org/questdb/StrPosBenchmark.java
浏览文件 @
8c5576d9
...
...
@@ -26,13 +26,12 @@ package org.questdb;
import
io.questdb.cairo.sql.Function
;
import
io.questdb.cairo.sql.Record
;
import
io.questdb.griffin.engine.functions.CharFunction
;
import
io.questdb.griffin.engine.functions.StrFunction
;
import
io.questdb.griffin.engine.functions.constants.CharConstant
;
import
io.questdb.griffin.engine.functions.str.StrPosCharFunctionFactory
;
import
io.questdb.griffin.engine.functions.str.StrPosFunctionFactory
;
import
io.questdb.std.Rnd
;
import
org.openjdk.jmh.annotations.*
;
import
org.openjdk.jmh.profile.GCProfiler
;
import
org.openjdk.jmh.runner.Runner
;
import
org.openjdk.jmh.runner.RunnerException
;
import
org.openjdk.jmh.runner.options.Options
;
...
...
@@ -49,14 +48,15 @@ public class StrPosBenchmark {
private
final
Record
[]
records
;
private
final
String
[]
strings
;
private
final
Function
strposStrFunc
;
private
final
Function
strposCharFunc
;
private
final
Function
strFunc
;
private
final
Function
strConstFunc
;
private
final
Function
charFunc
;
private
final
Function
charConstFunc
;
private
final
Rnd
rnd
=
new
Rnd
();
public
static
void
main
(
String
[]
args
)
throws
RunnerException
{
Options
opt
=
new
OptionsBuilder
()
.
include
(
StrPosBenchmark
.
class
.
getSimpleName
())
.
addProfiler
(
GCProfiler
.
class
)
.
warmupIterations
(
2
)
.
measurementIterations
(
3
)
.
forks
(
1
)
...
...
@@ -70,7 +70,7 @@ public class StrPosBenchmark {
strings
=
new
String
[
N
];
for
(
int
i
=
0
;
i
<
N
;
i
++)
{
builder
.
setLength
(
0
);
int
startLen
=
rnd
.
nextInt
(
1000
);
int
startLen
=
rnd
.
nextInt
(
32
);
for
(
int
j
=
0
;
j
<
startLen
;
j
++)
{
builder
.
append
(
'a'
);
}
...
...
@@ -89,7 +89,7 @@ public class StrPosBenchmark {
};
}
Function
str
Func
=
new
StrFunction
()
{
final
Function
strInput
Func
=
new
StrFunction
()
{
@Override
public
CharSequence
getStr
(
Record
rec
)
{
return
rec
.
getStr
(
0
);
...
...
@@ -100,9 +100,28 @@ public class StrPosBenchmark {
return
rec
.
getStr
(
0
);
}
};
Function
substrFunc
=
new
CharConstant
(
','
);
strposStrFunc
=
new
StrPosFunctionFactory
.
Func
(
strFunc
,
substrFunc
);
strposCharFunc
=
new
StrPosCharFunctionFactory
.
Func
(
strFunc
,
substrFunc
);
final
Function
substrStrInputFunc
=
new
StrFunction
()
{
@Override
public
CharSequence
getStr
(
Record
rec
)
{
return
","
;
}
@Override
public
CharSequence
getStrB
(
Record
rec
)
{
return
","
;
}
};
final
Function
substrCharInputFunc
=
new
CharFunction
()
{
@Override
public
char
getChar
(
Record
rec
)
{
return
','
;
}
};
strFunc
=
new
StrPosFunctionFactory
.
Func
(
strInputFunc
,
substrStrInputFunc
);
strConstFunc
=
new
StrPosFunctionFactory
.
ConstFunc
(
strInputFunc
,
","
);
charFunc
=
new
StrPosCharFunctionFactory
.
Func
(
strInputFunc
,
substrCharInputFunc
);
charConstFunc
=
new
StrPosCharFunctionFactory
.
ConstFunc
(
strInputFunc
,
','
);
}
@Benchmark
...
...
@@ -113,12 +132,24 @@ public class StrPosBenchmark {
@Benchmark
public
int
testStrOverload
()
{
int
i
=
rnd
.
nextInt
(
N
);
return
strposStrFunc
.
getInt
(
records
[
i
]);
return
strFunc
.
getInt
(
records
[
i
]);
}
@Benchmark
public
int
testStrConstOverload
()
{
int
i
=
rnd
.
nextInt
(
N
);
return
strConstFunc
.
getInt
(
records
[
i
]);
}
@Benchmark
public
int
testCharOverload
()
{
int
i
=
rnd
.
nextInt
(
N
);
return
strposCharFunc
.
getInt
(
records
[
i
]);
return
charFunc
.
getInt
(
records
[
i
]);
}
@Benchmark
public
int
testCharConstOverload
()
{
int
i
=
rnd
.
nextInt
(
N
);
return
charConstFunc
.
getInt
(
records
[
i
]);
}
}
core/src/main/java/io/questdb/griffin/engine/functions/str/StrPosCharFunctionFactory.java
浏览文件 @
8c5576d9
...
...
@@ -32,6 +32,9 @@ import io.questdb.griffin.SqlException;
import
io.questdb.griffin.SqlExecutionContext
;
import
io.questdb.griffin.engine.functions.BinaryFunction
;
import
io.questdb.griffin.engine.functions.IntFunction
;
import
io.questdb.griffin.engine.functions.UnaryFunction
;
import
io.questdb.griffin.engine.functions.constants.CharConstant
;
import
io.questdb.griffin.engine.functions.constants.IntConstant
;
import
io.questdb.std.IntList
;
import
io.questdb.std.Numbers
;
import
io.questdb.std.ObjList
;
...
...
@@ -52,7 +55,29 @@ public class StrPosCharFunctionFactory implements FunctionFactory {
CairoConfiguration
configuration
,
SqlExecutionContext
sqlExecutionContext
)
throws
SqlException
{
return
new
Func
(
args
.
getQuick
(
0
),
args
.
getQuick
(
1
));
final
Function
substrFunc
=
args
.
getQuick
(
1
);
if
(
substrFunc
.
isConstant
())
{
char
substr
=
substrFunc
.
getChar
(
null
);
if
(
substr
==
CharConstant
.
ZERO
.
getChar
(
null
))
{
return
IntConstant
.
NULL
;
}
return
new
ConstFunc
(
args
.
getQuick
(
0
),
substr
);
}
return
new
Func
(
args
.
getQuick
(
0
),
substrFunc
);
}
private
static
int
strpos
(
@NotNull
CharSequence
str
,
char
substr
)
{
final
int
strLen
=
str
.
length
();
if
(
strLen
<
1
)
{
return
0
;
}
for
(
int
i
=
0
;
i
<
strLen
;
i
++)
{
if
(
str
.
charAt
(
i
)
==
substr
)
{
return
i
+
1
;
}
}
return
0
;
}
public
static
class
Func
extends
IntFunction
implements
BinaryFunction
{
...
...
@@ -72,21 +97,10 @@ public class StrPosCharFunctionFactory implements FunctionFactory {
return
Numbers
.
INT_NaN
;
}
final
char
substr
=
this
.
substrFunc
.
getChar
(
rec
);
return
strpos
(
str
,
substr
);
}
private
int
strpos
(
@NotNull
CharSequence
str
,
char
substr
)
{
final
int
strLen
=
str
.
length
();
if
(
strLen
<
1
)
{
return
0
;
}
for
(
int
i
=
0
;
i
<
strLen
;
i
++)
{
if
(
str
.
charAt
(
i
)
==
substr
)
{
return
i
+
1
;
}
if
(
substr
==
CharConstant
.
ZERO
.
getChar
(
null
))
{
return
Numbers
.
INT_NaN
;
}
return
0
;
return
strpos
(
str
,
substr
)
;
}
@Override
...
...
@@ -99,4 +113,29 @@ public class StrPosCharFunctionFactory implements FunctionFactory {
return
substrFunc
;
}
}
public
static
class
ConstFunc
extends
IntFunction
implements
UnaryFunction
{
private
final
Function
strFunc
;
private
final
char
substr
;
public
ConstFunc
(
Function
strFunc
,
char
substr
)
{
this
.
strFunc
=
strFunc
;
this
.
substr
=
substr
;
}
@Override
public
int
getInt
(
Record
rec
)
{
final
CharSequence
str
=
this
.
strFunc
.
getStr
(
rec
);
if
(
str
==
null
)
{
return
Numbers
.
INT_NaN
;
}
return
strpos
(
str
,
substr
);
}
@Override
public
Function
getArg
()
{
return
strFunc
;
}
}
}
core/src/main/java/io/questdb/griffin/engine/functions/str/StrPosFunctionFactory.java
浏览文件 @
8c5576d9
...
...
@@ -32,6 +32,8 @@ import io.questdb.griffin.SqlException;
import
io.questdb.griffin.SqlExecutionContext
;
import
io.questdb.griffin.engine.functions.BinaryFunction
;
import
io.questdb.griffin.engine.functions.IntFunction
;
import
io.questdb.griffin.engine.functions.UnaryFunction
;
import
io.questdb.griffin.engine.functions.constants.IntConstant
;
import
io.questdb.std.IntList
;
import
io.questdb.std.Numbers
;
import
io.questdb.std.ObjList
;
...
...
@@ -52,7 +54,40 @@ public class StrPosFunctionFactory implements FunctionFactory {
CairoConfiguration
configuration
,
SqlExecutionContext
sqlExecutionContext
)
throws
SqlException
{
return
new
Func
(
args
.
getQuick
(
0
),
args
.
getQuick
(
1
));
final
Function
substrFunc
=
args
.
getQuick
(
1
);
if
(
substrFunc
.
isConstant
())
{
CharSequence
substr
=
substrFunc
.
getStr
(
null
);
if
(
substr
==
null
)
{
return
IntConstant
.
NULL
;
}
return
new
ConstFunc
(
args
.
getQuick
(
0
),
substr
);
}
return
new
Func
(
args
.
getQuick
(
0
),
substrFunc
);
}
private
static
int
strpos
(
@NotNull
CharSequence
str
,
@NotNull
CharSequence
substr
)
{
final
int
substrLen
=
substr
.
length
();
if
(
substrLen
<
1
)
{
return
1
;
}
final
int
strLen
=
str
.
length
();
if
(
strLen
<
1
)
{
return
0
;
}
OUTER:
for
(
int
i
=
0
,
n
=
strLen
-
substrLen
+
1
;
i
<
n
;
i
++)
{
final
char
c
=
str
.
charAt
(
i
);
if
(
c
==
substr
.
charAt
(
0
))
{
for
(
int
k
=
1
;
k
<
substrLen
;
k
++)
{
if
(
str
.
charAt
(
i
+
k
)
!=
substr
.
charAt
(
k
))
{
continue
OUTER
;
}
}
return
i
+
1
;
}
}
return
0
;
}
public
static
class
Func
extends
IntFunction
implements
BinaryFunction
{
...
...
@@ -78,31 +113,6 @@ public class StrPosFunctionFactory implements FunctionFactory {
return
strpos
(
str
,
substr
);
}
private
int
strpos
(
@NotNull
CharSequence
str
,
@NotNull
CharSequence
substr
)
{
final
int
substrLen
=
substr
.
length
();
if
(
substrLen
<
1
)
{
return
1
;
}
final
int
strLen
=
str
.
length
();
if
(
strLen
<
1
)
{
return
0
;
}
OUTER:
for
(
int
i
=
0
;
i
<
strLen
-
substrLen
+
1
;
i
++)
{
final
char
c
=
str
.
charAt
(
i
);
if
(
c
==
substr
.
charAt
(
0
))
{
for
(
int
k
=
1
;
k
<
substrLen
;
k
++)
{
if
(
str
.
charAt
(
i
+
k
)
!=
substr
.
charAt
(
k
))
{
continue
OUTER
;
}
}
return
i
+
1
;
}
}
return
0
;
}
@Override
public
Function
getLeft
()
{
return
strFunc
;
...
...
@@ -113,4 +123,29 @@ public class StrPosFunctionFactory implements FunctionFactory {
return
substrFunc
;
}
}
public
static
class
ConstFunc
extends
IntFunction
implements
UnaryFunction
{
private
final
Function
strFunc
;
private
final
CharSequence
substr
;
public
ConstFunc
(
Function
strFunc
,
CharSequence
substr
)
{
this
.
strFunc
=
strFunc
;
this
.
substr
=
substr
;
}
@Override
public
int
getInt
(
Record
rec
)
{
final
CharSequence
str
=
this
.
strFunc
.
getStr
(
rec
);
if
(
str
==
null
)
{
return
Numbers
.
INT_NaN
;
}
return
strpos
(
str
,
substr
);
}
@Override
public
Function
getArg
()
{
return
strFunc
;
}
}
}
core/src/test/java/io/questdb/griffin/engine/functions/str/StrPosFunctionFactoryTest.java
浏览文件 @
8c5576d9
...
...
@@ -30,28 +30,81 @@ import org.junit.Test;
public
class
StrPosFunctionFactoryTest
extends
AbstractGriffinTest
{
@Test
public
void
test
Simple
()
throws
Exception
{
public
void
test
VarStr
()
throws
Exception
{
assertQuery
(
"substr\tstr\tstrpos\n"
+
"XYZ\tABC XYZ XYZ\t5\n"
+
"C\tXYZ\t0\n"
+
"\tXYZ\tNaN\n"
+
"\tXYZ\tNaN\n"
+
"C\tXYW\t0\n"
+
"C\tXYW\t0\n"
+
"XYZ\tABC XYZ XYZ\t5\n"
+
"XYZ\tXYZ\t1\n"
+
"C\tXYZ\t0\n"
+
"\tABC XYZ XYZ\tNaN\n"
+
"C\tXYW\t0\n"
+
"XYZ\tXYZ\t1\n"
+
"C\tABC XYZ XYZ\t3\n"
+
"XYZ\tABC XYZ XYZ\t5\n"
+
"C\tXYZ\t0\n"
+
"C\tABC XYZ XYZ\t3\n"
+
"XYZ\tABC XYZ XYZ\t5\n"
+
"XYZ\tXYW\t0\n"
+
"XYZ\tXYZ\t1\n"
,
"XYZ\t\tNaN\n"
+
"\tABC XYZ XYZ\tNaN\n"
+
"C\t\tNaN\n"
+
"C\tXYW\t0\n"
+
"XYZ\t\tNaN\n"
,
"select substr,str,strpos(str,substr) from x"
,
"create table x as ("
+
"select rnd_str('ABC XYZ XYZ','XYZ','XYW',NULL) as str\n"
+
", rnd_str('XYZ','C',NULL) as substr\n"
+
"from long_sequence(15)"
+
")"
,
null
,
true
,
false
,
true
);
}
@Test
public
void
testVarStrConstSubstr
()
throws
Exception
{
assertQuery
(
"str\tstrpos\n"
+
"ABC XYZ XYZ\t5\n"
+
"ABC XYZ XYZ\t5\n"
+
"XYZ\t1\n"
+
"XYW\t0\n"
+
"XYW\t0\n"
,
"select str,strpos(str,'XYZ') from x"
,
"create table x as ("
+
"select rnd_str('ABC XYZ XYZ','XYZ','XYW') as str\n"
+
", rnd_str('XYZ','C') as substr\n"
+
"from long_sequence(5)"
+
")"
,
null
,
true
,
false
,
true
);
}
@Test
public
void
testVarChar
()
throws
Exception
{
assertQuery
(
"substr\tstr\tstrpos\n"
+
"T\tTEST\t1\n"
+
"W\tA X X\t0\n"
+
"P\tA X X\t0\n"
+
"W\tCDE\t0\n"
+
"Y\tCDE\t0\n"
+
"X\tTEST\t0\n"
+
"E\tCDE\t3\n"
+
"N\tA X X\t0\n"
+
"X\tTEST\t0\n"
+
"Z\tA X X\t0\n"
+
"X\t\tNaN\n"
+
"X\tTEST\t0\n"
+
"B\t\tNaN\n"
+
"T\tCDE\t0\n"
+
"P\t\tNaN\n"
,
"select substr,str,strpos(str,substr) from x"
,
"create table x as ("
+
"select rnd_str('TEST','A X X','CDE',NULL) as str\n"
+
", rnd_char() as substr\n"
+
"from long_sequence(15)"
+
")"
,
null
,
...
...
@@ -61,12 +114,33 @@ public class StrPosFunctionFactoryTest extends AbstractGriffinTest {
);
}
@Test
public
void
testVarCharConstSubstr
()
throws
Exception
{
assertQuery
(
"str\tstrpos\n"
+
"ABC XYZ XYZ\t3\n"
+
"ABC XYZ XYZ\t3\n"
+
"CBA\t1\n"
+
"XYZ\t0\n"
+
"XYZ\t0\n"
,
"select str,strpos(str,'C') from x"
,
"create table x as ("
+
"select rnd_str('ABC XYZ XYZ','CBA','XYZ') as str\n"
+
"from long_sequence(5)"
+
")"
,
null
,
true
,
false
,
true
);
}
@Test
public
void
testConstantNull
()
throws
Exception
{
assertQuery
(
"pos1\tpos2\n"
+
"NaN\tNaN\n"
,
"select strpos(null,'a') pos1, strpos(
'a',null) pos2
"
,
"pos1\tpos2\
tpos3\
n"
+
"NaN\tNaN\
tNaN\
n"
,
"select strpos(null,'a') pos1, strpos(
null,'abc') pos2, strpos('a',null) pos3
"
,
null
,
null
,
true
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录