mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-19 16:20:50 +00:00
Compare commits
475 Commits
35dec23e1d
...
e8d10d0f34
Author | SHA1 | Date | |
---|---|---|---|
|
e8d10d0f34 | ||
|
b94a7167a8 | ||
|
64e58baba1 | ||
|
a3fe155579 | ||
|
a997cfad2b | ||
|
f4b4b3cc35 | ||
|
cb24849396 | ||
|
7fd2207626 | ||
|
4f73c677ac | ||
|
69f45acfd7 | ||
|
4c78206d0a | ||
|
429e8ada79 | ||
|
06b49d18d9 | ||
|
a17a8febf7 | ||
|
55529ec5a2 | ||
|
3106653852 | ||
|
82dbb3bb32 | ||
|
1bcdde3e62 | ||
|
2cef99c311 | ||
|
cd7a1a9288 | ||
|
6597a8ed04 | ||
|
3b901f49e5 | ||
|
958c3effae | ||
|
474499d240 | ||
|
839f06035f | ||
|
4f88ccb6a8 | ||
|
a226567bc2 | ||
|
fcda762a27 | ||
|
9c185374e4 | ||
|
13e82d6439 | ||
|
fdee35cccc | ||
|
b08e727aef | ||
|
9eba103c5e | ||
|
a210f98819 | ||
|
e574c49e25 | ||
|
7c5d55c6b2 | ||
|
665f362601 | ||
|
80259659ff | ||
|
574a26c63b | ||
|
3674c97ebb | ||
|
8508b1ba37 | ||
|
190d3f04c9 | ||
|
aba7de5091 | ||
|
8db3dddb3d | ||
|
ffaf97a390 | ||
|
452fde78c7 | ||
|
51fa9ebf8a | ||
|
e30ebfa23e | ||
|
b21be2bc54 | ||
|
14736d95c5 | ||
|
4b69d8e2ca | ||
|
5ce8604869 | ||
|
813bcd896f | ||
|
3a05282bce | ||
|
fd0c7a1c18 | ||
|
4704fb8a3b | ||
|
0369aaea87 | ||
|
3f663f8e09 | ||
|
f768717be8 | ||
|
64106e7b3c | ||
|
79223045c9 | ||
|
983b061b58 | ||
|
3a299f382d | ||
|
f8f72ccb00 | ||
|
1ccd461c97 | ||
|
de308acfad | ||
|
5aaff37b36 | ||
|
386d54cedf | ||
|
2c1c1a93c6 | ||
|
9f932fb453 | ||
|
f3654b8fc8 | ||
|
676b6238d0 | ||
|
e876997ebb | ||
|
e7eaa01bb3 | ||
|
52dc9a54a7 | ||
|
b4a6d41b52 | ||
|
a329150eef | ||
|
7b94dc1813 | ||
|
8c7c37de1d | ||
|
6a26c5cf8e | ||
|
0888b9746e | ||
|
0424329fc0 | ||
|
da993ad0a3 | ||
|
19dbee7cdb | ||
|
5eb3d9496a | ||
|
19e2197582 | ||
|
d793e06860 | ||
|
23e0e92f5f | ||
|
d223c4547f | ||
|
1986fb1418 | ||
|
58993d3f3b | ||
|
e5ae4c8e8b | ||
|
dc02b168a0 | ||
|
8507d209c0 | ||
|
f5b9d5ad34 | ||
|
4af369fbc4 | ||
|
20b25566f5 | ||
|
8cdcc431fe | ||
|
f401eccc64 | ||
|
6863dc7647 | ||
|
60f893bf87 | ||
|
f36408a666 | ||
|
de85f5f251 | ||
|
85af661b9c | ||
|
1963e971f3 | ||
|
056c7af356 | ||
|
cf9200f1d0 | ||
|
b42c6491e4 | ||
|
1a4c7b7c61 | ||
|
14feba8443 | ||
|
4c4a051d5e | ||
|
a55cc03973 | ||
|
187a717872 | ||
|
37411bf240 | ||
|
5f464a6d74 | ||
|
733c57dae7 | ||
|
4412946532 | ||
|
03737ddcab | ||
|
038f56cb5e | ||
|
63577507c9 | ||
|
9eb78773a6 | ||
|
918ead070a | ||
|
6f63a7b213 | ||
|
56cfa74a14 | ||
|
dbb1d043fe | ||
|
a461d20af9 | ||
|
8fd9345d2d | ||
|
56f3030b17 | ||
|
31ddfc6f5f | ||
|
ddf2e07fd0 | ||
|
5cc12ca9ee | ||
|
98a2c1c638 | ||
|
bab574d674 | ||
|
4225ba79f9 | ||
|
57a6a64d8c | ||
|
de78992966 | ||
|
42670a46d4 | ||
|
b55d0b54ea | ||
|
418ef3f8bc | ||
|
b420bbf855 | ||
|
e13247b67e | ||
|
2650a20628 | ||
|
9a31fc385d | ||
|
ddc506a677 | ||
|
2b6238a5e5 | ||
|
2812953a8a | ||
|
8111a32c72 | ||
|
492461271b | ||
|
721e9a7356 | ||
|
1b1db0081f | ||
|
6a7cfd13f7 | ||
|
3c47f3df4b | ||
|
54e75fd4dc | ||
|
ae6e236acf | ||
|
51f3245030 | ||
|
baf6aaef1d | ||
|
9ca149a487 | ||
|
2fce90ab76 | ||
|
11c7cdabf8 | ||
|
71553022e0 | ||
|
53e1975833 | ||
|
e0c4a88f98 | ||
|
d5c3adabde | ||
|
8299b31d47 | ||
|
97c8d2897c | ||
|
08fd6c8ab6 | ||
|
f330fdb1bf | ||
|
042194e3f6 | ||
|
2c165096cd | ||
|
11d2963497 | ||
|
e1a206c84d | ||
|
f9335a2fd5 | ||
|
8a89d7b2b9 | ||
|
59763a937e | ||
|
7e99f05981 | ||
|
aab0d3dd9e | ||
|
5a34b9f24e | ||
|
a0a4858e00 | ||
|
9c1f4f4545 | ||
|
2e82e06330 | ||
|
120e38c72a | ||
|
4963ab603c | ||
|
7b2810bea2 | ||
|
e2bfce66dd | ||
|
0bb3967d14 | ||
|
401a3d0931 | ||
|
51d770fa7a | ||
|
beffb92411 | ||
|
877002f689 | ||
|
16f93ea1b3 | ||
|
1e3bc6d359 | ||
|
bde54b96f7 | ||
|
4a9b376e2a | ||
|
562c23eac6 | ||
|
8d5babf65f | ||
|
99ede620be | ||
|
38b5ea9066 | ||
|
fe5e061fff | ||
|
92351a67e8 | ||
|
f292767778 | ||
|
7d36f3b764 | ||
|
21bd47f09e | ||
|
f6b965872f | ||
|
22c3b71196 | ||
|
1da5729f89 | ||
|
8e3ba4bd6c | ||
|
b30aabf635 | ||
|
fc83c1c7a2 | ||
|
f378047f30 | ||
|
dca72d2e0b | ||
|
146edca4f7 | ||
|
3556cf92c3 | ||
|
075a85f15c | ||
|
7425d4aa1a | ||
|
cf12e3924f | ||
|
085be6bf59 | ||
|
0de3b1dacb | ||
|
263cd9e1c3 | ||
|
5539faa54e | ||
|
8d5d7dd83a | ||
|
35df5ff28e | ||
|
be55e1d2e1 | ||
|
61ebcdc2ed | ||
|
1df897db27 | ||
|
d089a56272 | ||
|
11478b949f | ||
|
8cdc10cf65 | ||
|
65019c4b9b | ||
|
190339c4e6 | ||
|
5a86371b02 | ||
|
f5d49f8e10 | ||
|
ee304c7fc3 | ||
|
03c7f3817b | ||
|
fdbf8e71ab | ||
|
f44eaa808d | ||
|
e388f6f99b | ||
|
c9aedee24f | ||
|
32cfdc98b2 | ||
|
92507d9938 | ||
|
6170c15c90 | ||
|
d23145fd19 | ||
|
d17b20705a | ||
|
fb8999a885 | ||
|
03ac70f988 | ||
|
5f5acd3c44 | ||
|
a3e233a537 | ||
|
955412888c | ||
|
9633563fbd | ||
|
d9a4964cd9 | ||
|
83854cf293 | ||
|
e874c6e1de | ||
|
03ccf05d14 | ||
|
cfc931160d | ||
|
79fc8d67ad | ||
|
0bf95655aa | ||
|
15a67f10dc | ||
|
596ba574e3 | ||
|
e968984d17 | ||
|
a22f9fd91f | ||
|
7c766e7458 | ||
|
b2c4b771d8 | ||
|
f9b845486a | ||
|
edf4e09fb2 | ||
|
7000f214ab | ||
|
3d04f3d33a | ||
|
cb6d142947 | ||
|
a690539935 | ||
|
b2795f06dc | ||
|
7879915493 | ||
|
313b6b533f | ||
|
9f7f6c6f93 | ||
|
553c309477 | ||
|
ae582120ae | ||
|
b29e00b838 | ||
|
ae8d90f6b8 | ||
|
2c0ddd10a0 | ||
|
41a4a97ca3 | ||
|
50b3d3172c | ||
|
c298b20ba9 | ||
|
0b29aef1a0 | ||
|
a0ab22e031 | ||
|
6f806124a3 | ||
|
a65d175a81 | ||
|
aa4688a982 | ||
|
bf4b53390b | ||
|
7aaa0289e1 | ||
|
d6df83d561 | ||
|
1011f8ef9c | ||
|
cb7ef910e2 | ||
|
1c6976d7a5 | ||
|
43e9a7ba4b | ||
|
62ce2999ae | ||
|
91cceccb4b | ||
|
13d5b029a4 | ||
|
07f44fdb89 | ||
|
ca40da5c03 | ||
|
b0a0988c5b | ||
|
d7d40db036 | ||
|
34d02304d3 | ||
|
4fd19c3ad9 | ||
|
f0223aedde | ||
|
1980959c8b | ||
|
27ee4dd611 | ||
|
2fcbe2465a | ||
|
21e64f2aa9 | ||
|
03ab625265 | ||
|
dbd4ee44ed | ||
|
623c507e5f | ||
|
01f5337f69 | ||
|
d4a3a033b0 | ||
|
165d08f088 | ||
|
e0dbc53b58 | ||
|
f97551e2ad | ||
|
c252b3c8b0 | ||
|
30229a3bfd | ||
|
8a0f41da7a | ||
|
628a4300ba | ||
|
f88b5988c1 | ||
|
4bb2f7b3f6 | ||
|
95edca513c | ||
|
5004e4d2cc | ||
|
accade2390 | ||
|
e7fc89ba26 | ||
|
770804ffdc | ||
|
49ce2c7619 | ||
|
80d985a690 | ||
|
891f9c5358 | ||
|
cb0335446e | ||
|
70e7c4e63d | ||
|
12e6645058 | ||
|
714a4d871c | ||
|
72f1695014 | ||
|
17c1cef52b | ||
|
3247f3ad08 | ||
|
026fa0a7fd | ||
|
29bc7cf5d5 | ||
|
a39a4b1080 | ||
|
229fffcd56 | ||
|
3c586d80c8 | ||
|
0ff90e4a5c | ||
|
5d6d378f24 | ||
|
14dad25adc | ||
|
906a181b97 | ||
|
7b09ec9ccb | ||
|
d5bea37c96 | ||
|
ad24989b31 | ||
|
d36176ad85 | ||
|
64e10b2dda | ||
|
e8a40d9d52 | ||
|
9abc001296 | ||
|
c61fc591c4 | ||
|
dcbc590302 | ||
|
4c6aca2eed | ||
|
64d50d6e5b | ||
|
b6c3619543 | ||
|
b2172af817 | ||
|
ef40cc3bae | ||
|
f5c07b8938 | ||
|
5ea4844d69 | ||
|
fa6564dbe3 | ||
|
ae72bd57f2 | ||
|
c433d9cfdb | ||
|
f5ee7aaf26 | ||
|
352b502559 | ||
|
546cca1251 | ||
|
456613e7fa | ||
|
5a45563f1b | ||
|
a21529f66a | ||
|
921947e368 | ||
|
93cbd4bf9a | ||
|
77d46aad05 | ||
|
0404a8e800 | ||
|
8eda32600f | ||
|
f3f9d5f4de | ||
|
0204de640f | ||
|
0b151bbe8f | ||
|
48e7057200 | ||
|
f2c22408da | ||
|
006f20858a | ||
|
cc02ebca75 | ||
|
3ab6760412 | ||
|
ca0b821aaf | ||
|
2e9b7e8334 | ||
|
b428327c6e | ||
|
8e0e2cec28 | ||
|
300d4ae593 | ||
|
ee62318348 | ||
|
29e0d5c1e3 | ||
|
91e8ef6776 | ||
|
5a96290cce | ||
|
acc2249288 | ||
|
e36776551e | ||
|
cd0145113f | ||
|
5a2b0ea1cc | ||
|
cc13783acd | ||
|
7e22af06f1 | ||
|
6f020901a8 | ||
|
306d55f636 | ||
|
27c9bb9b10 | ||
|
1cd253e05f | ||
|
e9360221b7 | ||
|
eb8a18304f | ||
|
e111958762 | ||
|
43a9194739 | ||
|
50da0cb732 | ||
|
a948334b8b | ||
|
b219b99380 | ||
|
21de3e2961 | ||
|
f69a19d01d | ||
|
ec0d426a6f | ||
|
678700f137 | ||
|
95f584c5d0 | ||
|
c0e1095e66 | ||
|
938004c090 | ||
|
a77a0b5eb0 | ||
|
3e77101b16 | ||
|
341071402c | ||
|
f15551b47b | ||
|
c2dd3bb5d2 | ||
|
b93c21a041 | ||
|
4d800a8487 | ||
|
11e537cb28 | ||
|
35214a34ee | ||
|
57afc5f035 | ||
|
907a54e9f6 | ||
|
a1928bd299 | ||
|
c7aed3c98c | ||
|
96cb9f13dd | ||
|
4d5676f455 | ||
|
5bdd49f36c | ||
|
d4da0a0a21 | ||
|
fe0d3b3e27 | ||
|
9d19001945 | ||
|
f55d15d9b9 | ||
|
237abda2eb | ||
|
08c9cc18d6 | ||
|
55da169fe7 | ||
|
a1211a0f5a | ||
|
179d54505a | ||
|
1514dcbb34 | ||
|
ac78184fe7 | ||
|
1777ff37c0 | ||
|
7dca59da56 | ||
|
6ac24fcf54 | ||
|
70e4933221 | ||
|
c1250ccb35 | ||
|
98e5ea5206 | ||
|
b22776d3a8 | ||
|
d4c1faad3b | ||
|
0fa45c3954 | ||
|
c802d7d58a | ||
|
5ab06caffc | ||
|
737d7484c5 | ||
|
b3a742304e | ||
|
6514d72fea | ||
|
c3d4b429d9 | ||
|
7ff848c2c8 | ||
|
a11ba3f437 | ||
|
6604d94271 | ||
|
e30fa1da4d | ||
|
7ea3345e0d | ||
|
1e97d73bd0 | ||
|
f0e9703384 | ||
|
514941627b | ||
|
acc08c65d9 | ||
|
f1e4403f98 | ||
|
b1d53f0472 | ||
|
bc3cfb008e | ||
|
9791a2ea40 | ||
|
9fb9d16737 | ||
|
6be1d0724a | ||
|
9238520490 | ||
|
dd1bb579df | ||
|
57943798b7 | ||
|
b43c3d75a2 |
34
.github/actions/debug/action.yml
vendored
34
.github/actions/debug/action.yml
vendored
@ -4,15 +4,31 @@ description: Prints workflow debug info
|
|||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
- name: Print envs
|
- name: Envs, event.json and contexts
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo "::group::Envs"
|
echo '::group::Environment variables'
|
||||||
env
|
env | sort
|
||||||
echo "::endgroup::"
|
echo '::endgroup::'
|
||||||
- name: Print Event.json
|
|
||||||
shell: bash
|
echo '::group::event.json'
|
||||||
run: |
|
|
||||||
echo "::group::Event.json"
|
|
||||||
python3 -m json.tool "$GITHUB_EVENT_PATH"
|
python3 -m json.tool "$GITHUB_EVENT_PATH"
|
||||||
echo "::endgroup::"
|
echo '::endgroup::'
|
||||||
|
|
||||||
|
cat << 'EOF'
|
||||||
|
::group::github context
|
||||||
|
${{ toJSON(github) }}
|
||||||
|
::endgroup::
|
||||||
|
|
||||||
|
::group::env context
|
||||||
|
${{ toJSON(env) }}
|
||||||
|
::endgroup::
|
||||||
|
|
||||||
|
::group::runner context
|
||||||
|
${{ toJSON(runner) }}
|
||||||
|
::endgroup::
|
||||||
|
|
||||||
|
::group::job context
|
||||||
|
${{ toJSON(job) }}
|
||||||
|
::endgroup::
|
||||||
|
EOF
|
||||||
|
2
.github/workflows/backport_branches.yml
vendored
2
.github/workflows/backport_branches.yml
vendored
@ -27,6 +27,8 @@ jobs:
|
|||||||
clear-repository: true # to ensure correct digests
|
clear-repository: true # to ensure correct digests
|
||||||
fetch-depth: 0 # to get version
|
fetch-depth: 0 # to get version
|
||||||
filter: tree:0
|
filter: tree:0
|
||||||
|
- name: Debug Info
|
||||||
|
uses: ./.github/actions/debug
|
||||||
- name: Labels check
|
- name: Labels check
|
||||||
run: |
|
run: |
|
||||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||||
|
2
.github/workflows/cherry_pick.yml
vendored
2
.github/workflows/cherry_pick.yml
vendored
@ -33,6 +33,8 @@ jobs:
|
|||||||
clear-repository: true
|
clear-repository: true
|
||||||
token: ${{secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN}}
|
token: ${{secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN}}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
- name: Debug Info
|
||||||
|
uses: ./.github/actions/debug
|
||||||
- name: Cherry pick
|
- name: Cherry pick
|
||||||
run: |
|
run: |
|
||||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||||
|
4
.github/workflows/create_release.yml
vendored
4
.github/workflows/create_release.yml
vendored
@ -56,13 +56,13 @@ jobs:
|
|||||||
GH_TOKEN: ${{ secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN }}
|
GH_TOKEN: ${{ secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN }}
|
||||||
runs-on: [self-hosted, release-maker]
|
runs-on: [self-hosted, release-maker]
|
||||||
steps:
|
steps:
|
||||||
- name: DebugInfo
|
|
||||||
uses: hmarr/debug-action@f7318c783045ac39ed9bb497e22ce835fdafbfe6
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: ClickHouse/checkout@v1
|
uses: ClickHouse/checkout@v1
|
||||||
with:
|
with:
|
||||||
token: ${{secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN}}
|
token: ${{secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN}}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
- name: Debug Info
|
||||||
|
uses: ./.github/actions/debug
|
||||||
- name: Prepare Release Info
|
- name: Prepare Release Info
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
1
.github/workflows/docker_test_images.yml
vendored
1
.github/workflows/docker_test_images.yml
vendored
@ -11,6 +11,7 @@ name: Build docker images
|
|||||||
required: false
|
required: false
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
DockerBuildAarch64:
|
DockerBuildAarch64:
|
||||||
runs-on: [self-hosted, style-checker-aarch64]
|
runs-on: [self-hosted, style-checker-aarch64]
|
||||||
|
5
.github/workflows/jepsen.yml
vendored
5
.github/workflows/jepsen.yml
vendored
@ -8,20 +8,21 @@ on: # yamllint disable-line rule:truthy
|
|||||||
schedule:
|
schedule:
|
||||||
- cron: '0 */6 * * *'
|
- cron: '0 */6 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
RunConfig:
|
RunConfig:
|
||||||
runs-on: [self-hosted, style-checker-aarch64]
|
runs-on: [self-hosted, style-checker-aarch64]
|
||||||
outputs:
|
outputs:
|
||||||
data: ${{ steps.runconfig.outputs.CI_DATA }}
|
data: ${{ steps.runconfig.outputs.CI_DATA }}
|
||||||
steps:
|
steps:
|
||||||
- name: DebugInfo
|
|
||||||
uses: hmarr/debug-action@f7318c783045ac39ed9bb497e22ce835fdafbfe6
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: ClickHouse/checkout@v1
|
uses: ClickHouse/checkout@v1
|
||||||
with:
|
with:
|
||||||
clear-repository: true # to ensure correct digests
|
clear-repository: true # to ensure correct digests
|
||||||
fetch-depth: 0 # to get version
|
fetch-depth: 0 # to get version
|
||||||
filter: tree:0
|
filter: tree:0
|
||||||
|
- name: Debug Info
|
||||||
|
uses: ./.github/actions/debug
|
||||||
- name: PrepareRunConfig
|
- name: PrepareRunConfig
|
||||||
id: runconfig
|
id: runconfig
|
||||||
run: |
|
run: |
|
||||||
|
4
.github/workflows/master.yml
vendored
4
.github/workflows/master.yml
vendored
@ -15,14 +15,14 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
data: ${{ steps.runconfig.outputs.CI_DATA }}
|
data: ${{ steps.runconfig.outputs.CI_DATA }}
|
||||||
steps:
|
steps:
|
||||||
- name: DebugInfo
|
|
||||||
uses: hmarr/debug-action@f7318c783045ac39ed9bb497e22ce835fdafbfe6
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: ClickHouse/checkout@v1
|
uses: ClickHouse/checkout@v1
|
||||||
with:
|
with:
|
||||||
clear-repository: true # to ensure correct digests
|
clear-repository: true # to ensure correct digests
|
||||||
fetch-depth: 0 # to get version
|
fetch-depth: 0 # to get version
|
||||||
filter: tree:0
|
filter: tree:0
|
||||||
|
- name: Debug Info
|
||||||
|
uses: ./.github/actions/debug
|
||||||
- name: Merge sync PR
|
- name: Merge sync PR
|
||||||
run: |
|
run: |
|
||||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||||
|
4
.github/workflows/merge_queue.yml
vendored
4
.github/workflows/merge_queue.yml
vendored
@ -14,14 +14,14 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
data: ${{ steps.runconfig.outputs.CI_DATA }}
|
data: ${{ steps.runconfig.outputs.CI_DATA }}
|
||||||
steps:
|
steps:
|
||||||
- name: DebugInfo
|
|
||||||
uses: hmarr/debug-action@f7318c783045ac39ed9bb497e22ce835fdafbfe6
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: ClickHouse/checkout@v1
|
uses: ClickHouse/checkout@v1
|
||||||
with:
|
with:
|
||||||
clear-repository: true # to ensure correct digests
|
clear-repository: true # to ensure correct digests
|
||||||
fetch-depth: 0 # to get a version
|
fetch-depth: 0 # to get a version
|
||||||
filter: tree:0
|
filter: tree:0
|
||||||
|
- name: Debug Info
|
||||||
|
uses: ./.github/actions/debug
|
||||||
- name: Cancel PR workflow
|
- name: Cancel PR workflow
|
||||||
run: |
|
run: |
|
||||||
python3 "$GITHUB_WORKSPACE/tests/ci/ci.py" --cancel-previous-run
|
python3 "$GITHUB_WORKSPACE/tests/ci/ci.py" --cancel-previous-run
|
||||||
|
4
.github/workflows/nightly.yml
vendored
4
.github/workflows/nightly.yml
vendored
@ -15,14 +15,14 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
data: ${{ steps.runconfig.outputs.CI_DATA }}
|
data: ${{ steps.runconfig.outputs.CI_DATA }}
|
||||||
steps:
|
steps:
|
||||||
- name: DebugInfo
|
|
||||||
uses: hmarr/debug-action@f7318c783045ac39ed9bb497e22ce835fdafbfe6
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: ClickHouse/checkout@v1
|
uses: ClickHouse/checkout@v1
|
||||||
with:
|
with:
|
||||||
clear-repository: true # to ensure correct digests
|
clear-repository: true # to ensure correct digests
|
||||||
fetch-depth: 0 # to get version
|
fetch-depth: 0 # to get version
|
||||||
filter: tree:0
|
filter: tree:0
|
||||||
|
- name: Debug Info
|
||||||
|
uses: ./.github/actions/debug
|
||||||
- name: PrepareRunConfig
|
- name: PrepareRunConfig
|
||||||
id: runconfig
|
id: runconfig
|
||||||
run: |
|
run: |
|
||||||
|
4
.github/workflows/pull_request.yml
vendored
4
.github/workflows/pull_request.yml
vendored
@ -25,14 +25,14 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
data: ${{ steps.runconfig.outputs.CI_DATA }}
|
data: ${{ steps.runconfig.outputs.CI_DATA }}
|
||||||
steps:
|
steps:
|
||||||
- name: DebugInfo
|
|
||||||
uses: hmarr/debug-action@f7318c783045ac39ed9bb497e22ce835fdafbfe6
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: ClickHouse/checkout@v1
|
uses: ClickHouse/checkout@v1
|
||||||
with:
|
with:
|
||||||
clear-repository: true # to ensure correct digests
|
clear-repository: true # to ensure correct digests
|
||||||
fetch-depth: 0 # to get a version
|
fetch-depth: 0 # to get a version
|
||||||
filter: tree:0
|
filter: tree:0
|
||||||
|
- name: Debug Info
|
||||||
|
uses: ./.github/actions/debug
|
||||||
- name: Cancel previous Sync PR workflow
|
- name: Cancel previous Sync PR workflow
|
||||||
run: |
|
run: |
|
||||||
python3 "$GITHUB_WORKSPACE/tests/ci/ci.py" --cancel-previous-run
|
python3 "$GITHUB_WORKSPACE/tests/ci/ci.py" --cancel-previous-run
|
||||||
|
2
.github/workflows/release_branches.yml
vendored
2
.github/workflows/release_branches.yml
vendored
@ -24,6 +24,8 @@ jobs:
|
|||||||
clear-repository: true # to ensure correct digests
|
clear-repository: true # to ensure correct digests
|
||||||
fetch-depth: 0 # to get version
|
fetch-depth: 0 # to get version
|
||||||
filter: tree:0
|
filter: tree:0
|
||||||
|
- name: Debug Info
|
||||||
|
uses: ./.github/actions/debug
|
||||||
- name: Labels check
|
- name: Labels check
|
||||||
run: |
|
run: |
|
||||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||||
|
4
.github/workflows/reusable_simple_job.yml
vendored
4
.github/workflows/reusable_simple_job.yml
vendored
@ -62,8 +62,6 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_JOB_OVERRIDDEN: ${{inputs.test_name}}
|
GITHUB_JOB_OVERRIDDEN: ${{inputs.test_name}}
|
||||||
steps:
|
steps:
|
||||||
- name: DebugInfo
|
|
||||||
uses: hmarr/debug-action@f7318c783045ac39ed9bb497e22ce835fdafbfe6
|
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: ClickHouse/checkout@v1
|
uses: ClickHouse/checkout@v1
|
||||||
with:
|
with:
|
||||||
@ -72,6 +70,8 @@ jobs:
|
|||||||
submodules: ${{inputs.submodules}}
|
submodules: ${{inputs.submodules}}
|
||||||
fetch-depth: ${{inputs.checkout_depth}}
|
fetch-depth: ${{inputs.checkout_depth}}
|
||||||
filter: tree:0
|
filter: tree:0
|
||||||
|
- name: Debug Info
|
||||||
|
uses: ./.github/actions/debug
|
||||||
- name: Set build envs
|
- name: Set build envs
|
||||||
run: |
|
run: |
|
||||||
cat >> "$GITHUB_ENV" << 'EOF'
|
cat >> "$GITHUB_ENV" << 'EOF'
|
||||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -170,9 +170,6 @@
|
|||||||
[submodule "contrib/fast_float"]
|
[submodule "contrib/fast_float"]
|
||||||
path = contrib/fast_float
|
path = contrib/fast_float
|
||||||
url = https://github.com/fastfloat/fast_float
|
url = https://github.com/fastfloat/fast_float
|
||||||
[submodule "contrib/libpq"]
|
|
||||||
path = contrib/libpq
|
|
||||||
url = https://github.com/ClickHouse/libpq
|
|
||||||
[submodule "contrib/NuRaft"]
|
[submodule "contrib/NuRaft"]
|
||||||
path = contrib/NuRaft
|
path = contrib/NuRaft
|
||||||
url = https://github.com/ClickHouse/NuRaft
|
url = https://github.com/ClickHouse/NuRaft
|
||||||
@ -369,3 +366,6 @@
|
|||||||
[submodule "contrib/numactl"]
|
[submodule "contrib/numactl"]
|
||||||
path = contrib/numactl
|
path = contrib/numactl
|
||||||
url = https://github.com/ClickHouse/numactl.git
|
url = https://github.com/ClickHouse/numactl.git
|
||||||
|
[submodule "contrib/postgres"]
|
||||||
|
path = contrib/postgres
|
||||||
|
url = https://github.com/ClickHouse/postgres.git
|
||||||
|
20
README.md
20
README.md
@ -40,17 +40,8 @@ Every month we get together with the community (users, contributors, customers,
|
|||||||
|
|
||||||
Keep an eye out for upcoming meetups and events around the world. Somewhere else you want us to be? Please feel free to reach out to tyler `<at>` clickhouse `<dot>` com. You can also peruse [ClickHouse Events](https://clickhouse.com/company/news-events) for a list of all upcoming trainings, meetups, speaking engagements, etc.
|
Keep an eye out for upcoming meetups and events around the world. Somewhere else you want us to be? Please feel free to reach out to tyler `<at>` clickhouse `<dot>` com. You can also peruse [ClickHouse Events](https://clickhouse.com/company/news-events) for a list of all upcoming trainings, meetups, speaking engagements, etc.
|
||||||
|
|
||||||
The following upcoming meetups are featuring creator of ClickHouse & CTO, Alexey Milovidov:
|
Upcoming meetups
|
||||||
|
|
||||||
* [Raleigh Meetup (Deutsche Bank)](https://www.meetup.com/triangletechtalks/events/302723486/) - September 9
|
|
||||||
* [New York Meetup (Rokt)](https://www.meetup.com/clickhouse-new-york-user-group/events/302575342) - September 10
|
|
||||||
* [Chicago Meetup (Jump Capital)](https://lu.ma/43tvmrfw) - September 12
|
|
||||||
|
|
||||||
Other upcoming meetups
|
|
||||||
|
|
||||||
* [Toronto Meetup (Shopify)](https://www.meetup.com/clickhouse-toronto-user-group/events/301490855/) - September 10
|
|
||||||
* [Austin Meetup](https://www.meetup.com/clickhouse-austin-user-group/events/302558689/) - September 17
|
|
||||||
* [London Meetup](https://www.meetup.com/clickhouse-london-user-group/events/302977267) - September 17
|
|
||||||
* [Bangalore Meetup](https://www.meetup.com/clickhouse-bangalore-user-group/events/303208274/) - September 18
|
* [Bangalore Meetup](https://www.meetup.com/clickhouse-bangalore-user-group/events/303208274/) - September 18
|
||||||
* [Tel Aviv Meetup](https://www.meetup.com/clickhouse-meetup-israel/events/303095121) - September 22
|
* [Tel Aviv Meetup](https://www.meetup.com/clickhouse-meetup-israel/events/303095121) - September 22
|
||||||
* [Jakarta Meetup](https://www.meetup.com/clickhouse-indonesia-user-group/events/303191359/) - October 1
|
* [Jakarta Meetup](https://www.meetup.com/clickhouse-indonesia-user-group/events/303191359/) - October 1
|
||||||
@ -62,13 +53,20 @@ Other upcoming meetups
|
|||||||
* [Dubai Meetup](https://www.meetup.com/clickhouse-dubai-meetup-group/events/303096989/) - November 21
|
* [Dubai Meetup](https://www.meetup.com/clickhouse-dubai-meetup-group/events/303096989/) - November 21
|
||||||
* [Paris Meetup](https://www.meetup.com/clickhouse-france-user-group/events/303096434) - November 26
|
* [Paris Meetup](https://www.meetup.com/clickhouse-france-user-group/events/303096434) - November 26
|
||||||
|
|
||||||
Recently completed events
|
Recently completed meetups
|
||||||
|
|
||||||
* [ClickHouse Guangzhou User Group Meetup](https://mp.weixin.qq.com/s/GSvo-7xUoVzCsuUvlLTpCw) - August 25
|
* [ClickHouse Guangzhou User Group Meetup](https://mp.weixin.qq.com/s/GSvo-7xUoVzCsuUvlLTpCw) - August 25
|
||||||
* [Seattle Meetup (Statsig)](https://www.meetup.com/clickhouse-seattle-user-group/events/302518075/) - August 27
|
* [Seattle Meetup (Statsig)](https://www.meetup.com/clickhouse-seattle-user-group/events/302518075/) - August 27
|
||||||
* [Melbourne Meetup](https://www.meetup.com/clickhouse-australia-user-group/events/302732666/) - August 27
|
* [Melbourne Meetup](https://www.meetup.com/clickhouse-australia-user-group/events/302732666/) - August 27
|
||||||
* [Sydney Meetup](https://www.meetup.com/clickhouse-australia-user-group/events/302862966/) - September 5
|
* [Sydney Meetup](https://www.meetup.com/clickhouse-australia-user-group/events/302862966/) - September 5
|
||||||
* [Zurich Meetup](https://www.meetup.com/clickhouse-switzerland-meetup-group/events/302267429/) - September 5
|
* [Zurich Meetup](https://www.meetup.com/clickhouse-switzerland-meetup-group/events/302267429/) - September 5
|
||||||
* [San Francisco Meetup (Cloudflare)](https://www.meetup.com/clickhouse-silicon-valley-meetup-group/events/302540575) - September 5
|
* [San Francisco Meetup (Cloudflare)](https://www.meetup.com/clickhouse-silicon-valley-meetup-group/events/302540575) - September 5
|
||||||
|
* [Raleigh Meetup (Deutsche Bank)](https://www.meetup.com/triangletechtalks/events/302723486/) - September 9
|
||||||
|
* [New York Meetup (Rokt)](https://www.meetup.com/clickhouse-new-york-user-group/events/302575342) - September 10
|
||||||
|
* [Toronto Meetup (Shopify)](https://www.meetup.com/clickhouse-toronto-user-group/events/301490855/) - September 10
|
||||||
|
* [Chicago Meetup (Jump Capital)](https://lu.ma/43tvmrfw) - September 12
|
||||||
|
* [London Meetup](https://www.meetup.com/clickhouse-london-user-group/events/302977267) - September 17
|
||||||
|
* [Austin Meetup](https://www.meetup.com/clickhouse-austin-user-group/events/302558689/) - September 17
|
||||||
|
|
||||||
## Recent Recordings
|
## Recent Recordings
|
||||||
* **Recent Meetup Videos**: [Meetup Playlist](https://www.youtube.com/playlist?list=PL0Z2YDlm0b3iNDUzpY1S3L_iV4nARda_U) Whenever possible recordings of the ClickHouse Community Meetups are edited and presented as individual talks. Current featuring "Modern SQL in 2023", "Fast, Concurrent, and Consistent Asynchronous INSERTS in ClickHouse", and "Full-Text Indices: Design and Experiments"
|
* **Recent Meetup Videos**: [Meetup Playlist](https://www.youtube.com/playlist?list=PL0Z2YDlm0b3iNDUzpY1S3L_iV4nARda_U) Whenever possible recordings of the ClickHouse Community Meetups are edited and presented as individual talks. Current featuring "Modern SQL in 2023", "Fast, Concurrent, and Consistent Asynchronous INSERTS in ClickHouse", and "Full-Text Indices: Design and Experiments"
|
||||||
|
@ -188,8 +188,9 @@ namespace Crypto
|
|||||||
pFile = fopen(keyFile.c_str(), "r");
|
pFile = fopen(keyFile.c_str(), "r");
|
||||||
if (pFile)
|
if (pFile)
|
||||||
{
|
{
|
||||||
pem_password_cb * pCB = pass.empty() ? (pem_password_cb *)0 : &passCB;
|
pem_password_cb * pCB = &passCB;
|
||||||
void * pPassword = pass.empty() ? (void *)0 : (void *)pass.c_str();
|
static constexpr char * no_password = "";
|
||||||
|
void * pPassword = pass.empty() ? (void *)no_password : (void *)pass.c_str();
|
||||||
if (readFunc(pFile, &pKey, pCB, pPassword))
|
if (readFunc(pFile, &pKey, pCB, pPassword))
|
||||||
{
|
{
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
@ -225,6 +226,13 @@ namespace Crypto
|
|||||||
error:
|
error:
|
||||||
if (pFile)
|
if (pFile)
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
|
if (*ppKey)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<K, EVP_PKEY>)
|
||||||
|
EVP_PKEY_free(*ppKey);
|
||||||
|
else
|
||||||
|
EC_KEY_free(*ppKey);
|
||||||
|
}
|
||||||
throw OpenSSLException("EVPKey::loadKey(string)");
|
throw OpenSSLException("EVPKey::loadKey(string)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,6 +294,13 @@ namespace Crypto
|
|||||||
error:
|
error:
|
||||||
if (pBIO)
|
if (pBIO)
|
||||||
BIO_free(pBIO);
|
BIO_free(pBIO);
|
||||||
|
if (*ppKey)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<K, EVP_PKEY>)
|
||||||
|
EVP_PKEY_free(*ppKey);
|
||||||
|
else
|
||||||
|
EC_KEY_free(*ppKey);
|
||||||
|
}
|
||||||
throw OpenSSLException("EVPKey::loadKey(stream)");
|
throw OpenSSLException("EVPKey::loadKey(stream)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +248,9 @@ namespace Net
|
|||||||
SSL_CTX * sslContext() const;
|
SSL_CTX * sslContext() const;
|
||||||
/// Returns the underlying OpenSSL SSL Context object.
|
/// Returns the underlying OpenSSL SSL Context object.
|
||||||
|
|
||||||
|
SSL_CTX * takeSslContext();
|
||||||
|
/// Takes ownership of the underlying OpenSSL SSL Context object.
|
||||||
|
|
||||||
Usage usage() const;
|
Usage usage() const;
|
||||||
/// Returns whether the context is for use by a client or by a server
|
/// Returns whether the context is for use by a client or by a server
|
||||||
/// and whether TLSv1 is required.
|
/// and whether TLSv1 is required.
|
||||||
@ -401,6 +404,13 @@ namespace Net
|
|||||||
return _pSSLContext;
|
return _pSSLContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline SSL_CTX * Context::takeSslContext()
|
||||||
|
{
|
||||||
|
auto * result = _pSSLContext;
|
||||||
|
_pSSLContext = nullptr;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool Context::extendedCertificateVerificationEnabled() const
|
inline bool Context::extendedCertificateVerificationEnabled() const
|
||||||
{
|
{
|
||||||
|
@ -106,6 +106,11 @@ Context::Context(
|
|||||||
|
|
||||||
Context::~Context()
|
Context::~Context()
|
||||||
{
|
{
|
||||||
|
if (_pSSLContext == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SSL_CTX_free(_pSSLContext);
|
SSL_CTX_free(_pSSLContext);
|
||||||
|
7
contrib/CMakeLists.txt
vendored
7
contrib/CMakeLists.txt
vendored
@ -145,8 +145,13 @@ add_contrib (isa-l-cmake isa-l)
|
|||||||
add_contrib (libhdfs3-cmake libhdfs3) # requires: google-protobuf, krb5, isa-l
|
add_contrib (libhdfs3-cmake libhdfs3) # requires: google-protobuf, krb5, isa-l
|
||||||
add_contrib (hive-metastore-cmake hive-metastore) # requires: thrift, avro, arrow, libhdfs3
|
add_contrib (hive-metastore-cmake hive-metastore) # requires: thrift, avro, arrow, libhdfs3
|
||||||
add_contrib (cppkafka-cmake cppkafka)
|
add_contrib (cppkafka-cmake cppkafka)
|
||||||
|
|
||||||
|
option(ENABLE_LIBPQXX "Enable PostgreSQL" ${ENABLE_LIBRARIES})
|
||||||
|
if (ENABLE_LIBPQXX)
|
||||||
|
add_contrib (postgres-cmake postgres)
|
||||||
add_contrib (libpqxx-cmake libpqxx)
|
add_contrib (libpqxx-cmake libpqxx)
|
||||||
add_contrib (libpq-cmake libpq)
|
endif()
|
||||||
|
|
||||||
add_contrib (rocksdb-cmake rocksdb) # requires: jemalloc, snappy, zlib, lz4, zstd, liburing
|
add_contrib (rocksdb-cmake rocksdb) # requires: jemalloc, snappy, zlib, lz4, zstd, liburing
|
||||||
add_contrib (nuraft-cmake NuRaft)
|
add_contrib (nuraft-cmake NuRaft)
|
||||||
add_contrib (fast_float-cmake fast_float)
|
add_contrib (fast_float-cmake fast_float)
|
||||||
|
1
contrib/libpq
vendored
1
contrib/libpq
vendored
@ -1 +0,0 @@
|
|||||||
Subproject commit 2446f2c85650b56df9d4ebc4c2ea7f4b01beee57
|
|
@ -1,78 +0,0 @@
|
|||||||
if (NOT ENABLE_LIBPQXX)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(LIBPQ_SOURCE_DIR "${ClickHouse_SOURCE_DIR}/contrib/libpq")
|
|
||||||
|
|
||||||
set(SRCS
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-auth.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-auth-scram.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-connect.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-exec.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-lobj.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-misc.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-print.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-trace.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-protocol3.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-secure.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-secure-common.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/fe-secure-openssl.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/legacy-pqsignal.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/libpq-events.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/pqexpbuffer.c"
|
|
||||||
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/scram-common.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/sha2.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/sha1.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/md5.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/md5_common.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/hmac_openssl.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/cryptohash.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/saslprep.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/unicode_norm.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/ip.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/jsonapi.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/wchar.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/base64.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/link-canary.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/fe_memutils.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/string.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/pg_get_line.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/stringinfo.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/psprintf.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/encnames.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/common/logging.c"
|
|
||||||
|
|
||||||
"${LIBPQ_SOURCE_DIR}/port/snprintf.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/port/strlcpy.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/port/strerror.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/port/inet_net_ntop.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/port/getpeereid.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/port/chklocale.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/port/noblock.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/port/pg_strong_random.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/port/pgstrcasecmp.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/port/thread.c"
|
|
||||||
"${LIBPQ_SOURCE_DIR}/port/path.c"
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(_libpq ${SRCS})
|
|
||||||
|
|
||||||
add_definitions(-DHAVE_BIO_METH_NEW)
|
|
||||||
add_definitions(-DHAVE_HMAC_CTX_NEW)
|
|
||||||
add_definitions(-DHAVE_HMAC_CTX_FREE)
|
|
||||||
|
|
||||||
target_include_directories (_libpq SYSTEM PUBLIC ${LIBPQ_SOURCE_DIR})
|
|
||||||
target_include_directories (_libpq SYSTEM PUBLIC "${LIBPQ_SOURCE_DIR}/include")
|
|
||||||
target_include_directories (_libpq SYSTEM PRIVATE "${LIBPQ_SOURCE_DIR}/configs")
|
|
||||||
|
|
||||||
# NOTE: this is a dirty hack to avoid and instead pg_config.h should be shipped
|
|
||||||
# for different OS'es like for jemalloc, not one generic for all OS'es like
|
|
||||||
# now.
|
|
||||||
if (OS_DARWIN OR OS_FREEBSD OR USE_MUSL)
|
|
||||||
target_compile_definitions(_libpq PRIVATE -DSTRERROR_R_INT=1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_libraries (_libpq PRIVATE OpenSSL::SSL)
|
|
||||||
|
|
||||||
add_library(ch_contrib::libpq ALIAS _libpq)
|
|
2
contrib/libpqxx
vendored
2
contrib/libpqxx
vendored
@ -1 +1 @@
|
|||||||
Subproject commit c995193a3a14d71f4711f1f421f65a1a1db64640
|
Subproject commit 41e4c331564167cca97ad6eccbd5b8879c2ca044
|
@ -1,16 +1,9 @@
|
|||||||
option(ENABLE_LIBPQXX "Enalbe libpqxx" ${ENABLE_LIBRARIES})
|
|
||||||
|
|
||||||
if (NOT ENABLE_LIBPQXX)
|
|
||||||
message(STATUS "Not using libpqxx")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set (LIBRARY_DIR "${ClickHouse_SOURCE_DIR}/contrib/libpqxx")
|
set (LIBRARY_DIR "${ClickHouse_SOURCE_DIR}/contrib/libpqxx")
|
||||||
|
|
||||||
set (SRCS
|
set (SRCS
|
||||||
"${LIBRARY_DIR}/src/strconv.cxx"
|
|
||||||
"${LIBRARY_DIR}/src/array.cxx"
|
"${LIBRARY_DIR}/src/array.cxx"
|
||||||
"${LIBRARY_DIR}/src/binarystring.cxx"
|
"${LIBRARY_DIR}/src/binarystring.cxx"
|
||||||
|
"${LIBRARY_DIR}/src/blob.cxx"
|
||||||
"${LIBRARY_DIR}/src/connection.cxx"
|
"${LIBRARY_DIR}/src/connection.cxx"
|
||||||
"${LIBRARY_DIR}/src/cursor.cxx"
|
"${LIBRARY_DIR}/src/cursor.cxx"
|
||||||
"${LIBRARY_DIR}/src/encodings.cxx"
|
"${LIBRARY_DIR}/src/encodings.cxx"
|
||||||
@ -19,59 +12,25 @@ set (SRCS
|
|||||||
"${LIBRARY_DIR}/src/field.cxx"
|
"${LIBRARY_DIR}/src/field.cxx"
|
||||||
"${LIBRARY_DIR}/src/largeobject.cxx"
|
"${LIBRARY_DIR}/src/largeobject.cxx"
|
||||||
"${LIBRARY_DIR}/src/notification.cxx"
|
"${LIBRARY_DIR}/src/notification.cxx"
|
||||||
|
"${LIBRARY_DIR}/src/params.cxx"
|
||||||
"${LIBRARY_DIR}/src/pipeline.cxx"
|
"${LIBRARY_DIR}/src/pipeline.cxx"
|
||||||
"${LIBRARY_DIR}/src/result.cxx"
|
"${LIBRARY_DIR}/src/result.cxx"
|
||||||
"${LIBRARY_DIR}/src/robusttransaction.cxx"
|
"${LIBRARY_DIR}/src/robusttransaction.cxx"
|
||||||
|
"${LIBRARY_DIR}/src/row.cxx"
|
||||||
"${LIBRARY_DIR}/src/sql_cursor.cxx"
|
"${LIBRARY_DIR}/src/sql_cursor.cxx"
|
||||||
|
"${LIBRARY_DIR}/src/strconv.cxx"
|
||||||
"${LIBRARY_DIR}/src/stream_from.cxx"
|
"${LIBRARY_DIR}/src/stream_from.cxx"
|
||||||
"${LIBRARY_DIR}/src/stream_to.cxx"
|
"${LIBRARY_DIR}/src/stream_to.cxx"
|
||||||
"${LIBRARY_DIR}/src/subtransaction.cxx"
|
"${LIBRARY_DIR}/src/subtransaction.cxx"
|
||||||
|
"${LIBRARY_DIR}/src/time.cxx"
|
||||||
"${LIBRARY_DIR}/src/transaction.cxx"
|
"${LIBRARY_DIR}/src/transaction.cxx"
|
||||||
"${LIBRARY_DIR}/src/transaction_base.cxx"
|
"${LIBRARY_DIR}/src/transaction_base.cxx"
|
||||||
"${LIBRARY_DIR}/src/row.cxx"
|
|
||||||
"${LIBRARY_DIR}/src/params.cxx"
|
|
||||||
"${LIBRARY_DIR}/src/util.cxx"
|
"${LIBRARY_DIR}/src/util.cxx"
|
||||||
"${LIBRARY_DIR}/src/version.cxx"
|
"${LIBRARY_DIR}/src/version.cxx"
|
||||||
|
"${LIBRARY_DIR}/src/wait.cxx"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Need to explicitly include each header file, because in the directory include/pqxx there are also files
|
add_library(_libpqxx ${SRCS})
|
||||||
# like just 'array'. So if including the whole directory with `target_include_directories`, it will make
|
|
||||||
# conflicts with all includes of <array>.
|
|
||||||
set (HDRS
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/array.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/params.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/binarystring.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/composite.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/connection.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/cursor.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/dbtransaction.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/errorhandler.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/except.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/field.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/isolation.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/largeobject.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/nontransaction.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/notification.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/pipeline.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/prepared_statement.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/result.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/robusttransaction.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/row.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/separated_list.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/strconv.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/stream_from.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/stream_to.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/subtransaction.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/transaction.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/transaction_base.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/types.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/util.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/version.hxx"
|
|
||||||
"${LIBRARY_DIR}/include/pqxx/zview.hxx"
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(_libpqxx ${SRCS} ${HDRS})
|
|
||||||
|
|
||||||
target_link_libraries(_libpqxx PUBLIC ch_contrib::libpq)
|
target_link_libraries(_libpqxx PUBLIC ch_contrib::libpq)
|
||||||
target_include_directories (_libpqxx SYSTEM BEFORE PUBLIC "${LIBRARY_DIR}/include")
|
target_include_directories (_libpqxx SYSTEM BEFORE PUBLIC "${LIBRARY_DIR}/include")
|
||||||
|
|
||||||
|
1
contrib/postgres
vendored
Submodule
1
contrib/postgres
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit cfd77000af28469fcb650485bad65a35e7649e41
|
78
contrib/postgres-cmake/CMakeLists.txt
Normal file
78
contrib/postgres-cmake/CMakeLists.txt
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# Build description for libpq which is part of the PostgreSQL sources
|
||||||
|
|
||||||
|
set(POSTGRES_SOURCE_DIR "${ClickHouse_SOURCE_DIR}/contrib/postgres")
|
||||||
|
set(LIBPQ_SOURCE_DIR "${POSTGRES_SOURCE_DIR}/src/interfaces/libpq")
|
||||||
|
set(LIBPQ_CMAKE_SOURCE_DIR "${ClickHouse_SOURCE_DIR}/contrib/postgres-cmake")
|
||||||
|
|
||||||
|
set(SRCS
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-auth.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-auth-scram.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-connect.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-exec.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-lobj.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-misc.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-print.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-trace.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-protocol3.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-secure.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-secure-common.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/fe-secure-openssl.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/legacy-pqsignal.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/libpq-events.c"
|
||||||
|
"${LIBPQ_SOURCE_DIR}/pqexpbuffer.c"
|
||||||
|
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/scram-common.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/sha2.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/sha1.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/md5.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/md5_common.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/hmac_openssl.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/cryptohash.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/saslprep.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/unicode_norm.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/ip.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/jsonapi.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/wchar.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/base64.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/link-canary.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/fe_memutils.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/string.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/pg_get_line.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/stringinfo.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/psprintf.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/encnames.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/common/logging.c"
|
||||||
|
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/port/snprintf.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/port/strlcpy.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/port/strerror.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/port/inet_net_ntop.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/port/getpeereid.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/port/chklocale.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/port/noblock.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/port/pg_strong_random.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/port/pgstrcasecmp.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/port/thread.c"
|
||||||
|
"${POSTGRES_SOURCE_DIR}/src/port/path.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(_libpq ${SRCS})
|
||||||
|
|
||||||
|
add_definitions(-DHAVE_BIO_METH_NEW)
|
||||||
|
add_definitions(-DHAVE_HMAC_CTX_NEW)
|
||||||
|
add_definitions(-DHAVE_HMAC_CTX_FREE)
|
||||||
|
|
||||||
|
target_include_directories (_libpq SYSTEM PUBLIC ${LIBPQ_SOURCE_DIR})
|
||||||
|
target_include_directories (_libpq SYSTEM PUBLIC "${POSTGRES_SOURCE_DIR}/src/include")
|
||||||
|
target_include_directories (_libpq SYSTEM PUBLIC "${LIBPQ_CMAKE_SOURCE_DIR}") # pre-generated headers
|
||||||
|
|
||||||
|
# NOTE: this is a dirty hack to avoid and instead pg_config.h should be shipped
|
||||||
|
# for different OS'es like for jemalloc, not one generic for all OS'es like
|
||||||
|
# now.
|
||||||
|
if (OS_DARWIN OR OS_FREEBSD OR USE_MUSL)
|
||||||
|
target_compile_definitions(_libpq PRIVATE -DSTRERROR_R_INT=1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries (_libpq PRIVATE OpenSSL::SSL)
|
||||||
|
|
||||||
|
add_library(ch_contrib::libpq ALIAS _libpq)
|
943
contrib/postgres-cmake/pg_config.h
Normal file
943
contrib/postgres-cmake/pg_config.h
Normal file
@ -0,0 +1,943 @@
|
|||||||
|
/* src/include/pg_config.h. Generated from pg_config.h.in by configure. */
|
||||||
|
/* src/include/pg_config.h.in. Generated from configure.in by autoheader. */
|
||||||
|
|
||||||
|
/* Define if building universal (internal helper macro) */
|
||||||
|
/* #undef AC_APPLE_UNIVERSAL_BUILD */
|
||||||
|
|
||||||
|
/* The normal alignment of `double', in bytes. */
|
||||||
|
#define ALIGNOF_DOUBLE 4
|
||||||
|
|
||||||
|
/* The normal alignment of `int', in bytes. */
|
||||||
|
#define ALIGNOF_INT 4
|
||||||
|
|
||||||
|
/* The normal alignment of `long', in bytes. */
|
||||||
|
#define ALIGNOF_LONG 4
|
||||||
|
|
||||||
|
/* The normal alignment of `long long int', in bytes. */
|
||||||
|
#define ALIGNOF_LONG_LONG_INT 4
|
||||||
|
|
||||||
|
/* The normal alignment of `short', in bytes. */
|
||||||
|
#define ALIGNOF_SHORT 2
|
||||||
|
|
||||||
|
/* Size of a disk block --- this also limits the size of a tuple. You can set
|
||||||
|
it bigger if you need bigger tuples (although TOAST should reduce the need
|
||||||
|
to have large tuples, since fields can be spread across multiple tuples).
|
||||||
|
BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is
|
||||||
|
currently 2^15 (32768). This is determined by the 15-bit widths of the
|
||||||
|
lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h).
|
||||||
|
Changing BLCKSZ requires an initdb. */
|
||||||
|
#define BLCKSZ 8192
|
||||||
|
|
||||||
|
/* Define to the default TCP port number on which the server listens and to
|
||||||
|
which clients will try to connect. This can be overridden at run-time, but
|
||||||
|
it's convenient if your clients have the right default compiled in.
|
||||||
|
(--with-pgport=PORTNUM) */
|
||||||
|
#define DEF_PGPORT 5432
|
||||||
|
|
||||||
|
/* Define to the default TCP port number as a string constant. */
|
||||||
|
#define DEF_PGPORT_STR "5432"
|
||||||
|
|
||||||
|
/* Define to the file name extension of dynamically-loadable modules. */
|
||||||
|
#define DLSUFFIX ".so"
|
||||||
|
|
||||||
|
/* Define to build with GSSAPI support. (--with-gssapi) */
|
||||||
|
//#define ENABLE_GSS 0
|
||||||
|
|
||||||
|
/* Define to 1 if you want National Language Support. (--enable-nls) */
|
||||||
|
/* #undef ENABLE_NLS */
|
||||||
|
|
||||||
|
/* Define to 1 to build client libraries as thread-safe code.
|
||||||
|
(--enable-thread-safety) */
|
||||||
|
#define ENABLE_THREAD_SAFETY 1
|
||||||
|
|
||||||
|
/* Define to nothing if C supports flexible array members, and to 1 if it does
|
||||||
|
not. That way, with a declaration like `struct s { int n; double
|
||||||
|
d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99
|
||||||
|
compilers. When computing the size of such an object, don't use 'sizeof
|
||||||
|
(struct s)' as it overestimates the size. Use 'offsetof (struct s, d)'
|
||||||
|
instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with
|
||||||
|
MSVC and with C++ compilers. */
|
||||||
|
#define FLEXIBLE_ARRAY_MEMBER /**/
|
||||||
|
|
||||||
|
/* float4 values are passed by value if 'true', by reference if 'false' */
|
||||||
|
#define FLOAT4PASSBYVAL true
|
||||||
|
|
||||||
|
/* float8, int8, and related values are passed by value if 'true', by
|
||||||
|
reference if 'false' */
|
||||||
|
#define FLOAT8PASSBYVAL false
|
||||||
|
|
||||||
|
/* Define to 1 if gettimeofday() takes only 1 argument. */
|
||||||
|
/* #undef GETTIMEOFDAY_1ARG */
|
||||||
|
|
||||||
|
#ifdef GETTIMEOFDAY_1ARG
|
||||||
|
# define gettimeofday(a,b) gettimeofday(a)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `append_history' function. */
|
||||||
|
/* #undef HAVE_APPEND_HISTORY */
|
||||||
|
|
||||||
|
/* Define to 1 if you want to use atomics if available. */
|
||||||
|
#define HAVE_ATOMICS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <atomic.h> header file. */
|
||||||
|
/* #undef HAVE_ATOMIC_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `cbrt' function. */
|
||||||
|
#define HAVE_CBRT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `class' function. */
|
||||||
|
/* #undef HAVE_CLASS */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <crtdefs.h> header file. */
|
||||||
|
/* #undef HAVE_CRTDEFS_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `crypt' function. */
|
||||||
|
#define HAVE_CRYPT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <crypt.h> header file. */
|
||||||
|
#define HAVE_CRYPT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#define HAVE_DECL_FDATASYNC 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#define HAVE_DECL_F_FULLFSYNC 0
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#define HAVE_DECL_POSIX_FADVISE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `snprintf', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#define HAVE_DECL_SNPRINTF 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `sigwait', and to 0 if you don't. */
|
||||||
|
#define HAVE_DECL_SIGWAIT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#if OS_DARWIN
|
||||||
|
#define HAVE_DECL_STRLCAT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#if OS_DARWIN
|
||||||
|
#define HAVE_DECL_STRLCPY 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#define HAVE_DECL_SYS_SIGLIST 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you
|
||||||
|
don't. */
|
||||||
|
#define HAVE_DECL_VSNPRINTF 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dld.h> header file. */
|
||||||
|
/* #undef HAVE_DLD_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `dlopen' function. */
|
||||||
|
#define HAVE_DLOPEN 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <editline/history.h> header file. */
|
||||||
|
/* #undef HAVE_EDITLINE_HISTORY_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <editline/readline.h> header file. */
|
||||||
|
#define HAVE_EDITLINE_READLINE_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `fdatasync' function. */
|
||||||
|
#define HAVE_FDATASYNC 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `fls' function. */
|
||||||
|
/* #undef HAVE_FLS */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `fpclass' function. */
|
||||||
|
/* #undef HAVE_FPCLASS */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `fp_class' function. */
|
||||||
|
/* #undef HAVE_FP_CLASS */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `fp_class_d' function. */
|
||||||
|
/* #undef HAVE_FP_CLASS_D */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <fp_class.h> header file. */
|
||||||
|
/* #undef HAVE_FP_CLASS_H */
|
||||||
|
|
||||||
|
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
|
||||||
|
#define HAVE_FSEEKO 1
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands __func__. */
|
||||||
|
#define HAVE_FUNCNAME__FUNC 1
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands __FUNCTION__. */
|
||||||
|
/* #undef HAVE_FUNCNAME__FUNCTION */
|
||||||
|
|
||||||
|
/* Define to 1 if you have __atomic_compare_exchange_n(int *, int *, int). */
|
||||||
|
/* #undef HAVE_GCC__ATOMIC_INT32_CAS */
|
||||||
|
|
||||||
|
/* Define to 1 if you have __atomic_compare_exchange_n(int64 *, int *, int64).
|
||||||
|
*/
|
||||||
|
/* #undef HAVE_GCC__ATOMIC_INT64_CAS */
|
||||||
|
|
||||||
|
/* Define to 1 if you have __sync_lock_test_and_set(char *) and friends. */
|
||||||
|
#define HAVE_GCC__SYNC_CHAR_TAS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have __sync_compare_and_swap(int *, int, int). */
|
||||||
|
/* #undef HAVE_GCC__SYNC_INT32_CAS */
|
||||||
|
|
||||||
|
/* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */
|
||||||
|
#define HAVE_GCC__SYNC_INT32_TAS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have __sync_compare_and_swap(int64 *, int64, int64). */
|
||||||
|
/* #undef HAVE_GCC__SYNC_INT64_CAS */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||||
|
#define HAVE_GETADDRINFO 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `gethostbyname_r' function. */
|
||||||
|
#define HAVE_GETHOSTBYNAME_R 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getifaddrs' function. */
|
||||||
|
#define HAVE_GETIFADDRS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getopt' function. */
|
||||||
|
#define HAVE_GETOPT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <getopt.h> header file. */
|
||||||
|
#define HAVE_GETOPT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getopt_long' function. */
|
||||||
|
#define HAVE_GETOPT_LONG 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getpeereid' function. */
|
||||||
|
/* #undef HAVE_GETPEEREID */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getpeerucred' function. */
|
||||||
|
/* #undef HAVE_GETPEERUCRED */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getpwuid_r' function. */
|
||||||
|
#define HAVE_GETPWUID_R 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getrlimit' function. */
|
||||||
|
#define HAVE_GETRLIMIT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getrusage' function. */
|
||||||
|
#define HAVE_GETRUSAGE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `gettimeofday' function. */
|
||||||
|
/* #undef HAVE_GETTIMEOFDAY */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
|
||||||
|
//#define HAVE_GSSAPI_GSSAPI_H 0
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <gssapi.h> header file. */
|
||||||
|
/* #undef HAVE_GSSAPI_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <history.h> header file. */
|
||||||
|
/* #undef HAVE_HISTORY_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `history_truncate_file' function. */
|
||||||
|
#define HAVE_HISTORY_TRUNCATE_FILE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ieeefp.h> header file. */
|
||||||
|
/* #undef HAVE_IEEEFP_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ifaddrs.h> header file. */
|
||||||
|
#define HAVE_IFADDRS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `inet_aton' function. */
|
||||||
|
#define HAVE_INET_ATON 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `inet_pton' function. */
|
||||||
|
#define HAVE_INET_PTON 1
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `int64'. */
|
||||||
|
/* #undef HAVE_INT64 */
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `int8'. */
|
||||||
|
/* #undef HAVE_INT8 */
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `intptr_t'. */
|
||||||
|
#define HAVE_INTPTR_T 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#define HAVE_INTTYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the global variable 'int opterr'. */
|
||||||
|
#define HAVE_INT_OPTERR 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the global variable 'int optreset'. */
|
||||||
|
/* #undef HAVE_INT_OPTRESET */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the global variable 'int timezone'. */
|
||||||
|
#define HAVE_INT_TIMEZONE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have support for IPv6. */
|
||||||
|
#define HAVE_IPV6 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have isinf(). */
|
||||||
|
#define HAVE_ISINF 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <langinfo.h> header file. */
|
||||||
|
#define HAVE_LANGINFO_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ldap.h> header file. */
|
||||||
|
//#define HAVE_LDAP_H 0
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
||||||
|
#define HAVE_LIBCRYPTO 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `ldap' library (-lldap). */
|
||||||
|
//#define HAVE_LIBLDAP 0
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `m' library (-lm). */
|
||||||
|
#define HAVE_LIBM 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `pam' library (-lpam). */
|
||||||
|
#define HAVE_LIBPAM 1
|
||||||
|
|
||||||
|
/* Define if you have a function readline library */
|
||||||
|
#define HAVE_LIBREADLINE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `selinux' library (-lselinux). */
|
||||||
|
/* #undef HAVE_LIBSELINUX */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `ssl' library (-lssl). */
|
||||||
|
#define HAVE_LIBSSL 0
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `wldap32' library (-lwldap32). */
|
||||||
|
/* #undef HAVE_LIBWLDAP32 */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `xml2' library (-lxml2). */
|
||||||
|
#define HAVE_LIBXML2 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `xslt' library (-lxslt). */
|
||||||
|
#define HAVE_LIBXSLT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `z' library (-lz). */
|
||||||
|
#define HAVE_LIBZ 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `zstd' library (-lzstd). */
|
||||||
|
/* #undef HAVE_LIBZSTD */
|
||||||
|
|
||||||
|
/* Define to 1 if constants of type 'long long int' should have the suffix LL.
|
||||||
|
*/
|
||||||
|
#define HAVE_LL_CONSTANTS 1
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `locale_t'. */
|
||||||
|
#define HAVE_LOCALE_T 1
|
||||||
|
|
||||||
|
/* Define to 1 if `long int' works and is 64 bits. */
|
||||||
|
/* #undef HAVE_LONG_INT_64 */
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `long long int'. */
|
||||||
|
#define HAVE_LONG_LONG_INT 1
|
||||||
|
|
||||||
|
/* Define to 1 if `long long int' works and is 64 bits. */
|
||||||
|
#define HAVE_LONG_LONG_INT_64 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <mbarrier.h> header file. */
|
||||||
|
/* #undef HAVE_MBARRIER_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `mbstowcs_l' function. */
|
||||||
|
/* #undef HAVE_MBSTOWCS_L */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memmove' function. */
|
||||||
|
#define HAVE_MEMMOVE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#define HAVE_MEMORY_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `MINIDUMP_TYPE'. */
|
||||||
|
/* #undef HAVE_MINIDUMP_TYPE */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `mkdtemp' function. */
|
||||||
|
#define HAVE_MKDTEMP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||||
|
#define HAVE_NETINET_IN_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
||||||
|
#define HAVE_NETINET_TCP_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <net/if.h> header file. */
|
||||||
|
#define HAVE_NET_IF_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ossp/uuid.h> header file. */
|
||||||
|
/* #undef HAVE_OSSP_UUID_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <pam/pam_appl.h> header file. */
|
||||||
|
/* #undef HAVE_PAM_PAM_APPL_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `poll' function. */
|
||||||
|
#define HAVE_POLL 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <poll.h> header file. */
|
||||||
|
#define HAVE_POLL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have a POSIX-conforming sigwait declaration. */
|
||||||
|
/* #undef HAVE_POSIX_DECL_SIGWAIT */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `posix_fadvise' function. */
|
||||||
|
#define HAVE_POSIX_FADVISE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `preadv', and to 0 if you don't. */
|
||||||
|
/* #undef HAVE_DECL_PREADV */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the declaration of `pwritev', and to 0 if you don't. */
|
||||||
|
/* #define HAVE_DECL_PWRITEV */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `X509_get_signature_info' function. */
|
||||||
|
/* #undef HAVE_X509_GET_SIGNATURE_INFO */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the POSIX signal interface. */
|
||||||
|
#define HAVE_POSIX_SIGNALS 1
|
||||||
|
|
||||||
|
/* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */
|
||||||
|
/* #undef HAVE_PPC_LWARX_MUTEX_HINT */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `pstat' function. */
|
||||||
|
/* #undef HAVE_PSTAT */
|
||||||
|
|
||||||
|
/* Define to 1 if the PS_STRINGS thing exists. */
|
||||||
|
/* #undef HAVE_PS_STRINGS */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `pthread_is_threaded_np' function. */
|
||||||
|
/* #undef HAVE_PTHREAD_IS_THREADED_NP */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <pwd.h> header file. */
|
||||||
|
#define HAVE_PWD_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <readline.h> header file. */
|
||||||
|
/* #undef HAVE_READLINE_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <readline/history.h> header file. */
|
||||||
|
#define HAVE_READLINE_HISTORY_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <readline/readline.h> header file. */
|
||||||
|
/* #undef HAVE_READLINE_READLINE_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `readlink' function. */
|
||||||
|
#define HAVE_READLINK 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `rint' function. */
|
||||||
|
#define HAVE_RINT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `rl_completion_matches' function. */
|
||||||
|
#define HAVE_RL_COMPLETION_MATCHES 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `rl_filename_completion_function' function. */
|
||||||
|
#define HAVE_RL_FILENAME_COMPLETION_FUNCTION 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `rl_reset_screen_size' function. */
|
||||||
|
/* #undef HAVE_RL_RESET_SCREEN_SIZE */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `rl_variable_bind' function. */
|
||||||
|
#define HAVE_RL_VARIABLE_BIND 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <security/pam_appl.h> header file. */
|
||||||
|
#define HAVE_SECURITY_PAM_APPL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `setproctitle' function. */
|
||||||
|
/* #undef HAVE_SETPROCTITLE */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `setsid' function. */
|
||||||
|
#define HAVE_SETSID 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `shm_open' function. */
|
||||||
|
#define HAVE_SHM_OPEN 1
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `socklen_t'. */
|
||||||
|
#define HAVE_SOCKLEN_T 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `sigprocmask' function. */
|
||||||
|
#define HAVE_SIGPROCMASK 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have sigsetjmp(). */
|
||||||
|
#define HAVE_SIGSETJMP 1
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `sig_atomic_t'. */
|
||||||
|
#define HAVE_SIG_ATOMIC_T 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `snprintf' function. */
|
||||||
|
#define HAVE_SNPRINTF 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have spinlocks. */
|
||||||
|
#define HAVE_SPINLOCKS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `SSL_CTX_set_num_tickets' function. */
|
||||||
|
/* #define HAVE_SSL_CTX_SET_NUM_TICKETS */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `SSL_get_current_compression' function. */
|
||||||
|
#define HAVE_SSL_GET_CURRENT_COMPRESSION 0
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#define HAVE_STDINT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#define HAVE_STDLIB_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strerror' function. */
|
||||||
|
#define HAVE_STRERROR 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strerror_r' function. */
|
||||||
|
#define HAVE_STRERROR_R 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
//#define HAVE_STRINGS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#define HAVE_STRING_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strlcat' function. */
|
||||||
|
/* #undef HAVE_STRLCAT */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strlcpy' function. */
|
||||||
|
/* #undef HAVE_STRLCPY */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strtoll' function. */
|
||||||
|
#define HAVE_STRTOLL 1
|
||||||
|
|
||||||
|
#if (!OS_DARWIN)
|
||||||
|
#define HAVE_STRCHRNUL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strtoq' function. */
|
||||||
|
/* #undef HAVE_STRTOQ */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strtoull' function. */
|
||||||
|
#define HAVE_STRTOULL 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strtouq' function. */
|
||||||
|
/* #undef HAVE_STRTOUQ */
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `struct addrinfo'. */
|
||||||
|
#define HAVE_STRUCT_ADDRINFO 1
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `struct cmsgcred'. */
|
||||||
|
/* #undef HAVE_STRUCT_CMSGCRED */
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `struct option'. */
|
||||||
|
#define HAVE_STRUCT_OPTION 1
|
||||||
|
|
||||||
|
/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
|
||||||
|
/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
|
||||||
|
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
|
||||||
|
|
||||||
|
/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
|
||||||
|
#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1
|
||||||
|
|
||||||
|
/* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */
|
||||||
|
/* #undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */
|
||||||
|
|
||||||
|
/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */
|
||||||
|
/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */
|
||||||
|
|
||||||
|
/* Define to 1 if `__ss_len' is a member of `struct sockaddr_storage'. */
|
||||||
|
/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN */
|
||||||
|
|
||||||
|
/* Define to 1 if `tm_zone' is a member of `struct tm'. */
|
||||||
|
#define HAVE_STRUCT_TM_TM_ZONE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `symlink' function. */
|
||||||
|
#define HAVE_SYMLINK 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `sync_file_range' function. */
|
||||||
|
/* #undef HAVE_SYNC_FILE_RANGE */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the syslog interface. */
|
||||||
|
#define HAVE_SYSLOG 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||||
|
#define HAVE_SYS_IOCTL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
||||||
|
#define HAVE_SYS_IPC_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/personality.h> header file. */
|
||||||
|
/* #undef HAVE_SYS_PERSONALITY_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/poll.h> header file. */
|
||||||
|
#define HAVE_SYS_POLL_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/pstat.h> header file. */
|
||||||
|
/* #undef HAVE_SYS_PSTAT_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/resource.h> header file. */
|
||||||
|
#define HAVE_SYS_RESOURCE_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||||
|
#define HAVE_SYS_SELECT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/sem.h> header file. */
|
||||||
|
#define HAVE_SYS_SEM_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/shm.h> header file. */
|
||||||
|
#define HAVE_SYS_SHM_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/signalfd.h> header file. */
|
||||||
|
/* #undef HAVE_SYS_SIGNALFD_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||||
|
#define HAVE_SYS_SOCKET_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/sockio.h> header file. */
|
||||||
|
/* #undef HAVE_SYS_SOCKIO_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#define HAVE_SYS_STAT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/tas.h> header file. */
|
||||||
|
/* #undef HAVE_SYS_TAS_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
|
#define HAVE_SYS_TIME_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#define HAVE_SYS_TYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ucred.h> header file. */
|
||||||
|
#if (OS_DARWIN || OS_FREEBSD)
|
||||||
|
#define HAVE_SYS_UCRED_H 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/un.h> header file. */
|
||||||
|
#define HAVE_SYS_UN_H 1
|
||||||
|
#define _GNU_SOURCE 1 /* Needed for glibc struct ucred */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <termios.h> header file. */
|
||||||
|
#define HAVE_TERMIOS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use
|
||||||
|
`HAVE_STRUCT_TM_TM_ZONE' instead. */
|
||||||
|
#define HAVE_TM_ZONE 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `towlower' function. */
|
||||||
|
#define HAVE_TOWLOWER 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the external array `tzname'. */
|
||||||
|
#define HAVE_TZNAME 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ucred.h> header file. */
|
||||||
|
/* #undef HAVE_UCRED_H */
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `uint64'. */
|
||||||
|
/* #undef HAVE_UINT64 */
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `uint8'. */
|
||||||
|
/* #undef HAVE_UINT8 */
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `uintptr_t'. */
|
||||||
|
#define HAVE_UINTPTR_T 1
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `union semun'. */
|
||||||
|
/* #undef HAVE_UNION_SEMUN */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#define HAVE_UNISTD_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have unix sockets. */
|
||||||
|
#define HAVE_UNIX_SOCKETS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `unsetenv' function. */
|
||||||
|
#define HAVE_UNSETENV 1
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `unsigned long long int'. */
|
||||||
|
#define HAVE_UNSIGNED_LONG_LONG_INT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `utime' function. */
|
||||||
|
#define HAVE_UTIME 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `utimes' function. */
|
||||||
|
#define HAVE_UTIMES 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <utime.h> header file. */
|
||||||
|
#define HAVE_UTIME_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have BSD UUID support. */
|
||||||
|
/* #undef HAVE_UUID_BSD */
|
||||||
|
|
||||||
|
/* Define to 1 if you have E2FS UUID support. */
|
||||||
|
/* #undef HAVE_UUID_E2FS */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <uuid.h> header file. */
|
||||||
|
#define HAVE_UUID_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have OSSP UUID support. */
|
||||||
|
#define HAVE_UUID_OSSP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <uuid/uuid.h> header file. */
|
||||||
|
/* #undef HAVE_UUID_UUID_H */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `vsnprintf' function. */
|
||||||
|
#define HAVE_VSNPRINTF 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <wchar.h> header file. */
|
||||||
|
#define HAVE_WCHAR_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `wcstombs' function. */
|
||||||
|
#define HAVE_WCSTOMBS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `wcstombs_l' function. */
|
||||||
|
/* #undef HAVE_WCSTOMBS_L */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <wctype.h> header file. */
|
||||||
|
#define HAVE_WCTYPE_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <winldap.h> header file. */
|
||||||
|
/* #undef HAVE_WINLDAP_H */
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands __builtin_bswap32. */
|
||||||
|
/* #undef HAVE__BUILTIN_BSWAP32 */
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands __builtin_constant_p. */
|
||||||
|
#define HAVE__BUILTIN_CONSTANT_P 1
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands __builtin_frame_address. */
|
||||||
|
/* #undef HAVE__BUILTIN_FRAME_ADDRESS */
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands __builtin_types_compatible_p. */
|
||||||
|
#define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands __builtin_unreachable. */
|
||||||
|
/* #undef HAVE__BUILTIN_UNREACHABLE */
|
||||||
|
|
||||||
|
/* Define to 1 if you have __cpuid. */
|
||||||
|
/* #undef HAVE__CPUID */
|
||||||
|
|
||||||
|
/* Define to 1 if you have __get_cpuid. */
|
||||||
|
/* #undef HAVE__GET_CPUID */
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands _Static_assert. */
|
||||||
|
/* #undef HAVE__STATIC_ASSERT */
|
||||||
|
|
||||||
|
/* Define to 1 if your compiler understands __VA_ARGS__ in macros. */
|
||||||
|
#define HAVE__VA_ARGS 1
|
||||||
|
|
||||||
|
/* Define to the appropriate snprintf length modifier for 64-bit ints. */
|
||||||
|
#define INT64_MODIFIER "ll"
|
||||||
|
|
||||||
|
/* Define to 1 if `locale_t' requires <xlocale.h>. */
|
||||||
|
/* #undef LOCALE_T_IN_XLOCALE */
|
||||||
|
|
||||||
|
/* Define as the maximum alignment requirement of any C data type. */
|
||||||
|
#define MAXIMUM_ALIGNOF 4
|
||||||
|
|
||||||
|
/* Define bytes to use libc memset(). */
|
||||||
|
#define MEMSET_LOOP_LIMIT 1024
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#define PACKAGE_BUGREPORT "pgsql-bugs@postgresql.org"
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#define PACKAGE_NAME "PostgreSQL"
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#define PACKAGE_STRING "PostgreSQL 9.5.4"
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#define PACKAGE_TARNAME "postgresql"
|
||||||
|
|
||||||
|
/* Define to the home page for this package. */
|
||||||
|
#define PACKAGE_URL ""
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#define PACKAGE_VERSION "9.5.4"
|
||||||
|
|
||||||
|
/* Define to the name of a signed 128-bit integer type. */
|
||||||
|
/* #undef PG_INT128_TYPE */
|
||||||
|
|
||||||
|
/* Define to the name of a signed 64-bit integer type. */
|
||||||
|
#define PG_INT64_TYPE long long int
|
||||||
|
|
||||||
|
/* Define to the name of the default PostgreSQL service principal in Kerberos
|
||||||
|
(GSSAPI). (--with-krb-srvnam=NAME) */
|
||||||
|
#define PG_KRB_SRVNAM "postgres"
|
||||||
|
|
||||||
|
/* PostgreSQL major version as a string */
|
||||||
|
#define PG_MAJORVERSION "9.5"
|
||||||
|
|
||||||
|
/* Define to gnu_printf if compiler supports it, else printf. */
|
||||||
|
#define PG_PRINTF_ATTRIBUTE printf
|
||||||
|
|
||||||
|
/* Define to 1 if "static inline" works without unwanted warnings from
|
||||||
|
compilations where static inline functions are defined but not called. */
|
||||||
|
#define PG_USE_INLINE 1
|
||||||
|
|
||||||
|
/* PostgreSQL version as a string */
|
||||||
|
#define PG_VERSION "9.5.4"
|
||||||
|
|
||||||
|
/* PostgreSQL version as a number */
|
||||||
|
#define PG_VERSION_NUM 90504
|
||||||
|
|
||||||
|
/* A string containing the version number, platform, and C compiler */
|
||||||
|
#define PG_VERSION_STR "PostgreSQL 9.5.4 on i686-pc-linux-gnu, compiled by gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-55), 32-bit"
|
||||||
|
|
||||||
|
/* Define to 1 to allow profiling output to be saved separately for each
|
||||||
|
process. */
|
||||||
|
/* #undef PROFILE_PID_DIR */
|
||||||
|
|
||||||
|
/* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus,
|
||||||
|
the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger
|
||||||
|
than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be
|
||||||
|
less than your OS' limit on file size. This is often 2 GB or 4GB in a
|
||||||
|
32-bit operating system, unless you have large file support enabled. By
|
||||||
|
default, we make the limit 1 GB to avoid any possible integer-overflow
|
||||||
|
problems within the OS. A limit smaller than necessary only means we divide
|
||||||
|
a large relation into more chunks than necessary, so it seems best to err
|
||||||
|
in the direction of a small limit. A power-of-2 value is recommended to
|
||||||
|
save a few cycles in md.c, but is not absolutely required. Changing
|
||||||
|
RELSEG_SIZE requires an initdb. */
|
||||||
|
#define RELSEG_SIZE 131072
|
||||||
|
|
||||||
|
/* The size of `long', as computed by sizeof. */
|
||||||
|
#define SIZEOF_LONG 4
|
||||||
|
|
||||||
|
/* The size of `off_t', as computed by sizeof. */
|
||||||
|
#define SIZEOF_OFF_T 8
|
||||||
|
|
||||||
|
/* The size of `size_t', as computed by sizeof. */
|
||||||
|
#define SIZEOF_SIZE_T 4
|
||||||
|
|
||||||
|
/* The size of `void *', as computed by sizeof. */
|
||||||
|
#define SIZEOF_VOID_P 4
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#define STDC_HEADERS 1
|
||||||
|
|
||||||
|
/* Define to 1 if strerror_r() returns a int. */
|
||||||
|
/* #undef STRERROR_R_INT */
|
||||||
|
|
||||||
|
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
|
||||||
|
/* #undef TM_IN_SYS_TIME */
|
||||||
|
|
||||||
|
/* Define to 1 to build with assertion checks. (--enable-cassert) */
|
||||||
|
/* #undef USE_ASSERT_CHECKING */
|
||||||
|
|
||||||
|
/* Define to 1 to build with Bonjour support. (--with-bonjour) */
|
||||||
|
/* #undef USE_BONJOUR */
|
||||||
|
|
||||||
|
/* Define to 1 if you want float4 values to be passed by value.
|
||||||
|
(--enable-float4-byval) */
|
||||||
|
#define USE_FLOAT4_BYVAL 1
|
||||||
|
|
||||||
|
/* Define to 1 if you want float8, int8, etc values to be passed by value.
|
||||||
|
(--enable-float8-byval) */
|
||||||
|
/* #undef USE_FLOAT8_BYVAL */
|
||||||
|
|
||||||
|
/* Define to 1 if you want 64-bit integer timestamp and interval support.
|
||||||
|
(--enable-integer-datetimes) */
|
||||||
|
#define USE_INTEGER_DATETIMES 1
|
||||||
|
|
||||||
|
/* Define to 1 to build with LDAP support. (--with-ldap) */
|
||||||
|
//#define USE_LDAP 0
|
||||||
|
|
||||||
|
/* Define to 1 to build with XML support. (--with-libxml) */
|
||||||
|
#define USE_LIBXML 1
|
||||||
|
|
||||||
|
/* Define to 1 to use XSLT support when building contrib/xml2.
|
||||||
|
(--with-libxslt) */
|
||||||
|
#define USE_LIBXSLT 1
|
||||||
|
|
||||||
|
/* Define to select named POSIX semaphores. */
|
||||||
|
/* #undef USE_NAMED_POSIX_SEMAPHORES */
|
||||||
|
|
||||||
|
/* Define to build with OpenSSL support. (--with-openssl) */
|
||||||
|
#define USE_OPENSSL 0
|
||||||
|
|
||||||
|
#define USE_OPENSSL_RANDOM 0
|
||||||
|
|
||||||
|
#define FRONTEND 1
|
||||||
|
|
||||||
|
/* Define to 1 to build with PAM support. (--with-pam) */
|
||||||
|
#define USE_PAM 1
|
||||||
|
|
||||||
|
/* Use replacement snprintf() functions. */
|
||||||
|
/* #undef USE_REPL_SNPRINTF */
|
||||||
|
|
||||||
|
/* Define to 1 to use Intel SSE 4.2 CRC instructions with a runtime check. */
|
||||||
|
#define USE_SLICING_BY_8_CRC32C 1
|
||||||
|
|
||||||
|
/* Define to 1 use Intel SSE 4.2 CRC instructions. */
|
||||||
|
/* #undef USE_SSE42_CRC32C */
|
||||||
|
|
||||||
|
/* Define to 1 to use Intel SSSE 4.2 CRC instructions with a runtime check. */
|
||||||
|
/* #undef USE_SSE42_CRC32C_WITH_RUNTIME_CHECK */
|
||||||
|
|
||||||
|
/* Define to select SysV-style semaphores. */
|
||||||
|
#define USE_SYSV_SEMAPHORES 1
|
||||||
|
|
||||||
|
/* Define to select SysV-style shared memory. */
|
||||||
|
#define USE_SYSV_SHARED_MEMORY 1
|
||||||
|
|
||||||
|
/* Define to select unnamed POSIX semaphores. */
|
||||||
|
/* #undef USE_UNNAMED_POSIX_SEMAPHORES */
|
||||||
|
|
||||||
|
/* Define to select Win32-style semaphores. */
|
||||||
|
/* #undef USE_WIN32_SEMAPHORES */
|
||||||
|
|
||||||
|
/* Define to select Win32-style shared memory. */
|
||||||
|
/* #undef USE_WIN32_SHARED_MEMORY */
|
||||||
|
|
||||||
|
/* Define to 1 to build with ZSTD support. (--with-zstd) */
|
||||||
|
/* #undef USE_ZSTD */
|
||||||
|
|
||||||
|
/* Define to 1 if `wcstombs_l' requires <xlocale.h>. */
|
||||||
|
/* #undef WCSTOMBS_L_IN_XLOCALE */
|
||||||
|
|
||||||
|
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||||
|
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||||
|
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||||
|
# if defined __BIG_ENDIAN__
|
||||||
|
# define WORDS_BIGENDIAN 1
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# ifndef WORDS_BIGENDIAN
|
||||||
|
/* # undef WORDS_BIGENDIAN */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Size of a WAL file block. This need have no particular relation to BLCKSZ.
|
||||||
|
XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O,
|
||||||
|
XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O
|
||||||
|
buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb.
|
||||||
|
*/
|
||||||
|
#define XLOG_BLCKSZ 8192
|
||||||
|
|
||||||
|
/* XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2
|
||||||
|
and larger than XLOG_BLCKSZ (preferably, a great deal larger than
|
||||||
|
XLOG_BLCKSZ). Changing XLOG_SEG_SIZE requires an initdb. */
|
||||||
|
#define XLOG_SEG_SIZE (16 * 1024 * 1024)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
|
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
|
||||||
|
/* #undef _LARGEFILE_SOURCE */
|
||||||
|
|
||||||
|
/* Define for large files, on AIX-style hosts. */
|
||||||
|
/* #undef _LARGE_FILES */
|
||||||
|
|
||||||
|
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||||
|
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||||
|
#ifndef __cplusplus
|
||||||
|
/* #undef inline */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to the type of a signed integer type wide enough to hold a pointer,
|
||||||
|
if such a type exists, and if the system does not define it. */
|
||||||
|
/* #undef intptr_t */
|
||||||
|
|
||||||
|
/* Define to empty if the C compiler does not understand signed types. */
|
||||||
|
/* #undef signed */
|
||||||
|
|
||||||
|
/* Define to the type of an unsigned integer type wide enough to hold a
|
||||||
|
pointer, if such a type exists, and if the system does not define it. */
|
||||||
|
/* #undef uintptr_t */
|
7
contrib/postgres-cmake/pg_config_ext.h
Normal file
7
contrib/postgres-cmake/pg_config_ext.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* * src/include/pg_config_ext.h.in. This is generated manually, not by
|
||||||
|
* * autoheader, since we want to limit which symbols get defined here.
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* Define to the name of a signed 64-bit integer type. */
|
||||||
|
#define PG_INT64_TYPE long long int
|
34
contrib/postgres-cmake/pg_config_os.h
Normal file
34
contrib/postgres-cmake/pg_config_os.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#if defined(OS_DARWIN)
|
||||||
|
|
||||||
|
/* src/include/port/darwin.h */
|
||||||
|
#define __darwin__ 1
|
||||||
|
|
||||||
|
#if HAVE_DECL_F_FULLFSYNC /* not present before macOS 10.3 */
|
||||||
|
#define HAVE_FSYNC_WRITETHROUGH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
/* src/include/port/linux.h */
|
||||||
|
/*
|
||||||
|
* As of July 2007, all known versions of the Linux kernel will sometimes
|
||||||
|
* return EIDRM for a shmctl() operation when EINVAL is correct (it happens
|
||||||
|
* when the low-order 15 bits of the supplied shm ID match the slot number
|
||||||
|
* assigned to a newer shmem segment). We deal with this by assuming that
|
||||||
|
* EIDRM means EINVAL in PGSharedMemoryIsInUse(). This is reasonably safe
|
||||||
|
* since in fact Linux has no excuse for ever returning EIDRM; it doesn't
|
||||||
|
* track removed segments in a way that would allow distinguishing them from
|
||||||
|
* private ones. But someday that code might get upgraded, and we'd have
|
||||||
|
* to have a kernel version test here.
|
||||||
|
*/
|
||||||
|
#define HAVE_LINUX_EIDRM_BUG
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the default wal_sync_method to fdatasync. With recent Linux versions,
|
||||||
|
* xlogdefs.h's normal rules will prefer open_datasync, which (a) doesn't
|
||||||
|
* perform better and (b) causes outright failures on ext4 data=journal
|
||||||
|
* filesystems, because those don't support O_DIRECT.
|
||||||
|
*/
|
||||||
|
#define PLATFORM_DEFAULT_SYNC_METHOD SYNC_METHOD_FDATASYNC
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
12
contrib/postgres-cmake/pg_config_paths.h
Normal file
12
contrib/postgres-cmake/pg_config_paths.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#define PGBINDIR "/bin"
|
||||||
|
#define PGSHAREDIR "/share"
|
||||||
|
#define SYSCONFDIR "/etc"
|
||||||
|
#define INCLUDEDIR "/include"
|
||||||
|
#define PKGINCLUDEDIR "/include"
|
||||||
|
#define INCLUDEDIRSERVER "/include/server"
|
||||||
|
#define LIBDIR "/lib"
|
||||||
|
#define PKGLIBDIR "/lib"
|
||||||
|
#define LOCALEDIR "/share/locale"
|
||||||
|
#define DOCDIR "/doc"
|
||||||
|
#define HTMLDIR "/doc"
|
||||||
|
#define MANDIR "/man"
|
0
contrib/postgres-cmake/utils/errcodes.h
Normal file
0
contrib/postgres-cmake/utils/errcodes.h
Normal file
@ -109,7 +109,7 @@ if [ -n "$CLICKHOUSE_USER" ] && [ "$CLICKHOUSE_USER" != "default" ] || [ -n "$CL
|
|||||||
<networks>
|
<networks>
|
||||||
<ip>::/0</ip>
|
<ip>::/0</ip>
|
||||||
</networks>
|
</networks>
|
||||||
<password>${CLICKHOUSE_PASSWORD}</password>
|
<password><![CDATA[${CLICKHOUSE_PASSWORD//]]>/]]]]><![CDATA[>}]]></password>
|
||||||
<quota>default</quota>
|
<quota>default</quota>
|
||||||
<access_management>${CLICKHOUSE_ACCESS_MANAGEMENT}</access_management>
|
<access_management>${CLICKHOUSE_ACCESS_MANAGEMENT}</access_management>
|
||||||
</${CLICKHOUSE_USER}>
|
</${CLICKHOUSE_USER}>
|
||||||
|
@ -13,16 +13,17 @@ Here is a complete list of available database engines. Follow the links for more
|
|||||||
|
|
||||||
- [Atomic](../../engines/database-engines/atomic.md)
|
- [Atomic](../../engines/database-engines/atomic.md)
|
||||||
|
|
||||||
- [MySQL](../../engines/database-engines/mysql.md)
|
- [Lazy](../../engines/database-engines/lazy.md)
|
||||||
|
|
||||||
|
- [MaterializedPostgreSQL](../../engines/database-engines/materialized-postgresql.md)
|
||||||
|
|
||||||
- [MaterializedMySQL](../../engines/database-engines/materialized-mysql.md)
|
- [MaterializedMySQL](../../engines/database-engines/materialized-mysql.md)
|
||||||
|
|
||||||
- [Lazy](../../engines/database-engines/lazy.md)
|
- [MySQL](../../engines/database-engines/mysql.md)
|
||||||
|
|
||||||
- [PostgreSQL](../../engines/database-engines/postgresql.md)
|
- [PostgreSQL](../../engines/database-engines/postgresql.md)
|
||||||
|
|
||||||
- [MaterializedPostgreSQL](../../engines/database-engines/materialized-postgresql.md)
|
|
||||||
|
|
||||||
- [Replicated](../../engines/database-engines/replicated.md)
|
- [Replicated](../../engines/database-engines/replicated.md)
|
||||||
|
|
||||||
- [SQLite](../../engines/database-engines/sqlite.md)
|
- [SQLite](../../engines/database-engines/sqlite.md)
|
||||||
|
|
||||||
|
@ -155,6 +155,12 @@ Replication of [**TOAST**](https://www.postgresql.org/docs/9.5/storage-toast.htm
|
|||||||
|
|
||||||
Sets a comma-separated list of PostgreSQL database tables, which will be replicated via [MaterializedPostgreSQL](../../engines/database-engines/materialized-postgresql.md) database engine.
|
Sets a comma-separated list of PostgreSQL database tables, which will be replicated via [MaterializedPostgreSQL](../../engines/database-engines/materialized-postgresql.md) database engine.
|
||||||
|
|
||||||
|
Each table can have subset of replicated columns in brackets. If subset of columns is omitted, then all columns for table will be replicated.
|
||||||
|
|
||||||
|
``` sql
|
||||||
|
materialized_postgresql_tables_list = 'table1(co1, col2),table2,table3(co3, col5, col7)
|
||||||
|
```
|
||||||
|
|
||||||
Default value: empty list — means whole PostgreSQL database will be replicated.
|
Default value: empty list — means whole PostgreSQL database will be replicated.
|
||||||
|
|
||||||
### `materialized_postgresql_schema` {#materialized-postgresql-schema}
|
### `materialized_postgresql_schema` {#materialized-postgresql-schema}
|
||||||
|
@ -167,7 +167,7 @@ If you want to change the target table by using `ALTER`, we recommend disabling
|
|||||||
|
|
||||||
- `_subject` - NATS message subject. Data type: `String`.
|
- `_subject` - NATS message subject. Data type: `String`.
|
||||||
|
|
||||||
Additional virtual columns when `kafka_handle_error_mode='stream'`:
|
Additional virtual columns when `nats_handle_error_mode='stream'`:
|
||||||
|
|
||||||
- `_raw_message` - Raw message that couldn't be parsed successfully. Data type: `Nullable(String)`.
|
- `_raw_message` - Raw message that couldn't be parsed successfully. Data type: `Nullable(String)`.
|
||||||
- `_error` - Exception message happened during failed parsing. Data type: `Nullable(String)`.
|
- `_error` - Exception message happened during failed parsing. Data type: `Nullable(String)`.
|
||||||
|
@ -107,6 +107,10 @@ The vector similarity index currently does not work with per-table, non-default
|
|||||||
[here](https://github.com/ClickHouse/ClickHouse/pull/51325#issuecomment-1605920475)). If necessary, the value must be changed in config.xml.
|
[here](https://github.com/ClickHouse/ClickHouse/pull/51325#issuecomment-1605920475)). If necessary, the value must be changed in config.xml.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
Vector index creation is known to be slow. To speed the process up, index creation can be parallelized. The maximum number of threads can be
|
||||||
|
configured using server configuration
|
||||||
|
setting [max_build_vector_similarity_index_thread_pool_size](../../../operations/server-configuration-parameters/settings.md#server_configuration_parameters_max_build_vector_similarity_index_thread_pool_size).
|
||||||
|
|
||||||
ANN indexes are built during column insertion and merge. As a result, `INSERT` and `OPTIMIZE` statements will be slower than for ordinary
|
ANN indexes are built during column insertion and merge. As a result, `INSERT` and `OPTIMIZE` statements will be slower than for ordinary
|
||||||
tables. ANNIndexes are ideally used only with immutable or rarely changed data, respectively when are far more read requests than write
|
tables. ANNIndexes are ideally used only with immutable or rarely changed data, respectively when are far more read requests than write
|
||||||
requests.
|
requests.
|
||||||
|
@ -97,7 +97,7 @@ If you want to change the target table by using `ALTER`, we recommend disabling
|
|||||||
- `_filename` - Name of the log file. Data type: `LowCardinality(String)`.
|
- `_filename` - Name of the log file. Data type: `LowCardinality(String)`.
|
||||||
- `_offset` - Offset in the log file. Data type: `UInt64`.
|
- `_offset` - Offset in the log file. Data type: `UInt64`.
|
||||||
|
|
||||||
Additional virtual columns when `kafka_handle_error_mode='stream'`:
|
Additional virtual columns when `handle_error_mode='stream'`:
|
||||||
|
|
||||||
- `_raw_record` - Raw record that couldn't be parsed successfully. Data type: `Nullable(String)`.
|
- `_raw_record` - Raw record that couldn't be parsed successfully. Data type: `Nullable(String)`.
|
||||||
- `_error` - Exception message happened during failed parsing. Data type: `Nullable(String)`.
|
- `_error` - Exception message happened during failed parsing. Data type: `Nullable(String)`.
|
||||||
|
@ -826,17 +826,17 @@ Result:
|
|||||||
|
|
||||||
## JSONAsObject {#jsonasobject}
|
## JSONAsObject {#jsonasobject}
|
||||||
|
|
||||||
In this format, a single JSON object is interpreted as a single [Object('json')](/docs/en/sql-reference/data-types/json.md) value. If the input has several JSON objects (comma separated), they are interpreted as separate rows. If the input data is enclosed in square brackets, it is interpreted as an array of JSONs.
|
In this format, a single JSON object is interpreted as a single [JSON](/docs/en/sql-reference/data-types/newjson.md) value. If the input has several JSON objects (comma separated), they are interpreted as separate rows. If the input data is enclosed in square brackets, it is interpreted as an array of JSONs.
|
||||||
|
|
||||||
This format can only be parsed for a table with a single field of type [Object('json')](/docs/en/sql-reference/data-types/json.md). The remaining columns must be set to [DEFAULT](/docs/en/sql-reference/statements/create/table.md/#default) or [MATERIALIZED](/docs/en/sql-reference/statements/create/table.md/#materialized).
|
This format can only be parsed for a table with a single field of type [JSON](/docs/en/sql-reference/data-types/newjson.md). The remaining columns must be set to [DEFAULT](/docs/en/sql-reference/statements/create/table.md/#default) or [MATERIALIZED](/docs/en/sql-reference/statements/create/table.md/#materialized).
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
|
|
||||||
Query:
|
Query:
|
||||||
|
|
||||||
``` sql
|
``` sql
|
||||||
SET allow_experimental_object_type = 1;
|
SET allow_experimental_json_type = 1;
|
||||||
CREATE TABLE json_as_object (json Object('json')) ENGINE = Memory;
|
CREATE TABLE json_as_object (json JSON) ENGINE = Memory;
|
||||||
INSERT INTO json_as_object (json) FORMAT JSONAsObject {"foo":{"bar":{"x":"y"},"baz":1}},{},{"any json stucture":1}
|
INSERT INTO json_as_object (json) FORMAT JSONAsObject {"foo":{"bar":{"x":"y"},"baz":1}},{},{"any json stucture":1}
|
||||||
SELECT * FROM json_as_object FORMAT JSONEachRow;
|
SELECT * FROM json_as_object FORMAT JSONEachRow;
|
||||||
```
|
```
|
||||||
@ -844,9 +844,9 @@ SELECT * FROM json_as_object FORMAT JSONEachRow;
|
|||||||
Result:
|
Result:
|
||||||
|
|
||||||
``` response
|
``` response
|
||||||
{"json":{"any json stucture":0,"foo":{"bar":{"x":"y"},"baz":1}}}
|
{"json":{"foo":{"bar":{"x":"y"},"baz":"1"}}}
|
||||||
{"json":{"any json stucture":0,"foo":{"bar":{"x":""},"baz":0}}}
|
{"json":{}}
|
||||||
{"json":{"any json stucture":1,"foo":{"bar":{"x":""},"baz":0}}}
|
{"json":{"any json stucture":"1"}}
|
||||||
```
|
```
|
||||||
|
|
||||||
**An array of JSON objects**
|
**An array of JSON objects**
|
||||||
@ -854,35 +854,34 @@ Result:
|
|||||||
Query:
|
Query:
|
||||||
|
|
||||||
``` sql
|
``` sql
|
||||||
SET allow_experimental_object_type = 1;
|
SET allow_experimental_json_type = 1;
|
||||||
CREATE TABLE json_square_brackets (field Object('json')) ENGINE = Memory;
|
CREATE TABLE json_square_brackets (field JSON) ENGINE = Memory;
|
||||||
INSERT INTO json_square_brackets FORMAT JSONAsObject [{"id": 1, "name": "name1"}, {"id": 2, "name": "name2"}];
|
INSERT INTO json_square_brackets FORMAT JSONAsObject [{"id": 1, "name": "name1"}, {"id": 2, "name": "name2"}];
|
||||||
|
|
||||||
SELECT * FROM json_square_brackets FORMAT JSONEachRow;
|
SELECT * FROM json_square_brackets FORMAT JSONEachRow;
|
||||||
```
|
```
|
||||||
|
|
||||||
Result:
|
Result:
|
||||||
|
|
||||||
```response
|
```response
|
||||||
{"field":{"id":1,"name":"name1"}}
|
{"field":{"id":"1","name":"name1"}}
|
||||||
{"field":{"id":2,"name":"name2"}}
|
{"field":{"id":"2","name":"name2"}}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Columns with default values**
|
**Columns with default values**
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
SET allow_experimental_object_type = 1;
|
SET allow_experimental_json_type = 1;
|
||||||
CREATE TABLE json_as_object (json Object('json'), time DateTime MATERIALIZED now()) ENGINE = Memory;
|
CREATE TABLE json_as_object (json JSON, time DateTime MATERIALIZED now()) ENGINE = Memory;
|
||||||
INSERT INTO json_as_object (json) FORMAT JSONAsObject {"foo":{"bar":{"x":"y"},"baz":1}};
|
INSERT INTO json_as_object (json) FORMAT JSONAsObject {"foo":{"bar":{"x":"y"},"baz":1}};
|
||||||
INSERT INTO json_as_object (json) FORMAT JSONAsObject {};
|
INSERT INTO json_as_object (json) FORMAT JSONAsObject {};
|
||||||
INSERT INTO json_as_object (json) FORMAT JSONAsObject {"any json stucture":1}
|
INSERT INTO json_as_object (json) FORMAT JSONAsObject {"any json stucture":1}
|
||||||
SELECT * FROM json_as_object FORMAT JSONEachRow
|
SELECT time, json FROM json_as_object FORMAT JSONEachRow
|
||||||
```
|
```
|
||||||
|
|
||||||
```resonse
|
```resonse
|
||||||
{"json":{"any json stucture":0,"foo":{"bar":{"x":"y"},"baz":1}},"time":"2024-07-25 17:02:45"}
|
{"time":"2024-09-16 12:18:10","json":{}}
|
||||||
{"json":{"any json stucture":0,"foo":{"bar":{"x":""},"baz":0}},"time":"2024-07-25 17:02:47"}
|
{"time":"2024-09-16 12:18:13","json":{"any json stucture":"1"}}
|
||||||
{"json":{"any json stucture":1,"foo":{"bar":{"x":""},"baz":0}},"time":"2024-07-25 17:02:50"}
|
{"time":"2024-09-16 12:18:08","json":{"foo":{"bar":{"x":"y"},"baz":"1"}}}
|
||||||
```
|
```
|
||||||
|
|
||||||
## JSONCompact {#jsoncompact}
|
## JSONCompact {#jsoncompact}
|
||||||
@ -1396,6 +1395,7 @@ SELECT * FROM json_each_row_nested
|
|||||||
- [input_format_json_ignore_unknown_keys_in_named_tuple](/docs/en/operations/settings/settings-formats.md/#input_format_json_ignore_unknown_keys_in_named_tuple) - ignore unknown keys in json object for named tuples. Default value - `false`.
|
- [input_format_json_ignore_unknown_keys_in_named_tuple](/docs/en/operations/settings/settings-formats.md/#input_format_json_ignore_unknown_keys_in_named_tuple) - ignore unknown keys in json object for named tuples. Default value - `false`.
|
||||||
- [input_format_json_compact_allow_variable_number_of_columns](/docs/en/operations/settings/settings-formats.md/#input_format_json_compact_allow_variable_number_of_columns) - allow variable number of columns in JSONCompact/JSONCompactEachRow format, ignore extra columns and use default values on missing columns. Default value - `false`.
|
- [input_format_json_compact_allow_variable_number_of_columns](/docs/en/operations/settings/settings-formats.md/#input_format_json_compact_allow_variable_number_of_columns) - allow variable number of columns in JSONCompact/JSONCompactEachRow format, ignore extra columns and use default values on missing columns. Default value - `false`.
|
||||||
- [input_format_json_throw_on_bad_escape_sequence](/docs/en/operations/settings/settings-formats.md/#input_format_json_throw_on_bad_escape_sequence) - throw an exception if JSON string contains bad escape sequence. If disabled, bad escape sequences will remain as is in the data. Default value - `true`.
|
- [input_format_json_throw_on_bad_escape_sequence](/docs/en/operations/settings/settings-formats.md/#input_format_json_throw_on_bad_escape_sequence) - throw an exception if JSON string contains bad escape sequence. If disabled, bad escape sequences will remain as is in the data. Default value - `true`.
|
||||||
|
- [input_format_json_empty_as_default](/docs/en/operations/settings/settings-formats.md/#input_format_json_empty_as_default) - treat empty fields in JSON input as default values. Default value - `false`. For complex default expressions [input_format_defaults_for_omitted_fields](/docs/en/operations/settings/settings-formats.md/#input_format_defaults_for_omitted_fields) must be enabled too.
|
||||||
- [output_format_json_quote_64bit_integers](/docs/en/operations/settings/settings-formats.md/#output_format_json_quote_64bit_integers) - controls quoting of 64-bit integers in JSON output format. Default value - `true`.
|
- [output_format_json_quote_64bit_integers](/docs/en/operations/settings/settings-formats.md/#output_format_json_quote_64bit_integers) - controls quoting of 64-bit integers in JSON output format. Default value - `true`.
|
||||||
- [output_format_json_quote_64bit_floats](/docs/en/operations/settings/settings-formats.md/#output_format_json_quote_64bit_floats) - controls quoting of 64-bit floats in JSON output format. Default value - `false`.
|
- [output_format_json_quote_64bit_floats](/docs/en/operations/settings/settings-formats.md/#output_format_json_quote_64bit_floats) - controls quoting of 64-bit floats in JSON output format. Default value - `false`.
|
||||||
- [output_format_json_quote_denormals](/docs/en/operations/settings/settings-formats.md/#output_format_json_quote_denormals) - enables '+nan', '-nan', '+inf', '-inf' outputs in JSON output format. Default value - `false`.
|
- [output_format_json_quote_denormals](/docs/en/operations/settings/settings-formats.md/#output_format_json_quote_denormals) - enables '+nan', '-nan', '+inf', '-inf' outputs in JSON output format. Default value - `false`.
|
||||||
|
@ -491,6 +491,14 @@ Type: Double
|
|||||||
|
|
||||||
Default: 0.9
|
Default: 0.9
|
||||||
|
|
||||||
|
## max_build_vector_similarity_index_thread_pool_size {#server_configuration_parameters_max_build_vector_similarity_index_thread_pool_size}
|
||||||
|
|
||||||
|
The maximum number of threads to use for building vector indexes. 0 means all cores.
|
||||||
|
|
||||||
|
Type: UInt64
|
||||||
|
|
||||||
|
Default: 16
|
||||||
|
|
||||||
## cgroups_memory_usage_observer_wait_time
|
## cgroups_memory_usage_observer_wait_time
|
||||||
|
|
||||||
Interval in seconds during which the server's maximum allowed memory consumption is adjusted by the corresponding threshold in cgroups. (see
|
Interval in seconds during which the server's maximum allowed memory consumption is adjusted by the corresponding threshold in cgroups. (see
|
||||||
@ -3142,3 +3150,15 @@ Default value: "default"
|
|||||||
|
|
||||||
**See Also**
|
**See Also**
|
||||||
- [Workload Scheduling](/docs/en/operations/workload-scheduling.md)
|
- [Workload Scheduling](/docs/en/operations/workload-scheduling.md)
|
||||||
|
|
||||||
|
## max_authentication_methods_per_user {#max_authentication_methods_per_user}
|
||||||
|
|
||||||
|
The maximum number of authentication methods a user can be created with or altered to.
|
||||||
|
Changing this setting does not affect existing users. Create/alter authentication-related queries will fail if they exceed the limit specified in this setting.
|
||||||
|
Non authentication create/alter queries will succeed.
|
||||||
|
|
||||||
|
Type: UInt64
|
||||||
|
|
||||||
|
Default value: 100
|
||||||
|
|
||||||
|
Zero means unlimited
|
||||||
|
@ -752,6 +752,17 @@ Possible values:
|
|||||||
|
|
||||||
Default value: 0.
|
Default value: 0.
|
||||||
|
|
||||||
|
### input_format_json_empty_as_default {#input_format_json_empty_as_default}
|
||||||
|
|
||||||
|
When enabled, replace empty input fields in JSON with default values. For complex default expressions `input_format_defaults_for_omitted_fields` must be enabled too.
|
||||||
|
|
||||||
|
Possible values:
|
||||||
|
|
||||||
|
+ 0 — Disable.
|
||||||
|
+ 1 — Enable.
|
||||||
|
|
||||||
|
Default value: 0.
|
||||||
|
|
||||||
## TSV format settings {#tsv-format-settings}
|
## TSV format settings {#tsv-format-settings}
|
||||||
|
|
||||||
### input_format_tsv_empty_as_default {#input_format_tsv_empty_as_default}
|
### input_format_tsv_empty_as_default {#input_format_tsv_empty_as_default}
|
||||||
|
@ -9,7 +9,7 @@ Computes an approximate [quantile](https://en.wikipedia.org/wiki/Quantile) of a
|
|||||||
**Syntax**
|
**Syntax**
|
||||||
|
|
||||||
``` sql
|
``` sql
|
||||||
quantileDDsketch[relative_accuracy, (level)](expr)
|
quantileDD(relative_accuracy, [level])(expr)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Arguments**
|
**Arguments**
|
||||||
|
@ -12,9 +12,10 @@ Syntax:
|
|||||||
``` sql
|
``` sql
|
||||||
ALTER USER [IF EXISTS] name1 [ON CLUSTER cluster_name1] [RENAME TO new_name1]
|
ALTER USER [IF EXISTS] name1 [ON CLUSTER cluster_name1] [RENAME TO new_name1]
|
||||||
[, name2 [ON CLUSTER cluster_name2] [RENAME TO new_name2] ...]
|
[, name2 [ON CLUSTER cluster_name2] [RENAME TO new_name2] ...]
|
||||||
[NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']} | {WITH ssl_certificate CN 'common_name' | SAN 'TYPE:subject_alt_name'}]
|
[NOT IDENTIFIED | IDENTIFIED | ADD IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']} | {WITH ssl_certificate CN 'common_name' | SAN 'TYPE:subject_alt_name'}]
|
||||||
[[ADD | DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
|
[[ADD | DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
|
||||||
[VALID UNTIL datetime]
|
[VALID UNTIL datetime]
|
||||||
|
[RESET AUTHENTICATION METHODS TO NEW]
|
||||||
[DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]
|
[DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]
|
||||||
[GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
|
[GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
|
||||||
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY | WRITABLE] | PROFILE 'profile_name'] [,...]
|
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY | WRITABLE] | PROFILE 'profile_name'] [,...]
|
||||||
@ -62,3 +63,31 @@ Allows the user with `john` account to grant his privileges to the user with `ja
|
|||||||
``` sql
|
``` sql
|
||||||
ALTER USER john GRANTEES jack;
|
ALTER USER john GRANTEES jack;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Adds new authentication methods to the user while keeping the existing ones:
|
||||||
|
|
||||||
|
``` sql
|
||||||
|
ALTER USER user1 ADD IDENTIFIED WITH plaintext_password by '1', bcrypt_password by '2', plaintext_password by '3'
|
||||||
|
```
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
1. Older versions of ClickHouse might not support the syntax of multiple authentication methods. Therefore, if the ClickHouse server contains such users and is downgraded to a version that does not support it, such users will become unusable and some user related operations will be broken. In order to downgrade gracefully, one must set all users to contain a single authentication method prior to downgrading. Alternatively, if the server was downgraded without the proper procedure, the faulty users should be dropped.
|
||||||
|
2. `no_password` can not co-exist with other authentication methods for security reasons.
|
||||||
|
Because of that, it is not possible to `ADD` a `no_password` authentication method. The below query will throw an error:
|
||||||
|
|
||||||
|
``` sql
|
||||||
|
ALTER USER user1 ADD IDENTIFIED WITH no_password
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to drop authentication methods for a user and rely on `no_password`, you must specify in the below replacing form.
|
||||||
|
|
||||||
|
Reset authentication methods and adds the ones specified in the query (effect of leading IDENTIFIED without the ADD keyword):
|
||||||
|
|
||||||
|
``` sql
|
||||||
|
ALTER USER user1 IDENTIFIED WITH plaintext_password by '1', bcrypt_password by '2', plaintext_password by '3'
|
||||||
|
```
|
||||||
|
|
||||||
|
Reset authentication methods and keep the most recent added one:
|
||||||
|
``` sql
|
||||||
|
ALTER USER user1 RESET AUTHENTICATION METHODS TO NEW
|
||||||
|
```
|
||||||
|
@ -15,6 +15,7 @@ CREATE USER [IF NOT EXISTS | OR REPLACE] name1 [ON CLUSTER cluster_name1]
|
|||||||
[NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']} | {WITH ssl_certificate CN 'common_name' | SAN 'TYPE:subject_alt_name'} | {WITH ssh_key BY KEY 'public_key' TYPE 'ssh-rsa|...'} | {WITH http SERVER 'server_name' [SCHEME 'Basic']}]
|
[NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']} | {WITH ssl_certificate CN 'common_name' | SAN 'TYPE:subject_alt_name'} | {WITH ssh_key BY KEY 'public_key' TYPE 'ssh-rsa|...'} | {WITH http SERVER 'server_name' [SCHEME 'Basic']}]
|
||||||
[HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
|
[HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
|
||||||
[VALID UNTIL datetime]
|
[VALID UNTIL datetime]
|
||||||
|
[RESET AUTHENTICATION METHODS TO NEW]
|
||||||
[IN access_storage_type]
|
[IN access_storage_type]
|
||||||
[DEFAULT ROLE role [,...]]
|
[DEFAULT ROLE role [,...]]
|
||||||
[DEFAULT DATABASE database | NONE]
|
[DEFAULT DATABASE database | NONE]
|
||||||
@ -144,6 +145,17 @@ In ClickHouse Cloud, by default, passwords must meet the following complexity re
|
|||||||
|
|
||||||
The available password types are: `plaintext_password`, `sha256_password`, `double_sha1_password`.
|
The available password types are: `plaintext_password`, `sha256_password`, `double_sha1_password`.
|
||||||
|
|
||||||
|
7. Multiple authentication methods can be specified:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE USER user1 IDENTIFIED WITH plaintext_password by '1', bcrypt_password by '2', plaintext_password by '3''
|
||||||
|
```
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
1. Older versions of ClickHouse might not support the syntax of multiple authentication methods. Therefore, if the ClickHouse server contains such users and is downgraded to a version that does not support it, such users will become unusable and some user related operations will be broken. In order to downgrade gracefully, one must set all users to contain a single authentication method prior to downgrading. Alternatively, if the server was downgraded without the proper procedure, the faulty users should be dropped.
|
||||||
|
2. `no_password` can not co-exist with other authentication methods for security reasons. Therefore, you can only specify
|
||||||
|
`no_password` if it is the only authentication method in the query.
|
||||||
|
|
||||||
## User Host
|
## User Host
|
||||||
|
|
||||||
User host is a host from which a connection to ClickHouse server could be established. The host can be specified in the `HOST` query section in the following ways:
|
User host is a host from which a connection to ClickHouse server could be established. The host can be specified in the `HOST` query section in the following ways:
|
||||||
|
@ -29,6 +29,7 @@ namespace DB
|
|||||||
namespace ErrorCodes
|
namespace ErrorCodes
|
||||||
{
|
{
|
||||||
extern const int CANNOT_RESTORE_TABLE;
|
extern const int CANNOT_RESTORE_TABLE;
|
||||||
|
extern const int ACCESS_ENTITY_ALREADY_EXISTS;
|
||||||
extern const int LOGICAL_ERROR;
|
extern const int LOGICAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,9 +176,46 @@ namespace
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<UUID, UUID> resolveDependencies(const std::unordered_map<UUID, std::pair<String, AccessEntityType>> & dependencies, const AccessControl & access_control, bool allow_unresolved_dependencies)
|
/// Checks if new entities (which we're going to restore) already exist,
|
||||||
|
/// and either skips them or throws an exception depending on the restore settings.
|
||||||
|
void checkExistingEntities(std::vector<std::pair<UUID, AccessEntityPtr>> & entities,
|
||||||
|
std::unordered_map<UUID, UUID> & old_to_new_id,
|
||||||
|
const AccessControl & access_control,
|
||||||
|
RestoreAccessCreationMode creation_mode)
|
||||||
|
{
|
||||||
|
if (creation_mode == RestoreAccessCreationMode::kReplace)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto should_skip = [&](const std::pair<UUID, AccessEntityPtr> & id_and_entity)
|
||||||
|
{
|
||||||
|
const auto & id = id_and_entity.first;
|
||||||
|
const auto & entity = *id_and_entity.second;
|
||||||
|
auto existing_id = access_control.find(entity.getType(), entity.getName());
|
||||||
|
if (!existing_id)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (creation_mode == RestoreAccessCreationMode::kCreateIfNotExists)
|
||||||
|
{
|
||||||
|
old_to_new_id[id] = *existing_id;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw Exception(ErrorCodes::ACCESS_ENTITY_ALREADY_EXISTS, "Cannot restore {} because it already exists", entity.formatTypeWithName());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::erase_if(entities, should_skip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If new entities (which we're going to restore) depend on other entities which are not going to be restored or not present in the backup
|
||||||
|
/// then we should try to replace those dependencies with already existing entities.
|
||||||
|
void resolveDependencies(const std::unordered_map<UUID, std::pair<String, AccessEntityType>> & dependencies,
|
||||||
|
std::unordered_map<UUID, UUID> & old_to_new_ids,
|
||||||
|
const AccessControl & access_control,
|
||||||
|
bool allow_unresolved_dependencies)
|
||||||
{
|
{
|
||||||
std::unordered_map<UUID, UUID> old_to_new_ids;
|
|
||||||
for (const auto & [id, name_and_type] : dependencies)
|
for (const auto & [id, name_and_type] : dependencies)
|
||||||
{
|
{
|
||||||
std::optional<UUID> new_id;
|
std::optional<UUID> new_id;
|
||||||
@ -188,9 +226,9 @@ namespace
|
|||||||
if (new_id)
|
if (new_id)
|
||||||
old_to_new_ids.emplace(id, *new_id);
|
old_to_new_ids.emplace(id, *new_id);
|
||||||
}
|
}
|
||||||
return old_to_new_ids;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generates random IDs for the new entities.
|
||||||
void generateRandomIDs(std::vector<std::pair<UUID, AccessEntityPtr>> & entities, std::unordered_map<UUID, UUID> & old_to_new_ids)
|
void generateRandomIDs(std::vector<std::pair<UUID, AccessEntityPtr>> & entities, std::unordered_map<UUID, UUID> & old_to_new_ids)
|
||||||
{
|
{
|
||||||
Poco::UUIDGenerator generator;
|
Poco::UUIDGenerator generator;
|
||||||
@ -203,27 +241,12 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceDependencies(std::vector<std::pair<UUID, AccessEntityPtr>> & entities, const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
/// Updates dependencies of the new entities using a specified map.
|
||||||
|
void replaceDependencies(std::vector<std::pair<UUID, AccessEntityPtr>> & entities,
|
||||||
|
const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
||||||
{
|
{
|
||||||
for (auto & entity : entities | boost::adaptors::map_values)
|
for (auto & entity : entities | boost::adaptors::map_values)
|
||||||
{
|
IAccessEntity::replaceDependencies(entity, old_to_new_ids);
|
||||||
bool need_replace = false;
|
|
||||||
for (const auto & dependency : entity->findDependencies())
|
|
||||||
{
|
|
||||||
if (old_to_new_ids.contains(dependency))
|
|
||||||
{
|
|
||||||
need_replace = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!need_replace)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto new_entity = entity->clone();
|
|
||||||
new_entity->replaceDependencies(old_to_new_ids);
|
|
||||||
entity = new_entity;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessRightsElements getRequiredAccessToRestore(const std::vector<std::pair<UUID, AccessEntityPtr>> & entities)
|
AccessRightsElements getRequiredAccessToRestore(const std::vector<std::pair<UUID, AccessEntityPtr>> & entities)
|
||||||
@ -314,7 +337,9 @@ std::pair<String, BackupEntryPtr> makeBackupEntryForAccess(
|
|||||||
|
|
||||||
AccessRestorerFromBackup::AccessRestorerFromBackup(
|
AccessRestorerFromBackup::AccessRestorerFromBackup(
|
||||||
const BackupPtr & backup_, const RestoreSettings & restore_settings_)
|
const BackupPtr & backup_, const RestoreSettings & restore_settings_)
|
||||||
: backup(backup_), allow_unresolved_access_dependencies(restore_settings_.allow_unresolved_access_dependencies)
|
: backup(backup_)
|
||||||
|
, creation_mode(restore_settings_.create_access)
|
||||||
|
, allow_unresolved_dependencies(restore_settings_.allow_unresolved_access_dependencies)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +387,9 @@ std::vector<std::pair<UUID, AccessEntityPtr>> AccessRestorerFromBackup::getAcces
|
|||||||
{
|
{
|
||||||
auto new_entities = entities;
|
auto new_entities = entities;
|
||||||
|
|
||||||
auto old_to_new_ids = resolveDependencies(dependencies, access_control, allow_unresolved_access_dependencies);
|
std::unordered_map<UUID, UUID> old_to_new_ids;
|
||||||
|
checkExistingEntities(new_entities, old_to_new_ids, access_control, creation_mode);
|
||||||
|
resolveDependencies(dependencies, old_to_new_ids, access_control, allow_unresolved_dependencies);
|
||||||
generateRandomIDs(new_entities, old_to_new_ids);
|
generateRandomIDs(new_entities, old_to_new_ids);
|
||||||
replaceDependencies(new_entities, old_to_new_ids);
|
replaceDependencies(new_entities, old_to_new_ids);
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ using BackupPtr = std::shared_ptr<const IBackup>;
|
|||||||
class IBackupEntry;
|
class IBackupEntry;
|
||||||
using BackupEntryPtr = std::shared_ptr<const IBackupEntry>;
|
using BackupEntryPtr = std::shared_ptr<const IBackupEntry>;
|
||||||
struct RestoreSettings;
|
struct RestoreSettings;
|
||||||
|
enum class RestoreAccessCreationMode : uint8_t;
|
||||||
|
|
||||||
|
|
||||||
/// Makes a backup of access entities of a specified type.
|
/// Makes a backup of access entities of a specified type.
|
||||||
@ -45,7 +46,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BackupPtr backup;
|
BackupPtr backup;
|
||||||
bool allow_unresolved_access_dependencies = false;
|
RestoreAccessCreationMode creation_mode;
|
||||||
|
bool allow_unresolved_dependencies = false;
|
||||||
std::vector<std::pair<UUID, AccessEntityPtr>> entities;
|
std::vector<std::pair<UUID, AccessEntityPtr>> entities;
|
||||||
std::unordered_map<UUID, std::pair<String, AccessEntityType>> dependencies;
|
std::unordered_map<UUID, std::pair<String, AccessEntityType>> dependencies;
|
||||||
std::unordered_set<String> data_paths;
|
std::unordered_set<String> data_paths;
|
||||||
|
@ -544,9 +544,9 @@ scope_guard AccessControl::subscribeForChanges(const std::vector<UUID> & ids, co
|
|||||||
return changes_notifier->subscribeForChanges(ids, handler);
|
return changes_notifier->subscribeForChanges(ids, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AccessControl::insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists)
|
bool AccessControl::insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id)
|
||||||
{
|
{
|
||||||
if (MultipleAccessStorage::insertImpl(id, entity, replace_if_exists, throw_if_exists))
|
if (MultipleAccessStorage::insertImpl(id, entity, replace_if_exists, throw_if_exists, conflicting_id))
|
||||||
{
|
{
|
||||||
changes_notifier->sendNotifications();
|
changes_notifier->sendNotifications();
|
||||||
return true;
|
return true;
|
||||||
|
@ -243,7 +243,7 @@ private:
|
|||||||
class CustomSettingsPrefixes;
|
class CustomSettingsPrefixes;
|
||||||
class PasswordComplexityRules;
|
class PasswordComplexityRules;
|
||||||
|
|
||||||
bool insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists) override;
|
bool insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id) override;
|
||||||
bool removeImpl(const UUID & id, bool throw_if_not_exists) override;
|
bool removeImpl(const UUID & id, bool throw_if_not_exists) override;
|
||||||
bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists) override;
|
bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists) override;
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ AccessEntityPtr deserializeAccessEntityImpl(const String & definition)
|
|||||||
if (res)
|
if (res)
|
||||||
throw Exception(ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION, "Two access entities attached in the same file");
|
throw Exception(ErrorCodes::INCORRECT_ACCESS_ENTITY_DEFINITION, "Two access entities attached in the same file");
|
||||||
res = user = std::make_unique<User>();
|
res = user = std::make_unique<User>();
|
||||||
InterpreterCreateUserQuery::updateUserFromQuery(*user, *create_user_query, /* allow_no_password = */ true, /* allow_plaintext_password = */ true);
|
InterpreterCreateUserQuery::updateUserFromQuery(*user, *create_user_query, /* allow_no_password = */ true, /* allow_plaintext_password = */ true, /* max_number_of_authentication_methods = zero is unlimited*/ 0);
|
||||||
}
|
}
|
||||||
else if (auto * create_role_query = query->as<ASTCreateRoleQuery>())
|
else if (auto * create_role_query = query->as<ASTCreateRoleQuery>())
|
||||||
{
|
{
|
||||||
|
@ -14,11 +14,6 @@
|
|||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
namespace ErrorCodes
|
|
||||||
{
|
|
||||||
extern const int NOT_IMPLEMENTED;
|
|
||||||
extern const int SUPPORT_IS_DISABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -84,165 +79,98 @@ namespace
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool checkKerberosAuthentication(
|
||||||
|
const GSSAcceptorContext * gss_acceptor_context,
|
||||||
|
const AuthenticationData & authentication_method,
|
||||||
|
const ExternalAuthenticators & external_authenticators)
|
||||||
|
{
|
||||||
|
return authentication_method.getType() == AuthenticationType::KERBEROS
|
||||||
|
&& external_authenticators.checkKerberosCredentials(authentication_method.getKerberosRealm(), *gss_acceptor_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool checkMySQLAuthentication(
|
||||||
|
const MySQLNative41Credentials * mysql_credentials,
|
||||||
|
const AuthenticationData & authentication_method)
|
||||||
|
{
|
||||||
|
switch (authentication_method.getType())
|
||||||
|
{
|
||||||
|
case AuthenticationType::PLAINTEXT_PASSWORD:
|
||||||
|
return checkPasswordPlainTextMySQL(
|
||||||
|
mysql_credentials->getScramble(),
|
||||||
|
mysql_credentials->getScrambledPassword(),
|
||||||
|
authentication_method.getPasswordHashBinary());
|
||||||
|
case AuthenticationType::DOUBLE_SHA1_PASSWORD:
|
||||||
|
return checkPasswordDoubleSHA1MySQL(
|
||||||
|
mysql_credentials->getScramble(),
|
||||||
|
mysql_credentials->getScrambledPassword(),
|
||||||
|
authentication_method.getPasswordHashBinary());
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Authentication::areCredentialsValid(
|
bool checkBasicAuthentication(
|
||||||
const Credentials & credentials,
|
const BasicCredentials * basic_credentials,
|
||||||
const AuthenticationData & auth_data,
|
const AuthenticationData & authentication_method,
|
||||||
const ExternalAuthenticators & external_authenticators,
|
const ExternalAuthenticators & external_authenticators,
|
||||||
SettingsChanges & settings)
|
SettingsChanges & settings)
|
||||||
{
|
{
|
||||||
if (!credentials.isReady())
|
switch (authentication_method.getType())
|
||||||
return false;
|
|
||||||
|
|
||||||
if (const auto * gss_acceptor_context = typeid_cast<const GSSAcceptorContext *>(&credentials))
|
|
||||||
{
|
|
||||||
switch (auth_data.getType())
|
|
||||||
{
|
{
|
||||||
case AuthenticationType::NO_PASSWORD:
|
case AuthenticationType::NO_PASSWORD:
|
||||||
case AuthenticationType::PLAINTEXT_PASSWORD:
|
|
||||||
case AuthenticationType::SHA256_PASSWORD:
|
|
||||||
case AuthenticationType::DOUBLE_SHA1_PASSWORD:
|
|
||||||
case AuthenticationType::BCRYPT_PASSWORD:
|
|
||||||
case AuthenticationType::LDAP:
|
|
||||||
case AuthenticationType::HTTP:
|
|
||||||
throw Authentication::Require<BasicCredentials>("ClickHouse Basic Authentication");
|
|
||||||
|
|
||||||
case AuthenticationType::JWT:
|
|
||||||
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "JWT is available only in ClickHouse Cloud");
|
|
||||||
|
|
||||||
case AuthenticationType::KERBEROS:
|
|
||||||
return external_authenticators.checkKerberosCredentials(auth_data.getKerberosRealm(), *gss_acceptor_context);
|
|
||||||
|
|
||||||
case AuthenticationType::SSL_CERTIFICATE:
|
|
||||||
throw Authentication::Require<BasicCredentials>("ClickHouse X.509 Authentication");
|
|
||||||
|
|
||||||
case AuthenticationType::SSH_KEY:
|
|
||||||
#if USE_SSH
|
|
||||||
throw Authentication::Require<SshCredentials>("SSH Keys Authentication");
|
|
||||||
#else
|
|
||||||
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "SSH is disabled, because ClickHouse is built without libssh");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case AuthenticationType::MAX:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const auto * mysql_credentials = typeid_cast<const MySQLNative41Credentials *>(&credentials))
|
|
||||||
{
|
{
|
||||||
switch (auth_data.getType())
|
|
||||||
{
|
|
||||||
case AuthenticationType::NO_PASSWORD:
|
|
||||||
return true; // N.B. even if the password is not empty!
|
return true; // N.B. even if the password is not empty!
|
||||||
|
|
||||||
case AuthenticationType::PLAINTEXT_PASSWORD:
|
|
||||||
return checkPasswordPlainTextMySQL(mysql_credentials->getScramble(), mysql_credentials->getScrambledPassword(), auth_data.getPasswordHashBinary());
|
|
||||||
|
|
||||||
case AuthenticationType::DOUBLE_SHA1_PASSWORD:
|
|
||||||
return checkPasswordDoubleSHA1MySQL(mysql_credentials->getScramble(), mysql_credentials->getScrambledPassword(), auth_data.getPasswordHashBinary());
|
|
||||||
|
|
||||||
case AuthenticationType::SHA256_PASSWORD:
|
|
||||||
case AuthenticationType::BCRYPT_PASSWORD:
|
|
||||||
case AuthenticationType::LDAP:
|
|
||||||
case AuthenticationType::KERBEROS:
|
|
||||||
case AuthenticationType::HTTP:
|
|
||||||
throw Authentication::Require<BasicCredentials>("ClickHouse Basic Authentication");
|
|
||||||
|
|
||||||
case AuthenticationType::SSL_CERTIFICATE:
|
|
||||||
throw Authentication::Require<BasicCredentials>("ClickHouse X.509 Authentication");
|
|
||||||
|
|
||||||
case AuthenticationType::JWT:
|
|
||||||
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "JWT is available only in ClickHouse Cloud");
|
|
||||||
|
|
||||||
case AuthenticationType::SSH_KEY:
|
|
||||||
#if USE_SSH
|
|
||||||
throw Authentication::Require<SshCredentials>("SSH Keys Authentication");
|
|
||||||
#else
|
|
||||||
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "SSH is disabled, because ClickHouse is built without libssh");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case AuthenticationType::MAX:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (const auto * basic_credentials = typeid_cast<const BasicCredentials *>(&credentials))
|
|
||||||
{
|
|
||||||
switch (auth_data.getType())
|
|
||||||
{
|
|
||||||
case AuthenticationType::NO_PASSWORD:
|
|
||||||
return true; // N.B. even if the password is not empty!
|
|
||||||
|
|
||||||
case AuthenticationType::PLAINTEXT_PASSWORD:
|
case AuthenticationType::PLAINTEXT_PASSWORD:
|
||||||
return checkPasswordPlainText(basic_credentials->getPassword(), auth_data.getPasswordHashBinary());
|
|
||||||
|
|
||||||
case AuthenticationType::SHA256_PASSWORD:
|
|
||||||
return checkPasswordSHA256(basic_credentials->getPassword(), auth_data.getPasswordHashBinary(), auth_data.getSalt());
|
|
||||||
|
|
||||||
case AuthenticationType::DOUBLE_SHA1_PASSWORD:
|
|
||||||
return checkPasswordDoubleSHA1(basic_credentials->getPassword(), auth_data.getPasswordHashBinary());
|
|
||||||
|
|
||||||
case AuthenticationType::LDAP:
|
|
||||||
return external_authenticators.checkLDAPCredentials(auth_data.getLDAPServerName(), *basic_credentials);
|
|
||||||
|
|
||||||
case AuthenticationType::KERBEROS:
|
|
||||||
throw Authentication::Require<GSSAcceptorContext>(auth_data.getKerberosRealm());
|
|
||||||
|
|
||||||
case AuthenticationType::SSL_CERTIFICATE:
|
|
||||||
throw Authentication::Require<BasicCredentials>("ClickHouse X.509 Authentication");
|
|
||||||
|
|
||||||
case AuthenticationType::SSH_KEY:
|
|
||||||
#if USE_SSH
|
|
||||||
throw Authentication::Require<SshCredentials>("SSH Keys Authentication");
|
|
||||||
#else
|
|
||||||
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "SSH is disabled, because ClickHouse is built without libssh");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case AuthenticationType::JWT:
|
|
||||||
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "JWT is available only in ClickHouse Cloud");
|
|
||||||
|
|
||||||
case AuthenticationType::BCRYPT_PASSWORD:
|
|
||||||
return checkPasswordBcrypt(basic_credentials->getPassword(), auth_data.getPasswordHashBinary());
|
|
||||||
|
|
||||||
case AuthenticationType::HTTP:
|
|
||||||
switch (auth_data.getHTTPAuthenticationScheme())
|
|
||||||
{
|
{
|
||||||
case HTTPAuthenticationScheme::BASIC:
|
return checkPasswordPlainText(basic_credentials->getPassword(), authentication_method.getPasswordHashBinary());
|
||||||
|
}
|
||||||
|
case AuthenticationType::SHA256_PASSWORD:
|
||||||
|
{
|
||||||
|
return checkPasswordSHA256(
|
||||||
|
basic_credentials->getPassword(), authentication_method.getPasswordHashBinary(), authentication_method.getSalt());
|
||||||
|
}
|
||||||
|
case AuthenticationType::DOUBLE_SHA1_PASSWORD:
|
||||||
|
{
|
||||||
|
return checkPasswordDoubleSHA1(basic_credentials->getPassword(), authentication_method.getPasswordHashBinary());
|
||||||
|
}
|
||||||
|
case AuthenticationType::LDAP:
|
||||||
|
{
|
||||||
|
return external_authenticators.checkLDAPCredentials(authentication_method.getLDAPServerName(), *basic_credentials);
|
||||||
|
}
|
||||||
|
case AuthenticationType::BCRYPT_PASSWORD:
|
||||||
|
{
|
||||||
|
return checkPasswordBcrypt(basic_credentials->getPassword(), authentication_method.getPasswordHashBinary());
|
||||||
|
}
|
||||||
|
case AuthenticationType::HTTP:
|
||||||
|
{
|
||||||
|
if (authentication_method.getHTTPAuthenticationScheme() == HTTPAuthenticationScheme::BASIC)
|
||||||
|
{
|
||||||
return external_authenticators.checkHTTPBasicCredentials(
|
return external_authenticators.checkHTTPBasicCredentials(
|
||||||
auth_data.getHTTPAuthenticationServerName(), *basic_credentials, settings);
|
authentication_method.getHTTPAuthenticationServerName(), *basic_credentials, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
case AuthenticationType::MAX:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto * ssl_certificate_credentials = typeid_cast<const SSLCertificateCredentials *>(&credentials))
|
return false;
|
||||||
{
|
}
|
||||||
switch (auth_data.getType())
|
|
||||||
{
|
|
||||||
case AuthenticationType::NO_PASSWORD:
|
|
||||||
case AuthenticationType::PLAINTEXT_PASSWORD:
|
|
||||||
case AuthenticationType::SHA256_PASSWORD:
|
|
||||||
case AuthenticationType::DOUBLE_SHA1_PASSWORD:
|
|
||||||
case AuthenticationType::BCRYPT_PASSWORD:
|
|
||||||
case AuthenticationType::LDAP:
|
|
||||||
case AuthenticationType::HTTP:
|
|
||||||
throw Authentication::Require<BasicCredentials>("ClickHouse Basic Authentication");
|
|
||||||
|
|
||||||
case AuthenticationType::JWT:
|
bool checkSSLCertificateAuthentication(
|
||||||
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "JWT is available only in ClickHouse Cloud");
|
const SSLCertificateCredentials * ssl_certificate_credentials,
|
||||||
|
const AuthenticationData & authentication_method)
|
||||||
case AuthenticationType::KERBEROS:
|
|
||||||
throw Authentication::Require<GSSAcceptorContext>(auth_data.getKerberosRealm());
|
|
||||||
|
|
||||||
case AuthenticationType::SSL_CERTIFICATE:
|
|
||||||
{
|
{
|
||||||
|
if (AuthenticationType::SSL_CERTIFICATE != authentication_method.getType())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (SSLCertificateSubjects::Type type : {SSLCertificateSubjects::Type::CN, SSLCertificateSubjects::Type::SAN})
|
for (SSLCertificateSubjects::Type type : {SSLCertificateSubjects::Type::CN, SSLCertificateSubjects::Type::SAN})
|
||||||
{
|
{
|
||||||
for (const auto & subject : auth_data.getSSLCertificateSubjects().at(type))
|
for (const auto & subject : authentication_method.getSSLCertificateSubjects().at(type))
|
||||||
{
|
{
|
||||||
if (ssl_certificate_credentials->getSSLCertificateSubjects().at(type).contains(subject))
|
if (ssl_certificate_credentials->getSSLCertificateSubjects().at(type).contains(subject))
|
||||||
return true;
|
return true;
|
||||||
@ -267,56 +195,61 @@ bool Authentication::areCredentialsValid(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AuthenticationType::SSH_KEY:
|
|
||||||
#if USE_SSH
|
#if USE_SSH
|
||||||
throw Authentication::Require<SshCredentials>("SSH Keys Authentication");
|
bool checkSshAuthentication(
|
||||||
#else
|
const SshCredentials * ssh_credentials,
|
||||||
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "SSH is disabled, because ClickHouse is built without libssh");
|
const AuthenticationData & authentication_method)
|
||||||
#endif
|
{
|
||||||
|
return AuthenticationType::SSH_KEY == authentication_method.getType()
|
||||||
case AuthenticationType::MAX:
|
&& checkSshSignature(authentication_method.getSSHKeys(), ssh_credentials->getSignature(), ssh_credentials->getOriginal());
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Authentication::areCredentialsValid(
|
||||||
|
const Credentials & credentials,
|
||||||
|
const AuthenticationData & authentication_method,
|
||||||
|
const ExternalAuthenticators & external_authenticators,
|
||||||
|
SettingsChanges & settings)
|
||||||
|
{
|
||||||
|
if (!credentials.isReady())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (const auto * gss_acceptor_context = typeid_cast<const GSSAcceptorContext *>(&credentials))
|
||||||
|
{
|
||||||
|
return checkKerberosAuthentication(gss_acceptor_context, authentication_method, external_authenticators);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto * mysql_credentials = typeid_cast<const MySQLNative41Credentials *>(&credentials))
|
||||||
|
{
|
||||||
|
return checkMySQLAuthentication(mysql_credentials, authentication_method);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto * basic_credentials = typeid_cast<const BasicCredentials *>(&credentials))
|
||||||
|
{
|
||||||
|
return checkBasicAuthentication(basic_credentials, authentication_method, external_authenticators, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto * ssl_certificate_credentials = typeid_cast<const SSLCertificateCredentials *>(&credentials))
|
||||||
|
{
|
||||||
|
return checkSSLCertificateAuthentication(ssl_certificate_credentials, authentication_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_SSH
|
#if USE_SSH
|
||||||
if (const auto * ssh_credentials = typeid_cast<const SshCredentials *>(&credentials))
|
if (const auto * ssh_credentials = typeid_cast<const SshCredentials *>(&credentials))
|
||||||
{
|
{
|
||||||
switch (auth_data.getType())
|
return checkSshAuthentication(ssh_credentials, authentication_method);
|
||||||
{
|
|
||||||
case AuthenticationType::NO_PASSWORD:
|
|
||||||
case AuthenticationType::PLAINTEXT_PASSWORD:
|
|
||||||
case AuthenticationType::SHA256_PASSWORD:
|
|
||||||
case AuthenticationType::DOUBLE_SHA1_PASSWORD:
|
|
||||||
case AuthenticationType::BCRYPT_PASSWORD:
|
|
||||||
case AuthenticationType::LDAP:
|
|
||||||
case AuthenticationType::HTTP:
|
|
||||||
throw Authentication::Require<BasicCredentials>("ClickHouse Basic Authentication");
|
|
||||||
|
|
||||||
case AuthenticationType::JWT:
|
|
||||||
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "JWT is available only in ClickHouse Cloud");
|
|
||||||
|
|
||||||
case AuthenticationType::KERBEROS:
|
|
||||||
throw Authentication::Require<GSSAcceptorContext>(auth_data.getKerberosRealm());
|
|
||||||
|
|
||||||
case AuthenticationType::SSL_CERTIFICATE:
|
|
||||||
throw Authentication::Require<SSLCertificateCredentials>("ClickHouse X.509 Authentication");
|
|
||||||
|
|
||||||
case AuthenticationType::SSH_KEY:
|
|
||||||
return checkSshSignature(auth_data.getSSHKeys(), ssh_credentials->getSignature(), ssh_credentials->getOriginal());
|
|
||||||
case AuthenticationType::MAX:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ([[maybe_unused]] const auto * always_allow_credentials = typeid_cast<const AlwaysAllowCredentials *>(&credentials))
|
if ([[maybe_unused]] const auto * always_allow_credentials = typeid_cast<const AlwaysAllowCredentials *>(&credentials))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "areCredentialsValid(): authentication type {} not supported", toString(auth_data.getType()));
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ struct Authentication
|
|||||||
/// returned by the authentication server
|
/// returned by the authentication server
|
||||||
static bool areCredentialsValid(
|
static bool areCredentialsValid(
|
||||||
const Credentials & credentials,
|
const Credentials & credentials,
|
||||||
const AuthenticationData & auth_data,
|
const AuthenticationData & authentication_method,
|
||||||
const ExternalAuthenticators & external_authenticators,
|
const ExternalAuthenticators & external_authenticators,
|
||||||
SettingsChanges & settings);
|
SettingsChanges & settings);
|
||||||
|
|
||||||
|
@ -375,7 +375,8 @@ std::shared_ptr<ASTAuthenticationData> AuthenticationData::toAST() const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AuthenticationType::NO_PASSWORD: [[fallthrough]];
|
case AuthenticationType::NO_PASSWORD:
|
||||||
|
break;
|
||||||
case AuthenticationType::MAX:
|
case AuthenticationType::MAX:
|
||||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "AST: Unexpected authentication type {}", toString(auth_type));
|
throw Exception(ErrorCodes::LOGICAL_ERROR, "AST: Unexpected authentication type {}", toString(auth_type));
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#include <Access/DiskAccessStorage.h>
|
#include <Access/DiskAccessStorage.h>
|
||||||
#include <Access/AccessEntityIO.h>
|
#include <Access/AccessEntityIO.h>
|
||||||
#include <Access/AccessChangesNotifier.h>
|
#include <Access/AccessChangesNotifier.h>
|
||||||
#include <Backups/RestorerFromBackup.h>
|
|
||||||
#include <Backups/RestoreSettings.h>
|
|
||||||
#include <IO/WriteHelpers.h>
|
#include <IO/WriteHelpers.h>
|
||||||
#include <IO/ReadHelpers.h>
|
#include <IO/ReadHelpers.h>
|
||||||
#include <IO/ReadBufferFromFile.h>
|
#include <IO/ReadBufferFromFile.h>
|
||||||
@ -418,7 +416,7 @@ void DiskAccessStorage::setAllInMemory(const std::vector<std::pair<UUID, AccessE
|
|||||||
|
|
||||||
/// Insert or update entities.
|
/// Insert or update entities.
|
||||||
for (const auto & [id, entity] : entities_without_conflicts)
|
for (const auto & [id, entity] : entities_without_conflicts)
|
||||||
insertNoLock(id, entity, /* replace_if_exists = */ true, /* throw_if_exists = */ false, /* write_on_disk= */ false);
|
insertNoLock(id, entity, /* replace_if_exists = */ true, /* throw_if_exists = */ false, /* conflicting_id = */ nullptr, /* write_on_disk= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiskAccessStorage::removeAllExceptInMemory(const boost::container::flat_set<UUID> & ids_to_keep)
|
void DiskAccessStorage::removeAllExceptInMemory(const boost::container::flat_set<UUID> & ids_to_keep)
|
||||||
@ -507,14 +505,14 @@ std::optional<std::pair<String, AccessEntityType>> DiskAccessStorage::readNameWi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DiskAccessStorage::insertImpl(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists)
|
bool DiskAccessStorage::insertImpl(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id)
|
||||||
{
|
{
|
||||||
std::lock_guard lock{mutex};
|
std::lock_guard lock{mutex};
|
||||||
return insertNoLock(id, new_entity, replace_if_exists, throw_if_exists, /* write_on_disk = */ true);
|
return insertNoLock(id, new_entity, replace_if_exists, throw_if_exists, conflicting_id, /* write_on_disk = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DiskAccessStorage::insertNoLock(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists, bool write_on_disk)
|
bool DiskAccessStorage::insertNoLock(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id, bool write_on_disk)
|
||||||
{
|
{
|
||||||
const String & name = new_entity->getName();
|
const String & name = new_entity->getName();
|
||||||
AccessEntityType type = new_entity->getType();
|
AccessEntityType type = new_entity->getType();
|
||||||
@ -533,10 +531,16 @@ bool DiskAccessStorage::insertNoLock(const UUID & id, const AccessEntityPtr & ne
|
|||||||
if (name_collision && !replace_if_exists)
|
if (name_collision && !replace_if_exists)
|
||||||
{
|
{
|
||||||
if (throw_if_exists)
|
if (throw_if_exists)
|
||||||
|
{
|
||||||
throwNameCollisionCannotInsert(type, name);
|
throwNameCollisionCannotInsert(type, name);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (conflicting_id)
|
||||||
|
*conflicting_id = id_by_name;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto it_by_id = entries_by_id.find(id);
|
auto it_by_id = entries_by_id.find(id);
|
||||||
bool id_collision = (it_by_id != entries_by_id.end());
|
bool id_collision = (it_by_id != entries_by_id.end());
|
||||||
@ -548,8 +552,12 @@ bool DiskAccessStorage::insertNoLock(const UUID & id, const AccessEntityPtr & ne
|
|||||||
throwIDCollisionCannotInsert(id, type, name, existing_entry.type, existing_entry.name);
|
throwIDCollisionCannotInsert(id, type, name, existing_entry.type, existing_entry.name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (conflicting_id)
|
||||||
|
*conflicting_id = id;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (write_on_disk)
|
if (write_on_disk)
|
||||||
scheduleWriteLists(type);
|
scheduleWriteLists(type);
|
||||||
@ -727,25 +735,4 @@ void DiskAccessStorage::deleteAccessEntityOnDisk(const UUID & id) const
|
|||||||
throw Exception(ErrorCodes::FILE_DOESNT_EXIST, "Couldn't delete {}", file_path);
|
throw Exception(ErrorCodes::FILE_DOESNT_EXIST, "Couldn't delete {}", file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DiskAccessStorage::restoreFromBackup(RestorerFromBackup & restorer)
|
|
||||||
{
|
|
||||||
if (!isRestoreAllowed())
|
|
||||||
throwRestoreNotAllowed();
|
|
||||||
|
|
||||||
auto entities = restorer.getAccessEntitiesToRestore();
|
|
||||||
if (entities.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto create_access = restorer.getRestoreSettings().create_access;
|
|
||||||
bool replace_if_exists = (create_access == RestoreAccessCreationMode::kReplace);
|
|
||||||
bool throw_if_exists = (create_access == RestoreAccessCreationMode::kCreate);
|
|
||||||
|
|
||||||
restorer.addDataRestoreTask([this, my_entities = std::move(entities), replace_if_exists, throw_if_exists]
|
|
||||||
{
|
|
||||||
for (const auto & [id, entity] : my_entities)
|
|
||||||
insert(id, entity, replace_if_exists, throw_if_exists);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,14 +34,13 @@ public:
|
|||||||
bool exists(const UUID & id) const override;
|
bool exists(const UUID & id) const override;
|
||||||
|
|
||||||
bool isBackupAllowed() const override { return backup_allowed; }
|
bool isBackupAllowed() const override { return backup_allowed; }
|
||||||
void restoreFromBackup(RestorerFromBackup & restorer) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
|
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
|
||||||
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
|
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
|
||||||
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
|
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
|
||||||
std::optional<std::pair<String, AccessEntityType>> readNameWithTypeImpl(const UUID & id, bool throw_if_not_exists) const override;
|
std::optional<std::pair<String, AccessEntityType>> readNameWithTypeImpl(const UUID & id, bool throw_if_not_exists) const override;
|
||||||
bool insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists) override;
|
bool insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id) override;
|
||||||
bool removeImpl(const UUID & id, bool throw_if_not_exists) override;
|
bool removeImpl(const UUID & id, bool throw_if_not_exists) override;
|
||||||
bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists) override;
|
bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists) override;
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ private:
|
|||||||
void listsWritingThreadFunc() TSA_NO_THREAD_SAFETY_ANALYSIS;
|
void listsWritingThreadFunc() TSA_NO_THREAD_SAFETY_ANALYSIS;
|
||||||
void stopListsWritingThread();
|
void stopListsWritingThread();
|
||||||
|
|
||||||
bool insertNoLock(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists, bool write_on_disk) TSA_REQUIRES(mutex);
|
bool insertNoLock(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id, bool write_on_disk) TSA_REQUIRES(mutex);
|
||||||
bool updateNoLock(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists, bool write_on_disk) TSA_REQUIRES(mutex);
|
bool updateNoLock(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists, bool write_on_disk) TSA_REQUIRES(mutex);
|
||||||
bool removeNoLock(const UUID & id, bool throw_if_not_exists, bool write_on_disk) TSA_REQUIRES(mutex);
|
bool removeNoLock(const UUID & id, bool throw_if_not_exists, bool write_on_disk) TSA_REQUIRES(mutex);
|
||||||
|
|
||||||
|
@ -9,4 +9,28 @@ bool IAccessEntity::equal(const IAccessEntity & other) const
|
|||||||
return (name == other.name) && (getType() == other.getType());
|
return (name == other.name) && (getType() == other.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IAccessEntity::replaceDependencies(std::shared_ptr<const IAccessEntity> & entity, const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
||||||
|
{
|
||||||
|
if (old_to_new_ids.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool need_replace_dependencies = false;
|
||||||
|
auto dependencies = entity->findDependencies();
|
||||||
|
for (const auto & dependency : dependencies)
|
||||||
|
{
|
||||||
|
if (old_to_new_ids.contains(dependency))
|
||||||
|
{
|
||||||
|
need_replace_dependencies = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!need_replace_dependencies)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto new_entity = entity->clone();
|
||||||
|
new_entity->replaceDependencies(old_to_new_ids);
|
||||||
|
entity = new_entity;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,8 @@ struct IAccessEntity
|
|||||||
virtual std::vector<UUID> findDependencies() const { return {}; }
|
virtual std::vector<UUID> findDependencies() const { return {}; }
|
||||||
|
|
||||||
/// Replaces dependencies according to a specified map.
|
/// Replaces dependencies according to a specified map.
|
||||||
virtual void replaceDependencies(const std::unordered_map<UUID, UUID> & /* old_to_new_ids */) {}
|
void replaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids) { doReplaceDependencies(old_to_new_ids); }
|
||||||
|
static void replaceDependencies(std::shared_ptr<const IAccessEntity> & entity, const std::unordered_map<UUID, UUID> & old_to_new_ids);
|
||||||
|
|
||||||
/// Whether this access entity should be written to a backup.
|
/// Whether this access entity should be written to a backup.
|
||||||
virtual bool isBackupAllowed() const { return false; }
|
virtual bool isBackupAllowed() const { return false; }
|
||||||
@ -66,6 +67,8 @@ protected:
|
|||||||
{
|
{
|
||||||
return std::make_shared<EntityClassT>(typeid_cast<const EntityClassT &>(*this));
|
return std::make_shared<EntityClassT>(typeid_cast<const EntityClassT &>(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void doReplaceDependencies(const std::unordered_map<UUID, UUID> & /* old_to_new_ids */) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
using AccessEntityPtr = std::shared_ptr<const IAccessEntity>;
|
using AccessEntityPtr = std::shared_ptr<const IAccessEntity>;
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <Access/User.h>
|
#include <Access/User.h>
|
||||||
#include <Access/AccessBackup.h>
|
#include <Access/AccessBackup.h>
|
||||||
#include <Backups/BackupEntriesCollector.h>
|
#include <Backups/BackupEntriesCollector.h>
|
||||||
|
#include <Backups/RestorerFromBackup.h>
|
||||||
|
#include <Backups/RestoreSettings.h>
|
||||||
#include <Common/Exception.h>
|
#include <Common/Exception.h>
|
||||||
#include <Common/quoteString.h>
|
#include <Common/quoteString.h>
|
||||||
#include <Common/callOnce.h>
|
#include <Common/callOnce.h>
|
||||||
@ -14,10 +16,11 @@
|
|||||||
#include <base/FnTraits.h>
|
#include <base/FnTraits.h>
|
||||||
#include <boost/algorithm/string/join.hpp>
|
#include <boost/algorithm/string/join.hpp>
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
#include <boost/range/adaptor/map.hpp>
|
||||||
#include <boost/range/adaptor/reversed.hpp>
|
#include <boost/range/adaptor/reversed.hpp>
|
||||||
|
#include <boost/range/algorithm/copy.hpp>
|
||||||
#include <boost/range/algorithm_ext/erase.hpp>
|
#include <boost/range/algorithm_ext/erase.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
namespace ErrorCodes
|
namespace ErrorCodes
|
||||||
@ -30,7 +33,6 @@ namespace ErrorCodes
|
|||||||
extern const int IP_ADDRESS_NOT_ALLOWED;
|
extern const int IP_ADDRESS_NOT_ALLOWED;
|
||||||
extern const int LOGICAL_ERROR;
|
extern const int LOGICAL_ERROR;
|
||||||
extern const int NOT_IMPLEMENTED;
|
extern const int NOT_IMPLEMENTED;
|
||||||
extern const int AUTHENTICATION_FAILED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -179,20 +181,20 @@ UUID IAccessStorage::insert(const AccessEntityPtr & entity)
|
|||||||
return *insert(entity, /* replace_if_exists = */ false, /* throw_if_exists = */ true);
|
return *insert(entity, /* replace_if_exists = */ false, /* throw_if_exists = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<UUID> IAccessStorage::insert(const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists)
|
std::optional<UUID> IAccessStorage::insert(const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id)
|
||||||
{
|
{
|
||||||
auto id = generateRandomID();
|
auto id = generateRandomID();
|
||||||
|
|
||||||
if (insert(id, entity, replace_if_exists, throw_if_exists))
|
if (insert(id, entity, replace_if_exists, throw_if_exists, conflicting_id))
|
||||||
return id;
|
return id;
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool IAccessStorage::insert(const DB::UUID & id, const DB::AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists)
|
bool IAccessStorage::insert(const DB::UUID & id, const DB::AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id)
|
||||||
{
|
{
|
||||||
return insertImpl(id, entity, replace_if_exists, throw_if_exists);
|
return insertImpl(id, entity, replace_if_exists, throw_if_exists, conflicting_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -286,7 +288,7 @@ std::vector<UUID> IAccessStorage::insertOrReplace(const std::vector<AccessEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool IAccessStorage::insertImpl(const UUID &, const AccessEntityPtr & entity, bool, bool)
|
bool IAccessStorage::insertImpl(const UUID &, const AccessEntityPtr & entity, bool, bool, UUID *)
|
||||||
{
|
{
|
||||||
if (isReadOnly())
|
if (isReadOnly())
|
||||||
throwReadonlyCannotInsert(entity->getType(), entity->getName());
|
throwReadonlyCannotInsert(entity->getType(), entity->getName());
|
||||||
@ -525,27 +527,45 @@ std::optional<AuthResult> IAccessStorage::authenticateImpl(
|
|||||||
if (!isAddressAllowed(*user, address))
|
if (!isAddressAllowed(*user, address))
|
||||||
throwAddressNotAllowed(address);
|
throwAddressNotAllowed(address);
|
||||||
|
|
||||||
auto auth_type = user->auth_data.getType();
|
bool skipped_not_allowed_authentication_methods = false;
|
||||||
|
|
||||||
|
for (const auto & auth_method : user->authentication_methods)
|
||||||
|
{
|
||||||
|
auto auth_type = auth_method.getType();
|
||||||
if (((auth_type == AuthenticationType::NO_PASSWORD) && !allow_no_password) ||
|
if (((auth_type == AuthenticationType::NO_PASSWORD) && !allow_no_password) ||
|
||||||
((auth_type == AuthenticationType::PLAINTEXT_PASSWORD) && !allow_plaintext_password))
|
((auth_type == AuthenticationType::PLAINTEXT_PASSWORD) && !allow_plaintext_password))
|
||||||
throwAuthenticationTypeNotAllowed(auth_type);
|
{
|
||||||
|
skipped_not_allowed_authentication_methods = true;
|
||||||
if (!areCredentialsValid(*user, credentials, external_authenticators, auth_result.settings))
|
continue;
|
||||||
throwInvalidCredentials();
|
}
|
||||||
|
|
||||||
|
if (areCredentialsValid(user->getName(), user->valid_until, auth_method, credentials, external_authenticators, auth_result.settings))
|
||||||
|
{
|
||||||
|
auth_result.authentication_data = auth_method;
|
||||||
return auth_result;
|
return auth_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (skipped_not_allowed_authentication_methods)
|
||||||
|
{
|
||||||
|
LOG_INFO(log, "Skipped the check for not allowed authentication methods,"
|
||||||
|
"check allow_no_password and allow_plaintext_password settings in the server configuration");
|
||||||
|
}
|
||||||
|
|
||||||
|
throwInvalidCredentials();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (throw_if_user_not_exists)
|
if (throw_if_user_not_exists)
|
||||||
throwNotFound(AccessEntityType::USER, credentials.getUserName());
|
throwNotFound(AccessEntityType::USER, credentials.getUserName());
|
||||||
else
|
else
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool IAccessStorage::areCredentialsValid(
|
bool IAccessStorage::areCredentialsValid(
|
||||||
const User & user,
|
const std::string & user_name,
|
||||||
|
time_t valid_until,
|
||||||
|
const AuthenticationData & authentication_method,
|
||||||
const Credentials & credentials,
|
const Credentials & credentials,
|
||||||
const ExternalAuthenticators & external_authenticators,
|
const ExternalAuthenticators & external_authenticators,
|
||||||
SettingsChanges & settings) const
|
SettingsChanges & settings) const
|
||||||
@ -553,21 +573,20 @@ bool IAccessStorage::areCredentialsValid(
|
|||||||
if (!credentials.isReady())
|
if (!credentials.isReady())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (credentials.getUserName() != user.getName())
|
if (credentials.getUserName() != user_name)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (user.valid_until)
|
if (valid_until)
|
||||||
{
|
{
|
||||||
const time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
const time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||||
|
|
||||||
if (now > user.valid_until)
|
if (now > valid_until)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Authentication::areCredentialsValid(credentials, user.auth_data, external_authenticators, settings);
|
return Authentication::areCredentialsValid(credentials, authentication_method, external_authenticators, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool IAccessStorage::isAddressAllowed(const User & user, const Poco::Net::IPAddress & address) const
|
bool IAccessStorage::isAddressAllowed(const User & user, const Poco::Net::IPAddress & address) const
|
||||||
{
|
{
|
||||||
return user.allowed_client_hosts.contains(address);
|
return user.allowed_client_hosts.contains(address);
|
||||||
@ -595,12 +614,51 @@ void IAccessStorage::backup(BackupEntriesCollector & backup_entries_collector, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void IAccessStorage::restoreFromBackup(RestorerFromBackup &)
|
void IAccessStorage::restoreFromBackup(RestorerFromBackup & restorer)
|
||||||
{
|
{
|
||||||
if (!isRestoreAllowed())
|
if (!isRestoreAllowed())
|
||||||
throwRestoreNotAllowed();
|
throwRestoreNotAllowed();
|
||||||
|
|
||||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "restoreFromBackup() is not implemented in {}", getStorageType());
|
if (isReplicated() && !acquireReplicatedRestore(restorer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto entities = restorer.getAccessEntitiesToRestore();
|
||||||
|
if (entities.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto create_access = restorer.getRestoreSettings().create_access;
|
||||||
|
bool replace_if_exists = (create_access == RestoreAccessCreationMode::kReplace);
|
||||||
|
bool throw_if_exists = (create_access == RestoreAccessCreationMode::kCreate);
|
||||||
|
|
||||||
|
restorer.addDataRestoreTask([this, entities_to_restore = std::move(entities), replace_if_exists, throw_if_exists] mutable
|
||||||
|
{
|
||||||
|
std::unordered_map<UUID, UUID> new_to_existing_ids;
|
||||||
|
for (auto & [id, entity] : entities_to_restore)
|
||||||
|
{
|
||||||
|
UUID existing_entity_id;
|
||||||
|
if (!insert(id, entity, replace_if_exists, throw_if_exists, &existing_entity_id))
|
||||||
|
{
|
||||||
|
/// Couldn't insert `entity` because there is an existing entity with the same name.
|
||||||
|
new_to_existing_ids[id] = existing_entity_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new_to_existing_ids.empty())
|
||||||
|
{
|
||||||
|
/// If new entities restored from backup have dependencies on other entities from backup which were not restored because they existed,
|
||||||
|
/// then we should correct those dependencies.
|
||||||
|
auto update_func = [&](const AccessEntityPtr & entity) -> AccessEntityPtr
|
||||||
|
{
|
||||||
|
auto res = entity;
|
||||||
|
IAccessEntity::replaceDependencies(res, new_to_existing_ids);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
std::vector<UUID> ids;
|
||||||
|
ids.reserve(entities_to_restore.size());
|
||||||
|
boost::copy(entities_to_restore | boost::adaptors::map_keys, std::back_inserter(ids));
|
||||||
|
tryUpdate(ids, update_func);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -747,14 +805,6 @@ void IAccessStorage::throwAddressNotAllowed(const Poco::Net::IPAddress & address
|
|||||||
throw Exception(ErrorCodes::IP_ADDRESS_NOT_ALLOWED, "Connections from {} are not allowed", address.toString());
|
throw Exception(ErrorCodes::IP_ADDRESS_NOT_ALLOWED, "Connections from {} are not allowed", address.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAccessStorage::throwAuthenticationTypeNotAllowed(AuthenticationType auth_type)
|
|
||||||
{
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::AUTHENTICATION_FAILED,
|
|
||||||
"Authentication type {} is not allowed, check the setting allow_{} in the server configuration",
|
|
||||||
toString(auth_type), AuthenticationTypeInfo::get(auth_type).name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IAccessStorage::throwInvalidCredentials()
|
void IAccessStorage::throwInvalidCredentials()
|
||||||
{
|
{
|
||||||
throw Exception(ErrorCodes::WRONG_PASSWORD, "Invalid credentials");
|
throw Exception(ErrorCodes::WRONG_PASSWORD, "Invalid credentials");
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Access/IAccessEntity.h>
|
#include <Access/IAccessEntity.h>
|
||||||
|
#include <Access/AuthenticationData.h>
|
||||||
#include <Core/Types.h>
|
#include <Core/Types.h>
|
||||||
#include <Core/UUID.h>
|
#include <Core/UUID.h>
|
||||||
#include <Parsers/IParser.h>
|
#include <Parsers/IParser.h>
|
||||||
@ -34,6 +35,7 @@ struct AuthResult
|
|||||||
UUID user_id;
|
UUID user_id;
|
||||||
/// Session settings received from authentication server (if any)
|
/// Session settings received from authentication server (if any)
|
||||||
SettingsChanges settings{};
|
SettingsChanges settings{};
|
||||||
|
AuthenticationData authentication_data {};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Contains entities, i.e. instances of classes derived from IAccessEntity.
|
/// Contains entities, i.e. instances of classes derived from IAccessEntity.
|
||||||
@ -62,6 +64,9 @@ public:
|
|||||||
/// Returns true if this entity is readonly.
|
/// Returns true if this entity is readonly.
|
||||||
virtual bool isReadOnly(const UUID &) const { return isReadOnly(); }
|
virtual bool isReadOnly(const UUID &) const { return isReadOnly(); }
|
||||||
|
|
||||||
|
/// Returns true if this storage is replicated.
|
||||||
|
virtual bool isReplicated() const { return false; }
|
||||||
|
|
||||||
/// Starts periodic reloading and updating of entities in this storage.
|
/// Starts periodic reloading and updating of entities in this storage.
|
||||||
virtual void startPeriodicReloading() {}
|
virtual void startPeriodicReloading() {}
|
||||||
|
|
||||||
@ -151,8 +156,8 @@ public:
|
|||||||
/// Inserts an entity to the storage. Returns ID of a new entry in the storage.
|
/// Inserts an entity to the storage. Returns ID of a new entry in the storage.
|
||||||
/// Throws an exception if the specified name already exists.
|
/// Throws an exception if the specified name already exists.
|
||||||
UUID insert(const AccessEntityPtr & entity);
|
UUID insert(const AccessEntityPtr & entity);
|
||||||
std::optional<UUID> insert(const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists);
|
std::optional<UUID> insert(const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id = nullptr);
|
||||||
bool insert(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists);
|
bool insert(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id = nullptr);
|
||||||
std::vector<UUID> insert(const std::vector<AccessEntityPtr> & multiple_entities, bool replace_if_exists = false, bool throw_if_exists = true);
|
std::vector<UUID> insert(const std::vector<AccessEntityPtr> & multiple_entities, bool replace_if_exists = false, bool throw_if_exists = true);
|
||||||
std::vector<UUID> insert(const std::vector<AccessEntityPtr> & multiple_entities, const std::vector<UUID> & ids, bool replace_if_exists = false, bool throw_if_exists = true);
|
std::vector<UUID> insert(const std::vector<AccessEntityPtr> & multiple_entities, const std::vector<UUID> & ids, bool replace_if_exists = false, bool throw_if_exists = true);
|
||||||
|
|
||||||
@ -216,7 +221,7 @@ protected:
|
|||||||
virtual std::vector<UUID> findAllImpl(AccessEntityType type) const = 0;
|
virtual std::vector<UUID> findAllImpl(AccessEntityType type) const = 0;
|
||||||
virtual AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const = 0;
|
virtual AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const = 0;
|
||||||
virtual std::optional<std::pair<String, AccessEntityType>> readNameWithTypeImpl(const UUID & id, bool throw_if_not_exists) const;
|
virtual std::optional<std::pair<String, AccessEntityType>> readNameWithTypeImpl(const UUID & id, bool throw_if_not_exists) const;
|
||||||
virtual bool insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists);
|
virtual bool insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id);
|
||||||
virtual bool removeImpl(const UUID & id, bool throw_if_not_exists);
|
virtual bool removeImpl(const UUID & id, bool throw_if_not_exists);
|
||||||
virtual bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists);
|
virtual bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists);
|
||||||
virtual std::optional<AuthResult> authenticateImpl(
|
virtual std::optional<AuthResult> authenticateImpl(
|
||||||
@ -227,7 +232,9 @@ protected:
|
|||||||
bool allow_no_password,
|
bool allow_no_password,
|
||||||
bool allow_plaintext_password) const;
|
bool allow_plaintext_password) const;
|
||||||
virtual bool areCredentialsValid(
|
virtual bool areCredentialsValid(
|
||||||
const User & user,
|
const std::string & user_name,
|
||||||
|
time_t valid_until,
|
||||||
|
const AuthenticationData & authentication_method,
|
||||||
const Credentials & credentials,
|
const Credentials & credentials,
|
||||||
const ExternalAuthenticators & external_authenticators,
|
const ExternalAuthenticators & external_authenticators,
|
||||||
SettingsChanges & settings) const;
|
SettingsChanges & settings) const;
|
||||||
@ -236,6 +243,7 @@ protected:
|
|||||||
LoggerPtr getLogger() const;
|
LoggerPtr getLogger() const;
|
||||||
static String formatEntityTypeWithName(AccessEntityType type, const String & name) { return AccessEntityTypeInfo::get(type).formatEntityNameWithType(name); }
|
static String formatEntityTypeWithName(AccessEntityType type, const String & name) { return AccessEntityTypeInfo::get(type).formatEntityNameWithType(name); }
|
||||||
static void clearConflictsInEntitiesList(std::vector<std::pair<UUID, AccessEntityPtr>> & entities, LoggerPtr log_);
|
static void clearConflictsInEntitiesList(std::vector<std::pair<UUID, AccessEntityPtr>> & entities, LoggerPtr log_);
|
||||||
|
virtual bool acquireReplicatedRestore(RestorerFromBackup &) const { return false; }
|
||||||
[[noreturn]] void throwNotFound(const UUID & id) const;
|
[[noreturn]] void throwNotFound(const UUID & id) const;
|
||||||
[[noreturn]] void throwNotFound(AccessEntityType type, const String & name) const;
|
[[noreturn]] void throwNotFound(AccessEntityType type, const String & name) const;
|
||||||
[[noreturn]] static void throwBadCast(const UUID & id, AccessEntityType type, const String & name, AccessEntityType required_type);
|
[[noreturn]] static void throwBadCast(const UUID & id, AccessEntityType type, const String & name, AccessEntityType required_type);
|
||||||
@ -248,7 +256,6 @@ protected:
|
|||||||
[[noreturn]] void throwReadonlyCannotRemove(AccessEntityType type, const String & name) const;
|
[[noreturn]] void throwReadonlyCannotRemove(AccessEntityType type, const String & name) const;
|
||||||
[[noreturn]] static void throwAddressNotAllowed(const Poco::Net::IPAddress & address);
|
[[noreturn]] static void throwAddressNotAllowed(const Poco::Net::IPAddress & address);
|
||||||
[[noreturn]] static void throwInvalidCredentials();
|
[[noreturn]] static void throwInvalidCredentials();
|
||||||
[[noreturn]] static void throwAuthenticationTypeNotAllowed(AuthenticationType auth_type);
|
|
||||||
[[noreturn]] void throwBackupNotAllowed() const;
|
[[noreturn]] void throwBackupNotAllowed() const;
|
||||||
[[noreturn]] void throwRestoreNotAllowed() const;
|
[[noreturn]] void throwRestoreNotAllowed() const;
|
||||||
|
|
||||||
|
@ -468,8 +468,8 @@ std::optional<AuthResult> LDAPAccessStorage::authenticateImpl(
|
|||||||
// User does not exist, so we create one, and will add it if authentication is successful.
|
// User does not exist, so we create one, and will add it if authentication is successful.
|
||||||
new_user = std::make_shared<User>();
|
new_user = std::make_shared<User>();
|
||||||
new_user->setName(credentials.getUserName());
|
new_user->setName(credentials.getUserName());
|
||||||
new_user->auth_data = AuthenticationData(AuthenticationType::LDAP);
|
new_user->authentication_methods.emplace_back(AuthenticationType::LDAP);
|
||||||
new_user->auth_data.setLDAPServerName(ldap_server_name);
|
new_user->authentication_methods.back().setLDAPServerName(ldap_server_name);
|
||||||
user = new_user;
|
user = new_user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,7 +504,7 @@ std::optional<AuthResult> LDAPAccessStorage::authenticateImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id)
|
if (id)
|
||||||
return AuthResult{ .user_id = *id };
|
return AuthResult{ .user_id = *id, .authentication_data = AuthenticationData(AuthenticationType::LDAP) };
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include <Access/MemoryAccessStorage.h>
|
#include <Access/MemoryAccessStorage.h>
|
||||||
#include <Access/AccessChangesNotifier.h>
|
#include <Access/AccessChangesNotifier.h>
|
||||||
#include <Backups/RestorerFromBackup.h>
|
|
||||||
#include <Backups/RestoreSettings.h>
|
|
||||||
#include <base/scope_guard.h>
|
#include <base/scope_guard.h>
|
||||||
#include <boost/container/flat_set.hpp>
|
#include <boost/container/flat_set.hpp>
|
||||||
#include <boost/range/adaptor/map.hpp>
|
#include <boost/range/adaptor/map.hpp>
|
||||||
@ -63,14 +61,14 @@ AccessEntityPtr MemoryAccessStorage::readImpl(const UUID & id, bool throw_if_not
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool MemoryAccessStorage::insertImpl(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists)
|
bool MemoryAccessStorage::insertImpl(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id)
|
||||||
{
|
{
|
||||||
std::lock_guard lock{mutex};
|
std::lock_guard lock{mutex};
|
||||||
return insertNoLock(id, new_entity, replace_if_exists, throw_if_exists);
|
return insertNoLock(id, new_entity, replace_if_exists, throw_if_exists, conflicting_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool MemoryAccessStorage::insertNoLock(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists)
|
bool MemoryAccessStorage::insertNoLock(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id)
|
||||||
{
|
{
|
||||||
const String & name = new_entity->getName();
|
const String & name = new_entity->getName();
|
||||||
AccessEntityType type = new_entity->getType();
|
AccessEntityType type = new_entity->getType();
|
||||||
@ -86,10 +84,16 @@ bool MemoryAccessStorage::insertNoLock(const UUID & id, const AccessEntityPtr &
|
|||||||
if (name_collision && !replace_if_exists)
|
if (name_collision && !replace_if_exists)
|
||||||
{
|
{
|
||||||
if (throw_if_exists)
|
if (throw_if_exists)
|
||||||
|
{
|
||||||
throwNameCollisionCannotInsert(type, name);
|
throwNameCollisionCannotInsert(type, name);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (conflicting_id)
|
||||||
|
*conflicting_id = id_by_name;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto it_by_id = entries_by_id.find(id);
|
auto it_by_id = entries_by_id.find(id);
|
||||||
bool id_collision = (it_by_id != entries_by_id.end());
|
bool id_collision = (it_by_id != entries_by_id.end());
|
||||||
@ -97,10 +101,16 @@ bool MemoryAccessStorage::insertNoLock(const UUID & id, const AccessEntityPtr &
|
|||||||
{
|
{
|
||||||
const auto & existing_entry = it_by_id->second;
|
const auto & existing_entry = it_by_id->second;
|
||||||
if (throw_if_exists)
|
if (throw_if_exists)
|
||||||
|
{
|
||||||
throwIDCollisionCannotInsert(id, type, name, existing_entry.entity->getType(), existing_entry.entity->getName());
|
throwIDCollisionCannotInsert(id, type, name, existing_entry.entity->getType(), existing_entry.entity->getName());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (conflicting_id)
|
||||||
|
*conflicting_id = id;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Remove collisions if necessary.
|
/// Remove collisions if necessary.
|
||||||
if (name_collision && (id_by_name != id))
|
if (name_collision && (id_by_name != id))
|
||||||
@ -270,28 +280,7 @@ void MemoryAccessStorage::setAll(const std::vector<std::pair<UUID, AccessEntityP
|
|||||||
|
|
||||||
/// Insert or update entities.
|
/// Insert or update entities.
|
||||||
for (const auto & [id, entity] : entities_without_conflicts)
|
for (const auto & [id, entity] : entities_without_conflicts)
|
||||||
insertNoLock(id, entity, /* replace_if_exists = */ true, /* throw_if_exists = */ false);
|
insertNoLock(id, entity, /* replace_if_exists = */ true, /* throw_if_exists = */ false, /* conflicting_id = */ nullptr);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MemoryAccessStorage::restoreFromBackup(RestorerFromBackup & restorer)
|
|
||||||
{
|
|
||||||
if (!isRestoreAllowed())
|
|
||||||
throwRestoreNotAllowed();
|
|
||||||
|
|
||||||
auto entities = restorer.getAccessEntitiesToRestore();
|
|
||||||
if (entities.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto create_access = restorer.getRestoreSettings().create_access;
|
|
||||||
bool replace_if_exists = (create_access == RestoreAccessCreationMode::kReplace);
|
|
||||||
bool throw_if_exists = (create_access == RestoreAccessCreationMode::kCreate);
|
|
||||||
|
|
||||||
restorer.addDataRestoreTask([this, my_entities = std::move(entities), replace_if_exists, throw_if_exists]
|
|
||||||
{
|
|
||||||
for (const auto & [id, entity] : my_entities)
|
|
||||||
insert(id, entity, replace_if_exists, throw_if_exists);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,17 +34,16 @@ public:
|
|||||||
bool exists(const UUID & id) const override;
|
bool exists(const UUID & id) const override;
|
||||||
|
|
||||||
bool isBackupAllowed() const override { return backup_allowed; }
|
bool isBackupAllowed() const override { return backup_allowed; }
|
||||||
void restoreFromBackup(RestorerFromBackup & restorer) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
|
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
|
||||||
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
|
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
|
||||||
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
|
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
|
||||||
bool insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists) override;
|
bool insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id) override;
|
||||||
bool removeImpl(const UUID & id, bool throw_if_not_exists) override;
|
bool removeImpl(const UUID & id, bool throw_if_not_exists) override;
|
||||||
bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists) override;
|
bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists) override;
|
||||||
|
|
||||||
bool insertNoLock(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists);
|
bool insertNoLock(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id);
|
||||||
bool removeNoLock(const UUID & id, bool throw_if_not_exists);
|
bool removeNoLock(const UUID & id, bool throw_if_not_exists);
|
||||||
bool updateNoLock(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists);
|
bool updateNoLock(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists);
|
||||||
|
|
||||||
|
@ -353,7 +353,7 @@ void MultipleAccessStorage::reload(ReloadMode reload_mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool MultipleAccessStorage::insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists)
|
bool MultipleAccessStorage::insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id)
|
||||||
{
|
{
|
||||||
std::shared_ptr<IAccessStorage> storage_for_insertion;
|
std::shared_ptr<IAccessStorage> storage_for_insertion;
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ bool MultipleAccessStorage::insertImpl(const UUID & id, const AccessEntityPtr &
|
|||||||
getStorageName());
|
getStorageName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (storage_for_insertion->insert(id, entity, replace_if_exists, throw_if_exists))
|
if (storage_for_insertion->insert(id, entity, replace_if_exists, throw_if_exists, conflicting_id))
|
||||||
{
|
{
|
||||||
std::lock_guard lock{mutex};
|
std::lock_guard lock{mutex};
|
||||||
ids_cache.set(id, storage_for_insertion);
|
ids_cache.set(id, storage_for_insertion);
|
||||||
|
@ -67,7 +67,7 @@ protected:
|
|||||||
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
|
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
|
||||||
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
|
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
|
||||||
std::optional<std::pair<String, AccessEntityType>> readNameWithTypeImpl(const UUID & id, bool throw_if_not_exists) const override;
|
std::optional<std::pair<String, AccessEntityType>> readNameWithTypeImpl(const UUID & id, bool throw_if_not_exists) const override;
|
||||||
bool insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists) override;
|
bool insertImpl(const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id) override;
|
||||||
bool removeImpl(const UUID & id, bool throw_if_not_exists) override;
|
bool removeImpl(const UUID & id, bool throw_if_not_exists) override;
|
||||||
bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists) override;
|
bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists) override;
|
||||||
std::optional<AuthResult> authenticateImpl(const Credentials & credentials, const Poco::Net::IPAddress & address, const ExternalAuthenticators & external_authenticators, bool throw_if_user_not_exists, bool allow_no_password, bool allow_plaintext_password) const override;
|
std::optional<AuthResult> authenticateImpl(const Credentials & credentials, const Poco::Net::IPAddress & address, const ExternalAuthenticators & external_authenticators, bool throw_if_user_not_exists, bool allow_no_password, bool allow_plaintext_password) const override;
|
||||||
|
@ -24,7 +24,7 @@ std::vector<UUID> Quota::findDependencies() const
|
|||||||
return to_roles.findDependencies();
|
return to_roles.findDependencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Quota::replaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
void Quota::doReplaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
||||||
{
|
{
|
||||||
to_roles.replaceDependencies(old_to_new_ids);
|
to_roles.replaceDependencies(old_to_new_ids);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ struct Quota : public IAccessEntity
|
|||||||
AccessEntityType getType() const override { return TYPE; }
|
AccessEntityType getType() const override { return TYPE; }
|
||||||
|
|
||||||
std::vector<UUID> findDependencies() const override;
|
std::vector<UUID> findDependencies() const override;
|
||||||
void replaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids) override;
|
void doReplaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids) override;
|
||||||
bool isBackupAllowed() const override { return true; }
|
bool isBackupAllowed() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,10 +5,9 @@
|
|||||||
#include <Access/AccessChangesNotifier.h>
|
#include <Access/AccessChangesNotifier.h>
|
||||||
#include <Access/AccessBackup.h>
|
#include <Access/AccessBackup.h>
|
||||||
#include <Backups/BackupEntriesCollector.h>
|
#include <Backups/BackupEntriesCollector.h>
|
||||||
#include <Backups/RestorerFromBackup.h>
|
|
||||||
#include <Backups/RestoreSettings.h>
|
|
||||||
#include <Backups/IBackupCoordination.h>
|
#include <Backups/IBackupCoordination.h>
|
||||||
#include <Backups/IRestoreCoordination.h>
|
#include <Backups/IRestoreCoordination.h>
|
||||||
|
#include <Backups/RestorerFromBackup.h>
|
||||||
#include <IO/ReadHelpers.h>
|
#include <IO/ReadHelpers.h>
|
||||||
#include <Interpreters/Context.h>
|
#include <Interpreters/Context.h>
|
||||||
#include <Common/ZooKeeper/KeeperException.h>
|
#include <Common/ZooKeeper/KeeperException.h>
|
||||||
@ -120,7 +119,7 @@ static void retryOnZooKeeperUserError(size_t attempts, Func && function)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReplicatedAccessStorage::insertImpl(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists)
|
bool ReplicatedAccessStorage::insertImpl(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id)
|
||||||
{
|
{
|
||||||
const AccessEntityTypeInfo type_info = AccessEntityTypeInfo::get(new_entity->getType());
|
const AccessEntityTypeInfo type_info = AccessEntityTypeInfo::get(new_entity->getType());
|
||||||
const String & name = new_entity->getName();
|
const String & name = new_entity->getName();
|
||||||
@ -128,7 +127,7 @@ bool ReplicatedAccessStorage::insertImpl(const UUID & id, const AccessEntityPtr
|
|||||||
|
|
||||||
auto zookeeper = getZooKeeper();
|
auto zookeeper = getZooKeeper();
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
retryOnZooKeeperUserError(10, [&]{ ok = insertZooKeeper(zookeeper, id, new_entity, replace_if_exists, throw_if_exists); });
|
retryOnZooKeeperUserError(10, [&]{ ok = insertZooKeeper(zookeeper, id, new_entity, replace_if_exists, throw_if_exists, conflicting_id); });
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
return false;
|
return false;
|
||||||
@ -143,7 +142,8 @@ bool ReplicatedAccessStorage::insertZooKeeper(
|
|||||||
const UUID & id,
|
const UUID & id,
|
||||||
const AccessEntityPtr & new_entity,
|
const AccessEntityPtr & new_entity,
|
||||||
bool replace_if_exists,
|
bool replace_if_exists,
|
||||||
bool throw_if_exists)
|
bool throw_if_exists,
|
||||||
|
UUID * conflicting_id)
|
||||||
{
|
{
|
||||||
const String & name = new_entity->getName();
|
const String & name = new_entity->getName();
|
||||||
const AccessEntityType type = new_entity->getType();
|
const AccessEntityType type = new_entity->getType();
|
||||||
@ -167,16 +167,16 @@ bool ReplicatedAccessStorage::insertZooKeeper(
|
|||||||
|
|
||||||
if (res == Coordination::Error::ZNODEEXISTS)
|
if (res == Coordination::Error::ZNODEEXISTS)
|
||||||
{
|
{
|
||||||
if (!throw_if_exists && !replace_if_exists)
|
if (!replace_if_exists)
|
||||||
return false; /// Couldn't insert a new entity.
|
|
||||||
|
|
||||||
if (throw_if_exists)
|
|
||||||
{
|
{
|
||||||
if (responses[0]->error == Coordination::Error::ZNODEEXISTS)
|
if (responses[0]->error == Coordination::Error::ZNODEEXISTS)
|
||||||
|
{
|
||||||
|
/// Couldn't insert the new entity because there is an existing entity with such UUID.
|
||||||
|
if (throw_if_exists)
|
||||||
{
|
{
|
||||||
/// To fail with a nice error message, we need info about what already exists.
|
/// To fail with a nice error message, we need info about what already exists.
|
||||||
/// This itself could fail if the conflicting uuid disappears in the meantime.
|
/// This itself can fail if the conflicting uuid disappears in the meantime.
|
||||||
/// If that happens, then we'll just retry from the start.
|
/// If that happens, then retryOnZooKeeperUserError() will just retry the operation from the start.
|
||||||
String existing_entity_definition = zookeeper->get(entity_path);
|
String existing_entity_definition = zookeeper->get(entity_path);
|
||||||
|
|
||||||
AccessEntityPtr existing_entity = deserializeAccessEntity(existing_entity_definition, entity_path);
|
AccessEntityPtr existing_entity = deserializeAccessEntity(existing_entity_definition, entity_path);
|
||||||
@ -186,9 +186,34 @@ bool ReplicatedAccessStorage::insertZooKeeper(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/// Couldn't insert the new entity because there is an existing entity with such name.
|
if (conflicting_id)
|
||||||
|
*conflicting_id = id;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (responses[1]->error == Coordination::Error::ZNODEEXISTS)
|
||||||
|
{
|
||||||
|
/// Couldn't insert the new entity because there is an existing entity with the same name.
|
||||||
|
if (throw_if_exists)
|
||||||
|
{
|
||||||
throwNameCollisionCannotInsert(type, name);
|
throwNameCollisionCannotInsert(type, name);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (conflicting_id)
|
||||||
|
{
|
||||||
|
/// Get UUID of the existing entry with the same name.
|
||||||
|
/// This itself can fail if the conflicting name disappears in the meantime.
|
||||||
|
/// If that happens, then retryOnZooKeeperUserError() will just retry the operation from the start.
|
||||||
|
*conflicting_id = parseUUID(zookeeper->get(name_path));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zkutil::KeeperMultiException::check(res, ops, responses);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(replace_if_exists);
|
assert(replace_if_exists);
|
||||||
@ -693,28 +718,10 @@ void ReplicatedAccessStorage::backup(BackupEntriesCollector & backup_entries_col
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ReplicatedAccessStorage::restoreFromBackup(RestorerFromBackup & restorer)
|
bool ReplicatedAccessStorage::acquireReplicatedRestore(RestorerFromBackup & restorer) const
|
||||||
{
|
{
|
||||||
if (!isRestoreAllowed())
|
|
||||||
throwRestoreNotAllowed();
|
|
||||||
|
|
||||||
auto restore_coordination = restorer.getRestoreCoordination();
|
auto restore_coordination = restorer.getRestoreCoordination();
|
||||||
if (!restore_coordination->acquireReplicatedAccessStorage(zookeeper_path))
|
return restore_coordination->acquireReplicatedAccessStorage(zookeeper_path);
|
||||||
return;
|
|
||||||
|
|
||||||
auto entities = restorer.getAccessEntitiesToRestore();
|
|
||||||
if (entities.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto create_access = restorer.getRestoreSettings().create_access;
|
|
||||||
bool replace_if_exists = (create_access == RestoreAccessCreationMode::kReplace);
|
|
||||||
bool throw_if_exists = (create_access == RestoreAccessCreationMode::kCreate);
|
|
||||||
|
|
||||||
restorer.addDataRestoreTask([this, my_entities = std::move(entities), replace_if_exists, throw_if_exists]
|
|
||||||
{
|
|
||||||
for (const auto & [id, entity] : my_entities)
|
|
||||||
insert(id, entity, replace_if_exists, throw_if_exists);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ public:
|
|||||||
void shutdown() override;
|
void shutdown() override;
|
||||||
|
|
||||||
const char * getStorageType() const override { return STORAGE_TYPE; }
|
const char * getStorageType() const override { return STORAGE_TYPE; }
|
||||||
|
bool isReplicated() const override { return true; }
|
||||||
|
|
||||||
void startPeriodicReloading() override { startWatchingThread(); }
|
void startPeriodicReloading() override { startWatchingThread(); }
|
||||||
void stopPeriodicReloading() override { stopWatchingThread(); }
|
void stopPeriodicReloading() override { stopWatchingThread(); }
|
||||||
@ -35,7 +36,6 @@ public:
|
|||||||
|
|
||||||
bool isBackupAllowed() const override { return backup_allowed; }
|
bool isBackupAllowed() const override { return backup_allowed; }
|
||||||
void backup(BackupEntriesCollector & backup_entries_collector, const String & data_path_in_backup, AccessEntityType type) const override;
|
void backup(BackupEntriesCollector & backup_entries_collector, const String & data_path_in_backup, AccessEntityType type) const override;
|
||||||
void restoreFromBackup(RestorerFromBackup & restorer) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
String zookeeper_path;
|
String zookeeper_path;
|
||||||
@ -48,11 +48,11 @@ private:
|
|||||||
std::unique_ptr<ThreadFromGlobalPool> watching_thread;
|
std::unique_ptr<ThreadFromGlobalPool> watching_thread;
|
||||||
std::shared_ptr<ConcurrentBoundedQueue<UUID>> watched_queue;
|
std::shared_ptr<ConcurrentBoundedQueue<UUID>> watched_queue;
|
||||||
|
|
||||||
bool insertImpl(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists) override;
|
bool insertImpl(const UUID & id, const AccessEntityPtr & new_entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id) override;
|
||||||
bool removeImpl(const UUID & id, bool throw_if_not_exists) override;
|
bool removeImpl(const UUID & id, bool throw_if_not_exists) override;
|
||||||
bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists) override;
|
bool updateImpl(const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists) override;
|
||||||
|
|
||||||
bool insertZooKeeper(const zkutil::ZooKeeperPtr & zookeeper, const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists);
|
bool insertZooKeeper(const zkutil::ZooKeeperPtr & zookeeper, const UUID & id, const AccessEntityPtr & entity, bool replace_if_exists, bool throw_if_exists, UUID * conflicting_id);
|
||||||
bool removeZooKeeper(const zkutil::ZooKeeperPtr & zookeeper, const UUID & id, bool throw_if_not_exists);
|
bool removeZooKeeper(const zkutil::ZooKeeperPtr & zookeeper, const UUID & id, bool throw_if_not_exists);
|
||||||
bool updateZooKeeper(const zkutil::ZooKeeperPtr & zookeeper, const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists);
|
bool updateZooKeeper(const zkutil::ZooKeeperPtr & zookeeper, const UUID & id, const UpdateFunc & update_func, bool throw_if_not_exists);
|
||||||
|
|
||||||
@ -80,6 +80,7 @@ private:
|
|||||||
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
|
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
|
||||||
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
|
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
|
||||||
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
|
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
|
||||||
|
bool acquireReplicatedRestore(RestorerFromBackup & restorer) const override;
|
||||||
|
|
||||||
mutable std::mutex mutex;
|
mutable std::mutex mutex;
|
||||||
MemoryAccessStorage memory_storage TSA_GUARDED_BY(mutex);
|
MemoryAccessStorage memory_storage TSA_GUARDED_BY(mutex);
|
||||||
|
@ -21,7 +21,7 @@ std::vector<UUID> Role::findDependencies() const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Role::replaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
void Role::doReplaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
||||||
{
|
{
|
||||||
granted_roles.replaceDependencies(old_to_new_ids);
|
granted_roles.replaceDependencies(old_to_new_ids);
|
||||||
settings.replaceDependencies(old_to_new_ids);
|
settings.replaceDependencies(old_to_new_ids);
|
||||||
|
@ -21,7 +21,7 @@ struct Role : public IAccessEntity
|
|||||||
AccessEntityType getType() const override { return TYPE; }
|
AccessEntityType getType() const override { return TYPE; }
|
||||||
|
|
||||||
std::vector<UUID> findDependencies() const override;
|
std::vector<UUID> findDependencies() const override;
|
||||||
void replaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids) override;
|
void doReplaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids) override;
|
||||||
bool isBackupAllowed() const override { return settings.isBackupAllowed(); }
|
bool isBackupAllowed() const override { return settings.isBackupAllowed(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ std::vector<UUID> RowPolicy::findDependencies() const
|
|||||||
return to_roles.findDependencies();
|
return to_roles.findDependencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RowPolicy::replaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
void RowPolicy::doReplaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
||||||
{
|
{
|
||||||
to_roles.replaceDependencies(old_to_new_ids);
|
to_roles.replaceDependencies(old_to_new_ids);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ struct RowPolicy : public IAccessEntity
|
|||||||
AccessEntityType getType() const override { return TYPE; }
|
AccessEntityType getType() const override { return TYPE; }
|
||||||
|
|
||||||
std::vector<UUID> findDependencies() const override;
|
std::vector<UUID> findDependencies() const override;
|
||||||
void replaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids) override;
|
void doReplaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids) override;
|
||||||
bool isBackupAllowed() const override { return true; }
|
bool isBackupAllowed() const override { return true; }
|
||||||
|
|
||||||
/// Which roles or users should use this row policy.
|
/// Which roles or users should use this row policy.
|
||||||
|
@ -21,7 +21,7 @@ std::vector<UUID> SettingsProfile::findDependencies() const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsProfile::replaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
void SettingsProfile::doReplaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
||||||
{
|
{
|
||||||
elements.replaceDependencies(old_to_new_ids);
|
elements.replaceDependencies(old_to_new_ids);
|
||||||
to_roles.replaceDependencies(old_to_new_ids);
|
to_roles.replaceDependencies(old_to_new_ids);
|
||||||
|
@ -22,7 +22,7 @@ struct SettingsProfile : public IAccessEntity
|
|||||||
AccessEntityType getType() const override { return TYPE; }
|
AccessEntityType getType() const override { return TYPE; }
|
||||||
|
|
||||||
std::vector<UUID> findDependencies() const override;
|
std::vector<UUID> findDependencies() const override;
|
||||||
void replaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids) override;
|
void doReplaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids) override;
|
||||||
bool isBackupAllowed() const override { return elements.isBackupAllowed(); }
|
bool isBackupAllowed() const override { return elements.isBackupAllowed(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@ bool User::equal(const IAccessEntity & other) const
|
|||||||
if (!IAccessEntity::equal(other))
|
if (!IAccessEntity::equal(other))
|
||||||
return false;
|
return false;
|
||||||
const auto & other_user = typeid_cast<const User &>(other);
|
const auto & other_user = typeid_cast<const User &>(other);
|
||||||
return (auth_data == other_user.auth_data) && (allowed_client_hosts == other_user.allowed_client_hosts)
|
return (authentication_methods == other_user.authentication_methods)
|
||||||
|
&& (allowed_client_hosts == other_user.allowed_client_hosts)
|
||||||
&& (access == other_user.access) && (granted_roles == other_user.granted_roles) && (default_roles == other_user.default_roles)
|
&& (access == other_user.access) && (granted_roles == other_user.granted_roles) && (default_roles == other_user.default_roles)
|
||||||
&& (settings == other_user.settings) && (grantees == other_user.grantees) && (default_database == other_user.default_database)
|
&& (settings == other_user.settings) && (grantees == other_user.grantees) && (default_database == other_user.default_database)
|
||||||
&& (valid_until == other_user.valid_until);
|
&& (valid_until == other_user.valid_until);
|
||||||
@ -48,7 +49,7 @@ std::vector<UUID> User::findDependencies() const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void User::replaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
void User::doReplaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids)
|
||||||
{
|
{
|
||||||
default_roles.replaceDependencies(old_to_new_ids);
|
default_roles.replaceDependencies(old_to_new_ids);
|
||||||
granted_roles.replaceDependencies(old_to_new_ids);
|
granted_roles.replaceDependencies(old_to_new_ids);
|
||||||
|
@ -15,7 +15,7 @@ namespace DB
|
|||||||
*/
|
*/
|
||||||
struct User : public IAccessEntity
|
struct User : public IAccessEntity
|
||||||
{
|
{
|
||||||
AuthenticationData auth_data;
|
std::vector<AuthenticationData> authentication_methods;
|
||||||
AllowedClientHosts allowed_client_hosts = AllowedClientHosts::AnyHostTag{};
|
AllowedClientHosts allowed_client_hosts = AllowedClientHosts::AnyHostTag{};
|
||||||
AccessRights access;
|
AccessRights access;
|
||||||
GrantedRoles granted_roles;
|
GrantedRoles granted_roles;
|
||||||
@ -32,7 +32,7 @@ struct User : public IAccessEntity
|
|||||||
void setName(const String & name_) override;
|
void setName(const String & name_) override;
|
||||||
|
|
||||||
std::vector<UUID> findDependencies() const override;
|
std::vector<UUID> findDependencies() const override;
|
||||||
void replaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids) override;
|
void doReplaceDependencies(const std::unordered_map<UUID, UUID> & old_to_new_ids) override;
|
||||||
bool isBackupAllowed() const override { return settings.isBackupAllowed(); }
|
bool isBackupAllowed() const override { return settings.isBackupAllowed(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -155,18 +155,18 @@ namespace
|
|||||||
|
|
||||||
if (has_password_plaintext)
|
if (has_password_plaintext)
|
||||||
{
|
{
|
||||||
user->auth_data = AuthenticationData{AuthenticationType::PLAINTEXT_PASSWORD};
|
user->authentication_methods.emplace_back(AuthenticationType::PLAINTEXT_PASSWORD);
|
||||||
user->auth_data.setPassword(config.getString(user_config + ".password"));
|
user->authentication_methods.back().setPassword(config.getString(user_config + ".password"));
|
||||||
}
|
}
|
||||||
else if (has_password_sha256_hex)
|
else if (has_password_sha256_hex)
|
||||||
{
|
{
|
||||||
user->auth_data = AuthenticationData{AuthenticationType::SHA256_PASSWORD};
|
user->authentication_methods.emplace_back(AuthenticationType::SHA256_PASSWORD);
|
||||||
user->auth_data.setPasswordHashHex(config.getString(user_config + ".password_sha256_hex"));
|
user->authentication_methods.back().setPasswordHashHex(config.getString(user_config + ".password_sha256_hex"));
|
||||||
}
|
}
|
||||||
else if (has_password_double_sha1_hex)
|
else if (has_password_double_sha1_hex)
|
||||||
{
|
{
|
||||||
user->auth_data = AuthenticationData{AuthenticationType::DOUBLE_SHA1_PASSWORD};
|
user->authentication_methods.emplace_back(AuthenticationType::DOUBLE_SHA1_PASSWORD);
|
||||||
user->auth_data.setPasswordHashHex(config.getString(user_config + ".password_double_sha1_hex"));
|
user->authentication_methods.back().setPasswordHashHex(config.getString(user_config + ".password_double_sha1_hex"));
|
||||||
}
|
}
|
||||||
else if (has_ldap)
|
else if (has_ldap)
|
||||||
{
|
{
|
||||||
@ -178,19 +178,19 @@ namespace
|
|||||||
if (ldap_server_name.empty())
|
if (ldap_server_name.empty())
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "LDAP server name cannot be empty for user {}.", user_name);
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "LDAP server name cannot be empty for user {}.", user_name);
|
||||||
|
|
||||||
user->auth_data = AuthenticationData{AuthenticationType::LDAP};
|
user->authentication_methods.emplace_back(AuthenticationType::LDAP);
|
||||||
user->auth_data.setLDAPServerName(ldap_server_name);
|
user->authentication_methods.back().setLDAPServerName(ldap_server_name);
|
||||||
}
|
}
|
||||||
else if (has_kerberos)
|
else if (has_kerberos)
|
||||||
{
|
{
|
||||||
const auto realm = config.getString(user_config + ".kerberos.realm", "");
|
const auto realm = config.getString(user_config + ".kerberos.realm", "");
|
||||||
|
|
||||||
user->auth_data = AuthenticationData{AuthenticationType::KERBEROS};
|
user->authentication_methods.emplace_back(AuthenticationType::KERBEROS);
|
||||||
user->auth_data.setKerberosRealm(realm);
|
user->authentication_methods.back().setKerberosRealm(realm);
|
||||||
}
|
}
|
||||||
else if (has_certificates)
|
else if (has_certificates)
|
||||||
{
|
{
|
||||||
user->auth_data = AuthenticationData{AuthenticationType::SSL_CERTIFICATE};
|
user->authentication_methods.emplace_back(AuthenticationType::SSL_CERTIFICATE);
|
||||||
|
|
||||||
/// Fill list of allowed certificates.
|
/// Fill list of allowed certificates.
|
||||||
Poco::Util::AbstractConfiguration::Keys keys;
|
Poco::Util::AbstractConfiguration::Keys keys;
|
||||||
@ -200,14 +200,14 @@ namespace
|
|||||||
if (key.starts_with("common_name"))
|
if (key.starts_with("common_name"))
|
||||||
{
|
{
|
||||||
String value = config.getString(certificates_config + "." + key);
|
String value = config.getString(certificates_config + "." + key);
|
||||||
user->auth_data.addSSLCertificateSubject(SSLCertificateSubjects::Type::CN, std::move(value));
|
user->authentication_methods.back().addSSLCertificateSubject(SSLCertificateSubjects::Type::CN, std::move(value));
|
||||||
}
|
}
|
||||||
else if (key.starts_with("subject_alt_name"))
|
else if (key.starts_with("subject_alt_name"))
|
||||||
{
|
{
|
||||||
String value = config.getString(certificates_config + "." + key);
|
String value = config.getString(certificates_config + "." + key);
|
||||||
if (value.empty())
|
if (value.empty())
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Expected ssl_certificates.subject_alt_name to not be empty");
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Expected ssl_certificates.subject_alt_name to not be empty");
|
||||||
user->auth_data.addSSLCertificateSubject(SSLCertificateSubjects::Type::SAN, std::move(value));
|
user->authentication_methods.back().addSSLCertificateSubject(SSLCertificateSubjects::Type::SAN, std::move(value));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown certificate pattern type: {}", key);
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown certificate pattern type: {}", key);
|
||||||
@ -216,7 +216,7 @@ namespace
|
|||||||
else if (has_ssh_keys)
|
else if (has_ssh_keys)
|
||||||
{
|
{
|
||||||
#if USE_SSH
|
#if USE_SSH
|
||||||
user->auth_data = AuthenticationData{AuthenticationType::SSH_KEY};
|
user->authentication_methods.emplace_back(AuthenticationType::SSH_KEY);
|
||||||
|
|
||||||
Poco::Util::AbstractConfiguration::Keys entries;
|
Poco::Util::AbstractConfiguration::Keys entries;
|
||||||
config.keys(ssh_keys_config, entries);
|
config.keys(ssh_keys_config, entries);
|
||||||
@ -253,20 +253,26 @@ namespace
|
|||||||
else
|
else
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown ssh_key entry pattern type: {}", entry);
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown ssh_key entry pattern type: {}", entry);
|
||||||
}
|
}
|
||||||
user->auth_data.setSSHKeys(std::move(keys));
|
user->authentication_methods.back().setSSHKeys(std::move(keys));
|
||||||
#else
|
#else
|
||||||
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "SSH is disabled, because ClickHouse is built without libssh");
|
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "SSH is disabled, because ClickHouse is built without libssh");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (has_http_auth)
|
else if (has_http_auth)
|
||||||
{
|
{
|
||||||
user->auth_data = AuthenticationData{AuthenticationType::HTTP};
|
user->authentication_methods.emplace_back(AuthenticationType::HTTP);
|
||||||
user->auth_data.setHTTPAuthenticationServerName(config.getString(http_auth_config + ".server"));
|
user->authentication_methods.back().setHTTPAuthenticationServerName(config.getString(http_auth_config + ".server"));
|
||||||
auto scheme = config.getString(http_auth_config + ".scheme");
|
auto scheme = config.getString(http_auth_config + ".scheme");
|
||||||
user->auth_data.setHTTPAuthenticationScheme(parseHTTPAuthenticationScheme(scheme));
|
user->authentication_methods.back().setHTTPAuthenticationScheme(parseHTTPAuthenticationScheme(scheme));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user->authentication_methods.emplace_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto auth_type = user->auth_data.getType();
|
for (const auto & authentication_method : user->authentication_methods)
|
||||||
|
{
|
||||||
|
auto auth_type = authentication_method.getType();
|
||||||
if (((auth_type == AuthenticationType::NO_PASSWORD) && !allow_no_password) ||
|
if (((auth_type == AuthenticationType::NO_PASSWORD) && !allow_no_password) ||
|
||||||
((auth_type == AuthenticationType::PLAINTEXT_PASSWORD) && !allow_plaintext_password))
|
((auth_type == AuthenticationType::PLAINTEXT_PASSWORD) && !allow_plaintext_password))
|
||||||
{
|
{
|
||||||
@ -274,6 +280,7 @@ namespace
|
|||||||
"Authentication type {} is not allowed, check the setting allow_{} in the server configuration",
|
"Authentication type {} is not allowed, check the setting allow_{} in the server configuration",
|
||||||
toString(auth_type), AuthenticationTypeInfo::get(auth_type).name);
|
toString(auth_type), AuthenticationTypeInfo::get(auth_type).name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const auto profile_name_config = user_config + ".profile";
|
const auto profile_name_config = user_config + ".profile";
|
||||||
if (config.has(profile_name_config))
|
if (config.has(profile_name_config))
|
||||||
|
@ -3,195 +3,27 @@
|
|||||||
#include <Parsers/FunctionSecretArgumentsFinder.h>
|
#include <Parsers/FunctionSecretArgumentsFinder.h>
|
||||||
#include <Analyzer/ConstantNode.h>
|
#include <Analyzer/ConstantNode.h>
|
||||||
#include <Analyzer/FunctionNode.h>
|
#include <Analyzer/FunctionNode.h>
|
||||||
#include <Analyzer/IQueryTreeNode.h>
|
|
||||||
#include <Analyzer/IdentifierNode.h>
|
#include <Analyzer/IdentifierNode.h>
|
||||||
#include <Analyzer/ListNode.h>
|
|
||||||
#include <Common/KnownObjectNames.h>
|
|
||||||
#include <Core/QualifiedTableName.h>
|
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class FunctionTreeNode : public AbstractFunction
|
||||||
/// Finds arguments of a specified function which should not be displayed for most users for security reasons.
|
|
||||||
/// That involves passwords and secret keys.
|
|
||||||
class FunctionSecretArgumentsFinderTreeNode
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit FunctionSecretArgumentsFinderTreeNode(const FunctionNode & function_) : function(function_), arguments(function.getArguments())
|
class ArgumentTreeNode : public Argument
|
||||||
{
|
{
|
||||||
if (arguments.getNodes().empty())
|
public:
|
||||||
return;
|
explicit ArgumentTreeNode(const IQueryTreeNode * argument_) : argument(argument_) {}
|
||||||
|
std::unique_ptr<AbstractFunction> getFunction() const override
|
||||||
findFunctionSecretArguments();
|
{
|
||||||
|
if (const auto * f = argument->as<FunctionNode>())
|
||||||
|
return std::make_unique<FunctionTreeNode>(*f);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
bool isIdentifier() const override { return argument->as<IdentifierNode>(); }
|
||||||
struct Result
|
bool tryGetString(String * res, bool allow_identifier) const override
|
||||||
{
|
|
||||||
/// Result constructed by default means no arguments will be hidden.
|
|
||||||
size_t start = static_cast<size_t>(-1);
|
|
||||||
size_t count = 0; /// Mostly it's either 0 or 1. There are only a few cases where `count` can be greater than 1 (e.g. see `encrypt`).
|
|
||||||
/// In all known cases secret arguments are consecutive
|
|
||||||
bool are_named = false; /// Arguments like `password = 'password'` are considered as named arguments.
|
|
||||||
/// E.g. "headers" in `url('..', headers('foo' = '[HIDDEN]'))`
|
|
||||||
std::vector<std::string> nested_maps;
|
|
||||||
|
|
||||||
bool hasSecrets() const
|
|
||||||
{
|
|
||||||
return count != 0 || !nested_maps.empty();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
FunctionSecretArgumentsFinder::Result getResult() const { return result; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const FunctionNode & function;
|
|
||||||
const ListNode & arguments;
|
|
||||||
FunctionSecretArgumentsFinder::Result result;
|
|
||||||
|
|
||||||
void markSecretArgument(size_t index, bool argument_is_named = false)
|
|
||||||
{
|
|
||||||
if (index >= arguments.getNodes().size())
|
|
||||||
return;
|
|
||||||
if (!result.count)
|
|
||||||
{
|
|
||||||
result.start = index;
|
|
||||||
result.are_named = argument_is_named;
|
|
||||||
}
|
|
||||||
chassert(index >= result.start); /// We always check arguments consecutively
|
|
||||||
result.count = index + 1 - result.start;
|
|
||||||
if (!argument_is_named)
|
|
||||||
result.are_named = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void findFunctionSecretArguments()
|
|
||||||
{
|
|
||||||
const auto & name = function.getFunctionName();
|
|
||||||
|
|
||||||
if ((name == "mysql") || (name == "postgresql") || (name == "mongodb"))
|
|
||||||
{
|
|
||||||
/// mysql('host:port', 'database', 'table', 'user', 'password', ...)
|
|
||||||
/// postgresql('host:port', 'database', 'table', 'user', 'password', ...)
|
|
||||||
/// mongodb('host:port', 'database', 'collection', 'user', 'password', ...)
|
|
||||||
findMySQLFunctionSecretArguments();
|
|
||||||
}
|
|
||||||
else if ((name == "s3") || (name == "cosn") || (name == "oss") ||
|
|
||||||
(name == "deltaLake") || (name == "hudi") || (name == "iceberg"))
|
|
||||||
{
|
|
||||||
/// s3('url', 'aws_access_key_id', 'aws_secret_access_key', ...)
|
|
||||||
findS3FunctionSecretArguments(/* is_cluster_function= */ false);
|
|
||||||
}
|
|
||||||
else if (name == "s3Cluster")
|
|
||||||
{
|
|
||||||
/// s3Cluster('cluster_name', 'url', 'aws_access_key_id', 'aws_secret_access_key', ...)
|
|
||||||
findS3FunctionSecretArguments(/* is_cluster_function= */ true);
|
|
||||||
}
|
|
||||||
else if ((name == "remote") || (name == "remoteSecure"))
|
|
||||||
{
|
|
||||||
/// remote('addresses_expr', 'db', 'table', 'user', 'password', ...)
|
|
||||||
findRemoteFunctionSecretArguments();
|
|
||||||
}
|
|
||||||
else if ((name == "encrypt") || (name == "decrypt") ||
|
|
||||||
(name == "aes_encrypt_mysql") || (name == "aes_decrypt_mysql") ||
|
|
||||||
(name == "tryDecrypt"))
|
|
||||||
{
|
|
||||||
/// encrypt('mode', 'plaintext', 'key' [, iv, aad])
|
|
||||||
findEncryptionFunctionSecretArguments();
|
|
||||||
}
|
|
||||||
else if (name == "url")
|
|
||||||
{
|
|
||||||
findURLSecretArguments();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void findMySQLFunctionSecretArguments()
|
|
||||||
{
|
|
||||||
if (isNamedCollectionName(0))
|
|
||||||
{
|
|
||||||
/// mysql(named_collection, ..., password = 'password', ...)
|
|
||||||
findSecretNamedArgument("password", 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/// mysql('host:port', 'database', 'table', 'user', 'password', ...)
|
|
||||||
markSecretArgument(4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of arguments excluding "headers" and "extra_credentials" (which should
|
|
||||||
/// always be at the end). Marks "headers" as secret, if found.
|
|
||||||
size_t excludeS3OrURLNestedMaps()
|
|
||||||
{
|
|
||||||
const auto & nodes = arguments.getNodes();
|
|
||||||
size_t count = nodes.size();
|
|
||||||
while (count > 0)
|
|
||||||
{
|
|
||||||
const FunctionNode * f = nodes.at(count - 1)->as<FunctionNode>();
|
|
||||||
if (!f)
|
|
||||||
break;
|
|
||||||
if (f->getFunctionName() == "headers")
|
|
||||||
result.nested_maps.push_back(f->getFunctionName());
|
|
||||||
else if (f->getFunctionName() != "extra_credentials")
|
|
||||||
break;
|
|
||||||
count -= 1;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void findS3FunctionSecretArguments(bool is_cluster_function)
|
|
||||||
{
|
|
||||||
/// s3Cluster('cluster_name', 'url', ...) has 'url' as its second argument.
|
|
||||||
size_t url_arg_idx = is_cluster_function ? 1 : 0;
|
|
||||||
|
|
||||||
if (!is_cluster_function && isNamedCollectionName(0))
|
|
||||||
{
|
|
||||||
/// s3(named_collection, ..., secret_access_key = 'secret_access_key', ...)
|
|
||||||
findSecretNamedArgument("secret_access_key", 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// We should check other arguments first because we don't need to do any replacement in case of
|
|
||||||
/// s3('url', NOSIGN, 'format' [, 'compression'] [, extra_credentials(..)] [, headers(..)])
|
|
||||||
/// s3('url', 'format', 'structure' [, 'compression'] [, extra_credentials(..)] [, headers(..)])
|
|
||||||
size_t count = excludeS3OrURLNestedMaps();
|
|
||||||
if ((url_arg_idx + 3 <= count) && (count <= url_arg_idx + 4))
|
|
||||||
{
|
|
||||||
String second_arg;
|
|
||||||
if (tryGetStringFromArgument(url_arg_idx + 1, &second_arg))
|
|
||||||
{
|
|
||||||
if (boost::iequals(second_arg, "NOSIGN"))
|
|
||||||
return; /// The argument after 'url' is "NOSIGN".
|
|
||||||
|
|
||||||
if (second_arg == "auto" || KnownFormatNames::instance().exists(second_arg))
|
|
||||||
return; /// The argument after 'url' is a format: s3('url', 'format', ...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// We're going to replace 'aws_secret_access_key' with '[HIDDEN]' for the following signatures:
|
|
||||||
/// s3('url', 'aws_access_key_id', 'aws_secret_access_key', ...)
|
|
||||||
/// s3Cluster('cluster_name', 'url', 'aws_access_key_id', 'aws_secret_access_key', 'format', 'compression')
|
|
||||||
if (url_arg_idx + 2 < count)
|
|
||||||
markSecretArgument(url_arg_idx + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void findURLSecretArguments()
|
|
||||||
{
|
|
||||||
if (!isNamedCollectionName(0))
|
|
||||||
excludeS3OrURLNestedMaps();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tryGetStringFromArgument(size_t arg_idx, String * res, bool allow_identifier = true) const
|
|
||||||
{
|
|
||||||
if (arg_idx >= arguments.getNodes().size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return tryGetStringFromArgument(arguments.getNodes()[arg_idx], res, allow_identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool tryGetStringFromArgument(const QueryTreeNodePtr argument, String * res, bool allow_identifier = true)
|
|
||||||
{
|
{
|
||||||
if (const auto * literal = argument->as<ConstantNode>())
|
if (const auto * literal = argument->as<ConstantNode>())
|
||||||
{
|
{
|
||||||
@ -214,159 +46,46 @@ private:
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
const IQueryTreeNode * argument = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
void findRemoteFunctionSecretArguments()
|
class ArgumentsTreeNode : public Arguments
|
||||||
{
|
{
|
||||||
if (isNamedCollectionName(0))
|
public:
|
||||||
|
explicit ArgumentsTreeNode(const QueryTreeNodes * arguments_) : arguments(arguments_) {}
|
||||||
|
size_t size() const override { return arguments ? arguments->size() : 0; }
|
||||||
|
std::unique_ptr<Argument> at(size_t n) const override { return std::make_unique<ArgumentTreeNode>(arguments->at(n).get()); }
|
||||||
|
private:
|
||||||
|
const QueryTreeNodes * arguments = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit FunctionTreeNode(const FunctionNode & function_) : function(&function_)
|
||||||
{
|
{
|
||||||
/// remote(named_collection, ..., password = 'password', ...)
|
if (const auto & nodes = function->getArguments().getNodes(); !nodes.empty())
|
||||||
findSecretNamedArgument("password", 1);
|
arguments = std::make_unique<ArgumentsTreeNode>(&nodes);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
String name() const override { return function->getFunctionName(); }
|
||||||
|
private:
|
||||||
|
const FunctionNode * function = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
/// We're going to replace 'password' with '[HIDDEN'] for the following signatures:
|
|
||||||
/// remote('addresses_expr', db.table, 'user' [, 'password'] [, sharding_key])
|
|
||||||
/// remote('addresses_expr', 'db', 'table', 'user' [, 'password'] [, sharding_key])
|
|
||||||
/// remote('addresses_expr', table_function(), 'user' [, 'password'] [, sharding_key])
|
|
||||||
|
|
||||||
/// But we should check the number of arguments first because we don't need to do any replacements in case of
|
/// Finds arguments of a specified function which should not be displayed for most users for security reasons.
|
||||||
/// remote('addresses_expr', db.table)
|
/// That involves passwords and secret keys.
|
||||||
if (arguments.getNodes().size() < 3)
|
class FunctionSecretArgumentsFinderTreeNode : public FunctionSecretArgumentsFinder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit FunctionSecretArgumentsFinderTreeNode(const FunctionNode & function_)
|
||||||
|
: FunctionSecretArgumentsFinder(std::make_unique<FunctionTreeNode>(function_))
|
||||||
|
{
|
||||||
|
if (!function->hasArguments())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
size_t arg_num = 1;
|
findOrdinaryFunctionSecretArguments();
|
||||||
|
|
||||||
/// Skip 1 or 2 arguments with table_function() or db.table or 'db', 'table'.
|
|
||||||
const auto * table_function = arguments.getNodes()[arg_num]->as<FunctionNode>();
|
|
||||||
if (table_function && KnownTableFunctionNames::instance().exists(table_function->getFunctionName()))
|
|
||||||
{
|
|
||||||
++arg_num;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::optional<String> database;
|
|
||||||
std::optional<QualifiedTableName> qualified_table_name;
|
|
||||||
if (!tryGetDatabaseNameOrQualifiedTableName(arg_num, database, qualified_table_name))
|
|
||||||
{
|
|
||||||
/// We couldn't evaluate the argument so we don't know whether it is 'db.table' or just 'db'.
|
|
||||||
/// Hence we can't figure out whether we should skip one argument 'user' or two arguments 'table', 'user'
|
|
||||||
/// before the argument 'password'. So it's safer to wipe two arguments just in case.
|
|
||||||
/// The last argument can be also a `sharding_key`, so we need to check that argument is a literal string
|
|
||||||
/// before wiping it (because the `password` argument is always a literal string).
|
|
||||||
if (tryGetStringFromArgument(arg_num + 2, nullptr, /* allow_identifier= */ false))
|
|
||||||
{
|
|
||||||
/// Wipe either `password` or `user`.
|
|
||||||
markSecretArgument(arg_num + 2);
|
|
||||||
}
|
|
||||||
if (tryGetStringFromArgument(arg_num + 3, nullptr, /* allow_identifier= */ false))
|
|
||||||
{
|
|
||||||
/// Wipe either `password` or `sharding_key`.
|
|
||||||
markSecretArgument(arg_num + 3);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Skip the current argument (which is either a database name or a qualified table name).
|
FunctionSecretArgumentsFinder::Result getResult() const { return result; }
|
||||||
++arg_num;
|
|
||||||
if (database)
|
|
||||||
{
|
|
||||||
/// Skip the 'table' argument if the previous argument was a database name.
|
|
||||||
++arg_num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Skip username.
|
|
||||||
++arg_num;
|
|
||||||
|
|
||||||
/// Do our replacement:
|
|
||||||
/// remote('addresses_expr', db.table, 'user', 'password', ...) -> remote('addresses_expr', db.table, 'user', '[HIDDEN]', ...)
|
|
||||||
/// The last argument can be also a `sharding_key`, so we need to check that argument is a literal string
|
|
||||||
/// before wiping it (because the `password` argument is always a literal string).
|
|
||||||
bool can_be_password = tryGetStringFromArgument(arg_num, nullptr, /* allow_identifier= */ false);
|
|
||||||
if (can_be_password)
|
|
||||||
markSecretArgument(arg_num);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tries to get either a database name or a qualified table name from an argument.
|
|
||||||
/// Empty string is also allowed (it means the default database).
|
|
||||||
/// The function is used by findRemoteFunctionSecretArguments() to determine how many arguments to skip before a password.
|
|
||||||
bool tryGetDatabaseNameOrQualifiedTableName(
|
|
||||||
size_t arg_idx,
|
|
||||||
std::optional<String> & res_database,
|
|
||||||
std::optional<QualifiedTableName> & res_qualified_table_name) const
|
|
||||||
{
|
|
||||||
res_database.reset();
|
|
||||||
res_qualified_table_name.reset();
|
|
||||||
|
|
||||||
String str;
|
|
||||||
if (!tryGetStringFromArgument(arg_idx, &str, /* allow_identifier= */ true))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (str.empty())
|
|
||||||
{
|
|
||||||
res_database = "";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto qualified_table_name = QualifiedTableName::tryParseFromString(str);
|
|
||||||
if (!qualified_table_name)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (qualified_table_name->database.empty())
|
|
||||||
res_database = std::move(qualified_table_name->table);
|
|
||||||
else
|
|
||||||
res_qualified_table_name = std::move(qualified_table_name);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void findEncryptionFunctionSecretArguments()
|
|
||||||
{
|
|
||||||
if (arguments.getNodes().empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
/// We replace all arguments after 'mode' with '[HIDDEN]':
|
|
||||||
/// encrypt('mode', 'plaintext', 'key' [, iv, aad]) -> encrypt('mode', '[HIDDEN]')
|
|
||||||
result.start = 1;
|
|
||||||
result.count = arguments.getNodes().size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Whether a specified argument can be the name of a named collection?
|
|
||||||
bool isNamedCollectionName(size_t arg_idx) const
|
|
||||||
{
|
|
||||||
if (arguments.getNodes().size() <= arg_idx)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto * identifier = arguments.getNodes()[arg_idx]->as<IdentifierNode>();
|
|
||||||
return identifier != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Looks for a secret argument with a specified name. This function looks for arguments in format `key=value` where the key is specified.
|
|
||||||
void findSecretNamedArgument(const std::string_view & key, size_t start = 0)
|
|
||||||
{
|
|
||||||
for (size_t i = start; i < arguments.getNodes().size(); ++i)
|
|
||||||
{
|
|
||||||
const auto & argument = arguments.getNodes()[i];
|
|
||||||
const auto * equals_func = argument->as<FunctionNode>();
|
|
||||||
if (!equals_func || (equals_func->getFunctionName() != "equals"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto * expr_list = equals_func->getArguments().as<ListNode>();
|
|
||||||
if (!expr_list)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto & equal_args = expr_list->getNodes();
|
|
||||||
if (equal_args.size() != 2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
String found_key;
|
|
||||||
if (!tryGetStringFromArgument(equal_args[0], &found_key))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (found_key == key)
|
|
||||||
markSecretArgument(i, /* argument_is_named= */ true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2564,8 +2564,8 @@ void checkFunctionNodeHasEmptyNullsAction(FunctionNode const & node)
|
|||||||
if (node.getNullsAction() != NullsAction::EMPTY)
|
if (node.getNullsAction() != NullsAction::EMPTY)
|
||||||
throw Exception(
|
throw Exception(
|
||||||
ErrorCodes::SYNTAX_ERROR,
|
ErrorCodes::SYNTAX_ERROR,
|
||||||
"Function with name '{}' cannot use {} NULLS",
|
"Function with name {} cannot use {} NULLS",
|
||||||
node.getFunctionName(),
|
backQuote(node.getFunctionName()),
|
||||||
node.getNullsAction() == NullsAction::IGNORE_NULLS ? "IGNORE" : "RESPECT");
|
node.getNullsAction() == NullsAction::IGNORE_NULLS ? "IGNORE" : "RESPECT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3228,16 +3228,16 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
|
|||||||
auto hints = NamePrompter<2>::getHints(function_name, possible_function_names);
|
auto hints = NamePrompter<2>::getHints(function_name, possible_function_names);
|
||||||
|
|
||||||
throw Exception(ErrorCodes::UNKNOWN_FUNCTION,
|
throw Exception(ErrorCodes::UNKNOWN_FUNCTION,
|
||||||
"Function with name '{}' does not exist. In scope {}{}",
|
"Function with name {} does not exist. In scope {}{}",
|
||||||
function_name,
|
backQuote(function_name),
|
||||||
scope.scope_node->formatASTForErrorMessage(),
|
scope.scope_node->formatASTForErrorMessage(),
|
||||||
getHintsErrorMessageSuffix(hints));
|
getHintsErrorMessageSuffix(hints));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!function_lambda_arguments_indexes.empty())
|
if (!function_lambda_arguments_indexes.empty())
|
||||||
throw Exception(ErrorCodes::UNSUPPORTED_METHOD,
|
throw Exception(ErrorCodes::UNSUPPORTED_METHOD,
|
||||||
"Aggregate function '{}' does not support lambda arguments",
|
"Aggregate function {} does not support lambda arguments",
|
||||||
function_name);
|
backQuote(function_name));
|
||||||
|
|
||||||
auto action = function_node_ptr->getNullsAction();
|
auto action = function_node_ptr->getNullsAction();
|
||||||
std::string aggregate_function_name = rewriteAggregateFunctionNameIfNeeded(function_name, action, scope.context);
|
std::string aggregate_function_name = rewriteAggregateFunctionNameIfNeeded(function_name, action, scope.context);
|
||||||
@ -3679,10 +3679,10 @@ ProjectionNames QueryAnalyzer::resolveExpressionNode(
|
|||||||
|
|
||||||
auto hints = IdentifierResolver::collectIdentifierTypoHints(unresolved_identifier, valid_identifiers);
|
auto hints = IdentifierResolver::collectIdentifierTypoHints(unresolved_identifier, valid_identifiers);
|
||||||
|
|
||||||
throw Exception(ErrorCodes::UNKNOWN_IDENTIFIER, "Unknown {}{} identifier '{}' in scope {}{}",
|
throw Exception(ErrorCodes::UNKNOWN_IDENTIFIER, "Unknown {}{} identifier {} in scope {}{}",
|
||||||
toStringLowercase(IdentifierLookupContext::EXPRESSION),
|
toStringLowercase(IdentifierLookupContext::EXPRESSION),
|
||||||
message_clarification,
|
message_clarification,
|
||||||
unresolved_identifier.getFullName(),
|
backQuote(unresolved_identifier.getFullName()),
|
||||||
scope.scope_node->formatASTForErrorMessage(),
|
scope.scope_node->formatASTForErrorMessage(),
|
||||||
getHintsErrorMessageSuffix(hints));
|
getHintsErrorMessageSuffix(hints));
|
||||||
}
|
}
|
||||||
|
@ -1875,11 +1875,11 @@ void ClientBase::processParsedSingleQuery(const String & full_query, const Strin
|
|||||||
|
|
||||||
if (const auto * create_user_query = parsed_query->as<ASTCreateUserQuery>())
|
if (const auto * create_user_query = parsed_query->as<ASTCreateUserQuery>())
|
||||||
{
|
{
|
||||||
if (!create_user_query->attach && create_user_query->auth_data)
|
if (!create_user_query->attach && !create_user_query->authentication_methods.empty())
|
||||||
{
|
{
|
||||||
if (const auto * auth_data = create_user_query->auth_data->as<ASTAuthenticationData>())
|
for (const auto & authentication_method : create_user_query->authentication_methods)
|
||||||
{
|
{
|
||||||
auto password = auth_data->getPassword();
|
auto password = authentication_method->getPassword();
|
||||||
|
|
||||||
if (password)
|
if (password)
|
||||||
client_context->getAccessControl().checkPasswordComplexityRules(*password);
|
client_context->getAccessControl().checkPasswordComplexityRules(*password);
|
||||||
|
@ -455,6 +455,9 @@ void Connection::sendAddendum()
|
|||||||
writeStringBinary(proto_recv_chunked, *out);
|
writeStringBinary(proto_recv_chunked, *out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (server_revision >= DBMS_MIN_REVISION_WITH_VERSIONED_PARALLEL_REPLICAS_PROTOCOL)
|
||||||
|
writeVarUInt(DBMS_PARALLEL_REPLICAS_PROTOCOL_VERSION, *out);
|
||||||
|
|
||||||
out->next();
|
out->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,6 +528,8 @@ void Connection::receiveHello(const Poco::Timespan & handshake_timeout)
|
|||||||
readVarUInt(server_version_major, *in);
|
readVarUInt(server_version_major, *in);
|
||||||
readVarUInt(server_version_minor, *in);
|
readVarUInt(server_version_minor, *in);
|
||||||
readVarUInt(server_revision, *in);
|
readVarUInt(server_revision, *in);
|
||||||
|
if (server_revision >= DBMS_MIN_REVISION_WITH_VERSIONED_PARALLEL_REPLICAS_PROTOCOL)
|
||||||
|
readVarUInt(server_parallel_replicas_protocol_version, *in);
|
||||||
if (server_revision >= DBMS_MIN_REVISION_WITH_SERVER_TIMEZONE)
|
if (server_revision >= DBMS_MIN_REVISION_WITH_SERVER_TIMEZONE)
|
||||||
readStringBinary(server_timezone, *in);
|
readStringBinary(server_timezone, *in);
|
||||||
if (server_revision >= DBMS_MIN_REVISION_WITH_SERVER_DISPLAY_NAME)
|
if (server_revision >= DBMS_MIN_REVISION_WITH_SERVER_DISPLAY_NAME)
|
||||||
@ -959,7 +964,7 @@ void Connection::sendReadTaskResponse(const String & response)
|
|||||||
void Connection::sendMergeTreeReadTaskResponse(const ParallelReadResponse & response)
|
void Connection::sendMergeTreeReadTaskResponse(const ParallelReadResponse & response)
|
||||||
{
|
{
|
||||||
writeVarUInt(Protocol::Client::MergeTreeReadTaskResponse, *out);
|
writeVarUInt(Protocol::Client::MergeTreeReadTaskResponse, *out);
|
||||||
response.serialize(*out);
|
response.serialize(*out, server_parallel_replicas_protocol_version);
|
||||||
out->finishChunk();
|
out->finishChunk();
|
||||||
out->next();
|
out->next();
|
||||||
}
|
}
|
||||||
@ -1413,7 +1418,7 @@ ParallelReadRequest Connection::receiveParallelReadRequest() const
|
|||||||
|
|
||||||
InitialAllRangesAnnouncement Connection::receiveInitialParallelReadAnnouncement() const
|
InitialAllRangesAnnouncement Connection::receiveInitialParallelReadAnnouncement() const
|
||||||
{
|
{
|
||||||
return InitialAllRangesAnnouncement::deserialize(*in);
|
return InitialAllRangesAnnouncement::deserialize(*in, server_parallel_replicas_protocol_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,6 +210,7 @@ private:
|
|||||||
UInt64 server_version_minor = 0;
|
UInt64 server_version_minor = 0;
|
||||||
UInt64 server_version_patch = 0;
|
UInt64 server_version_patch = 0;
|
||||||
UInt64 server_revision = 0;
|
UInt64 server_revision = 0;
|
||||||
|
UInt64 server_parallel_replicas_protocol_version = 0;
|
||||||
String server_timezone;
|
String server_timezone;
|
||||||
String server_display_name;
|
String server_display_name;
|
||||||
|
|
||||||
|
@ -178,6 +178,9 @@
|
|||||||
M(ObjectStorageAzureThreads, "Number of threads in the AzureObjectStorage thread pool.") \
|
M(ObjectStorageAzureThreads, "Number of threads in the AzureObjectStorage thread pool.") \
|
||||||
M(ObjectStorageAzureThreadsActive, "Number of threads in the AzureObjectStorage thread pool running a task.") \
|
M(ObjectStorageAzureThreadsActive, "Number of threads in the AzureObjectStorage thread pool running a task.") \
|
||||||
M(ObjectStorageAzureThreadsScheduled, "Number of queued or active jobs in the AzureObjectStorage thread pool.") \
|
M(ObjectStorageAzureThreadsScheduled, "Number of queued or active jobs in the AzureObjectStorage thread pool.") \
|
||||||
|
M(BuildVectorSimilarityIndexThreads, "Number of threads in the build vector similarity index thread pool.") \
|
||||||
|
M(BuildVectorSimilarityIndexThreadsActive, "Number of threads in the build vector similarity index thread pool running a task.") \
|
||||||
|
M(BuildVectorSimilarityIndexThreadsScheduled, "Number of queued or active jobs in the build vector similarity index thread pool.") \
|
||||||
\
|
\
|
||||||
M(DiskPlainRewritableAzureDirectoryMapSize, "Number of local-to-remote path entries in the 'plain_rewritable' in-memory map for AzureObjectStorage.") \
|
M(DiskPlainRewritableAzureDirectoryMapSize, "Number of local-to-remote path entries in the 'plain_rewritable' in-memory map for AzureObjectStorage.") \
|
||||||
M(DiskPlainRewritableLocalDirectoryMapSize, "Number of local-to-remote path entries in the 'plain_rewritable' in-memory map for LocalObjectStorage.") \
|
M(DiskPlainRewritableLocalDirectoryMapSize, "Number of local-to-remote path entries in the 'plain_rewritable' in-memory map for LocalObjectStorage.") \
|
||||||
|
@ -609,6 +609,7 @@
|
|||||||
M(728, UNEXPECTED_DATA_TYPE) \
|
M(728, UNEXPECTED_DATA_TYPE) \
|
||||||
M(729, ILLEGAL_TIME_SERIES_TAGS) \
|
M(729, ILLEGAL_TIME_SERIES_TAGS) \
|
||||||
M(730, REFRESH_FAILED) \
|
M(730, REFRESH_FAILED) \
|
||||||
|
M(731, QUERY_CACHE_USED_WITH_NON_THROW_OVERFLOW_MODE) \
|
||||||
\
|
\
|
||||||
M(900, DISTRIBUTED_CACHE_ERROR) \
|
M(900, DISTRIBUTED_CACHE_ERROR) \
|
||||||
M(901, CANNOT_USE_DISTRIBUTED_CACHE) \
|
M(901, CANNOT_USE_DISTRIBUTED_CACHE) \
|
||||||
|
@ -63,6 +63,8 @@ static struct InitFiu
|
|||||||
REGULAR(keepermap_fail_drop_data) \
|
REGULAR(keepermap_fail_drop_data) \
|
||||||
REGULAR(lazy_pipe_fds_fail_close) \
|
REGULAR(lazy_pipe_fds_fail_close) \
|
||||||
PAUSEABLE(infinite_sleep) \
|
PAUSEABLE(infinite_sleep) \
|
||||||
|
PAUSEABLE(stop_moving_part_before_swap_with_active) \
|
||||||
|
REGULAR(slowdown_index_analysis) \
|
||||||
|
|
||||||
|
|
||||||
namespace FailPoints
|
namespace FailPoints
|
||||||
|
@ -376,6 +376,7 @@ The server successfully detected this situation and will download merged part fr
|
|||||||
M(ParallelReplicasReadAssignedMarks, "Sum across all replicas of how many of scheduled marks were assigned by consistent hash") \
|
M(ParallelReplicasReadAssignedMarks, "Sum across all replicas of how many of scheduled marks were assigned by consistent hash") \
|
||||||
M(ParallelReplicasReadUnassignedMarks, "Sum across all replicas of how many unassigned marks were scheduled") \
|
M(ParallelReplicasReadUnassignedMarks, "Sum across all replicas of how many unassigned marks were scheduled") \
|
||||||
M(ParallelReplicasReadAssignedForStealingMarks, "Sum across all replicas of how many of scheduled marks were assigned for stealing by consistent hash") \
|
M(ParallelReplicasReadAssignedForStealingMarks, "Sum across all replicas of how many of scheduled marks were assigned for stealing by consistent hash") \
|
||||||
|
M(ParallelReplicasReadMarks, "How many marks were read by the given replica") \
|
||||||
\
|
\
|
||||||
M(ParallelReplicasStealingByHashMicroseconds, "Time spent collecting segments meant for stealing by hash") \
|
M(ParallelReplicasStealingByHashMicroseconds, "Time spent collecting segments meant for stealing by hash") \
|
||||||
M(ParallelReplicasProcessingPartsMicroseconds, "Time spent processing data parts") \
|
M(ParallelReplicasProcessingPartsMicroseconds, "Time spent processing data parts") \
|
||||||
@ -529,6 +530,7 @@ The server successfully detected this situation and will download merged part fr
|
|||||||
M(CachedReadBufferReadFromCacheMicroseconds, "Time reading from filesystem cache") \
|
M(CachedReadBufferReadFromCacheMicroseconds, "Time reading from filesystem cache") \
|
||||||
M(CachedReadBufferReadFromSourceBytes, "Bytes read from filesystem cache source (from remote fs, etc)") \
|
M(CachedReadBufferReadFromSourceBytes, "Bytes read from filesystem cache source (from remote fs, etc)") \
|
||||||
M(CachedReadBufferReadFromCacheBytes, "Bytes read from filesystem cache") \
|
M(CachedReadBufferReadFromCacheBytes, "Bytes read from filesystem cache") \
|
||||||
|
M(CachedReadBufferPredownloadedBytes, "Bytes read from filesystem cache source. Cache segments are read from left to right as a whole, it might be that we need to predownload some part of the segment irrelevant for the current task just to get to the needed data") \
|
||||||
M(CachedReadBufferCacheWriteBytes, "Bytes written from source (remote fs, etc) to filesystem cache") \
|
M(CachedReadBufferCacheWriteBytes, "Bytes written from source (remote fs, etc) to filesystem cache") \
|
||||||
M(CachedReadBufferCacheWriteMicroseconds, "Time spent writing data into filesystem cache") \
|
M(CachedReadBufferCacheWriteMicroseconds, "Time spent writing data into filesystem cache") \
|
||||||
M(CachedReadBufferCreateBufferMicroseconds, "Prepare buffer time") \
|
M(CachedReadBufferCreateBufferMicroseconds, "Prepare buffer time") \
|
||||||
|
@ -181,12 +181,6 @@ void SetACLRequest::addRootPath(const String & root_path) { Coordination::addRoo
|
|||||||
void GetACLRequest::addRootPath(const String & root_path) { Coordination::addRootPath(path, root_path); }
|
void GetACLRequest::addRootPath(const String & root_path) { Coordination::addRootPath(path, root_path); }
|
||||||
void SyncRequest::addRootPath(const String & root_path) { Coordination::addRootPath(path, root_path); }
|
void SyncRequest::addRootPath(const String & root_path) { Coordination::addRootPath(path, root_path); }
|
||||||
|
|
||||||
void MultiRequest::addRootPath(const String & root_path)
|
|
||||||
{
|
|
||||||
for (auto & request : requests)
|
|
||||||
request->addRootPath(root_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreateResponse::removeRootPath(const String & root_path) { Coordination::removeRootPath(path_created, root_path); }
|
void CreateResponse::removeRootPath(const String & root_path) { Coordination::removeRootPath(path_created, root_path); }
|
||||||
void WatchResponse::removeRootPath(const String & root_path) { Coordination::removeRootPath(path, root_path); }
|
void WatchResponse::removeRootPath(const String & root_path) { Coordination::removeRootPath(path, root_path); }
|
||||||
|
|
||||||
|
@ -408,11 +408,17 @@ struct ReconfigResponse : virtual Response
|
|||||||
size_t bytesSize() const override { return value.size() + sizeof(stat); }
|
size_t bytesSize() const override { return value.size() + sizeof(stat); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
struct MultiRequest : virtual Request
|
struct MultiRequest : virtual Request
|
||||||
{
|
{
|
||||||
Requests requests;
|
std::vector<T> requests;
|
||||||
|
|
||||||
|
void addRootPath(const String & root_path) override
|
||||||
|
{
|
||||||
|
for (auto & request : requests)
|
||||||
|
request->addRootPath(root_path);
|
||||||
|
}
|
||||||
|
|
||||||
void addRootPath(const String & root_path) override;
|
|
||||||
String getPath() const override { return {}; }
|
String getPath() const override { return {}; }
|
||||||
|
|
||||||
size_t bytesSize() const override
|
size_t bytesSize() const override
|
||||||
|
@ -184,7 +184,7 @@ struct TestKeeperReconfigRequest final : ReconfigRequest, TestKeeperRequest
|
|||||||
std::pair<ResponsePtr, Undo> process(TestKeeper::Container & container, int64_t zxid) const override;
|
std::pair<ResponsePtr, Undo> process(TestKeeper::Container & container, int64_t zxid) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestKeeperMultiRequest final : MultiRequest, TestKeeperRequest
|
struct TestKeeperMultiRequest final : MultiRequest<RequestPtr>, TestKeeperRequest
|
||||||
{
|
{
|
||||||
explicit TestKeeperMultiRequest(const Requests & generic_requests)
|
explicit TestKeeperMultiRequest(const Requests & generic_requests)
|
||||||
: TestKeeperMultiRequest(std::span(generic_requests))
|
: TestKeeperMultiRequest(std::span(generic_requests))
|
||||||
|
@ -18,14 +18,16 @@ using namespace DB;
|
|||||||
|
|
||||||
void ZooKeeperResponse::write(WriteBuffer & out) const
|
void ZooKeeperResponse::write(WriteBuffer & out) const
|
||||||
{
|
{
|
||||||
/// Excessive copy to calculate length.
|
auto response_size = Coordination::size(xid) + Coordination::size(zxid) + Coordination::size(error);
|
||||||
WriteBufferFromOwnString buf;
|
|
||||||
Coordination::write(xid, buf);
|
|
||||||
Coordination::write(zxid, buf);
|
|
||||||
Coordination::write(error, buf);
|
|
||||||
if (error == Error::ZOK)
|
if (error == Error::ZOK)
|
||||||
writeImpl(buf);
|
response_size += sizeImpl();
|
||||||
Coordination::write(buf.str(), out);
|
|
||||||
|
Coordination::write(static_cast<int32_t>(response_size), out);
|
||||||
|
Coordination::write(xid, out);
|
||||||
|
Coordination::write(zxid, out);
|
||||||
|
Coordination::write(error, out);
|
||||||
|
if (error == Error::ZOK)
|
||||||
|
writeImpl(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ZooKeeperRequest::toString(bool short_format) const
|
std::string ZooKeeperRequest::toString(bool short_format) const
|
||||||
@ -41,12 +43,12 @@ std::string ZooKeeperRequest::toString(bool short_format) const
|
|||||||
|
|
||||||
void ZooKeeperRequest::write(WriteBuffer & out) const
|
void ZooKeeperRequest::write(WriteBuffer & out) const
|
||||||
{
|
{
|
||||||
/// Excessive copy to calculate length.
|
auto request_size = Coordination::size(xid) + Coordination::size(getOpNum()) + sizeImpl();
|
||||||
WriteBufferFromOwnString buf;
|
|
||||||
Coordination::write(xid, buf);
|
Coordination::write(static_cast<int32_t>(request_size), out);
|
||||||
Coordination::write(getOpNum(), buf);
|
Coordination::write(xid, out);
|
||||||
writeImpl(buf);
|
Coordination::write(getOpNum(), out);
|
||||||
Coordination::write(buf.str(), out);
|
writeImpl(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZooKeeperSyncRequest::writeImpl(WriteBuffer & out) const
|
void ZooKeeperSyncRequest::writeImpl(WriteBuffer & out) const
|
||||||
@ -54,6 +56,11 @@ void ZooKeeperSyncRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(path, out);
|
Coordination::write(path, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperSyncRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperSyncRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperSyncRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(path, in);
|
Coordination::read(path, in);
|
||||||
@ -74,6 +81,11 @@ void ZooKeeperSyncResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(path, out);
|
Coordination::write(path, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperSyncResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperReconfigRequest::writeImpl(WriteBuffer & out) const
|
void ZooKeeperReconfigRequest::writeImpl(WriteBuffer & out) const
|
||||||
{
|
{
|
||||||
Coordination::write(joining, out);
|
Coordination::write(joining, out);
|
||||||
@ -82,6 +94,11 @@ void ZooKeeperReconfigRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(version, out);
|
Coordination::write(version, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperReconfigRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(joining) + Coordination::size(leaving) + Coordination::size(new_members) + Coordination::size(version);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperReconfigRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperReconfigRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(joining, in);
|
Coordination::read(joining, in);
|
||||||
@ -109,6 +126,11 @@ void ZooKeeperReconfigResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(stat, out);
|
Coordination::write(stat, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperReconfigResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(value) + Coordination::size(stat);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperWatchResponse::readImpl(ReadBuffer & in)
|
void ZooKeeperWatchResponse::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(type, in);
|
Coordination::read(type, in);
|
||||||
@ -123,6 +145,11 @@ void ZooKeeperWatchResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(path, out);
|
Coordination::write(path, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperWatchResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(type) + Coordination::size(state) + Coordination::size(path);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperWatchResponse::write(WriteBuffer & out) const
|
void ZooKeeperWatchResponse::write(WriteBuffer & out) const
|
||||||
{
|
{
|
||||||
if (error == Error::ZOK)
|
if (error == Error::ZOK)
|
||||||
@ -137,6 +164,11 @@ void ZooKeeperAuthRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(data, out);
|
Coordination::write(data, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperAuthRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(type) + Coordination::size(scheme) + Coordination::size(data);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperAuthRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperAuthRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(type, in);
|
Coordination::read(type, in);
|
||||||
@ -175,6 +207,12 @@ void ZooKeeperCreateRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(flags, out);
|
Coordination::write(flags, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperCreateRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
int32_t flags = 0;
|
||||||
|
return Coordination::size(path) + Coordination::size(data) + Coordination::size(acls) + Coordination::size(flags);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperCreateRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperCreateRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(path, in);
|
Coordination::read(path, in);
|
||||||
@ -211,12 +249,22 @@ void ZooKeeperCreateResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(path_created, out);
|
Coordination::write(path_created, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperCreateResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path_created);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperRemoveRequest::writeImpl(WriteBuffer & out) const
|
void ZooKeeperRemoveRequest::writeImpl(WriteBuffer & out) const
|
||||||
{
|
{
|
||||||
Coordination::write(path, out);
|
Coordination::write(path, out);
|
||||||
Coordination::write(version, out);
|
Coordination::write(version, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperRemoveRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path) + Coordination::size(version);
|
||||||
|
}
|
||||||
|
|
||||||
std::string ZooKeeperRemoveRequest::toStringImpl(bool /*short_format*/) const
|
std::string ZooKeeperRemoveRequest::toStringImpl(bool /*short_format*/) const
|
||||||
{
|
{
|
||||||
return fmt::format(
|
return fmt::format(
|
||||||
@ -244,6 +292,11 @@ void ZooKeeperRemoveRecursiveRequest::readImpl(ReadBuffer & in)
|
|||||||
Coordination::read(remove_nodes_limit, in);
|
Coordination::read(remove_nodes_limit, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperRemoveRecursiveRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path) + Coordination::size(remove_nodes_limit);
|
||||||
|
}
|
||||||
|
|
||||||
std::string ZooKeeperRemoveRecursiveRequest::toStringImpl(bool /*short_format*/) const
|
std::string ZooKeeperRemoveRecursiveRequest::toStringImpl(bool /*short_format*/) const
|
||||||
{
|
{
|
||||||
return fmt::format(
|
return fmt::format(
|
||||||
@ -259,6 +312,11 @@ void ZooKeeperExistsRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(has_watch, out);
|
Coordination::write(has_watch, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperExistsRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path) + Coordination::size(has_watch);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperExistsRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperExistsRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(path, in);
|
Coordination::read(path, in);
|
||||||
@ -280,12 +338,22 @@ void ZooKeeperExistsResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(stat, out);
|
Coordination::write(stat, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperExistsResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(stat);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperGetRequest::writeImpl(WriteBuffer & out) const
|
void ZooKeeperGetRequest::writeImpl(WriteBuffer & out) const
|
||||||
{
|
{
|
||||||
Coordination::write(path, out);
|
Coordination::write(path, out);
|
||||||
Coordination::write(has_watch, out);
|
Coordination::write(has_watch, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperGetRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path) + Coordination::size(has_watch);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperGetRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperGetRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(path, in);
|
Coordination::read(path, in);
|
||||||
@ -309,6 +377,11 @@ void ZooKeeperGetResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(stat, out);
|
Coordination::write(stat, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperGetResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(data) + Coordination::size(stat);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperSetRequest::writeImpl(WriteBuffer & out) const
|
void ZooKeeperSetRequest::writeImpl(WriteBuffer & out) const
|
||||||
{
|
{
|
||||||
Coordination::write(path, out);
|
Coordination::write(path, out);
|
||||||
@ -316,6 +389,11 @@ void ZooKeeperSetRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(version, out);
|
Coordination::write(version, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperSetRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path) + Coordination::size(data) + Coordination::size(version);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperSetRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperSetRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(path, in);
|
Coordination::read(path, in);
|
||||||
@ -342,12 +420,22 @@ void ZooKeeperSetResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(stat, out);
|
Coordination::write(stat, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperSetResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(stat);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperListRequest::writeImpl(WriteBuffer & out) const
|
void ZooKeeperListRequest::writeImpl(WriteBuffer & out) const
|
||||||
{
|
{
|
||||||
Coordination::write(path, out);
|
Coordination::write(path, out);
|
||||||
Coordination::write(has_watch, out);
|
Coordination::write(has_watch, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperListRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path) + Coordination::size(has_watch);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperListRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperListRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(path, in);
|
Coordination::read(path, in);
|
||||||
@ -366,6 +454,11 @@ void ZooKeeperFilteredListRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(static_cast<uint8_t>(list_request_type), out);
|
Coordination::write(static_cast<uint8_t>(list_request_type), out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperFilteredListRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path) + Coordination::size(has_watch) + Coordination::size(static_cast<uint8_t>(list_request_type));
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperFilteredListRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperFilteredListRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(path, in);
|
Coordination::read(path, in);
|
||||||
@ -397,6 +490,11 @@ void ZooKeeperListResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(stat, out);
|
Coordination::write(stat, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperListResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(names) + Coordination::size(stat);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperSimpleListResponse::readImpl(ReadBuffer & in)
|
void ZooKeeperSimpleListResponse::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(names, in);
|
Coordination::read(names, in);
|
||||||
@ -407,6 +505,11 @@ void ZooKeeperSimpleListResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(names, out);
|
Coordination::write(names, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperSimpleListResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(names);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperSetACLRequest::writeImpl(WriteBuffer & out) const
|
void ZooKeeperSetACLRequest::writeImpl(WriteBuffer & out) const
|
||||||
{
|
{
|
||||||
Coordination::write(path, out);
|
Coordination::write(path, out);
|
||||||
@ -414,6 +517,11 @@ void ZooKeeperSetACLRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(version, out);
|
Coordination::write(version, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperSetACLRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path) + Coordination::size(acls) + Coordination::size(version);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperSetACLRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperSetACLRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(path, in);
|
Coordination::read(path, in);
|
||||||
@ -431,6 +539,11 @@ void ZooKeeperSetACLResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(stat, out);
|
Coordination::write(stat, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperSetACLResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(stat);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperSetACLResponse::readImpl(ReadBuffer & in)
|
void ZooKeeperSetACLResponse::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(stat, in);
|
Coordination::read(stat, in);
|
||||||
@ -446,6 +559,11 @@ void ZooKeeperGetACLRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(path, out);
|
Coordination::write(path, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperGetACLRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path);
|
||||||
|
}
|
||||||
|
|
||||||
std::string ZooKeeperGetACLRequest::toStringImpl(bool /*short_format*/) const
|
std::string ZooKeeperGetACLRequest::toStringImpl(bool /*short_format*/) const
|
||||||
{
|
{
|
||||||
return fmt::format("path = {}", path);
|
return fmt::format("path = {}", path);
|
||||||
@ -457,6 +575,11 @@ void ZooKeeperGetACLResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(stat, out);
|
Coordination::write(stat, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperGetACLResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(acl) + Coordination::size(stat);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperGetACLResponse::readImpl(ReadBuffer & in)
|
void ZooKeeperGetACLResponse::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(acl, in);
|
Coordination::read(acl, in);
|
||||||
@ -469,6 +592,11 @@ void ZooKeeperCheckRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(version, out);
|
Coordination::write(version, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperCheckRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(path) + Coordination::size(version);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperCheckRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperCheckRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(path, in);
|
Coordination::read(path, in);
|
||||||
@ -494,6 +622,11 @@ void ZooKeeperErrorResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(error, out);
|
Coordination::write(error, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperErrorResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(error);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperMultiRequest::checkOperationType(OperationType type)
|
void ZooKeeperMultiRequest::checkOperationType(OperationType type)
|
||||||
{
|
{
|
||||||
chassert(!operation_type.has_value() || *operation_type == type);
|
chassert(!operation_type.has_value() || *operation_type == type);
|
||||||
@ -596,6 +729,27 @@ void ZooKeeperMultiRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(error, out);
|
Coordination::write(error, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperMultiRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
size_t total_size = 0;
|
||||||
|
for (const auto & request : requests)
|
||||||
|
{
|
||||||
|
const auto & zk_request = dynamic_cast<const ZooKeeperRequest &>(*request);
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
int32_t error = -1;
|
||||||
|
|
||||||
|
total_size
|
||||||
|
+= Coordination::size(zk_request.getOpNum()) + Coordination::size(done) + Coordination::size(error) + zk_request.sizeImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
OpNum op_num = OpNum::Error;
|
||||||
|
bool done = true;
|
||||||
|
int32_t error = -1;
|
||||||
|
|
||||||
|
return total_size + Coordination::size(op_num) + Coordination::size(done) + Coordination::size(error);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperMultiRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperMultiRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
@ -729,31 +883,54 @@ void ZooKeeperMultiResponse::writeImpl(WriteBuffer & out) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZooKeeperResponsePtr ZooKeeperHeartbeatRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperHeartbeatResponse>()); }
|
size_t ZooKeeperMultiResponse::sizeImpl() const
|
||||||
ZooKeeperResponsePtr ZooKeeperSyncRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperSyncResponse>()); }
|
{
|
||||||
ZooKeeperResponsePtr ZooKeeperAuthRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperAuthResponse>()); }
|
size_t total_size = 0;
|
||||||
ZooKeeperResponsePtr ZooKeeperRemoveRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperRemoveResponse>()); }
|
for (const auto & response : responses)
|
||||||
ZooKeeperResponsePtr ZooKeeperRemoveRecursiveRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperRemoveRecursiveResponse>()); }
|
{
|
||||||
ZooKeeperResponsePtr ZooKeeperExistsRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperExistsResponse>()); }
|
const ZooKeeperResponse & zk_response = dynamic_cast<const ZooKeeperResponse &>(*response);
|
||||||
ZooKeeperResponsePtr ZooKeeperGetRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperGetResponse>()); }
|
OpNum op_num = zk_response.getOpNum();
|
||||||
ZooKeeperResponsePtr ZooKeeperSetRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperSetResponse>()); }
|
bool done = false;
|
||||||
ZooKeeperResponsePtr ZooKeeperReconfigRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperReconfigResponse>()); }
|
Error op_error = zk_response.error;
|
||||||
ZooKeeperResponsePtr ZooKeeperListRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperListResponse>()); }
|
|
||||||
ZooKeeperResponsePtr ZooKeeperSimpleListRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperSimpleListResponse>()); }
|
total_size += Coordination::size(op_num) + Coordination::size(done) + Coordination::size(op_error);
|
||||||
|
if (op_error == Error::ZOK || op_num == OpNum::Error)
|
||||||
|
total_size += zk_response.sizeImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Footer.
|
||||||
|
OpNum op_num = OpNum::Error;
|
||||||
|
bool done = true;
|
||||||
|
int32_t error_read = - 1;
|
||||||
|
|
||||||
|
return total_size + Coordination::size(op_num) + Coordination::size(done) + Coordination::size(error_read);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZooKeeperResponsePtr ZooKeeperHeartbeatRequest::makeResponse() const { return std::make_shared<ZooKeeperHeartbeatResponse>(); }
|
||||||
|
ZooKeeperResponsePtr ZooKeeperSyncRequest::makeResponse() const { return std::make_shared<ZooKeeperSyncResponse>(); }
|
||||||
|
ZooKeeperResponsePtr ZooKeeperAuthRequest::makeResponse() const { return std::make_shared<ZooKeeperAuthResponse>(); }
|
||||||
|
ZooKeeperResponsePtr ZooKeeperRemoveRequest::makeResponse() const { return std::make_shared<ZooKeeperRemoveResponse>(); }
|
||||||
|
ZooKeeperResponsePtr ZooKeeperRemoveRecursiveRequest::makeResponse() const { return std::make_shared<ZooKeeperRemoveRecursiveResponse>(); }
|
||||||
|
ZooKeeperResponsePtr ZooKeeperExistsRequest::makeResponse() const { return std::make_shared<ZooKeeperExistsResponse>(); }
|
||||||
|
ZooKeeperResponsePtr ZooKeeperGetRequest::makeResponse() const { return std::make_shared<ZooKeeperGetResponse>(); }
|
||||||
|
ZooKeeperResponsePtr ZooKeeperSetRequest::makeResponse() const { return std::make_shared<ZooKeeperSetResponse>(); }
|
||||||
|
ZooKeeperResponsePtr ZooKeeperReconfigRequest::makeResponse() const { return std::make_shared<ZooKeeperReconfigResponse>(); }
|
||||||
|
ZooKeeperResponsePtr ZooKeeperListRequest::makeResponse() const { return std::make_shared<ZooKeeperListResponse>(); }
|
||||||
|
ZooKeeperResponsePtr ZooKeeperSimpleListRequest::makeResponse() const { return std::make_shared<ZooKeeperSimpleListResponse>(); }
|
||||||
|
|
||||||
ZooKeeperResponsePtr ZooKeeperCreateRequest::makeResponse() const
|
ZooKeeperResponsePtr ZooKeeperCreateRequest::makeResponse() const
|
||||||
{
|
{
|
||||||
if (not_exists)
|
if (not_exists)
|
||||||
return setTime(std::make_shared<ZooKeeperCreateIfNotExistsResponse>());
|
return std::make_shared<ZooKeeperCreateIfNotExistsResponse>();
|
||||||
return setTime(std::make_shared<ZooKeeperCreateResponse>());
|
return std::make_shared<ZooKeeperCreateResponse>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ZooKeeperResponsePtr ZooKeeperCheckRequest::makeResponse() const
|
ZooKeeperResponsePtr ZooKeeperCheckRequest::makeResponse() const
|
||||||
{
|
{
|
||||||
if (not_exists)
|
if (not_exists)
|
||||||
return setTime(std::make_shared<ZooKeeperCheckNotExistsResponse>());
|
return std::make_shared<ZooKeeperCheckNotExistsResponse>();
|
||||||
|
|
||||||
return setTime(std::make_shared<ZooKeeperCheckResponse>());
|
return std::make_shared<ZooKeeperCheckResponse>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ZooKeeperResponsePtr ZooKeeperMultiRequest::makeResponse() const
|
ZooKeeperResponsePtr ZooKeeperMultiRequest::makeResponse() const
|
||||||
@ -764,11 +941,12 @@ ZooKeeperResponsePtr ZooKeeperMultiRequest::makeResponse() const
|
|||||||
else
|
else
|
||||||
response = std::make_shared<ZooKeeperMultiReadResponse>(requests);
|
response = std::make_shared<ZooKeeperMultiReadResponse>(requests);
|
||||||
|
|
||||||
return setTime(std::move(response));
|
return std::move(response);
|
||||||
}
|
}
|
||||||
ZooKeeperResponsePtr ZooKeeperCloseRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperCloseResponse>()); }
|
|
||||||
ZooKeeperResponsePtr ZooKeeperSetACLRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperSetACLResponse>()); }
|
ZooKeeperResponsePtr ZooKeeperCloseRequest::makeResponse() const { return std::make_shared<ZooKeeperCloseResponse>(); }
|
||||||
ZooKeeperResponsePtr ZooKeeperGetACLRequest::makeResponse() const { return setTime(std::make_shared<ZooKeeperGetACLResponse>()); }
|
ZooKeeperResponsePtr ZooKeeperSetACLRequest::makeResponse() const { return std::make_shared<ZooKeeperSetACLResponse>(); }
|
||||||
|
ZooKeeperResponsePtr ZooKeeperGetACLRequest::makeResponse() const { return std::make_shared<ZooKeeperGetACLResponse>(); }
|
||||||
|
|
||||||
void ZooKeeperSessionIDRequest::writeImpl(WriteBuffer & out) const
|
void ZooKeeperSessionIDRequest::writeImpl(WriteBuffer & out) const
|
||||||
{
|
{
|
||||||
@ -777,6 +955,11 @@ void ZooKeeperSessionIDRequest::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(server_id, out);
|
Coordination::write(server_id, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperSessionIDRequest::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(internal_id) + Coordination::size(session_timeout_ms) + Coordination::size(server_id);
|
||||||
|
}
|
||||||
|
|
||||||
void ZooKeeperSessionIDRequest::readImpl(ReadBuffer & in)
|
void ZooKeeperSessionIDRequest::readImpl(ReadBuffer & in)
|
||||||
{
|
{
|
||||||
Coordination::read(internal_id, in);
|
Coordination::read(internal_id, in);
|
||||||
@ -803,6 +986,11 @@ void ZooKeeperSessionIDResponse::writeImpl(WriteBuffer & out) const
|
|||||||
Coordination::write(server_id, out);
|
Coordination::write(server_id, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ZooKeeperSessionIDResponse::sizeImpl() const
|
||||||
|
{
|
||||||
|
return Coordination::size(internal_id) + Coordination::size(session_id) + Coordination::size(server_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ZooKeeperRequest::createLogElements(LogElements & elems) const
|
void ZooKeeperRequest::createLogElements(LogElements & elems) const
|
||||||
{
|
{
|
||||||
@ -960,40 +1148,6 @@ std::shared_ptr<ZooKeeperRequest> ZooKeeperRequest::read(ReadBuffer & in)
|
|||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZooKeeperRequest::~ZooKeeperRequest()
|
|
||||||
{
|
|
||||||
if (!request_created_time_ns)
|
|
||||||
return;
|
|
||||||
UInt64 elapsed_ns = clock_gettime_ns() - request_created_time_ns;
|
|
||||||
constexpr UInt64 max_request_time_ns = 1000000000ULL; /// 1 sec
|
|
||||||
if (max_request_time_ns < elapsed_ns)
|
|
||||||
{
|
|
||||||
LOG_TEST(getLogger(__PRETTY_FUNCTION__), "Processing of request xid={} took {} ms", xid, elapsed_ns / 1000000UL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ZooKeeperResponsePtr ZooKeeperRequest::setTime(ZooKeeperResponsePtr response) const
|
|
||||||
{
|
|
||||||
if (request_created_time_ns)
|
|
||||||
{
|
|
||||||
response->response_created_time_ns = clock_gettime_ns();
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZooKeeperResponse::~ZooKeeperResponse()
|
|
||||||
{
|
|
||||||
if (!response_created_time_ns)
|
|
||||||
return;
|
|
||||||
UInt64 elapsed_ns = clock_gettime_ns() - response_created_time_ns;
|
|
||||||
constexpr UInt64 max_request_time_ns = 1000000000ULL; /// 1 sec
|
|
||||||
if (max_request_time_ns < elapsed_ns)
|
|
||||||
{
|
|
||||||
LOG_TEST(getLogger(__PRETTY_FUNCTION__), "Processing of response xid={} took {} ms", xid, elapsed_ns / 1000000UL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ZooKeeperRequestPtr ZooKeeperRequestFactory::get(OpNum op_num) const
|
ZooKeeperRequestPtr ZooKeeperRequestFactory::get(OpNum op_num) const
|
||||||
{
|
{
|
||||||
auto it = op_num_to_request.find(op_num);
|
auto it = op_num_to_request.find(op_num);
|
||||||
@ -1015,7 +1169,6 @@ void registerZooKeeperRequest(ZooKeeperRequestFactory & factory)
|
|||||||
factory.registerRequest(num, []
|
factory.registerRequest(num, []
|
||||||
{
|
{
|
||||||
auto res = std::make_shared<RequestT>();
|
auto res = std::make_shared<RequestT>();
|
||||||
res->request_created_time_ns = clock_gettime_ns();
|
|
||||||
|
|
||||||
if constexpr (num == OpNum::MultiRead)
|
if constexpr (num == OpNum::MultiRead)
|
||||||
res->operation_type = ZooKeeperMultiRequest::OperationType::Read;
|
res->operation_type = ZooKeeperMultiRequest::OperationType::Read;
|
||||||
|
@ -7,13 +7,11 @@
|
|||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <IO/ReadBuffer.h>
|
#include <IO/ReadBuffer.h>
|
||||||
#include <IO/WriteBuffer.h>
|
#include <IO/WriteBuffer.h>
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <span>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Coordination
|
namespace Coordination
|
||||||
@ -25,13 +23,11 @@ struct ZooKeeperResponse : virtual Response
|
|||||||
{
|
{
|
||||||
XID xid = 0;
|
XID xid = 0;
|
||||||
|
|
||||||
UInt64 response_created_time_ns = 0;
|
|
||||||
|
|
||||||
ZooKeeperResponse() = default;
|
ZooKeeperResponse() = default;
|
||||||
ZooKeeperResponse(const ZooKeeperResponse &) = default;
|
ZooKeeperResponse(const ZooKeeperResponse &) = default;
|
||||||
~ZooKeeperResponse() override;
|
|
||||||
virtual void readImpl(ReadBuffer &) = 0;
|
virtual void readImpl(ReadBuffer &) = 0;
|
||||||
virtual void writeImpl(WriteBuffer &) const = 0;
|
virtual void writeImpl(WriteBuffer &) const = 0;
|
||||||
|
virtual size_t sizeImpl() const = 0;
|
||||||
virtual void write(WriteBuffer & out) const;
|
virtual void write(WriteBuffer & out) const;
|
||||||
virtual OpNum getOpNum() const = 0;
|
virtual OpNum getOpNum() const = 0;
|
||||||
virtual void fillLogElements(LogElements & elems, size_t idx) const;
|
virtual void fillLogElements(LogElements & elems, size_t idx) const;
|
||||||
@ -51,13 +47,11 @@ struct ZooKeeperRequest : virtual Request
|
|||||||
|
|
||||||
bool restored_from_zookeeper_log = false;
|
bool restored_from_zookeeper_log = false;
|
||||||
|
|
||||||
UInt64 request_created_time_ns = 0;
|
|
||||||
UInt64 thread_id = 0;
|
UInt64 thread_id = 0;
|
||||||
String query_id;
|
String query_id;
|
||||||
|
|
||||||
ZooKeeperRequest() = default;
|
ZooKeeperRequest() = default;
|
||||||
ZooKeeperRequest(const ZooKeeperRequest &) = default;
|
ZooKeeperRequest(const ZooKeeperRequest &) = default;
|
||||||
~ZooKeeperRequest() override;
|
|
||||||
|
|
||||||
virtual OpNum getOpNum() const = 0;
|
virtual OpNum getOpNum() const = 0;
|
||||||
|
|
||||||
@ -66,6 +60,7 @@ struct ZooKeeperRequest : virtual Request
|
|||||||
std::string toString(bool short_format = false) const;
|
std::string toString(bool short_format = false) const;
|
||||||
|
|
||||||
virtual void writeImpl(WriteBuffer &) const = 0;
|
virtual void writeImpl(WriteBuffer &) const = 0;
|
||||||
|
virtual size_t sizeImpl() const = 0;
|
||||||
virtual void readImpl(ReadBuffer &) = 0;
|
virtual void readImpl(ReadBuffer &) = 0;
|
||||||
|
|
||||||
virtual std::string toStringImpl(bool /*short_format*/) const { return ""; }
|
virtual std::string toStringImpl(bool /*short_format*/) const { return ""; }
|
||||||
@ -73,7 +68,6 @@ struct ZooKeeperRequest : virtual Request
|
|||||||
static std::shared_ptr<ZooKeeperRequest> read(ReadBuffer & in);
|
static std::shared_ptr<ZooKeeperRequest> read(ReadBuffer & in);
|
||||||
|
|
||||||
virtual ZooKeeperResponsePtr makeResponse() const = 0;
|
virtual ZooKeeperResponsePtr makeResponse() const = 0;
|
||||||
ZooKeeperResponsePtr setTime(ZooKeeperResponsePtr response) const;
|
|
||||||
virtual bool isReadRequest() const = 0;
|
virtual bool isReadRequest() const = 0;
|
||||||
|
|
||||||
virtual void createLogElements(LogElements & elems) const;
|
virtual void createLogElements(LogElements & elems) const;
|
||||||
@ -86,6 +80,7 @@ struct ZooKeeperHeartbeatRequest final : ZooKeeperRequest
|
|||||||
String getPath() const override { return {}; }
|
String getPath() const override { return {}; }
|
||||||
OpNum getOpNum() const override { return OpNum::Heartbeat; }
|
OpNum getOpNum() const override { return OpNum::Heartbeat; }
|
||||||
void writeImpl(WriteBuffer &) const override {}
|
void writeImpl(WriteBuffer &) const override {}
|
||||||
|
size_t sizeImpl() const override { return 0; }
|
||||||
void readImpl(ReadBuffer &) override {}
|
void readImpl(ReadBuffer &) override {}
|
||||||
ZooKeeperResponsePtr makeResponse() const override;
|
ZooKeeperResponsePtr makeResponse() const override;
|
||||||
bool isReadRequest() const override { return false; }
|
bool isReadRequest() const override { return false; }
|
||||||
@ -97,6 +92,7 @@ struct ZooKeeperSyncRequest final : ZooKeeperRequest
|
|||||||
String getPath() const override { return path; }
|
String getPath() const override { return path; }
|
||||||
OpNum getOpNum() const override { return OpNum::Sync; }
|
OpNum getOpNum() const override { return OpNum::Sync; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
ZooKeeperResponsePtr makeResponse() const override;
|
ZooKeeperResponsePtr makeResponse() const override;
|
||||||
@ -109,6 +105,7 @@ struct ZooKeeperSyncResponse final : SyncResponse, ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
OpNum getOpNum() const override { return OpNum::Sync; }
|
OpNum getOpNum() const override { return OpNum::Sync; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,6 +119,7 @@ struct ZooKeeperReconfigRequest final : ZooKeeperRequest
|
|||||||
String getPath() const override { return keeper_config_path; }
|
String getPath() const override { return keeper_config_path; }
|
||||||
OpNum getOpNum() const override { return OpNum::Reconfig; }
|
OpNum getOpNum() const override { return OpNum::Reconfig; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
ZooKeeperResponsePtr makeResponse() const override;
|
ZooKeeperResponsePtr makeResponse() const override;
|
||||||
@ -138,6 +136,7 @@ struct ZooKeeperReconfigResponse final : ReconfigResponse, ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
OpNum getOpNum() const override { return OpNum::Reconfig; }
|
OpNum getOpNum() const override { return OpNum::Reconfig; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -145,6 +144,7 @@ struct ZooKeeperHeartbeatResponse final : ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer &) override {}
|
void readImpl(ReadBuffer &) override {}
|
||||||
void writeImpl(WriteBuffer &) const override {}
|
void writeImpl(WriteBuffer &) const override {}
|
||||||
|
size_t sizeImpl() const override { return 0; }
|
||||||
OpNum getOpNum() const override { return OpNum::Heartbeat; }
|
OpNum getOpNum() const override { return OpNum::Heartbeat; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -153,6 +153,7 @@ struct ZooKeeperWatchResponse final : WatchResponse, ZooKeeperResponse
|
|||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
|
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
|
|
||||||
void write(WriteBuffer & out) const override;
|
void write(WriteBuffer & out) const override;
|
||||||
|
|
||||||
@ -175,6 +176,7 @@ struct ZooKeeperAuthRequest final : ZooKeeperRequest
|
|||||||
String getPath() const override { return {}; }
|
String getPath() const override { return {}; }
|
||||||
OpNum getOpNum() const override { return OpNum::Auth; }
|
OpNum getOpNum() const override { return OpNum::Auth; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
|
|
||||||
@ -189,6 +191,7 @@ struct ZooKeeperAuthResponse final : ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer &) override {}
|
void readImpl(ReadBuffer &) override {}
|
||||||
void writeImpl(WriteBuffer &) const override {}
|
void writeImpl(WriteBuffer &) const override {}
|
||||||
|
size_t sizeImpl() const override { return 0; }
|
||||||
|
|
||||||
OpNum getOpNum() const override { return OpNum::Auth; }
|
OpNum getOpNum() const override { return OpNum::Auth; }
|
||||||
|
|
||||||
@ -200,6 +203,7 @@ struct ZooKeeperCloseRequest final : ZooKeeperRequest
|
|||||||
String getPath() const override { return {}; }
|
String getPath() const override { return {}; }
|
||||||
OpNum getOpNum() const override { return OpNum::Close; }
|
OpNum getOpNum() const override { return OpNum::Close; }
|
||||||
void writeImpl(WriteBuffer &) const override {}
|
void writeImpl(WriteBuffer &) const override {}
|
||||||
|
size_t sizeImpl() const override { return 0; }
|
||||||
void readImpl(ReadBuffer &) override {}
|
void readImpl(ReadBuffer &) override {}
|
||||||
|
|
||||||
ZooKeeperResponsePtr makeResponse() const override;
|
ZooKeeperResponsePtr makeResponse() const override;
|
||||||
@ -214,6 +218,7 @@ struct ZooKeeperCloseResponse final : ZooKeeperResponse
|
|||||||
}
|
}
|
||||||
|
|
||||||
void writeImpl(WriteBuffer &) const override {}
|
void writeImpl(WriteBuffer &) const override {}
|
||||||
|
size_t sizeImpl() const override { return 0; }
|
||||||
|
|
||||||
OpNum getOpNum() const override { return OpNum::Close; }
|
OpNum getOpNum() const override { return OpNum::Close; }
|
||||||
};
|
};
|
||||||
@ -228,6 +233,7 @@ struct ZooKeeperCreateRequest final : public CreateRequest, ZooKeeperRequest
|
|||||||
|
|
||||||
OpNum getOpNum() const override { return not_exists ? OpNum::CreateIfNotExists : OpNum::Create; }
|
OpNum getOpNum() const override { return not_exists ? OpNum::CreateIfNotExists : OpNum::Create; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
|
|
||||||
@ -244,6 +250,7 @@ struct ZooKeeperCreateResponse : CreateResponse, ZooKeeperResponse
|
|||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
|
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
|
|
||||||
OpNum getOpNum() const override { return OpNum::Create; }
|
OpNum getOpNum() const override { return OpNum::Create; }
|
||||||
|
|
||||||
@ -265,6 +272,7 @@ struct ZooKeeperRemoveRequest final : RemoveRequest, ZooKeeperRequest
|
|||||||
|
|
||||||
OpNum getOpNum() const override { return OpNum::Remove; }
|
OpNum getOpNum() const override { return OpNum::Remove; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
|
|
||||||
@ -280,6 +288,7 @@ struct ZooKeeperRemoveResponse final : RemoveResponse, ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer &) override {}
|
void readImpl(ReadBuffer &) override {}
|
||||||
void writeImpl(WriteBuffer &) const override {}
|
void writeImpl(WriteBuffer &) const override {}
|
||||||
|
size_t sizeImpl() const override { return 0; }
|
||||||
OpNum getOpNum() const override { return OpNum::Remove; }
|
OpNum getOpNum() const override { return OpNum::Remove; }
|
||||||
|
|
||||||
size_t bytesSize() const override { return RemoveResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
size_t bytesSize() const override { return RemoveResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
||||||
@ -293,6 +302,7 @@ struct ZooKeeperRemoveRecursiveRequest final : RemoveRecursiveRequest, ZooKeeper
|
|||||||
OpNum getOpNum() const override { return OpNum::RemoveRecursive; }
|
OpNum getOpNum() const override { return OpNum::RemoveRecursive; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
|
|
||||||
ZooKeeperResponsePtr makeResponse() const override;
|
ZooKeeperResponsePtr makeResponse() const override;
|
||||||
@ -305,6 +315,7 @@ struct ZooKeeperRemoveRecursiveResponse : RemoveRecursiveResponse, ZooKeeperResp
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer &) override {}
|
void readImpl(ReadBuffer &) override {}
|
||||||
void writeImpl(WriteBuffer &) const override {}
|
void writeImpl(WriteBuffer &) const override {}
|
||||||
|
size_t sizeImpl() const override { return 0; }
|
||||||
OpNum getOpNum() const override { return OpNum::RemoveRecursive; }
|
OpNum getOpNum() const override { return OpNum::RemoveRecursive; }
|
||||||
|
|
||||||
size_t bytesSize() const override { return RemoveRecursiveResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
size_t bytesSize() const override { return RemoveRecursiveResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
||||||
@ -317,6 +328,7 @@ struct ZooKeeperExistsRequest final : ExistsRequest, ZooKeeperRequest
|
|||||||
|
|
||||||
OpNum getOpNum() const override { return OpNum::Exists; }
|
OpNum getOpNum() const override { return OpNum::Exists; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
|
|
||||||
@ -330,6 +342,7 @@ struct ZooKeeperExistsResponse final : ExistsResponse, ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
OpNum getOpNum() const override { return OpNum::Exists; }
|
OpNum getOpNum() const override { return OpNum::Exists; }
|
||||||
|
|
||||||
size_t bytesSize() const override { return ExistsResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
size_t bytesSize() const override { return ExistsResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
||||||
@ -344,6 +357,7 @@ struct ZooKeeperGetRequest final : GetRequest, ZooKeeperRequest
|
|||||||
|
|
||||||
OpNum getOpNum() const override { return OpNum::Get; }
|
OpNum getOpNum() const override { return OpNum::Get; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
|
|
||||||
@ -357,6 +371,7 @@ struct ZooKeeperGetResponse final : GetResponse, ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
OpNum getOpNum() const override { return OpNum::Get; }
|
OpNum getOpNum() const override { return OpNum::Get; }
|
||||||
|
|
||||||
size_t bytesSize() const override { return GetResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
size_t bytesSize() const override { return GetResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
||||||
@ -371,6 +386,7 @@ struct ZooKeeperSetRequest final : SetRequest, ZooKeeperRequest
|
|||||||
|
|
||||||
OpNum getOpNum() const override { return OpNum::Set; }
|
OpNum getOpNum() const override { return OpNum::Set; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
ZooKeeperResponsePtr makeResponse() const override;
|
ZooKeeperResponsePtr makeResponse() const override;
|
||||||
@ -385,6 +401,7 @@ struct ZooKeeperSetResponse final : SetResponse, ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
OpNum getOpNum() const override { return OpNum::Set; }
|
OpNum getOpNum() const override { return OpNum::Set; }
|
||||||
|
|
||||||
size_t bytesSize() const override { return SetResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
size_t bytesSize() const override { return SetResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
||||||
@ -399,6 +416,7 @@ struct ZooKeeperListRequest : ListRequest, ZooKeeperRequest
|
|||||||
|
|
||||||
OpNum getOpNum() const override { return OpNum::List; }
|
OpNum getOpNum() const override { return OpNum::List; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
ZooKeeperResponsePtr makeResponse() const override;
|
ZooKeeperResponsePtr makeResponse() const override;
|
||||||
@ -419,6 +437,7 @@ struct ZooKeeperFilteredListRequest final : ZooKeeperListRequest
|
|||||||
|
|
||||||
OpNum getOpNum() const override { return OpNum::FilteredList; }
|
OpNum getOpNum() const override { return OpNum::FilteredList; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
|
|
||||||
@ -429,6 +448,7 @@ struct ZooKeeperListResponse : ListResponse, ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
OpNum getOpNum() const override { return OpNum::List; }
|
OpNum getOpNum() const override { return OpNum::List; }
|
||||||
|
|
||||||
size_t bytesSize() const override { return ListResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
size_t bytesSize() const override { return ListResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
||||||
@ -440,6 +460,7 @@ struct ZooKeeperSimpleListResponse final : ZooKeeperListResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
OpNum getOpNum() const override { return OpNum::SimpleList; }
|
OpNum getOpNum() const override { return OpNum::SimpleList; }
|
||||||
|
|
||||||
size_t bytesSize() const override { return ZooKeeperListResponse::bytesSize() - sizeof(stat); }
|
size_t bytesSize() const override { return ZooKeeperListResponse::bytesSize() - sizeof(stat); }
|
||||||
@ -452,6 +473,7 @@ struct ZooKeeperCheckRequest : CheckRequest, ZooKeeperRequest
|
|||||||
|
|
||||||
OpNum getOpNum() const override { return not_exists ? OpNum::CheckNotExists : OpNum::Check; }
|
OpNum getOpNum() const override { return not_exists ? OpNum::CheckNotExists : OpNum::Check; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
|
|
||||||
@ -467,6 +489,7 @@ struct ZooKeeperCheckResponse : CheckResponse, ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer &) override {}
|
void readImpl(ReadBuffer &) override {}
|
||||||
void writeImpl(WriteBuffer &) const override {}
|
void writeImpl(WriteBuffer &) const override {}
|
||||||
|
size_t sizeImpl() const override { return 0; }
|
||||||
OpNum getOpNum() const override { return OpNum::Check; }
|
OpNum getOpNum() const override { return OpNum::Check; }
|
||||||
|
|
||||||
size_t bytesSize() const override { return CheckResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
size_t bytesSize() const override { return CheckResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
||||||
@ -483,6 +506,7 @@ struct ZooKeeperErrorResponse final : ErrorResponse, ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
|
|
||||||
OpNum getOpNum() const override { return OpNum::Error; }
|
OpNum getOpNum() const override { return OpNum::Error; }
|
||||||
|
|
||||||
@ -493,6 +517,7 @@ struct ZooKeeperSetACLRequest final : SetACLRequest, ZooKeeperRequest
|
|||||||
{
|
{
|
||||||
OpNum getOpNum() const override { return OpNum::SetACL; }
|
OpNum getOpNum() const override { return OpNum::SetACL; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
ZooKeeperResponsePtr makeResponse() const override;
|
ZooKeeperResponsePtr makeResponse() const override;
|
||||||
@ -505,6 +530,7 @@ struct ZooKeeperSetACLResponse final : SetACLResponse, ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
OpNum getOpNum() const override { return OpNum::SetACL; }
|
OpNum getOpNum() const override { return OpNum::SetACL; }
|
||||||
|
|
||||||
size_t bytesSize() const override { return SetACLResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
size_t bytesSize() const override { return SetACLResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
||||||
@ -514,6 +540,7 @@ struct ZooKeeperGetACLRequest final : GetACLRequest, ZooKeeperRequest
|
|||||||
{
|
{
|
||||||
OpNum getOpNum() const override { return OpNum::GetACL; }
|
OpNum getOpNum() const override { return OpNum::GetACL; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
ZooKeeperResponsePtr makeResponse() const override;
|
ZooKeeperResponsePtr makeResponse() const override;
|
||||||
@ -526,12 +553,13 @@ struct ZooKeeperGetACLResponse final : GetACLResponse, ZooKeeperResponse
|
|||||||
{
|
{
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
OpNum getOpNum() const override { return OpNum::GetACL; }
|
OpNum getOpNum() const override { return OpNum::GetACL; }
|
||||||
|
|
||||||
size_t bytesSize() const override { return GetACLResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
size_t bytesSize() const override { return GetACLResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZooKeeperMultiRequest final : MultiRequest, ZooKeeperRequest
|
struct ZooKeeperMultiRequest final : MultiRequest<ZooKeeperRequestPtr>, ZooKeeperRequest
|
||||||
{
|
{
|
||||||
OpNum getOpNum() const override;
|
OpNum getOpNum() const override;
|
||||||
ZooKeeperMultiRequest() = default;
|
ZooKeeperMultiRequest() = default;
|
||||||
@ -540,6 +568,7 @@ struct ZooKeeperMultiRequest final : MultiRequest, ZooKeeperRequest
|
|||||||
ZooKeeperMultiRequest(std::span<const Coordination::RequestPtr> generic_requests, const ACLs & default_acls);
|
ZooKeeperMultiRequest(std::span<const Coordination::RequestPtr> generic_requests, const ACLs & default_acls);
|
||||||
|
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
std::string toStringImpl(bool short_format) const override;
|
std::string toStringImpl(bool short_format) const override;
|
||||||
|
|
||||||
@ -563,12 +592,14 @@ private:
|
|||||||
|
|
||||||
struct ZooKeeperMultiResponse : MultiResponse, ZooKeeperResponse
|
struct ZooKeeperMultiResponse : MultiResponse, ZooKeeperResponse
|
||||||
{
|
{
|
||||||
explicit ZooKeeperMultiResponse(const Requests & requests)
|
ZooKeeperMultiResponse() = default;
|
||||||
|
|
||||||
|
explicit ZooKeeperMultiResponse(const std::vector<ZooKeeperRequestPtr> & requests)
|
||||||
{
|
{
|
||||||
responses.reserve(requests.size());
|
responses.reserve(requests.size());
|
||||||
|
|
||||||
for (const auto & request : requests)
|
for (const auto & request : requests)
|
||||||
responses.emplace_back(dynamic_cast<const ZooKeeperRequest &>(*request).makeResponse());
|
responses.emplace_back(request->makeResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit ZooKeeperMultiResponse(const Responses & responses_)
|
explicit ZooKeeperMultiResponse(const Responses & responses_)
|
||||||
@ -579,6 +610,7 @@ struct ZooKeeperMultiResponse : MultiResponse, ZooKeeperResponse
|
|||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
|
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
|
|
||||||
size_t bytesSize() const override { return MultiResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
size_t bytesSize() const override { return MultiResponse::bytesSize() + sizeof(xid) + sizeof(zxid); }
|
||||||
|
|
||||||
@ -609,6 +641,7 @@ struct ZooKeeperSessionIDRequest final : ZooKeeperRequest
|
|||||||
Coordination::OpNum getOpNum() const override { return OpNum::SessionID; }
|
Coordination::OpNum getOpNum() const override { return OpNum::SessionID; }
|
||||||
String getPath() const override { return {}; }
|
String getPath() const override { return {}; }
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
|
|
||||||
Coordination::ZooKeeperResponsePtr makeResponse() const override;
|
Coordination::ZooKeeperResponsePtr makeResponse() const override;
|
||||||
@ -627,6 +660,7 @@ struct ZooKeeperSessionIDResponse final : ZooKeeperResponse
|
|||||||
void readImpl(ReadBuffer & in) override;
|
void readImpl(ReadBuffer & in) override;
|
||||||
|
|
||||||
void writeImpl(WriteBuffer & out) const override;
|
void writeImpl(WriteBuffer & out) const override;
|
||||||
|
size_t sizeImpl() const override;
|
||||||
|
|
||||||
Coordination::OpNum getOpNum() const override { return OpNum::SessionID; }
|
Coordination::OpNum getOpNum() const override { return OpNum::SessionID; }
|
||||||
};
|
};
|
||||||
|
@ -42,6 +42,32 @@ void write(const Error & x, WriteBuffer & out)
|
|||||||
write(static_cast<int32_t>(x), out);
|
write(static_cast<int32_t>(x), out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t size(OpNum x)
|
||||||
|
{
|
||||||
|
return size(static_cast<int32_t>(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size(const std::string & s)
|
||||||
|
{
|
||||||
|
return size(static_cast<int32_t>(s.size())) + s.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size(const ACL & acl)
|
||||||
|
{
|
||||||
|
return size(acl.permissions) + size(acl.scheme) + size(acl.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size(const Stat & stat)
|
||||||
|
{
|
||||||
|
return size(stat.czxid) + size(stat.mzxid) + size(stat.ctime) + size(stat.mtime) + size(stat.version) + size(stat.cversion)
|
||||||
|
+ size(stat.aversion) + size(stat.ephemeralOwner) + size(stat.dataLength) + size(stat.numChildren) + size(stat.pzxid);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size(const Error & x)
|
||||||
|
{
|
||||||
|
return size(static_cast<int32_t>(x));
|
||||||
|
}
|
||||||
|
|
||||||
void read(OpNum & x, ReadBuffer & in)
|
void read(OpNum & x, ReadBuffer & in)
|
||||||
{
|
{
|
||||||
int32_t raw_op_num;
|
int32_t raw_op_num;
|
||||||
|
@ -43,6 +43,36 @@ void write(const std::vector<T> & arr, WriteBuffer & out)
|
|||||||
write(elem, out);
|
write(elem, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires is_arithmetic_v<T>
|
||||||
|
size_t size(T x)
|
||||||
|
{
|
||||||
|
return sizeof(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size(OpNum x);
|
||||||
|
size_t size(const std::string & s);
|
||||||
|
size_t size(const ACL & acl);
|
||||||
|
size_t size(const Stat & stat);
|
||||||
|
size_t size(const Error & x);
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
size_t size(const std::array<char, N>)
|
||||||
|
{
|
||||||
|
return size(static_cast<int32_t>(N)) + N;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
size_t size(const std::vector<T> & arr)
|
||||||
|
{
|
||||||
|
size_t total_size = size(static_cast<int32_t>(arr.size()));
|
||||||
|
for (const auto & elem : arr)
|
||||||
|
total_size += size(elem);
|
||||||
|
|
||||||
|
return total_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires is_arithmetic_v<T>
|
requires is_arithmetic_v<T>
|
||||||
void read(T & x, ReadBuffer & in)
|
void read(T & x, ReadBuffer & in)
|
||||||
|
@ -57,11 +57,13 @@ namespace ErrorCodes
|
|||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
|
||||||
static bool supportsAtomicRenameImpl()
|
static std::optional<std::string> supportsAtomicRenameImpl()
|
||||||
{
|
{
|
||||||
VersionNumber renameat2_minimal_version(3, 15, 0);
|
VersionNumber renameat2_minimal_version(3, 15, 0);
|
||||||
VersionNumber linux_version(Poco::Environment::osVersion());
|
VersionNumber linux_version(Poco::Environment::osVersion());
|
||||||
return linux_version >= renameat2_minimal_version;
|
if (linux_version >= renameat2_minimal_version)
|
||||||
|
return std::nullopt;
|
||||||
|
return fmt::format("Linux kernel 3.15+ is required, got {}", linux_version.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool renameat2(const std::string & old_path, const std::string & new_path, int flags)
|
static bool renameat2(const std::string & old_path, const std::string & new_path, int flags)
|
||||||
@ -97,10 +99,14 @@ static bool renameat2(const std::string & old_path, const std::string & new_path
|
|||||||
ErrnoException::throwFromPath(ErrorCodes::SYSTEM_ERROR, new_path, "Cannot rename {} to {}", old_path, new_path);
|
ErrnoException::throwFromPath(ErrorCodes::SYSTEM_ERROR, new_path, "Cannot rename {} to {}", old_path, new_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool supportsAtomicRename()
|
bool supportsAtomicRename(std::string * out_message)
|
||||||
{
|
{
|
||||||
static bool supports = supportsAtomicRenameImpl();
|
static auto error = supportsAtomicRenameImpl();
|
||||||
return supports;
|
if (!error.has_value())
|
||||||
|
return true;
|
||||||
|
if (out_message)
|
||||||
|
*out_message = error.value();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -152,16 +158,22 @@ static bool renameat2(const std::string & old_path, const std::string & new_path
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool supportsAtomicRenameImpl()
|
static std::optional<std::string> supportsAtomicRenameImpl()
|
||||||
{
|
{
|
||||||
auto fun = dlsym(RTLD_DEFAULT, "renamex_np");
|
auto fun = dlsym(RTLD_DEFAULT, "renamex_np");
|
||||||
return fun != nullptr;
|
if (fun != nullptr)
|
||||||
|
return std::nullopt;
|
||||||
|
return "macOS 10.12 or later is required";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool supportsAtomicRename()
|
bool supportsAtomicRename(std::string * out_message)
|
||||||
{
|
{
|
||||||
static bool supports = supportsAtomicRenameImpl();
|
static auto error = supportsAtomicRenameImpl();
|
||||||
return supports;
|
if (!error.has_value())
|
||||||
|
return true;
|
||||||
|
if (out_message)
|
||||||
|
*out_message = error.value();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -179,8 +191,10 @@ static bool renameat2(const std::string &, const std::string &, int)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool supportsAtomicRename()
|
bool supportsAtomicRename(std::string * out_message)
|
||||||
{
|
{
|
||||||
|
if (out_message)
|
||||||
|
*out_message = "only Linux and macOS are supported";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ namespace DB
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// Returns true, if the following functions supported by the system
|
/// Returns true, if the following functions supported by the system
|
||||||
bool supportsAtomicRename();
|
bool supportsAtomicRename(std::string * out_message = nullptr);
|
||||||
|
|
||||||
/// Atomically rename old_path to new_path. If new_path exists, do not overwrite it and throw exception
|
/// Atomically rename old_path to new_path. If new_path exists, do not overwrite it and throw exception
|
||||||
void renameNoReplace(const std::string & old_path, const std::string & new_path);
|
void renameNoReplace(const std::string & old_path, const std::string & new_path);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
clickhouse_add_executable(integer_hash_tables_and_hashes integer_hash_tables_and_hashes.cpp)
|
clickhouse_add_executable(integer_hash_tables_and_hashes integer_hash_tables_and_hashes.cpp orc_string_dictionary.cpp)
|
||||||
target_link_libraries (integer_hash_tables_and_hashes PRIVATE
|
target_link_libraries (integer_hash_tables_and_hashes PRIVATE
|
||||||
ch_contrib::gbenchmark_all
|
ch_contrib::gbenchmark_all
|
||||||
dbms
|
dbms
|
||||||
@ -7,3 +7,8 @@ target_link_libraries (integer_hash_tables_and_hashes PRIVATE
|
|||||||
ch_contrib::wyhash
|
ch_contrib::wyhash
|
||||||
ch_contrib::farmhash
|
ch_contrib::farmhash
|
||||||
ch_contrib::xxHash)
|
ch_contrib::xxHash)
|
||||||
|
|
||||||
|
clickhouse_add_executable(orc_string_dictionary orc_string_dictionary.cpp)
|
||||||
|
target_link_libraries (orc_string_dictionary PRIVATE
|
||||||
|
ch_contrib::gbenchmark_all
|
||||||
|
dbms)
|
||||||
|
311
src/Common/benchmarks/orc_string_dictionary.cpp
Normal file
311
src/Common/benchmarks/orc_string_dictionary.cpp
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
#include <cstdlib>
|
||||||
|
#include <base/defines.h>
|
||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
|
||||||
|
class OldSortedStringDictionary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct DictEntry
|
||||||
|
{
|
||||||
|
DictEntry(const char * str, size_t len) : data(str), length(len) { }
|
||||||
|
const char * data;
|
||||||
|
size_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
OldSortedStringDictionary() : totalLength(0) { }
|
||||||
|
|
||||||
|
// insert a new string into dictionary, return its insertion order
|
||||||
|
size_t insert(const char * str, size_t len);
|
||||||
|
|
||||||
|
// reorder input index buffer from insertion order to dictionary order
|
||||||
|
void reorder(std::vector<int64_t> & idxBuffer) const;
|
||||||
|
|
||||||
|
// get dict entries in insertion order
|
||||||
|
void getEntriesInInsertionOrder(std::vector<const DictEntry *> &) const;
|
||||||
|
|
||||||
|
size_t size() const;
|
||||||
|
|
||||||
|
// return total length of strings in the dictionary
|
||||||
|
uint64_t length() const;
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// store indexes of insertion order in the dictionary for not-null rows
|
||||||
|
std::vector<int64_t> idxInDictBuffer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct LessThan
|
||||||
|
{
|
||||||
|
bool operator()(const DictEntry & left, const DictEntry & right) const
|
||||||
|
{
|
||||||
|
int ret = memcmp(left.data, right.data, std::min(left.length, right.length));
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
return ret < 0;
|
||||||
|
}
|
||||||
|
return left.length < right.length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<DictEntry, size_t, LessThan> dict;
|
||||||
|
std::vector<std::vector<char>> data;
|
||||||
|
uint64_t totalLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
// insert a new string into dictionary, return its insertion order
|
||||||
|
size_t OldSortedStringDictionary::insert(const char * str, size_t len)
|
||||||
|
{
|
||||||
|
auto ret = dict.insert({DictEntry(str, len), dict.size()});
|
||||||
|
if (ret.second)
|
||||||
|
{
|
||||||
|
// make a copy to internal storage
|
||||||
|
data.push_back(std::vector<char>(len));
|
||||||
|
memcpy(data.back().data(), str, len);
|
||||||
|
// update dictionary entry to link pointer to internal storage
|
||||||
|
DictEntry * entry = const_cast<DictEntry *>(&(ret.first->first));
|
||||||
|
entry->data = data.back().data();
|
||||||
|
totalLength += len;
|
||||||
|
}
|
||||||
|
return ret.first->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reorder input index buffer from insertion order to dictionary order
|
||||||
|
*
|
||||||
|
* We require this function because string values are buffered by indexes
|
||||||
|
* in their insertion order. Until the entire dictionary is complete can
|
||||||
|
* we get their sorted indexes in the dictionary in that ORC specification
|
||||||
|
* demands dictionary should be ordered. Therefore this function transforms
|
||||||
|
* the indexes from insertion order to dictionary value order for final
|
||||||
|
* output.
|
||||||
|
*/
|
||||||
|
void OldSortedStringDictionary::reorder(std::vector<int64_t> & idxBuffer) const
|
||||||
|
{
|
||||||
|
// iterate the dictionary to get mapping from insertion order to value order
|
||||||
|
std::vector<size_t> mapping(dict.size());
|
||||||
|
size_t dictIdx = 0;
|
||||||
|
for (auto it = dict.cbegin(); it != dict.cend(); ++it)
|
||||||
|
{
|
||||||
|
mapping[it->second] = dictIdx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do the transformation
|
||||||
|
for (size_t i = 0; i != idxBuffer.size(); ++i)
|
||||||
|
{
|
||||||
|
idxBuffer[i] = static_cast<int64_t>(mapping[static_cast<size_t>(idxBuffer[i])]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get dict entries in insertion order
|
||||||
|
void OldSortedStringDictionary::getEntriesInInsertionOrder(std::vector<const DictEntry *> & entries) const
|
||||||
|
{
|
||||||
|
entries.resize(dict.size());
|
||||||
|
for (auto it = dict.cbegin(); it != dict.cend(); ++it)
|
||||||
|
{
|
||||||
|
entries[it->second] = &(it->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return count of entries
|
||||||
|
size_t OldSortedStringDictionary::size() const
|
||||||
|
{
|
||||||
|
return dict.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// return total length of strings in the dictionary
|
||||||
|
uint64_t OldSortedStringDictionary::length() const
|
||||||
|
{
|
||||||
|
return totalLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OldSortedStringDictionary::clear()
|
||||||
|
{
|
||||||
|
totalLength = 0;
|
||||||
|
data.clear();
|
||||||
|
dict.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of increasing sorted string dictionary
|
||||||
|
*/
|
||||||
|
class NewSortedStringDictionary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct DictEntry
|
||||||
|
{
|
||||||
|
DictEntry(const char * str, size_t len) : data(str), length(len) { }
|
||||||
|
const char * data;
|
||||||
|
size_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DictEntryWithIndex
|
||||||
|
{
|
||||||
|
DictEntryWithIndex(const char * str, size_t len, size_t index_) : entry(str, len), index(index_) { }
|
||||||
|
DictEntry entry;
|
||||||
|
size_t index;
|
||||||
|
};
|
||||||
|
|
||||||
|
NewSortedStringDictionary() : totalLength_(0) { }
|
||||||
|
|
||||||
|
// insert a new string into dictionary, return its insertion order
|
||||||
|
size_t insert(const char * str, size_t len);
|
||||||
|
|
||||||
|
// reorder input index buffer from insertion order to dictionary order
|
||||||
|
void reorder(std::vector<int64_t> & idxBuffer) const;
|
||||||
|
|
||||||
|
// get dict entries in insertion order
|
||||||
|
void getEntriesInInsertionOrder(std::vector<const DictEntry *> &) const;
|
||||||
|
|
||||||
|
// return count of entries
|
||||||
|
size_t size() const;
|
||||||
|
|
||||||
|
// return total length of strings in the dictionary
|
||||||
|
uint64_t length() const;
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// store indexes of insertion order in the dictionary for not-null rows
|
||||||
|
std::vector<int64_t> idxInDictBuffer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct LessThan
|
||||||
|
{
|
||||||
|
bool operator()(const DictEntryWithIndex & l, const DictEntryWithIndex & r)
|
||||||
|
{
|
||||||
|
const auto & left = l.entry;
|
||||||
|
const auto & right = r.entry;
|
||||||
|
int ret = memcmp(left.data, right.data, std::min(left.length, right.length));
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
return ret < 0;
|
||||||
|
}
|
||||||
|
return left.length < right.length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mutable std::vector<DictEntryWithIndex> flatDict_;
|
||||||
|
std::unordered_map<std::string, size_t> keyToIndex;
|
||||||
|
uint64_t totalLength_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// insert a new string into dictionary, return its insertion order
|
||||||
|
size_t NewSortedStringDictionary::insert(const char * str, size_t len)
|
||||||
|
{
|
||||||
|
size_t index = flatDict_.size();
|
||||||
|
auto ret = keyToIndex.emplace(std::string(str, len), index);
|
||||||
|
if (ret.second)
|
||||||
|
{
|
||||||
|
flatDict_.emplace_back(ret.first->first.data(), ret.first->first.size(), index);
|
||||||
|
totalLength_ += len;
|
||||||
|
}
|
||||||
|
return ret.first->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reorder input index buffer from insertion order to dictionary order
|
||||||
|
*
|
||||||
|
* We require this function because string values are buffered by indexes
|
||||||
|
* in their insertion order. Until the entire dictionary is complete can
|
||||||
|
* we get their sorted indexes in the dictionary in that ORC specification
|
||||||
|
* demands dictionary should be ordered. Therefore this function transforms
|
||||||
|
* the indexes from insertion order to dictionary value order for final
|
||||||
|
* output.
|
||||||
|
*/
|
||||||
|
void NewSortedStringDictionary::reorder(std::vector<int64_t> & idxBuffer) const
|
||||||
|
{
|
||||||
|
// iterate the dictionary to get mapping from insertion order to value order
|
||||||
|
std::vector<size_t> mapping(flatDict_.size());
|
||||||
|
for (size_t i = 0; i < flatDict_.size(); ++i)
|
||||||
|
{
|
||||||
|
mapping[flatDict_[i].index] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do the transformation
|
||||||
|
for (size_t i = 0; i != idxBuffer.size(); ++i)
|
||||||
|
{
|
||||||
|
idxBuffer[i] = static_cast<int64_t>(mapping[static_cast<size_t>(idxBuffer[i])]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get dict entries in insertion order
|
||||||
|
void NewSortedStringDictionary::getEntriesInInsertionOrder(std::vector<const DictEntry *> & entries) const
|
||||||
|
{
|
||||||
|
std::sort(
|
||||||
|
flatDict_.begin(),
|
||||||
|
flatDict_.end(),
|
||||||
|
[](const DictEntryWithIndex & left, const DictEntryWithIndex & right) { return left.index < right.index; });
|
||||||
|
|
||||||
|
entries.resize(flatDict_.size());
|
||||||
|
for (size_t i = 0; i < flatDict_.size(); ++i)
|
||||||
|
{
|
||||||
|
entries[i] = &(flatDict_[i].entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return count of entries
|
||||||
|
size_t NewSortedStringDictionary::size() const
|
||||||
|
{
|
||||||
|
return flatDict_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// return total length of strings in the dictionary
|
||||||
|
uint64_t NewSortedStringDictionary::length() const
|
||||||
|
{
|
||||||
|
return totalLength_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewSortedStringDictionary::clear()
|
||||||
|
{
|
||||||
|
totalLength_ = 0;
|
||||||
|
keyToIndex.clear();
|
||||||
|
flatDict_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t cardinality>
|
||||||
|
static std::vector<std::string> mockStrings()
|
||||||
|
{
|
||||||
|
std::vector<std::string> res(1000000);
|
||||||
|
for (auto & s : res)
|
||||||
|
{
|
||||||
|
s = "test string dictionary " + std::to_string(rand() % cardinality);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename DictionaryImpl>
|
||||||
|
static NO_INLINE std::unique_ptr<DictionaryImpl> createAndWriteStringDictionary(const std::vector<std::string> & strs)
|
||||||
|
{
|
||||||
|
auto dict = std::make_unique<DictionaryImpl>();
|
||||||
|
for (const auto & str : strs)
|
||||||
|
{
|
||||||
|
auto index = dict->insert(str.data(), str.size());
|
||||||
|
dict->idxInDictBuffer.push_back(index);
|
||||||
|
}
|
||||||
|
dict->reorder(dict->idxInDictBuffer);
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename DictionaryImpl, size_t cardinality>
|
||||||
|
static void BM_writeStringDictionary(benchmark::State & state)
|
||||||
|
{
|
||||||
|
auto strs = mockStrings<cardinality>();
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
auto dict = createAndWriteStringDictionary<DictionaryImpl>(strs);
|
||||||
|
benchmark::DoNotOptimize(dict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK_TEMPLATE(BM_writeStringDictionary, OldSortedStringDictionary, 10);
|
||||||
|
BENCHMARK_TEMPLATE(BM_writeStringDictionary, NewSortedStringDictionary, 10);
|
||||||
|
BENCHMARK_TEMPLATE(BM_writeStringDictionary, OldSortedStringDictionary, 100);
|
||||||
|
BENCHMARK_TEMPLATE(BM_writeStringDictionary, NewSortedStringDictionary, 100);
|
||||||
|
BENCHMARK_TEMPLATE(BM_writeStringDictionary, OldSortedStringDictionary, 1000);
|
||||||
|
BENCHMARK_TEMPLATE(BM_writeStringDictionary, NewSortedStringDictionary, 1000);
|
||||||
|
BENCHMARK_TEMPLATE(BM_writeStringDictionary, OldSortedStringDictionary, 10000);
|
||||||
|
BENCHMARK_TEMPLATE(BM_writeStringDictionary, NewSortedStringDictionary, 10000);
|
||||||
|
BENCHMARK_TEMPLATE(BM_writeStringDictionary, OldSortedStringDictionary, 100000);
|
||||||
|
BENCHMARK_TEMPLATE(BM_writeStringDictionary, NewSortedStringDictionary, 100000);
|
||||||
|
|
@ -45,6 +45,7 @@ uint64_t ACLMap::convertACLs(const Coordination::ACLs & acls)
|
|||||||
if (acls.empty())
|
if (acls.empty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
std::lock_guard lock(map_mutex);
|
||||||
if (acl_to_num.contains(acls))
|
if (acl_to_num.contains(acls))
|
||||||
return acl_to_num[acls];
|
return acl_to_num[acls];
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ Coordination::ACLs ACLMap::convertNumber(uint64_t acls_id) const
|
|||||||
if (acls_id == 0)
|
if (acls_id == 0)
|
||||||
return Coordination::ACLs{};
|
return Coordination::ACLs{};
|
||||||
|
|
||||||
|
std::lock_guard lock(map_mutex);
|
||||||
if (!num_to_acl.contains(acls_id))
|
if (!num_to_acl.contains(acls_id))
|
||||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unknown ACL id {}. It's a bug", acls_id);
|
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unknown ACL id {}. It's a bug", acls_id);
|
||||||
|
|
||||||
@ -70,6 +72,7 @@ Coordination::ACLs ACLMap::convertNumber(uint64_t acls_id) const
|
|||||||
|
|
||||||
void ACLMap::addMapping(uint64_t acls_id, const Coordination::ACLs & acls)
|
void ACLMap::addMapping(uint64_t acls_id, const Coordination::ACLs & acls)
|
||||||
{
|
{
|
||||||
|
std::lock_guard lock(map_mutex);
|
||||||
num_to_acl[acls_id] = acls;
|
num_to_acl[acls_id] = acls;
|
||||||
acl_to_num[acls] = acls_id;
|
acl_to_num[acls] = acls_id;
|
||||||
max_acl_id = std::max(acls_id + 1, max_acl_id); /// max_acl_id pointer next slot
|
max_acl_id = std::max(acls_id + 1, max_acl_id); /// max_acl_id pointer next slot
|
||||||
@ -77,11 +80,13 @@ void ACLMap::addMapping(uint64_t acls_id, const Coordination::ACLs & acls)
|
|||||||
|
|
||||||
void ACLMap::addUsage(uint64_t acl_id)
|
void ACLMap::addUsage(uint64_t acl_id)
|
||||||
{
|
{
|
||||||
|
std::lock_guard lock(map_mutex);
|
||||||
usage_counter[acl_id]++;
|
usage_counter[acl_id]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ACLMap::removeUsage(uint64_t acl_id)
|
void ACLMap::removeUsage(uint64_t acl_id)
|
||||||
{
|
{
|
||||||
|
std::lock_guard lock(map_mutex);
|
||||||
if (!usage_counter.contains(acl_id))
|
if (!usage_counter.contains(acl_id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ private:
|
|||||||
NumToACLMap num_to_acl;
|
NumToACLMap num_to_acl;
|
||||||
UsageCounter usage_counter;
|
UsageCounter usage_counter;
|
||||||
uint64_t max_acl_id{1};
|
uint64_t max_acl_id{1};
|
||||||
|
|
||||||
|
mutable std::mutex map_mutex;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Convert ACL to number. If it's new ACL than adds it to map
|
/// Convert ACL to number. If it's new ACL than adds it to map
|
||||||
|
@ -301,11 +301,13 @@ String MonitorCommand::run()
|
|||||||
|
|
||||||
print(ret, "server_state", keeper_info.getRole());
|
print(ret, "server_state", keeper_info.getRole());
|
||||||
|
|
||||||
print(ret, "znode_count", state_machine.getNodesCount());
|
const auto & storage_stats = state_machine.getStorageStats();
|
||||||
print(ret, "watch_count", state_machine.getTotalWatchesCount());
|
|
||||||
print(ret, "ephemerals_count", state_machine.getTotalEphemeralNodesCount());
|
print(ret, "znode_count", storage_stats.nodes_count.load(std::memory_order_relaxed));
|
||||||
print(ret, "approximate_data_size", state_machine.getApproximateDataSize());
|
print(ret, "watch_count", storage_stats.total_watches_count.load(std::memory_order_relaxed));
|
||||||
print(ret, "key_arena_size", state_machine.getKeyArenaSize());
|
print(ret, "ephemerals_count", storage_stats.total_emphemeral_nodes_count.load(std::memory_order_relaxed));
|
||||||
|
print(ret, "approximate_data_size", storage_stats.approximate_data_size.load(std::memory_order_relaxed));
|
||||||
|
print(ret, "key_arena_size", 0);
|
||||||
print(ret, "latest_snapshot_size", state_machine.getLatestSnapshotSize());
|
print(ret, "latest_snapshot_size", state_machine.getLatestSnapshotSize());
|
||||||
|
|
||||||
#if defined(OS_LINUX) || defined(OS_DARWIN)
|
#if defined(OS_LINUX) || defined(OS_DARWIN)
|
||||||
@ -387,6 +389,7 @@ String ServerStatCommand::run()
|
|||||||
|
|
||||||
auto & stats = keeper_dispatcher.getKeeperConnectionStats();
|
auto & stats = keeper_dispatcher.getKeeperConnectionStats();
|
||||||
Keeper4LWInfo keeper_info = keeper_dispatcher.getKeeper4LWInfo();
|
Keeper4LWInfo keeper_info = keeper_dispatcher.getKeeper4LWInfo();
|
||||||
|
const auto & storage_stats = keeper_dispatcher.getStateMachine().getStorageStats();
|
||||||
|
|
||||||
write("ClickHouse Keeper version", String(VERSION_DESCRIBE) + "-" + VERSION_GITHASH);
|
write("ClickHouse Keeper version", String(VERSION_DESCRIBE) + "-" + VERSION_GITHASH);
|
||||||
|
|
||||||
@ -398,9 +401,9 @@ String ServerStatCommand::run()
|
|||||||
write("Sent", toString(stats.getPacketsSent()));
|
write("Sent", toString(stats.getPacketsSent()));
|
||||||
write("Connections", toString(keeper_info.alive_connections_count));
|
write("Connections", toString(keeper_info.alive_connections_count));
|
||||||
write("Outstanding", toString(keeper_info.outstanding_requests_count));
|
write("Outstanding", toString(keeper_info.outstanding_requests_count));
|
||||||
write("Zxid", formatZxid(keeper_info.last_zxid));
|
write("Zxid", formatZxid(storage_stats.last_zxid.load(std::memory_order_relaxed)));
|
||||||
write("Mode", keeper_info.getRole());
|
write("Mode", keeper_info.getRole());
|
||||||
write("Node count", toString(keeper_info.total_nodes_count));
|
write("Node count", toString(storage_stats.nodes_count.load(std::memory_order_relaxed)));
|
||||||
|
|
||||||
return buf.str();
|
return buf.str();
|
||||||
}
|
}
|
||||||
@ -416,6 +419,7 @@ String StatCommand::run()
|
|||||||
|
|
||||||
auto & stats = keeper_dispatcher.getKeeperConnectionStats();
|
auto & stats = keeper_dispatcher.getKeeperConnectionStats();
|
||||||
Keeper4LWInfo keeper_info = keeper_dispatcher.getKeeper4LWInfo();
|
Keeper4LWInfo keeper_info = keeper_dispatcher.getKeeper4LWInfo();
|
||||||
|
const auto & storage_stats = keeper_dispatcher.getStateMachine().getStorageStats();
|
||||||
|
|
||||||
write("ClickHouse Keeper version", String(VERSION_DESCRIBE) + "-" + VERSION_GITHASH);
|
write("ClickHouse Keeper version", String(VERSION_DESCRIBE) + "-" + VERSION_GITHASH);
|
||||||
|
|
||||||
@ -431,9 +435,9 @@ String StatCommand::run()
|
|||||||
write("Sent", toString(stats.getPacketsSent()));
|
write("Sent", toString(stats.getPacketsSent()));
|
||||||
write("Connections", toString(keeper_info.alive_connections_count));
|
write("Connections", toString(keeper_info.alive_connections_count));
|
||||||
write("Outstanding", toString(keeper_info.outstanding_requests_count));
|
write("Outstanding", toString(keeper_info.outstanding_requests_count));
|
||||||
write("Zxid", formatZxid(keeper_info.last_zxid));
|
write("Zxid", formatZxid(storage_stats.last_zxid.load(std::memory_order_relaxed)));
|
||||||
write("Mode", keeper_info.getRole());
|
write("Mode", keeper_info.getRole());
|
||||||
write("Node count", toString(keeper_info.total_nodes_count));
|
write("Node count", toString(storage_stats.nodes_count.load(std::memory_order_relaxed)));
|
||||||
|
|
||||||
return buf.str();
|
return buf.str();
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <base/types.h>
|
#include <base/types.h>
|
||||||
#include <Common/Exception.h>
|
#include <Common/Exception.h>
|
||||||
|
|
||||||
@ -30,9 +28,6 @@ struct Keeper4LWInfo
|
|||||||
uint64_t follower_count;
|
uint64_t follower_count;
|
||||||
uint64_t synced_follower_count;
|
uint64_t synced_follower_count;
|
||||||
|
|
||||||
uint64_t total_nodes_count;
|
|
||||||
int64_t last_zxid;
|
|
||||||
|
|
||||||
String getRole() const
|
String getRole() const
|
||||||
{
|
{
|
||||||
if (is_standalone)
|
if (is_standalone)
|
||||||
|
@ -38,15 +38,16 @@ void updateKeeperInformation(KeeperDispatcher & keeper_dispatcher, AsynchronousM
|
|||||||
is_follower = static_cast<size_t>(keeper_info.is_follower);
|
is_follower = static_cast<size_t>(keeper_info.is_follower);
|
||||||
is_exceeding_mem_soft_limit = static_cast<size_t>(keeper_info.is_exceeding_mem_soft_limit);
|
is_exceeding_mem_soft_limit = static_cast<size_t>(keeper_info.is_exceeding_mem_soft_limit);
|
||||||
|
|
||||||
zxid = keeper_info.last_zxid;
|
|
||||||
const auto & state_machine = keeper_dispatcher.getStateMachine();
|
const auto & state_machine = keeper_dispatcher.getStateMachine();
|
||||||
znode_count = state_machine.getNodesCount();
|
const auto & storage_stats = state_machine.getStorageStats();
|
||||||
watch_count = state_machine.getTotalWatchesCount();
|
zxid = storage_stats.last_zxid.load(std::memory_order_relaxed);
|
||||||
ephemerals_count = state_machine.getTotalEphemeralNodesCount();
|
znode_count = storage_stats.nodes_count.load(std::memory_order_relaxed);
|
||||||
approximate_data_size = state_machine.getApproximateDataSize();
|
watch_count = storage_stats.total_watches_count.load(std::memory_order_relaxed);
|
||||||
key_arena_size = state_machine.getKeyArenaSize();
|
ephemerals_count = storage_stats.total_emphemeral_nodes_count.load(std::memory_order_relaxed);
|
||||||
session_with_watches = state_machine.getSessionsWithWatchesCount();
|
approximate_data_size = storage_stats.approximate_data_size.load(std::memory_order_relaxed);
|
||||||
paths_watched = state_machine.getWatchedPathsCount();
|
key_arena_size = 0;
|
||||||
|
session_with_watches = storage_stats.sessions_with_watches_count.load(std::memory_order_relaxed);
|
||||||
|
paths_watched = storage_stats.watched_paths_count.load(std::memory_order_relaxed);
|
||||||
|
|
||||||
# if defined(__linux__) || defined(__APPLE__)
|
# if defined(__linux__) || defined(__APPLE__)
|
||||||
open_file_descriptor_count = getCurrentProcessFDCount();
|
open_file_descriptor_count = getCurrentProcessFDCount();
|
||||||
|
@ -305,7 +305,7 @@ void KeeperDispatcher::requestThread()
|
|||||||
if (has_read_request)
|
if (has_read_request)
|
||||||
{
|
{
|
||||||
if (server->isLeaderAlive())
|
if (server->isLeaderAlive())
|
||||||
server->putLocalReadRequest(request);
|
server->putLocalReadRequest({request});
|
||||||
else
|
else
|
||||||
addErrorResponses({request}, Coordination::Error::ZCONNECTIONLOSS);
|
addErrorResponses({request}, Coordination::Error::ZCONNECTIONLOSS);
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,16 @@
|
|||||||
#include <Common/getMultipleKeysFromConfig.h>
|
#include <Common/getMultipleKeysFromConfig.h>
|
||||||
#include <Common/getNumberOfPhysicalCPUCores.h>
|
#include <Common/getNumberOfPhysicalCPUCores.h>
|
||||||
|
|
||||||
|
#if USE_SSL
|
||||||
|
# include <Server/CertificateReloader.h>
|
||||||
|
# include <openssl/ssl.h>
|
||||||
|
# include <Poco/Crypto/EVPPKey.h>
|
||||||
|
# include <Poco/Net/Context.h>
|
||||||
|
# include <Poco/Net/SSLManager.h>
|
||||||
|
# include <Poco/Net/Utility.h>
|
||||||
|
# include <Poco/StringTokenizer.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -48,6 +58,7 @@ namespace ErrorCodes
|
|||||||
extern const int SUPPORT_IS_DISABLED;
|
extern const int SUPPORT_IS_DISABLED;
|
||||||
extern const int LOGICAL_ERROR;
|
extern const int LOGICAL_ERROR;
|
||||||
extern const int INVALID_CONFIG_PARAMETER;
|
extern const int INVALID_CONFIG_PARAMETER;
|
||||||
|
extern const int BAD_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
@ -56,6 +67,16 @@ namespace
|
|||||||
{
|
{
|
||||||
|
|
||||||
#if USE_SSL
|
#if USE_SSL
|
||||||
|
|
||||||
|
int callSetCertificate(SSL * ssl, void * arg)
|
||||||
|
{
|
||||||
|
if (!arg)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
const CertificateReloader::Data * data = reinterpret_cast<CertificateReloader::Data *>(arg);
|
||||||
|
return setCertificateCallback(ssl, data, getLogger("SSLContext"));
|
||||||
|
}
|
||||||
|
|
||||||
void setSSLParams(nuraft::asio_service::options & asio_opts)
|
void setSSLParams(nuraft::asio_service::options & asio_opts)
|
||||||
{
|
{
|
||||||
const Poco::Util::LayeredConfiguration & config = Poco::Util::Application::instance().config();
|
const Poco::Util::LayeredConfiguration & config = Poco::Util::Application::instance().config();
|
||||||
@ -69,18 +90,55 @@ void setSSLParams(nuraft::asio_service::options & asio_opts)
|
|||||||
if (!config.has(private_key_file_property))
|
if (!config.has(private_key_file_property))
|
||||||
throw Exception(ErrorCodes::NO_ELEMENTS_IN_CONFIG, "Server private key file is not set.");
|
throw Exception(ErrorCodes::NO_ELEMENTS_IN_CONFIG, "Server private key file is not set.");
|
||||||
|
|
||||||
asio_opts.enable_ssl_ = true;
|
Poco::Net::Context::Params params;
|
||||||
asio_opts.server_cert_file_ = config.getString(certificate_file_property);
|
params.certificateFile = config.getString(certificate_file_property);
|
||||||
asio_opts.server_key_file_ = config.getString(private_key_file_property);
|
if (params.certificateFile.empty())
|
||||||
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Server certificate file in config '{}' is empty", certificate_file_property);
|
||||||
|
|
||||||
|
params.privateKeyFile = config.getString(private_key_file_property);
|
||||||
|
if (params.privateKeyFile.empty())
|
||||||
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Server key file in config '{}' is empty", private_key_file_property);
|
||||||
|
|
||||||
|
auto pass_phrase = config.getString("openSSL.server.privateKeyPassphraseHandler.options.password", "");
|
||||||
|
auto certificate_data = std::make_shared<CertificateReloader::Data>(params.certificateFile, params.privateKeyFile, pass_phrase);
|
||||||
|
|
||||||
if (config.has(root_ca_file_property))
|
if (config.has(root_ca_file_property))
|
||||||
asio_opts.root_cert_file_ = config.getString(root_ca_file_property);
|
params.caLocation = config.getString(root_ca_file_property);
|
||||||
|
|
||||||
if (config.getBool("openSSL.server.loadDefaultCAFile", false))
|
params.loadDefaultCAs = config.getBool("openSSL.server.loadDefaultCAFile", false);
|
||||||
asio_opts.load_default_ca_file_ = true;
|
params.verificationMode = Poco::Net::Utility::convertVerificationMode(config.getString("openSSL.server.verificationMode", "none"));
|
||||||
|
|
||||||
if (config.getString("openSSL.server.verificationMode", "none") == "none")
|
std::string disabled_protocols_list = config.getString("openSSL.server.disableProtocols", "");
|
||||||
asio_opts.skip_verification_ = true;
|
Poco::StringTokenizer dp_tok(disabled_protocols_list, ";,", Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY);
|
||||||
|
int disabled_protocols = 0;
|
||||||
|
for (const auto & token : dp_tok)
|
||||||
|
{
|
||||||
|
if (token == "sslv2")
|
||||||
|
disabled_protocols |= Poco::Net::Context::PROTO_SSLV2;
|
||||||
|
else if (token == "sslv3")
|
||||||
|
disabled_protocols |= Poco::Net::Context::PROTO_SSLV3;
|
||||||
|
else if (token == "tlsv1")
|
||||||
|
disabled_protocols |= Poco::Net::Context::PROTO_TLSV1;
|
||||||
|
else if (token == "tlsv1_1")
|
||||||
|
disabled_protocols |= Poco::Net::Context::PROTO_TLSV1_1;
|
||||||
|
else if (token == "tlsv1_2")
|
||||||
|
disabled_protocols |= Poco::Net::Context::PROTO_TLSV1_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
asio_opts.ssl_context_provider_server_ = [params, certificate_data, disabled_protocols]
|
||||||
|
{
|
||||||
|
Poco::Net::Context context(Poco::Net::Context::Usage::TLSV1_2_SERVER_USE, params);
|
||||||
|
context.disableProtocols(disabled_protocols);
|
||||||
|
SSL_CTX * ssl_ctx = context.takeSslContext();
|
||||||
|
SSL_CTX_set_cert_cb(ssl_ctx, callSetCertificate, reinterpret_cast<void *>(certificate_data.get()));
|
||||||
|
return ssl_ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
asio_opts.ssl_context_provider_client_ = [ctx_params = std::move(params)]
|
||||||
|
{
|
||||||
|
Poco::Net::Context context(Poco::Net::Context::Usage::TLSV1_2_CLIENT_USE, ctx_params);
|
||||||
|
return context.takeSslContext();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1149,8 +1207,6 @@ Keeper4LWInfo KeeperServer::getPartiallyFilled4LWInfo() const
|
|||||||
result.synced_follower_count = getSyncedFollowerCount();
|
result.synced_follower_count = getSyncedFollowerCount();
|
||||||
}
|
}
|
||||||
result.is_exceeding_mem_soft_limit = isExceedingMemorySoftLimit();
|
result.is_exceeding_mem_soft_limit = isExceedingMemorySoftLimit();
|
||||||
result.total_nodes_count = getKeeperStateMachine()->getNodesCount();
|
|
||||||
result.last_zxid = getKeeperStateMachine()->getLastProcessedZxid();
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user