Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
0e847731
C
ClickHouse
项目概览
2dot5
/
ClickHouse
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
ClickHouse
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
0e847731
编写于
1月 27, 2014
作者:
S
Sergey Fedorov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
functions: replaceRegexpOne and replaceRegexpAll implementation [METR-9582]
上级
1e220376
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
208 addition
and
9 deletion
+208
-9
dbms/include/DB/Functions/FunctionsStringSearch.h
dbms/include/DB/Functions/FunctionsStringSearch.h
+206
-9
dbms/src/Functions/FunctionFactory.cpp
dbms/src/Functions/FunctionFactory.cpp
+2
-0
未找到文件。
dbms/include/DB/Functions/FunctionsStringSearch.h
浏览文件 @
0e847731
...
...
@@ -36,6 +36,9 @@ namespace DB
* replaceOne(haystack, pattern, replacement) - замена шаблона по заданным правилам, только первое вхождение.
* replaceAll(haystack, pattern, replacement) - замена шаблона по заданным правилам, все вхождения.
*
* replaceRegexpOne(haystack, pattern, replacement) - замена шаблона по заданному регекспу, только первое вхождение.
* replaceRegexpAll(haystack, pattern, replacement) - замена шаблона по заданному регекспу, все вхождения.
*
* Внимание! На данный момент, аргументы needle, pattern, n, replacement обязаны быть константами.
*/
...
...
@@ -383,10 +386,192 @@ struct ExtractImpl
};
/** Заменить все вхождения регекспа needle на строку replacement. needle и replacement - константы.
*/
template
<
bool
replaceOne
=
false
>
struct
ReplaceRegexpImpl
{
static
void
vector
(
const
ColumnString
::
Chars_t
&
data
,
const
ColumnString
::
Offsets_t
&
offsets
,
const
std
::
string
&
needle
,
const
std
::
string
&
replacement
,
ColumnString
::
Chars_t
&
res_data
,
ColumnString
::
Offsets_t
&
res_offsets
)
{
const
UInt8
*
begin
=
&
data
[
0
];
const
UInt8
*
pos
=
begin
;
const
UInt8
*
end
=
pos
+
data
.
size
();
ColumnString
::
Offset_t
res_offset
=
0
;
res_data
.
reserve
(
data
.
size
());
size_t
size
=
offsets
.
size
();
res_offsets
.
resize
(
size
);
/// Текущий индекс в массиве строк.
size_t
i
=
0
;
const
OptimizedRegularExpression
&
regexp
=
Regexps
::
get
(
needle
);
/// Искать будем следующее вхождение сразу во всех строках.
while
(
pos
<
end
)
{
OptimizedRegularExpression
::
Match
match
;
if
(
!
regexp
.
match
(
reinterpret_cast
<
const
char
*>
(
pos
),
static_cast
<
size_t
>
(
end
-
pos
),
match
))
{
match
.
offset
=
end
-
pos
;
match
.
length
=
1
;
}
/// Копируем данные без изменения
res_data
.
resize
(
res_data
.
size
()
+
match
.
offset
);
memcpy
(
&
res_data
[
res_offset
],
pos
,
match
.
offset
);
/// Определим, к какому индексу оно относится.
while
(
i
<
offsets
.
size
()
&&
begin
+
offsets
[
i
]
<
pos
+
match
.
offset
)
{
res_offsets
[
i
]
=
res_offset
+
((
begin
+
offsets
[
i
])
-
pos
);
++
i
;
}
res_offset
+=
match
.
offset
;
/// Если дошли до конца, пора остановиться
if
(
i
==
offsets
.
size
())
break
;
/// Правда ли, что с этой строкой больше не надо выполнять преобразования.
bool
can_finish_current_string
=
false
;
/// Проверяем, что вхождение не переходит через границы строк.
if
(
pos
+
match
.
offset
+
match
.
length
<
begin
+
offsets
[
i
])
{
res_data
.
resize
(
res_data
.
size
()
+
replacement
.
size
());
memcpy
(
&
res_data
[
res_offset
],
replacement
.
data
(),
replacement
.
size
());
res_offset
+=
replacement
.
size
();
pos
=
pos
+
match
.
offset
+
match
.
length
;
if
(
replaceOne
)
can_finish_current_string
=
true
;
}
else
{
pos
=
pos
+
match
.
offset
;
can_finish_current_string
=
true
;
}
if
(
can_finish_current_string
)
{
res_data
.
resize
(
res_data
.
size
()
+
(
begin
+
offsets
[
i
]
-
pos
));
memcpy
(
&
res_data
[
res_offset
],
pos
,
(
begin
+
offsets
[
i
]
-
pos
));
res_offset
+=
(
begin
+
offsets
[
i
]
-
pos
);
res_offsets
[
i
]
=
res_offset
;
pos
=
begin
+
offsets
[
i
];
}
}
}
static
void
vector_fixed
(
const
ColumnString
::
Chars_t
&
data
,
size_t
n
,
const
std
::
string
&
needle
,
const
std
::
string
&
replacement
,
ColumnString
::
Chars_t
&
res_data
,
ColumnString
::
Offsets_t
&
res_offsets
)
{
const
UInt8
*
begin
=
&
data
[
0
];
const
UInt8
*
pos
=
begin
;
const
UInt8
*
end
=
pos
+
data
.
size
();
ColumnString
::
Offset_t
res_offset
=
0
;
size_t
size
=
data
.
size
()
/
n
;
res_data
.
reserve
(
data
.
size
());
res_offsets
.
resize
(
size
);
/// Текущий индекс в массиве строк.
size_t
i
=
0
;
const
OptimizedRegularExpression
&
regexp
=
Regexps
::
get
(
needle
);
/// Искать будем следующее вхождение сразу во всех строках.
while
(
pos
<
end
)
{
OptimizedRegularExpression
::
Match
match
;
if
(
!
regexp
.
match
(
reinterpret_cast
<
const
char
*>
(
pos
),
static_cast
<
size_t
>
(
end
-
pos
),
match
))
{
match
.
offset
=
end
-
pos
;
match
.
length
=
1
;
}
/// Копируем данные без изменения
res_data
.
resize
(
res_data
.
size
()
+
match
.
offset
);
memcpy
(
&
res_data
[
res_offset
],
pos
,
match
.
offset
);
/// Определим, к какому индексу оно относится.
while
(
i
<
size
&&
begin
+
n
*
(
i
+
1
)
<
pos
+
match
.
offset
)
{
res_offsets
[
i
]
=
res_offset
+
((
begin
+
n
*
(
i
+
1
))
-
pos
);
++
i
;
}
res_offset
+=
match
.
offset
;
/// Если дошли до конца, пора остановиться
if
(
i
==
size
)
break
;
/// Правда ли, что с этой строкой больше не надо выполнять преобразования.
bool
can_finish_current_string
=
false
;
/// Проверяем, что вхождение не переходит через границы строк.
if
(
pos
+
match
.
offset
+
match
.
length
<
begin
+
n
*
(
i
+
1
))
{
res_data
.
resize
(
res_data
.
size
()
+
replacement
.
size
());
memcpy
(
&
res_data
[
res_offset
],
replacement
.
data
(),
replacement
.
size
());
res_offset
+=
replacement
.
size
();
pos
=
pos
+
match
.
offset
+
match
.
length
;
if
(
replaceOne
)
can_finish_current_string
=
true
;
}
else
{
pos
=
pos
+
match
.
offset
;
can_finish_current_string
=
true
;
}
if
(
can_finish_current_string
)
{
res_data
.
resize
(
res_data
.
size
()
+
(
begin
+
n
*
(
i
+
1
)
-
pos
));
memcpy
(
&
res_data
[
res_offset
],
pos
,
(
begin
+
n
*
(
i
+
1
)
-
pos
));
res_offset
+=
(
begin
+
n
*
(
i
+
1
)
-
pos
);
res_offsets
[
i
]
=
res_offset
;
pos
=
begin
+
n
*
(
i
+
1
);
}
}
}
static
void
constant
(
const
std
::
string
&
data
,
const
std
::
string
&
needle
,
const
std
::
string
&
replacement
,
std
::
string
&
res_data
)
{
res_data
=
""
;
size_t
pos
=
0
;
const
OptimizedRegularExpression
&
regexp
=
Regexps
::
get
(
needle
);
while
(
pos
<
data
.
size
())
{
OptimizedRegularExpression
::
Match
match
;
if
(
!
regexp
.
match
(
data
.
substr
(
pos
,
data
.
size
()
-
pos
),
match
))
{
res_data
+=
data
.
substr
(
pos
);
break
;
}
if
(
match
.
offset
>
0
)
res_data
+=
data
.
substr
(
pos
,
match
.
offset
);
res_data
+=
replacement
;
pos
+=
match
.
offset
+
match
.
length
;
if
(
replaceOne
)
{
res_data
+=
data
.
substr
(
pos
);
break
;
}
}
}
};
/** Заменить все вхождения подстроки needle на строку replacement. needle и replacement - константы.
*/
template
<
bool
replaceOne
=
false
>
struct
ReplaceImpl
struct
Replace
String
Impl
{
static
void
vector
(
const
ColumnString
::
Chars_t
&
data
,
const
ColumnString
::
Offsets_t
&
offsets
,
const
std
::
string
&
needle
,
const
std
::
string
&
replacement
,
...
...
@@ -441,13 +626,17 @@ struct ReplaceImpl
can_finish_current_string
=
true
;
}
else
{
pos
=
match
;
can_finish_current_string
=
true
;
}
if
(
can_finish_current_string
)
{
res_data
.
resize
(
res_data
.
size
()
+
(
begin
+
offsets
[
i
]
-
match
));
memcpy
(
&
res_data
[
res_offset
],
match
,
(
begin
+
offsets
[
i
]
-
match
));
res_offsets
[
i
]
=
res_offset
+
(
begin
+
offsets
[
i
]
-
match
);
res_data
.
resize
(
res_data
.
size
()
+
(
begin
+
offsets
[
i
]
-
pos
));
memcpy
(
&
res_data
[
res_offset
],
pos
,
(
begin
+
offsets
[
i
]
-
pos
));
res_offset
+=
(
begin
+
offsets
[
i
]
-
pos
);
res_offsets
[
i
]
=
res_offset
;
pos
=
begin
+
offsets
[
i
];
}
}
...
...
@@ -506,13 +695,17 @@ struct ReplaceImpl
can_finish_current_string
=
true
;
}
else
{
pos
=
match
;
can_finish_current_string
=
true
;
}
if
(
can_finish_current_string
)
{
res_data
.
resize
(
res_data
.
size
()
+
(
begin
+
n
*
(
i
+
1
)
-
match
));
memcpy
(
&
res_data
[
res_offset
],
match
,
(
begin
+
n
*
(
i
+
1
)
-
match
));
res_offsets
[
i
]
=
res_offset
+
(
begin
+
n
*
(
i
+
1
)
-
match
);
res_data
.
resize
(
res_data
.
size
()
+
(
begin
+
n
*
(
i
+
1
)
-
pos
));
memcpy
(
&
res_data
[
res_offset
],
pos
,
(
begin
+
n
*
(
i
+
1
)
-
pos
));
res_offset
+=
(
begin
+
n
*
(
i
+
1
)
-
pos
);
res_offsets
[
i
]
=
res_offset
;
pos
=
begin
+
n
*
(
i
+
1
);
}
}
...
...
@@ -777,6 +970,8 @@ struct NameNotLike { static const char * get() { return "notLike"; } };
struct
NameExtract
{
static
const
char
*
get
()
{
return
"extract"
;
}
};
struct
NameReplaceOne
{
static
const
char
*
get
()
{
return
"replaceOne"
;
}
};
struct
NameReplaceAll
{
static
const
char
*
get
()
{
return
"replaceAll"
;
}
};
struct
NameReplaceRegexpOne
{
static
const
char
*
get
()
{
return
"replaceRegexpOne"
;
}
};
struct
NameReplaceRegexpAll
{
static
const
char
*
get
()
{
return
"replaceRegexpAll"
;
}
};
typedef
FunctionsStringSearch
<
PositionImpl
,
NamePosition
>
FunctionPosition
;
typedef
FunctionsStringSearch
<
PositionUTF8Impl
,
NamePositionUTF8
>
FunctionPositionUTF8
;
...
...
@@ -784,7 +979,9 @@ typedef FunctionsStringSearch<MatchImpl<false>, NameMatch> FunctionMatch;
typedef
FunctionsStringSearch
<
MatchImpl
<
true
>
,
NameLike
>
FunctionLike
;
typedef
FunctionsStringSearch
<
MatchImpl
<
true
,
true
>
,
NameNotLike
>
FunctionNotLike
;
typedef
FunctionsStringSearchToString
<
ExtractImpl
,
NameExtract
>
FunctionExtract
;
typedef
FunctionStringReplace
<
ReplaceImpl
<
true
>
,
NameReplaceOne
>
FunctionReplaceOne
;
typedef
FunctionStringReplace
<
ReplaceImpl
<
false
>
,
NameReplaceAll
>
FunctionReplaceAll
;
typedef
FunctionStringReplace
<
ReplaceStringImpl
<
true
>
,
NameReplaceOne
>
FunctionReplaceOne
;
typedef
FunctionStringReplace
<
ReplaceStringImpl
<
false
>
,
NameReplaceAll
>
FunctionReplaceAll
;
typedef
FunctionStringReplace
<
ReplaceRegexpImpl
<
true
>
,
NameReplaceRegexpOne
>
FunctionReplaceRegexpOne
;
typedef
FunctionStringReplace
<
ReplaceRegexpImpl
<
false
>
,
NameReplaceRegexpAll
>
FunctionReplaceRegexpAll
;
}
dbms/src/Functions/FunctionFactory.cpp
浏览文件 @
0e847731
...
...
@@ -79,6 +79,8 @@ FunctionPtr FunctionFactory::get(
else
if
(
name
==
"substring"
)
return
new
FunctionSubstring
;
else
if
(
name
==
"replaceOne"
)
return
new
FunctionReplaceOne
;
else
if
(
name
==
"replaceAll"
)
return
new
FunctionReplaceAll
;
else
if
(
name
==
"replaceRegexpOne"
)
return
new
FunctionReplaceRegexpOne
;
else
if
(
name
==
"replaceRegexpAll"
)
return
new
FunctionReplaceRegexpAll
;
else
if
(
name
==
"substringUTF8"
)
return
new
FunctionSubstringUTF8
;
else
if
(
name
==
"bitmaskToList"
)
return
new
FunctionBitmaskToList
;
else
if
(
name
==
"bitmaskToArray"
)
return
new
FunctionBitmaskToArray
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录