├── .gitignore ├── .travis.yml ├── CREDITS ├── EXPERIMENTAL ├── LICENSE ├── README.md ├── SeasClick.cpp ├── config.m4 ├── config.w32.without ├── lib └── clickhouse-cpp │ ├── .buckconfig │ ├── .gitattributes │ ├── .gitignore │ ├── .travis.yml │ ├── BUCK │ ├── CMakeLists.txt │ ├── LICENSE │ ├── README.md │ ├── bench │ ├── CMakeLists.txt │ └── bench.cpp │ ├── clickhouse │ ├── CMakeLists.txt │ ├── base │ │ ├── buffer.h │ │ ├── coded.cpp │ │ ├── coded.h │ │ ├── compressed.cpp │ │ ├── compressed.h │ │ ├── input.cpp │ │ ├── input.h │ │ ├── output.cpp │ │ ├── output.h │ │ ├── platform.cpp │ │ ├── platform.h │ │ ├── singleton.h │ │ ├── socket.cpp │ │ ├── socket.h │ │ ├── string_utils.h │ │ ├── string_view.h │ │ └── wire_format.h │ ├── block.cpp │ ├── block.h │ ├── client.cpp │ ├── client.h │ ├── columns │ │ ├── array.cpp │ │ ├── array.h │ │ ├── column.h │ │ ├── date.cpp │ │ ├── date.h │ │ ├── enum.cpp │ │ ├── enum.h │ │ ├── factory.cpp │ │ ├── factory.h │ │ ├── nullable.cpp │ │ ├── nullable.h │ │ ├── numeric.cpp │ │ ├── numeric.h │ │ ├── string.cpp │ │ ├── string.h │ │ ├── tuple.cpp │ │ ├── tuple.h │ │ ├── utils.h │ │ ├── uuid.cpp │ │ └── uuid.h │ ├── error_codes.h │ ├── exceptions.h │ ├── protocol.h │ ├── query.cpp │ ├── query.h │ └── types │ │ ├── type_parser.cpp │ │ ├── type_parser.h │ │ ├── types.cpp │ │ └── types.h │ ├── cmake │ ├── cpp11.cmake │ └── subdirs.cmake │ ├── contrib │ ├── cityhash │ │ ├── BUCK │ │ ├── CMakeLists.txt │ │ ├── COPYING │ │ ├── city.cc │ │ ├── city.h │ │ ├── citycrc.h │ │ └── config.h │ ├── gtest │ │ ├── BUCK │ │ ├── CMakeLists.txt │ │ ├── gtest-all.cc │ │ └── gtest.h │ └── lz4 │ │ ├── BUCK │ │ ├── CMakeLists.txt │ │ ├── LICENSE │ │ ├── lz4.c │ │ ├── lz4.h │ │ ├── lz4hc.c │ │ └── lz4hc.h │ ├── tests │ └── simple │ │ ├── BUCK │ │ ├── CMakeLists.txt │ │ └── main.cpp │ └── ut │ ├── BUCK │ ├── CMakeLists.txt │ ├── client_ut.cpp │ ├── columns_ut.cpp │ ├── main.cpp │ ├── type_parser_ut.cpp │ └── types_ut.cpp ├── package.xml ├── php7_wrapper.h ├── php_SeasClick.h ├── tests ├── 001.phpt ├── 002.phpt ├── 003.phpt ├── 004.phpt ├── 005.phpt ├── 006.phpt ├── 007.phpt ├── 008.phpt ├── 009.phpt ├── 010.phpt ├── bench_mark │ ├── README.md │ ├── bench_mark.php │ ├── bench_mark.png │ ├── composer.json │ └── composer.lock └── test.php ├── travis └── run-tests.sh ├── typesToPhp.cpp └── typesToPhp.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | vendor 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | compiler: 4 | - gcc 5 | - clang 6 | 7 | os: 8 | - linux 9 | 10 | dist: trusty 11 | 12 | env: 13 | - REPORT_EXIT_STATUS=1 NO_INTERACTION=1 14 | 15 | services: 16 | - docker 17 | 18 | #hosts 19 | addons: 20 | hosts: 21 | - clickhouse 22 | 23 | php: 24 | - 5.4 25 | - 5.5 26 | - 5.6 27 | - 7.0 28 | - 7.1 29 | - 7.2 30 | - 7.3 31 | - 7.4 32 | 33 | notifications: 34 | email: whj199649@gmail.com 35 | 36 | #clickhouse 37 | before_install: 38 | - docker run -d -p 9000:9000 --name some-clickhouse-server --ulimit nofile=262144:262144 yandex/clickhouse-server 39 | - docker ps -a 40 | - g++ -v 41 | - gcc -v 42 | - clang -v 43 | - clang++ -v 44 | 45 | #Compile 46 | before_script: 47 | - phpize && ./configure && make clean && make 48 | 49 | # test 50 | script: 51 | - ./travis/run-tests.sh 52 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | SeasClick 2 | 3 | SeasX Group -------------------------------------------------------------------------------- /EXPERIMENTAL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeasX/SeasClick/46299d761096e7e62ea8c6a4717eea82492fd4cd/EXPERIMENTAL -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SeasClick 2 | ===== 3 | [![Build Status](https://travis-ci.org/SeasX/SeasClick.svg?branch=master)](https://travis-ci.org/SeasX/SeasClick) 4 | 5 | PHP client for [Yandex ClickHouse](https://clickhouse.yandex/),Based on [ClickHouse C++ client](https://github.com/aiwhj/clickhouse-cpp) 6 | 7 | ## ClickHouse 8 | * [What is ClickHouse](https://clickhouse.yandex/docs/en/) 9 | * [ClickHouse Performance](https://clickhouse.yandex/docs/en/introduction/performance/) 10 | * [Performance comparison with MySQL](https://clickhouse.yandex/benchmark.html#[%22100000000%22,[%22ClickHouse%22,%22MySQL%22],[%220%22,%221%22]]) 11 | 12 | ## Supported data types 13 | 14 | * Array(T) 15 | **Multidimensional arrays are not supported at this time** 16 | * Date 17 | * DateTime 18 | * Enum8, Enum16 19 | * FixedString(N) 20 | * Float32, Float64 21 | * Nullable(T) 22 | * String 23 | * UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64 24 | 25 | ## Supported PHP version 26 | PHP 5.4+ 27 | 28 | ## Performance 29 | ![image](https://github.com/SeasX/SeasClick/raw/master/tests/bench_mark/bench_mark.png) 30 | 31 | This performance test [demo](https://github.com/SeasX/SeasClick/blob/master/tests/bench_mark/bench_mark.php) is compared to [phpclickhouse](https://github.com/smi2/phpClickHouse) 32 | 33 | ## Install 34 | ```ssh 35 | git clone https://github.com/SeasX/SeasClick.git 36 | cd SeasClick 37 | phpize 38 | ./configure 39 | make && make install 40 | ``` 41 | 42 | ## Example 43 | 44 | ```php 45 | "clickhouse", 48 | "port" => 9000, 49 | "compression" => true 50 | ]; 51 | 52 | clientTest($config); 53 | 54 | function clientTest($config) 55 | { 56 | $deleteTable = true; 57 | $client = new SeasClick($config); 58 | 59 | $client->execute("CREATE DATABASE IF NOT EXISTS test"); 60 | 61 | testArray($client, $deleteTable); 62 | } 63 | 64 | function testArray($client, $deleteTable = false) { 65 | $client->execute("CREATE TABLE IF NOT EXISTS test.array_test (string_c String, array_c Array(Int8), arraynull_c Array(Nullable(String))) ENGINE = Memory"); 66 | 67 | $client->insert("test.array_test", [ 68 | 'string_c', 'array_c', 'arraynull_c' 69 | ], [ 70 | ['string_c1', [1, 2, 3], ['string']], 71 | ['string_c2', [4, 5, 6], [null]] 72 | ]); 73 | 74 | $result = $client->select("SELECT {select} FROM {table}", [ 75 | 'select' => 'string_c, array_c, arraynull_c', 76 | 'table' => 'test.array_test' 77 | ]); 78 | var_dump($result); 79 | 80 | if ($deleteTable) { 81 | $client->execute("DROP TABLE {table}", [ 82 | 'table' => 'test.array_test' 83 | ]); 84 | } 85 | } 86 | ``` 87 | #### [More examples](https://github.com/SeasX/SeasClick/blob/master/tests/test.php) 88 | 89 | ## Support 90 | SeasX Group 91 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl $Id$ 2 | dnl config.m4 for extension SeasClick 3 | 4 | dnl Comments in this file start with the string 'dnl'. 5 | dnl Remove where necessary. This file will not work 6 | dnl without editing. 7 | 8 | dnl If your extension references something external, use with: 9 | 10 | dnl PHP_ARG_WITH(SeasClick, for SeasClick support, 11 | dnl Make sure that the comment is aligned: 12 | dnl [ --with-SeasClick Include SeasClick support]) 13 | 14 | dnl Otherwise use enable: 15 | 16 | PHP_ARG_ENABLE(SeasClick, whether to enable SeasClick support, 17 | Make sure that the comment is aligned: 18 | [ --enable-SeasClick Enable SeasClick support]) 19 | 20 | if test "$PHP_SEASCLICK" != "no"; then 21 | dnl Write more examples of tests here... 22 | 23 | dnl # --with-SeasClick -> check with-path 24 | dnl SEARCH_PATH="/usr/local /usr" # you might want to change this 25 | dnl SEARCH_FOR="/include/SeasClick.h" # you most likely want to change this 26 | dnl if test -r $PHP_SEASCLICK/$SEARCH_FOR; then # path given as parameter 27 | dnl SEASCLICK_DIR=$PHP_SEASCLICK 28 | dnl else # search default path list 29 | dnl AC_MSG_CHECKING([for SeasClick files in default path]) 30 | dnl for i in $SEARCH_PATH ; do 31 | dnl if test -r $i/$SEARCH_FOR; then 32 | dnl SEASCLICK_DIR=$i 33 | dnl AC_MSG_RESULT(found in $i) 34 | dnl fi 35 | dnl done 36 | dnl fi 37 | dnl 38 | dnl if test -z "$SEASCLICK_DIR"; then 39 | dnl AC_MSG_RESULT([not found]) 40 | dnl AC_MSG_ERROR([Please reinstall the SeasClick distribution]) 41 | dnl fi 42 | 43 | dnl # --with-SeasClick -> add include path 44 | dnl PHP_ADD_INCLUDE($SEASCLICK_DIR/include) 45 | 46 | dnl # --with-SeasClick -> check for lib and symbol presence 47 | dnl LIBNAME=SeasClick # you may want to change this 48 | dnl LIBSYMBOL=SeasClick # you most likely want to change this 49 | 50 | dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, 51 | dnl [ 52 | dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SEASCLICK_DIR/$PHP_LIBDIR, SEASCLICK_SHARED_LIBADD) 53 | dnl AC_DEFINE(HAVE_SEASCLICKLIB,1,[ ]) 54 | dnl ],[ 55 | dnl AC_MSG_ERROR([wrong SeasClick lib version or lib not found]) 56 | dnl ],[ 57 | dnl -L$SEASCLICK_DIR/$PHP_LIBDIR -lm 58 | dnl ]) 59 | dnl 60 | dnl PHP_SUBST(SEASCLICK_SHARED_LIBADD) 61 | PHP_REQUIRE_CXX() 62 | PHP_SUBST(SEASCLICK_SHARED_LIBADD) 63 | PHP_ADD_LIBRARY(stdc++, 1, SEASCLICK_SHARED_LIBADD) 64 | CXXFLAGS="$CXXFLAGS -Wall -Wno-unused-function -Wno-deprecated -Wno-deprecated-declarations -std=c++11" 65 | SeasClick_source_file="SeasClick.cpp \ 66 | typesToPhp.cpp \ 67 | lib/clickhouse-cpp/clickhouse/base/coded.cpp \ 68 | lib/clickhouse-cpp/clickhouse/base/compressed.cpp \ 69 | lib/clickhouse-cpp/clickhouse/base/input.cpp \ 70 | lib/clickhouse-cpp/clickhouse/base/output.cpp \ 71 | lib/clickhouse-cpp/clickhouse/base/platform.cpp \ 72 | lib/clickhouse-cpp/clickhouse/base/socket.cpp \ 73 | lib/clickhouse-cpp/clickhouse/columns/array.cpp \ 74 | lib/clickhouse-cpp/clickhouse/columns/date.cpp \ 75 | lib/clickhouse-cpp/clickhouse/columns/enum.cpp \ 76 | lib/clickhouse-cpp/clickhouse/columns/factory.cpp \ 77 | lib/clickhouse-cpp/clickhouse/columns/nullable.cpp \ 78 | lib/clickhouse-cpp/clickhouse/columns/numeric.cpp \ 79 | lib/clickhouse-cpp/clickhouse/columns/string.cpp \ 80 | lib/clickhouse-cpp/clickhouse/columns/tuple.cpp \ 81 | lib/clickhouse-cpp/clickhouse/columns/uuid.cpp \ 82 | lib/clickhouse-cpp/clickhouse/types/type_parser.cpp \ 83 | lib/clickhouse-cpp/clickhouse/types/types.cpp \ 84 | lib/clickhouse-cpp/contrib/cityhash/city.cc \ 85 | lib/clickhouse-cpp/contrib/lz4/lz4.c \ 86 | lib/clickhouse-cpp/contrib/lz4/lz4hc.c \ 87 | lib/clickhouse-cpp/contrib/gtest/gtest-all.cc \ 88 | lib/clickhouse-cpp/clickhouse/block.cpp \ 89 | lib/clickhouse-cpp/clickhouse/client.cpp \ 90 | lib/clickhouse-cpp/clickhouse/query.cpp" 91 | SeasClick_header_file="lib/clickhouse-cpp/contrib" 92 | 93 | THIS_DIR=`dirname $0` 94 | PHP_ADD_INCLUDE($THIS_DIR/lib/clickhouse-cpp/contrib) 95 | 96 | PHP_NEW_EXTENSION(SeasClick, $SeasClick_source_file, $ext_shared,,-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) 97 | PHP_ADD_BUILD_DIR($ext_builddir/lib/clickhouse-cpp) 98 | PHP_ADD_BUILD_DIR($ext_builddir/lib/clickhouse-cpp/contrib) 99 | PHP_ADD_BUILD_DIR($ext_builddir/lib/clickhouse-cpp/contrib/cityhash) 100 | PHP_ADD_BUILD_DIR($ext_builddir/lib/clickhouse-cpp/contrib/gtest) 101 | PHP_ADD_BUILD_DIR($ext_builddir/lib/clickhouse-cpp/contrib/lz4) 102 | PHP_ADD_BUILD_DIR($ext_builddir/lib/clickhouse-cpp/clickhouse) 103 | PHP_ADD_BUILD_DIR($ext_builddir/lib/clickhouse-cpp/clickhouse/base) 104 | PHP_ADD_BUILD_DIR($ext_builddir/lib/clickhouse-cpp/clickhouse/types) 105 | PHP_ADD_BUILD_DIR($ext_builddir/lib/clickhouse-cpp/clickhouse/columns) 106 | PHP_ADD_BUILD_DIR($ext_builddir/lib/clickhouse-cpp) 107 | fi 108 | -------------------------------------------------------------------------------- /config.w32.without: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | // If your extension references something external, use ARG_WITH 5 | // ARG_WITH("SeasClick", "for SeasClick support", "no"); 6 | 7 | // Otherwise, use ARG_ENABLE 8 | // ARG_ENABLE("SeasClick", "enable SeasClick support", "no"); 9 | 10 | if (PHP_SEASCLICK != "no") { 11 | EXTENSION("SeasClick", "SeasClick.c", PHP_EXTNAME_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/.buckconfig: -------------------------------------------------------------------------------- 1 | [cxx] 2 | gtest_dep = //contrib/gtest:gtest 3 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | # Temporary solution for VS 2015 13 | vs/ 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | build/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | 28 | # Visual Studio 2015 cache/options directory 29 | .vs/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | 33 | # MSTest test Results 34 | [Tt]est[Rr]esult*/ 35 | [Bb]uild[Ll]og.* 36 | 37 | # NUNIT 38 | *.VisualState.xml 39 | TestResult.xml 40 | 41 | # Build Results of an ATL Project 42 | [Dd]ebugPS/ 43 | [Rr]eleasePS/ 44 | dlldata.c 45 | 46 | # DNX 47 | project.lock.json 48 | project.fragment.lock.json 49 | artifacts/ 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # NCrunch 117 | _NCrunch_* 118 | .*crunch*.local.xml 119 | nCrunchTemp_* 120 | 121 | # MightyMoose 122 | *.mm.* 123 | AutoTest.Net/ 124 | 125 | # Web workbench (sass) 126 | .sass-cache/ 127 | 128 | # Installshield output folder 129 | [Ee]xpress/ 130 | 131 | # DocProject is a documentation generator add-in 132 | DocProject/buildhelp/ 133 | DocProject/Help/*.HxT 134 | DocProject/Help/*.HxC 135 | DocProject/Help/*.hhc 136 | DocProject/Help/*.hhk 137 | DocProject/Help/*.hhp 138 | DocProject/Help/Html2 139 | DocProject/Help/html 140 | 141 | # Click-Once directory 142 | publish/ 143 | 144 | # Publish Web Output 145 | *.[Pp]ublish.xml 146 | *.azurePubxml 147 | # TODO: Comment the next line if you want to checkin your web deploy settings 148 | # but database connection strings (with potential passwords) will be unencrypted 149 | #*.pubxml 150 | *.publishproj 151 | 152 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 153 | # checkin your Azure Web App publish settings, but sensitive information contained 154 | # in these scripts will be unencrypted 155 | PublishScripts/ 156 | 157 | # NuGet Packages 158 | *.nupkg 159 | # The packages folder can be ignored because of Package Restore 160 | **/packages/* 161 | # except build/, which is used as an MSBuild target. 162 | !**/packages/build/ 163 | # Uncomment if necessary however generally it will be regenerated when needed 164 | #!**/packages/repositories.config 165 | # NuGet v3's project.json files produces more ignoreable files 166 | *.nuget.props 167 | *.nuget.targets 168 | 169 | # Microsoft Azure Build Output 170 | csx/ 171 | *.build.csdef 172 | 173 | # Microsoft Azure Emulator 174 | ecf/ 175 | rcf/ 176 | 177 | # Windows Store app package directories and files 178 | AppPackages/ 179 | BundleArtifacts/ 180 | Package.StoreAssociation.xml 181 | _pkginfo.txt 182 | 183 | # Visual Studio cache files 184 | # files ending in .cache can be ignored 185 | *.[Cc]ache 186 | # but keep track of directories ending in .cache 187 | !*.[Cc]ache/ 188 | 189 | # Others 190 | ClientBin/ 191 | ~$* 192 | *~ 193 | *.dbmdl 194 | *.dbproj.schemaview 195 | *.jfm 196 | *.pfx 197 | *.publishsettings 198 | node_modules/ 199 | orleans.codegen.cs 200 | 201 | # Since there are multiple workflows, uncomment next line to ignore bower_components 202 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 203 | #bower_components/ 204 | 205 | # RIA/Silverlight projects 206 | Generated_Code/ 207 | 208 | # Backup & report files from converting an old project file 209 | # to a newer Visual Studio version. Backup files are not needed, 210 | # because we have git ;-) 211 | _UpgradeReport_Files/ 212 | Backup*/ 213 | UpgradeLog*.XML 214 | UpgradeLog*.htm 215 | 216 | # SQL Server files 217 | *.mdf 218 | *.ldf 219 | 220 | # Business Intelligence projects 221 | *.rdl.data 222 | *.bim.layout 223 | *.bim_*.settings 224 | 225 | # Microsoft Fakes 226 | FakesAssemblies/ 227 | 228 | # GhostDoc plugin setting file 229 | *.GhostDoc.xml 230 | 231 | # Node.js Tools for Visual Studio 232 | .ntvs_analysis.dat 233 | 234 | # Visual Studio 6 build log 235 | *.plg 236 | 237 | # Visual Studio 6 workspace options file 238 | *.opt 239 | 240 | # Visual Studio LightSwitch build output 241 | **/*.HTMLClient/GeneratedArtifacts 242 | **/*.DesktopClient/GeneratedArtifacts 243 | **/*.DesktopClient/ModelManifest.xml 244 | **/*.Server/GeneratedArtifacts 245 | **/*.Server/ModelManifest.xml 246 | _Pvt_Extensions 247 | 248 | # Paket dependency manager 249 | .paket/paket.exe 250 | paket-files/ 251 | 252 | # FAKE - F# Make 253 | .fake/ 254 | 255 | # JetBrains Rider 256 | .idea/ 257 | *.sln.iml 258 | 259 | # CodeRush 260 | .cr/ 261 | 262 | # Python Tools for Visual Studio (PTVS) 263 | __pycache__/ 264 | *.pyc 265 | 266 | # Buck 267 | /buck-out/ 268 | /.buckd/ 269 | /buckaroo/ 270 | .buckconfig.local 271 | BUCKAROO_DEPS 272 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/.travis.yml: -------------------------------------------------------------------------------- 1 | # Enable C++ support 2 | language: cpp 3 | 4 | matrix: 5 | include: 6 | - os: linux 7 | dist: trusty 8 | sudo: required 9 | compiler: gcc 10 | 11 | - os: linux 12 | dist: trusty 13 | sudo: required 14 | compiler: clang 15 | 16 | - os: osx 17 | osx_image: xcode8.2 18 | compiler: clang 19 | 20 | before_install: 21 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo 'deb http://repo.yandex.ru/clickhouse/deb/stable main/' | sudo tee /etc/apt/sources.list.d/clickhouse.list ; fi 22 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E0C56BD4 ; fi 23 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -q && sudo apt-get install -q -y clickhouse-server-common ; fi 24 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo service clickhouse-server start ; fi 25 | 26 | # Build steps 27 | script: 28 | - mkdir build 29 | - cd build 30 | - cmake .. && make 31 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./ut/clickhouse-cpp-ut ; fi 32 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./ut/clickhouse-cpp-ut --gtest_filter='-Client/*' ; fi 33 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/BUCK: -------------------------------------------------------------------------------- 1 | cxx_library( 2 | name = 'clickhouse-cpp', 3 | header_namespace = 'clickhouse', 4 | exported_headers = subdir_glob([ 5 | ('clickhouse', '**/*.h'), 6 | ]), 7 | srcs = glob([ 8 | 'clickhouse/**/*.cpp', 9 | ]), 10 | compiler_flags = [ 11 | '-std=c++11', 12 | ], 13 | visibility = [ 14 | 'PUBLIC', 15 | ], 16 | deps = [ 17 | '//contrib/cityhash:cityhash', 18 | '//contrib/lz4:lz4', 19 | ] 20 | ) 21 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2) 2 | 3 | INCLUDE (cmake/cpp11.cmake) 4 | INCLUDE (cmake/subdirs.cmake) 5 | 6 | OPTION(BUILD_BENCHMARK "Build benchmark" OFF) 7 | 8 | PROJECT (CLICKHOUSE-CLIENT) 9 | 10 | USE_CXX11() 11 | 12 | IF (UNIX) 13 | IF (APPLE) 14 | SET (CMAKE_CXX_FLAGS "-O2 -Wall -Wextra -Werror") 15 | ELSE () 16 | SET (CMAKE_CXX_FLAGS "-O2 -pthread -Wall -Wextra -Werror") 17 | ENDIF () 18 | SET (CMAKE_EXE_LINKER_FLAGS, "-lpthread") 19 | ENDIF () 20 | 21 | INCLUDE_DIRECTORIES(.) 22 | INCLUDE_DIRECTORIES(contrib) 23 | 24 | SUBDIRS ( 25 | clickhouse 26 | contrib/cityhash 27 | contrib/gtest 28 | contrib/lz4 29 | tests/simple 30 | ut 31 | ) 32 | 33 | IF (BUILD_BENCHMARK) 34 | SUBDIRS(bench) 35 | ENDIF (BUILD_BENCHMARK) 36 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Pavel Artemkin 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/README.md: -------------------------------------------------------------------------------- 1 | ClickHouse C++ client [![Build Status](https://travis-ci.org/artpaul/clickhouse-cpp.svg?branch=master)](https://travis-ci.org/artpaul/clickhouse-cpp) 2 | ===== 3 | 4 | C++ client for [Yandex ClickHouse](https://clickhouse.yandex/) 5 | 6 | ## This repositorie change 7 | * [Add InsertQuery and InsertData methods](https://github.com/aiwhj/clickhouse-cpp/commit/bab28bcb5a509d80b8e2e0c7e89512446283dde5) 8 | 9 | ## Supported data types 10 | 11 | * Array(T) 12 | * Date 13 | * DateTime 14 | * Enum8, Enum16 15 | * FixedString(N) 16 | * Float32, Float64 17 | * Nullable(T) 18 | * String 19 | * Tuple 20 | * UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64 21 | 22 | ## Building 23 | 24 | ```sh 25 | $ mkdir build . 26 | $ cd build 27 | $ cmake .. 28 | $ make 29 | ``` 30 | 31 | ## Example 32 | 33 | ```cpp 34 | #include 35 | 36 | using namespace clickhouse; 37 | 38 | /// Initialize client connection. 39 | Client client(ClientOptions().SetHost("localhost")); 40 | 41 | /// Create a table. 42 | client.Execute("CREATE TABLE IF NOT EXISTS test.numbers (id UInt64, name String) ENGINE = Memory"); 43 | 44 | /// Insert some values. 45 | { 46 | Block block; 47 | 48 | auto id = std::make_shared(); 49 | id->Append(1); 50 | id->Append(7); 51 | 52 | auto name = std::make_shared(); 53 | name->Append("one"); 54 | name->Append("seven"); 55 | 56 | block.AppendColumn("id" , id); 57 | block.AppendColumn("name", name); 58 | 59 | client.Insert("test.numbers", block); 60 | } 61 | 62 | /// Select values inserted in the previous step. 63 | client.Select("SELECT id, name FROM test.numbers", [] (const Block& block) 64 | { 65 | for (size_t i = 0; i < block.GetRowCount(); ++i) { 66 | std::cout << block[0]->As()->At(i) << " " 67 | << block[1]->As()->At(i) << "\n"; 68 | } 69 | } 70 | ); 71 | 72 | /// Delete table. 73 | client.Execute("DROP TABLE test.numbers"); 74 | ``` 75 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/bench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_EXECUTABLE (bench 2 | bench.cpp 3 | ) 4 | 5 | TARGET_LINK_LIBRARIES (bench 6 | clickhouse-cpp-lib 7 | benchmark 8 | ) 9 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/bench/bench.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace clickhouse { 6 | 7 | Client g_client(ClientOptions() 8 | .SetHost("localhost") 9 | .SetPingBeforeQuery(false)); 10 | 11 | static void SelectNumber(benchmark::State& state) { 12 | while (state.KeepRunning()) { 13 | g_client.Select("SELECT number, number, number FROM system.numbers LIMIT 1000", 14 | [](const Block& block) { block.GetRowCount(); } 15 | ); 16 | } 17 | } 18 | BENCHMARK(SelectNumber); 19 | 20 | static void SelectNumberMoreColumns(benchmark::State& state) { 21 | // Mainly test performance on type name parsing. 22 | while (state.KeepRunning()) { 23 | g_client.Select("SELECT " 24 | "number, number, number, number, number, number, number, number, number, number " 25 | "FROM system.numbers LIMIT 100", 26 | [](const Block& block) { block.GetRowCount(); } 27 | ); 28 | } 29 | } 30 | BENCHMARK(SelectNumberMoreColumns); 31 | 32 | } 33 | 34 | BENCHMARK_MAIN(); 35 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_LIBRARY (clickhouse-cpp-lib 2 | base/coded.cpp 3 | base/compressed.cpp 4 | base/input.cpp 5 | base/output.cpp 6 | base/platform.cpp 7 | base/socket.cpp 8 | 9 | columns/array.cpp 10 | columns/date.cpp 11 | columns/enum.cpp 12 | columns/factory.cpp 13 | columns/nullable.cpp 14 | columns/numeric.cpp 15 | columns/string.cpp 16 | columns/tuple.cpp 17 | columns/uuid.cpp 18 | 19 | types/type_parser.cpp 20 | types/types.cpp 21 | 22 | block.cpp 23 | client.cpp 24 | query.cpp 25 | ) 26 | 27 | SET_TARGET_PROPERTIES(clickhouse-cpp-lib 28 | PROPERTIES LINKER_LANGUAGE CXX) 29 | 30 | TARGET_LINK_LIBRARIES (clickhouse-cpp-lib 31 | cityhash-lib 32 | lz4-lib 33 | ) 34 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace clickhouse { 7 | 8 | using Buffer = std::vector; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/coded.cpp: -------------------------------------------------------------------------------- 1 | #include "coded.h" 2 | 3 | #include 4 | 5 | namespace clickhouse { 6 | 7 | static const int MAX_VARINT_BYTES = 10; 8 | 9 | CodedInputStream::CodedInputStream(ZeroCopyInput* input) 10 | : input_(input) 11 | { 12 | } 13 | 14 | bool CodedInputStream::ReadRaw(void* buffer, size_t size) { 15 | uint8_t* p = static_cast(buffer); 16 | 17 | while (size > 0) { 18 | const void* ptr; 19 | size_t len = input_->Next(&ptr, size); 20 | 21 | memcpy(p, ptr, len); 22 | 23 | p += len; 24 | size -= len; 25 | } 26 | 27 | return true; 28 | } 29 | 30 | bool CodedInputStream::Skip(size_t count) { 31 | while (count > 0) { 32 | const void* ptr; 33 | size_t len = input_->Next(&ptr, count); 34 | 35 | if (len == 0) { 36 | return false; 37 | } 38 | 39 | count -= len; 40 | } 41 | 42 | return true; 43 | } 44 | 45 | bool CodedInputStream::ReadVarint64(uint64_t* value) { 46 | *value = 0; 47 | 48 | for (size_t i = 0; i < 9; ++i) { 49 | uint8_t byte; 50 | 51 | if (!input_->ReadByte(&byte)) { 52 | return false; 53 | } else { 54 | *value |= (byte & 0x7F) << (7 * i); 55 | 56 | if (!(byte & 0x80)) { 57 | return true; 58 | } 59 | } 60 | } 61 | 62 | // TODO skip invalid 63 | return false; 64 | } 65 | 66 | 67 | CodedOutputStream::CodedOutputStream(ZeroCopyOutput* output) 68 | : output_(output) 69 | { 70 | } 71 | 72 | void CodedOutputStream::Flush() { 73 | output_->Flush(); 74 | } 75 | 76 | void CodedOutputStream::WriteRaw(const void* buffer, int size) { 77 | output_->Write(buffer, size); 78 | } 79 | 80 | void CodedOutputStream::WriteVarint64(uint64_t value) { 81 | uint8_t bytes[MAX_VARINT_BYTES]; 82 | int size = 0; 83 | 84 | for (size_t i = 0; i < 9; ++i) { 85 | uint8_t byte = value & 0x7F; 86 | if (value > 0x7F) 87 | byte |= 0x80; 88 | 89 | bytes[size++] = byte; 90 | 91 | value >>= 7; 92 | if (!value) { 93 | break; 94 | } 95 | } 96 | 97 | WriteRaw(bytes, size); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/coded.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "input.h" 4 | #include "output.h" 5 | 6 | #include 7 | 8 | namespace clickhouse { 9 | 10 | /** 11 | * Class which reads and decodes binary data which is composed of varint- 12 | * encoded integers and fixed-width pieces. 13 | */ 14 | class CodedInputStream { 15 | public: 16 | /// Create a CodedInputStream that reads from the given ZeroCopyInput. 17 | explicit CodedInputStream(ZeroCopyInput* input); 18 | 19 | // Read an unsigned integer with Varint encoding, truncating to 32 bits. 20 | // Reading a 32-bit value is equivalent to reading a 64-bit one and casting 21 | // it to uint32, but may be more efficient. 22 | bool ReadVarint32(uint32_t* value); 23 | 24 | // Read an unsigned integer with Varint encoding. 25 | bool ReadVarint64(uint64_t* value); 26 | 27 | // Read raw bytes, copying them into the given buffer. 28 | bool ReadRaw(void* buffer, size_t size); 29 | 30 | // Like ReadRaw, but reads into a string. 31 | // 32 | // Implementation Note: ReadString() grows the string gradually as it 33 | // reads in the data, rather than allocating the entire requested size 34 | // upfront. This prevents denial-of-service attacks in which a client 35 | // could claim that a string is going to be MAX_INT bytes long in order to 36 | // crash the server because it can't allocate this much space at once. 37 | bool ReadString(std::string* buffer, int size); 38 | 39 | // Skips a number of bytes. Returns false if an underlying read error 40 | // occurs. 41 | bool Skip(size_t count); 42 | 43 | private: 44 | ZeroCopyInput* input_; 45 | }; 46 | 47 | 48 | class CodedOutputStream { 49 | public: 50 | /// Create a CodedInputStream that writes to the given ZeroCopyOutput. 51 | explicit CodedOutputStream(ZeroCopyOutput* output); 52 | 53 | void Flush(); 54 | 55 | // Write raw bytes, copying them from the given buffer. 56 | void WriteRaw(const void* buffer, int size); 57 | 58 | /// Write an unsigned integer with Varint encoding. 59 | void WriteVarint64(const uint64_t value); 60 | 61 | private: 62 | ZeroCopyOutput* output_; 63 | }; 64 | 65 | } 66 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/compressed.cpp: -------------------------------------------------------------------------------- 1 | #include "compressed.h" 2 | #include "wire_format.h" 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #define DBMS_MAX_COMPRESSED_SIZE 0x40000000ULL // 1GB 10 | 11 | namespace clickhouse { 12 | 13 | CompressedInput::CompressedInput(CodedInputStream* input) 14 | : input_(input) 15 | { 16 | } 17 | 18 | CompressedInput::~CompressedInput() { 19 | if (!mem_.Exhausted()) { 20 | if (!std::uncaught_exception()) { 21 | throw std::runtime_error("some data was not readed"); 22 | } 23 | } 24 | } 25 | 26 | size_t CompressedInput::DoNext(const void** ptr, size_t len) { 27 | if (mem_.Exhausted()) { 28 | if (!Decompress()) { 29 | return 0; 30 | } 31 | } 32 | 33 | return mem_.Next(ptr, len); 34 | } 35 | 36 | bool CompressedInput::Decompress() { 37 | uint128 hash; 38 | uint32_t compressed = 0; 39 | uint32_t original = 0; 40 | uint8_t method = 0; 41 | 42 | if (!WireFormat::ReadFixed(input_, &hash)) { 43 | return false; 44 | } 45 | if (!WireFormat::ReadFixed(input_, &method)) { 46 | return false; 47 | } 48 | 49 | if (method != 0x82) { 50 | throw std::runtime_error("unsupported compression method " + 51 | std::to_string(int(method))); 52 | } else { 53 | if (!WireFormat::ReadFixed(input_, &compressed)) { 54 | return false; 55 | } 56 | if (!WireFormat::ReadFixed(input_, &original)) { 57 | return false; 58 | } 59 | 60 | if (compressed > DBMS_MAX_COMPRESSED_SIZE) { 61 | throw std::runtime_error("compressed data too big"); 62 | } 63 | 64 | Buffer tmp(compressed); 65 | 66 | // Заполнить заголовок сжатых данных. 67 | { 68 | BufferOutput out(&tmp); 69 | out.Write(&method, sizeof(method)); 70 | out.Write(&compressed, sizeof(compressed)); 71 | out.Write(&original, sizeof(original)); 72 | } 73 | 74 | if (!WireFormat::ReadBytes(input_, tmp.data() + 9, compressed - 9)) { 75 | return false; 76 | } else { 77 | if (hash != CityHash128((const char*)tmp.data(), compressed)) { 78 | throw std::runtime_error("data was corrupted"); 79 | } 80 | } 81 | 82 | data_ = Buffer(original); 83 | 84 | if (LZ4_decompress_fast((const char*)tmp.data() + 9, (char*)data_.data(), original) < 0) { 85 | throw std::runtime_error("can't decompress data"); 86 | } else { 87 | mem_.Reset(data_.data(), original); 88 | } 89 | } 90 | 91 | return true; 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/compressed.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "coded.h" 4 | 5 | namespace clickhouse { 6 | 7 | class CompressedInput : public ZeroCopyInput { 8 | public: 9 | CompressedInput(CodedInputStream* input); 10 | ~CompressedInput(); 11 | 12 | protected: 13 | size_t DoNext(const void** ptr, size_t len) override; 14 | 15 | bool Decompress(); 16 | 17 | private: 18 | CodedInputStream* const input_; 19 | 20 | Buffer data_; 21 | ArrayInput mem_; 22 | }; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/input.cpp: -------------------------------------------------------------------------------- 1 | #include "input.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace clickhouse { 7 | 8 | size_t ZeroCopyInput::DoRead(void* buf, size_t len) { 9 | const void* ptr; 10 | size_t result = DoNext(&ptr, len); 11 | 12 | if (result) { 13 | memcpy(buf, ptr, result); 14 | } 15 | 16 | return result; 17 | } 18 | 19 | ArrayInput::ArrayInput() noexcept 20 | : data_(nullptr) 21 | , len_(0) 22 | { 23 | } 24 | 25 | ArrayInput::ArrayInput(const void* buf, size_t len) noexcept 26 | : data_(static_cast(buf)) 27 | , len_(len) 28 | { 29 | } 30 | 31 | ArrayInput::~ArrayInput() = default; 32 | 33 | size_t ArrayInput::DoNext(const void** ptr, size_t len) { 34 | len = std::min(len_, len); 35 | 36 | *ptr = data_; 37 | len_ -= len; 38 | data_ += len; 39 | 40 | return len; 41 | } 42 | 43 | 44 | BufferedInput::BufferedInput(InputStream* slave, size_t buflen) 45 | : slave_(slave) 46 | , array_input_(nullptr, 0) 47 | , buffer_(buflen) 48 | { 49 | } 50 | 51 | BufferedInput::~BufferedInput() = default; 52 | 53 | void BufferedInput::Reset() { 54 | array_input_.Reset(nullptr, 0); 55 | } 56 | 57 | size_t BufferedInput::DoNext(const void** ptr, size_t len) { 58 | if (array_input_.Exhausted()) { 59 | array_input_.Reset( 60 | buffer_.data(), slave_->Read(buffer_.data(), buffer_.size()) 61 | ); 62 | } 63 | 64 | return array_input_.Next(ptr, len); 65 | } 66 | 67 | size_t BufferedInput::DoRead(void* buf, size_t len) { 68 | if (array_input_.Exhausted()) { 69 | if (len > buffer_.size() / 2) { 70 | return slave_->Read(buf, len); 71 | } 72 | 73 | array_input_.Reset( 74 | buffer_.data(), slave_->Read(buffer_.data(), buffer_.size()) 75 | ); 76 | } 77 | 78 | return array_input_.Read(buf, len); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/input.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace clickhouse { 8 | 9 | class InputStream { 10 | public: 11 | virtual ~InputStream() noexcept (false) 12 | { } 13 | 14 | /// Reads one byte from the stream. 15 | inline bool ReadByte(uint8_t* byte) { 16 | return DoRead(byte, sizeof(uint8_t)) == sizeof(uint8_t); 17 | } 18 | 19 | /// Reads some data from the stream. 20 | inline size_t Read(void* buf, size_t len) { 21 | return DoRead(buf, len); 22 | } 23 | 24 | protected: 25 | virtual size_t DoRead(void* buf, size_t len) = 0; 26 | }; 27 | 28 | 29 | class ZeroCopyInput : public InputStream { 30 | public: 31 | inline size_t Next(const void** buf, size_t len) { 32 | return DoNext(buf, len); 33 | } 34 | 35 | protected: 36 | virtual size_t DoNext(const void** ptr, size_t len) = 0; 37 | 38 | size_t DoRead(void* buf, size_t len) override; 39 | }; 40 | 41 | 42 | /** 43 | * A ZeroCopyInput stream backed by an in-memory array of bytes. 44 | */ 45 | class ArrayInput : public ZeroCopyInput { 46 | public: 47 | ArrayInput() noexcept; 48 | ArrayInput(const void* buf, size_t len) noexcept; 49 | ~ArrayInput() override; 50 | 51 | /// Number of bytes available in the stream. 52 | inline size_t Avail() const noexcept { 53 | return len_; 54 | } 55 | 56 | /// Current read position in the memory block used by this stream. 57 | inline const uint8_t* Data() const noexcept { 58 | return data_; 59 | } 60 | 61 | /// Whether there is more data in the stream. 62 | inline bool Exhausted() const noexcept { 63 | return !Avail(); 64 | } 65 | 66 | inline void Reset(const void* buf, size_t len) noexcept { 67 | data_ = static_cast(buf); 68 | len_ = len; 69 | } 70 | 71 | private: 72 | size_t DoNext(const void** ptr, size_t len) override; 73 | 74 | private: 75 | const uint8_t* data_; 76 | size_t len_; 77 | }; 78 | 79 | 80 | class BufferedInput : public ZeroCopyInput { 81 | public: 82 | BufferedInput(InputStream* slave, size_t buflen = 8192); 83 | ~BufferedInput() override; 84 | 85 | void Reset(); 86 | 87 | protected: 88 | size_t DoRead(void* buf, size_t len) override; 89 | size_t DoNext(const void** ptr, size_t len) override; 90 | 91 | private: 92 | InputStream* const slave_; 93 | ArrayInput array_input_; 94 | std::vector buffer_; 95 | }; 96 | 97 | } 98 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/output.cpp: -------------------------------------------------------------------------------- 1 | #include "output.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace clickhouse { 8 | 9 | void ZeroCopyOutput::DoWrite(const void* data, size_t len) { 10 | while (len > 0) { 11 | void* ptr; 12 | size_t result = DoNext(&ptr, len); 13 | 14 | if (result) { 15 | memcpy(ptr, data, result); 16 | len -= result; 17 | data = static_cast(data) + result; 18 | } else { 19 | break; 20 | } 21 | } 22 | } 23 | 24 | 25 | ArrayOutput::ArrayOutput(void* buf, size_t len) 26 | : buf_(static_cast(buf)) 27 | , end_(buf_ + len) 28 | { 29 | } 30 | 31 | ArrayOutput::~ArrayOutput() = default; 32 | 33 | size_t ArrayOutput::DoNext(void** data, size_t len) { 34 | len = std::min(len, Avail()); 35 | 36 | *data = buf_; 37 | buf_ += len; 38 | 39 | return len; 40 | } 41 | 42 | 43 | BufferOutput::BufferOutput(Buffer* buf) 44 | : buf_(buf) 45 | , pos_(0) 46 | { 47 | assert(buf_); 48 | } 49 | 50 | BufferOutput::~BufferOutput() 51 | { } 52 | 53 | size_t BufferOutput::DoNext(void** data, size_t len) { 54 | if (pos_ + len > buf_->size()) { 55 | buf_->resize(pos_ + len); 56 | } 57 | 58 | *data = buf_->data() + pos_; 59 | pos_ += len; 60 | 61 | return len; 62 | } 63 | 64 | 65 | BufferedOutput::BufferedOutput(OutputStream* slave, size_t buflen) 66 | : slave_(slave) 67 | , buffer_(buflen) 68 | , array_output_(buffer_.data(), buflen) 69 | { 70 | } 71 | 72 | BufferedOutput::~BufferedOutput() { 73 | Flush(); 74 | } 75 | 76 | void BufferedOutput::Reset() { 77 | array_output_.Reset(buffer_.data(), buffer_.size()); 78 | } 79 | 80 | void BufferedOutput::DoFlush() { 81 | if (array_output_.Data() != buffer_.data()) { 82 | slave_->Write(buffer_.data(), array_output_.Data() - buffer_.data()); 83 | slave_->Flush(); 84 | 85 | array_output_.Reset(buffer_.data(), buffer_.size()); 86 | } 87 | } 88 | 89 | size_t BufferedOutput::DoNext(void** data, size_t len) { 90 | if (array_output_.Avail() < len) { 91 | Flush(); 92 | } 93 | 94 | return array_output_.Next(data, len); 95 | 96 | } 97 | 98 | void BufferedOutput::DoWrite(const void* data, size_t len) { 99 | if (array_output_.Avail() < len) { 100 | Flush(); 101 | 102 | if (len > buffer_.size() / 2) { 103 | slave_->Write(data, len); 104 | return; 105 | } 106 | } 107 | 108 | array_output_.Write(data, len); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/output.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "buffer.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace clickhouse { 11 | 12 | class OutputStream { 13 | public: 14 | virtual ~OutputStream() 15 | { } 16 | 17 | inline void Flush() { 18 | DoFlush(); 19 | } 20 | 21 | inline void Write(const void* data, size_t len) { 22 | DoWrite(data, len); 23 | } 24 | 25 | protected: 26 | virtual void DoFlush() { } 27 | 28 | virtual void DoWrite(const void* data, size_t len) = 0; 29 | }; 30 | 31 | 32 | class ZeroCopyOutput : public OutputStream { 33 | public: 34 | inline size_t Next(void** data, size_t size) { 35 | return DoNext(data, size); 36 | } 37 | 38 | protected: 39 | // Obtains a buffer into which data can be written. Any data written 40 | // into this buffer will eventually (maybe instantly, maybe later on) 41 | // be written to the output. 42 | virtual size_t DoNext(void** data, size_t len) = 0; 43 | 44 | void DoWrite(const void* data, size_t len) override; 45 | }; 46 | 47 | 48 | /** 49 | * A ZeroCopyOutput stream backed by an in-memory array of bytes. 50 | */ 51 | class ArrayOutput : public ZeroCopyOutput { 52 | public: 53 | ArrayOutput(void* buf, size_t len); 54 | ~ArrayOutput() override; 55 | 56 | /// Number of bytes available in the stream. 57 | inline size_t Avail() const noexcept { 58 | return end_ - buf_; 59 | } 60 | 61 | /// Current write position in the memory block used by this stream. 62 | inline const uint8_t* Data() const noexcept { 63 | return buf_; 64 | } 65 | 66 | /// Whether there is more space in the stream. 67 | inline bool Exhausted() const noexcept { 68 | return !Avail(); 69 | } 70 | 71 | /// Initializes this stream with a new memory block. 72 | inline void Reset(void* buf, size_t len) noexcept { 73 | buf_ = static_cast(buf); 74 | end_ = buf_ + len; 75 | } 76 | 77 | protected: 78 | size_t DoNext(void** data, size_t len) override; 79 | 80 | private: 81 | uint8_t* buf_; 82 | uint8_t* end_; 83 | }; 84 | 85 | 86 | /** 87 | * A ZeroCopyOutput stream backed by an vector of bytes. 88 | */ 89 | class BufferOutput : public ZeroCopyOutput { 90 | public: 91 | BufferOutput(Buffer* buf); 92 | ~BufferOutput(); 93 | 94 | protected: 95 | size_t DoNext(void** data, size_t len) override; 96 | 97 | private: 98 | Buffer* buf_; 99 | size_t pos_; 100 | }; 101 | 102 | 103 | class BufferedOutput : public ZeroCopyOutput { 104 | public: 105 | BufferedOutput(OutputStream* slave, size_t buflen = 8192); 106 | ~BufferedOutput() override; 107 | 108 | void Reset(); 109 | 110 | protected: 111 | void DoFlush() override; 112 | size_t DoNext(void** data, size_t len) override; 113 | void DoWrite(const void* data, size_t len) override; 114 | 115 | private: 116 | OutputStream* const slave_; 117 | Buffer buffer_; 118 | ArrayOutput array_output_; 119 | }; 120 | 121 | template 122 | void WriteUnaligned(void* buf, const T& value) { 123 | memcpy(buf, &value, sizeof(value)); 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/platform.cpp: -------------------------------------------------------------------------------- 1 | #include "platform.h" 2 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/platform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(__linux__) 4 | # define _linux_ 5 | #elif defined(_WIN64) 6 | # define _win64_ 7 | # define _win32_ 8 | #elif defined(__WIN32__) || defined(_WIN32) 9 | # define _win32_ 10 | #elif defined(__APPLE__) 11 | # define _darwin_ 12 | #endif 13 | 14 | #if defined(_win32_) || defined(_win64_) 15 | # define _win_ 16 | #endif 17 | 18 | #if defined(_linux_) 19 | # define _unix_ 20 | #endif 21 | 22 | #if defined(_MSC_VER) 23 | # undef NOMINMAX 24 | # define NOMINMAX 25 | # include 26 | # define ssize_t SSIZE_T 27 | # define HAVE_SSIZE_T 1 28 | #endif 29 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/singleton.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace clickhouse { 4 | 5 | template 6 | T* Singleton() { 7 | static T instance; 8 | return &instance; 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/socket.cpp: -------------------------------------------------------------------------------- 1 | #include "socket.h" 2 | #include "singleton.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #if !defined(_win_) 11 | # include 12 | # include 13 | # include 14 | # include 15 | #endif 16 | 17 | namespace clickhouse { 18 | namespace { 19 | 20 | class LocalNames : public std::unordered_set { 21 | public: 22 | LocalNames() { 23 | emplace("localhost"); 24 | emplace("localhost.localdomain"); 25 | emplace("localhost6"); 26 | emplace("localhost6.localdomain6"); 27 | emplace("::1"); 28 | emplace("127.0.0.1"); 29 | } 30 | 31 | inline bool IsLocalName(const std::string& name) const noexcept { 32 | return find(name) != end(); 33 | } 34 | }; 35 | } 36 | 37 | NetworkAddress::NetworkAddress(const std::string& host, const std::string& port) 38 | : info_(nullptr) 39 | { 40 | struct addrinfo hints; 41 | memset(&hints, 0, sizeof(hints)); 42 | 43 | hints.ai_family = PF_UNSPEC; 44 | hints.ai_socktype = SOCK_STREAM; 45 | 46 | if (!Singleton()->IsLocalName(host)) { 47 | // https://linux.die.net/man/3/getaddrinfo 48 | // If hints.ai_flags includes the AI_ADDRCONFIG flag, 49 | // then IPv4 addresses are returned in the list pointed to by res only 50 | // if the local system has at least one IPv4 address configured, 51 | // and IPv6 addresses are only returned if the local system 52 | // has at least one IPv6 address configured. 53 | // The loopback address is not considered for this case 54 | // as valid as a configured address. 55 | hints.ai_flags |= AI_ADDRCONFIG; 56 | } 57 | 58 | const int error = getaddrinfo(host.c_str(), port.c_str(), &hints, &info_); 59 | 60 | if (error) { 61 | throw std::system_error(errno, std::system_category()); 62 | } 63 | } 64 | 65 | NetworkAddress::~NetworkAddress() { 66 | if (info_) { 67 | freeaddrinfo(info_); 68 | } 69 | } 70 | 71 | const struct addrinfo* NetworkAddress::Info() const { 72 | return info_; 73 | } 74 | 75 | 76 | SocketHolder::SocketHolder() 77 | : handle_(-1) 78 | { 79 | } 80 | 81 | SocketHolder::SocketHolder(SOCKET s) 82 | : handle_(s) 83 | { 84 | } 85 | 86 | SocketHolder::SocketHolder(SocketHolder&& other) 87 | : handle_(other.handle_) 88 | { 89 | other.handle_ = -1; 90 | } 91 | 92 | SocketHolder::~SocketHolder() { 93 | Close(); 94 | } 95 | 96 | void SocketHolder::Close() noexcept { 97 | if (handle_ != -1) { 98 | #if defined(_win_) 99 | closesocket(handle_); 100 | #else 101 | close(handle_); 102 | #endif 103 | handle_ = -1; 104 | } 105 | } 106 | 107 | bool SocketHolder::Closed() const noexcept { 108 | return handle_ == -1; 109 | } 110 | 111 | SocketHolder& SocketHolder::operator = (SocketHolder&& other) noexcept { 112 | if (this != &other) { 113 | Close(); 114 | 115 | handle_ = other.handle_; 116 | other.handle_ = -1; 117 | } 118 | 119 | return *this; 120 | } 121 | 122 | SocketHolder::operator SOCKET () const noexcept { 123 | return handle_; 124 | } 125 | 126 | 127 | SocketInput::SocketInput(SOCKET s) 128 | : s_(s) 129 | { 130 | } 131 | 132 | SocketInput::~SocketInput() = default; 133 | 134 | size_t SocketInput::DoRead(void* buf, size_t len) { 135 | const ssize_t ret = ::recv(s_, (char*)buf, (int)len, 0); 136 | 137 | if (ret > 0) { 138 | return (size_t)ret; 139 | } 140 | 141 | if (ret == 0) { 142 | throw std::system_error( 143 | errno, std::system_category(), "closed" 144 | ); 145 | } 146 | 147 | throw std::system_error( 148 | errno, std::system_category(), "can't receive string data" 149 | ); 150 | } 151 | 152 | 153 | SocketOutput::SocketOutput(SOCKET s) 154 | : s_(s) 155 | { 156 | } 157 | 158 | SocketOutput::~SocketOutput() = default; 159 | 160 | void SocketOutput::DoWrite(const void* data, size_t len) { 161 | #if defined (_linux_) 162 | static const int flags = MSG_NOSIGNAL; 163 | #else 164 | static const int flags = 0; 165 | #endif 166 | 167 | if (::send(s_, (const char*)data, len, flags) != (int)len) { 168 | throw std::system_error( 169 | errno, std::system_category(), "fail to send data" 170 | ); 171 | } 172 | } 173 | 174 | 175 | NetrworkInitializer::NetrworkInitializer() { 176 | struct NetrworkInitializerImpl { 177 | NetrworkInitializerImpl() { 178 | #if defined (_win_) 179 | WSADATA data; 180 | const int result = WSAStartup(MAKEWORD(2, 2), &data); 181 | if (result) { 182 | assert(false); 183 | exit(-1); 184 | } 185 | #elif defined(_unix_) 186 | signal(SIGPIPE, SIG_IGN); 187 | #endif 188 | } 189 | }; 190 | 191 | 192 | (void)Singleton(); 193 | } 194 | 195 | 196 | SOCKET SocketConnect(const NetworkAddress& addr) { 197 | for (auto res = addr.Info(); res != nullptr; res = res->ai_next) { 198 | SOCKET s(socket(res->ai_family, res->ai_socktype, res->ai_protocol)); 199 | 200 | if (s == -1) { 201 | continue; 202 | } 203 | 204 | if (connect(s, res->ai_addr, (int)res->ai_addrlen)) { 205 | if (errno == EINPROGRESS || 206 | errno == EAGAIN || 207 | errno == EWOULDBLOCK) 208 | { 209 | pollfd fd; 210 | fd.fd = s; 211 | fd.events = POLLOUT; 212 | int rval = Poll(&fd, 1, 1000); 213 | 214 | if (rval > 0) { 215 | int opt; 216 | socklen_t len = sizeof(opt); 217 | getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&opt, &len); 218 | 219 | return opt; 220 | } else { 221 | continue; 222 | } 223 | } 224 | } else { 225 | return s; 226 | } 227 | } 228 | 229 | throw std::system_error( 230 | errno, std::system_category(), "fail to connect" 231 | ); 232 | } 233 | 234 | 235 | ssize_t Poll(struct pollfd* fds, int nfds, int timeout) noexcept { 236 | #if defined(_win_) 237 | int rval = WSAPoll(fds, nfds, timeout); 238 | #else 239 | return poll(fds, nfds, timeout); 240 | #endif 241 | return -1; 242 | } 243 | 244 | } 245 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "input.h" 4 | #include "output.h" 5 | #include "platform.h" 6 | 7 | #include 8 | #include 9 | 10 | #if defined(_win_) 11 | # pragma comment(lib, "Ws2_32.lib") 12 | 13 | # include 14 | # include 15 | #else 16 | # include 17 | # include 18 | # include 19 | 20 | # if !defined(SOCKET) 21 | # define SOCKET int 22 | # endif 23 | #endif 24 | 25 | struct addrinfo; 26 | 27 | namespace clickhouse { 28 | 29 | /** 30 | * 31 | */ 32 | class NetworkAddress { 33 | public: 34 | explicit NetworkAddress(const std::string& host, 35 | const std::string& port = "0"); 36 | ~NetworkAddress(); 37 | 38 | const struct addrinfo* Info() const; 39 | 40 | private: 41 | struct addrinfo* info_; 42 | }; 43 | 44 | 45 | class SocketHolder { 46 | public: 47 | SocketHolder(); 48 | SocketHolder(SOCKET s); 49 | SocketHolder(SocketHolder&& other); 50 | 51 | ~SocketHolder(); 52 | 53 | void Close() noexcept; 54 | 55 | bool Closed() const noexcept; 56 | 57 | SocketHolder& operator = (SocketHolder&& other) noexcept; 58 | 59 | operator SOCKET () const noexcept; 60 | 61 | private: 62 | SocketHolder(const SocketHolder&) = delete; 63 | SocketHolder& operator = (const SocketHolder&) = delete; 64 | 65 | SOCKET handle_; 66 | }; 67 | 68 | 69 | /** 70 | * 71 | */ 72 | class SocketInput : public InputStream { 73 | public: 74 | explicit SocketInput(SOCKET s); 75 | ~SocketInput(); 76 | 77 | protected: 78 | size_t DoRead(void* buf, size_t len) override; 79 | 80 | private: 81 | SOCKET s_; 82 | }; 83 | 84 | class SocketOutput : public OutputStream { 85 | public: 86 | explicit SocketOutput(SOCKET s); 87 | ~SocketOutput(); 88 | 89 | protected: 90 | void DoWrite(const void* data, size_t len) override; 91 | 92 | private: 93 | SOCKET s_; 94 | }; 95 | 96 | static struct NetrworkInitializer { 97 | NetrworkInitializer(); 98 | } gNetrworkInitializer; 99 | 100 | /// 101 | SOCKET SocketConnect(const NetworkAddress& addr); 102 | 103 | ssize_t Poll(struct pollfd* fds, int nfds, int timeout) noexcept; 104 | 105 | } 106 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/string_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "string_view.h" 4 | 5 | #include 6 | #include 7 | 8 | namespace clickhouse { 9 | 10 | template 11 | inline T FromString(const std::string& s) { 12 | std::istringstream iss(s); 13 | T result; 14 | iss >> result; 15 | return result; 16 | } 17 | 18 | template 19 | inline T FromString(const StringView& s) { 20 | std::istringstream iss((std::string(s))); 21 | T result; 22 | iss >> result; 23 | return result; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/string_view.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | /** 8 | * A lightweight non-owning read-only view into a subsequence of a string. 9 | */ 10 | template < 11 | typename TChar, 12 | typename TTraits = std::char_traits 13 | > 14 | class StringViewImpl { 15 | public: 16 | using size_type = size_t; 17 | using traits_type = TTraits; 18 | using value_type = typename TTraits::char_type; 19 | 20 | static constexpr size_type npos = size_type(-1); 21 | 22 | public: 23 | inline StringViewImpl() noexcept 24 | : data_(nullptr) 25 | , size_(0) 26 | { 27 | } 28 | 29 | constexpr inline StringViewImpl(const TChar* data, size_t len) noexcept 30 | : data_(data) 31 | , size_(len) 32 | { 33 | } 34 | 35 | template 36 | constexpr inline StringViewImpl(const TChar (&str)[len]) noexcept 37 | : data_(str) 38 | , size_(len - 1) 39 | { 40 | } 41 | 42 | inline StringViewImpl(const TChar* begin, const TChar* end) noexcept 43 | : data_(begin) 44 | , size_(end - begin) 45 | { 46 | assert(begin <= end); 47 | } 48 | 49 | inline StringViewImpl(const std::basic_string& str) noexcept 50 | : data_(str.data()) 51 | , size_(str.size()) 52 | { 53 | } 54 | 55 | inline TChar at(size_type pos) const { 56 | if (pos >= size_) 57 | throw std::out_of_range("pos must be less than len"); 58 | return data_[pos]; 59 | } 60 | 61 | inline const TChar* data() const noexcept { 62 | return data_; 63 | } 64 | 65 | inline bool empty() const noexcept { 66 | return size_ == 0; 67 | } 68 | 69 | inline bool null() const noexcept { 70 | assert(size_ == 0); 71 | return data_ == nullptr; 72 | } 73 | 74 | inline size_type size() const noexcept { 75 | return size_; 76 | } 77 | 78 | public: 79 | // Returns a substring [pos, pos + count). 80 | // If the requested substring extends past the end of the string, 81 | // or if count == npos, the returned substring is [pos, size()). 82 | StringViewImpl substr(size_type pos, size_type count = npos) const { 83 | if (pos >= size_) 84 | throw std::out_of_range("pos must be less than len"); 85 | if (pos + count >= size_ || count == npos) 86 | return StringViewImpl(data_ + pos, size_ - pos); 87 | else 88 | return StringViewImpl(data_ + pos, count); 89 | } 90 | 91 | inline const std::basic_string to_string() const { 92 | return std::basic_string(data_, size_); 93 | } 94 | 95 | public: 96 | inline operator bool () const noexcept { 97 | return !empty(); 98 | } 99 | 100 | inline explicit operator const std::basic_string () const { 101 | return to_string(); 102 | } 103 | 104 | inline TChar operator [] (size_type pos) const noexcept { 105 | return data_[pos]; 106 | } 107 | 108 | inline bool operator < (const StringViewImpl& other) const noexcept { 109 | if (size_ < other.size_) 110 | return true; 111 | if (size_ > other.size_) 112 | return false; 113 | return TTraits::compare(data_, other.data_, size_) < 0; 114 | } 115 | 116 | inline bool operator == (const StringViewImpl& other) const noexcept { 117 | if (size_ == other.size_) 118 | return TTraits::compare(data_, other.data_, size_) == 0; 119 | return false; 120 | } 121 | 122 | private: 123 | const TChar* data_; 124 | size_t size_; 125 | }; 126 | 127 | 128 | // It creates StringView from literal constant at compile time. 129 | template 130 | constexpr inline StringViewImpl MakeStringView(const TChar (&str)[size]) { 131 | return StringViewImpl(str, size - 1); 132 | } 133 | 134 | 135 | using StringView = StringViewImpl; 136 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/base/wire_format.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "coded.h" 4 | 5 | #include 6 | 7 | namespace clickhouse { 8 | 9 | class WireFormat { 10 | public: 11 | template 12 | static bool ReadFixed(CodedInputStream* input, T* value); 13 | 14 | static bool ReadString(CodedInputStream* input, std::string* value); 15 | 16 | static bool ReadBytes(CodedInputStream* input, void* buf, size_t len); 17 | 18 | static bool ReadUInt64(CodedInputStream* input, uint64_t* value); 19 | 20 | 21 | template 22 | static void WriteFixed(CodedOutputStream* output, const T& value); 23 | 24 | static void WriteBytes(CodedOutputStream* output, const void* buf, size_t len); 25 | 26 | static void WriteString(CodedOutputStream* output, const std::string& value); 27 | 28 | static void WriteUInt64(CodedOutputStream* output, const uint64_t value); 29 | }; 30 | 31 | template 32 | inline bool WireFormat::ReadFixed( 33 | CodedInputStream* input, 34 | T* value) 35 | { 36 | return input->ReadRaw(value, sizeof(T)); 37 | } 38 | 39 | inline bool WireFormat::ReadString( 40 | CodedInputStream* input, 41 | std::string* value) 42 | { 43 | uint64_t len; 44 | 45 | if (input->ReadVarint64(&len)) { 46 | if (len > 0x00FFFFFFULL) { 47 | return false; 48 | } 49 | value->resize((size_t)len); 50 | return input->ReadRaw(&(*value)[0], (size_t)len); 51 | } 52 | 53 | return false; 54 | } 55 | 56 | inline bool WireFormat::ReadBytes( 57 | CodedInputStream* input, void* buf, size_t len) 58 | { 59 | return input->ReadRaw(buf, len); 60 | } 61 | 62 | inline bool WireFormat::ReadUInt64( 63 | CodedInputStream* input, 64 | uint64_t* value) 65 | { 66 | return input->ReadVarint64(value); 67 | } 68 | 69 | 70 | template 71 | inline void WireFormat::WriteFixed( 72 | CodedOutputStream* output, 73 | const T& value) 74 | { 75 | output->WriteRaw(&value, sizeof(T)); 76 | } 77 | 78 | inline void WireFormat::WriteBytes( 79 | CodedOutputStream* output, 80 | const void* buf, 81 | size_t len) 82 | { 83 | output->WriteRaw(buf, len); 84 | } 85 | 86 | inline void WireFormat::WriteString( 87 | CodedOutputStream* output, 88 | const std::string& value) 89 | { 90 | output->WriteVarint64(value.size()); 91 | output->WriteRaw(value.data(), value.size()); 92 | } 93 | 94 | inline void WireFormat::WriteUInt64( 95 | CodedOutputStream* output, 96 | const uint64_t value) 97 | { 98 | output->WriteVarint64(value); 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/block.cpp: -------------------------------------------------------------------------------- 1 | #include "block.h" 2 | 3 | #include 4 | 5 | namespace clickhouse { 6 | 7 | Block::Iterator::Iterator(const Block& block) 8 | : block_(block) 9 | , idx_(0) 10 | { 11 | } 12 | 13 | const std::string& Block::Iterator::Name() const { 14 | return block_.columns_[idx_].name; 15 | } 16 | 17 | TypeRef Block::Iterator::Type() const { 18 | return block_.columns_[idx_].column->Type(); 19 | } 20 | 21 | ColumnRef Block::Iterator::Column() const { 22 | return block_.columns_[idx_].column; 23 | } 24 | 25 | void Block::Iterator::Next() { 26 | ++idx_; 27 | } 28 | 29 | bool Block::Iterator::IsValid() const { 30 | return idx_ < block_.columns_.size(); 31 | } 32 | 33 | 34 | Block::Block() 35 | : rows_(0) 36 | { 37 | } 38 | 39 | Block::Block(size_t cols, size_t rows) 40 | : rows_(rows) 41 | { 42 | columns_.reserve(cols); 43 | } 44 | 45 | Block::~Block() = default; 46 | 47 | void Block::AppendColumn(const std::string& name, const ColumnRef& col) { 48 | if (columns_.empty()) { 49 | rows_ = col->Size(); 50 | } else if (col->Size() != rows_) { 51 | throw std::runtime_error("all columns in block must have same count of rows. Name: ["+name+"], rows: ["+std::to_string(rows_)+"], columns: [" + std::to_string(col->Size())+"]"); 52 | } 53 | 54 | columns_.push_back(ColumnItem{name, col}); 55 | } 56 | 57 | /// Count of columns in the block. 58 | size_t Block::GetColumnCount() const { 59 | return columns_.size(); 60 | } 61 | 62 | const BlockInfo& Block::Info() const { 63 | return info_; 64 | } 65 | 66 | /// Count of rows in the block. 67 | size_t Block::GetRowCount() const { 68 | return rows_; 69 | } 70 | 71 | ColumnRef Block::operator [] (size_t idx) const { 72 | if (idx < columns_.size()) { 73 | return columns_[idx].column; 74 | } 75 | 76 | throw std::out_of_range("column index is out of range. Index: ["+std::to_string(idx)+"], columns: [" + std::to_string(columns_.size())+"]"); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/block.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "columns/column.h" 4 | 5 | namespace clickhouse { 6 | 7 | struct BlockInfo { 8 | uint8_t is_overflows = 0; 9 | int32_t bucket_num = -1; 10 | }; 11 | 12 | class Block { 13 | public: 14 | /// Allow to iterate over block's columns. 15 | class Iterator { 16 | public: 17 | Iterator(const Block& block); 18 | 19 | /// Name of column. 20 | const std::string& Name() const; 21 | 22 | /// Type of column. 23 | TypeRef Type() const; 24 | 25 | /// Reference to column object. 26 | ColumnRef Column() const; 27 | 28 | /// Move to next column. 29 | void Next(); 30 | 31 | /// Is the iterator still valid. 32 | bool IsValid() const; 33 | 34 | private: 35 | Iterator() = delete; 36 | 37 | const Block& block_; 38 | size_t idx_; 39 | }; 40 | 41 | public: 42 | Block(); 43 | Block(size_t cols, size_t rows); 44 | ~Block(); 45 | 46 | /// Append named column to the block. 47 | void AppendColumn(const std::string& name, const ColumnRef& col); 48 | 49 | /// Count of columns in the block. 50 | size_t GetColumnCount() const; 51 | 52 | const BlockInfo& Info() const; 53 | 54 | /// Count of rows in the block. 55 | size_t GetRowCount() const; 56 | 57 | const std::string& GetColumnName(size_t idx) const { 58 | return columns_.at(idx).name; 59 | } 60 | 61 | /// Reference to column by index in the block. 62 | ColumnRef operator [] (size_t idx) const; 63 | 64 | private: 65 | struct ColumnItem { 66 | std::string name; 67 | ColumnRef column; 68 | }; 69 | 70 | BlockInfo info_; 71 | std::vector columns_; 72 | /// Count of rows in the block. 73 | size_t rows_; 74 | }; 75 | 76 | } 77 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/client.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "query.h" 4 | #include "exceptions.h" 5 | 6 | #include "columns/array.h" 7 | #include "columns/date.h" 8 | #include "columns/enum.h" 9 | #include "columns/nullable.h" 10 | #include "columns/numeric.h" 11 | #include "columns/string.h" 12 | #include "columns/tuple.h" 13 | #include "columns/uuid.h" 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace clickhouse { 21 | 22 | /// Methods of block compression. 23 | enum class CompressionMethod { 24 | None = -1, 25 | LZ4 = 1, 26 | }; 27 | 28 | struct ClientOptions { 29 | #define DECLARE_FIELD(name, type, setter, default) \ 30 | type name = default; \ 31 | inline ClientOptions& setter(const type& value) { \ 32 | name = value; \ 33 | return *this; \ 34 | } 35 | 36 | /// Hostname of the server. 37 | DECLARE_FIELD(host, std::string, SetHost, std::string()); 38 | /// Service port. 39 | DECLARE_FIELD(port, int, SetPort, 9000); 40 | 41 | /// Default database. 42 | DECLARE_FIELD(default_database, std::string, SetDefaultDatabase, "default"); 43 | /// User name. 44 | DECLARE_FIELD(user, std::string, SetUser, "default"); 45 | /// Access password. 46 | DECLARE_FIELD(password, std::string, SetPassword, std::string()); 47 | 48 | /// By default all exceptions received during query execution will be 49 | /// passed to OnException handler. Set rethrow_exceptions to true to 50 | /// enable throwing exceptions with standard c++ exception mechanism. 51 | DECLARE_FIELD(rethrow_exceptions, bool, SetRethrowException, true); 52 | 53 | /// Ping server every time before execute any query. 54 | DECLARE_FIELD(ping_before_query, bool, SetPingBeforeQuery, false); 55 | /// Count of retry to send request to server. 56 | DECLARE_FIELD(send_retries, int, SetSendRetries, 1); 57 | /// Amount of time to wait before next retry. 58 | DECLARE_FIELD(retry_timeout, std::chrono::seconds, SetRetryTimeout, std::chrono::seconds(5)); 59 | 60 | /// Compression method. 61 | DECLARE_FIELD(compression_method, CompressionMethod, SetCompressionMethod, CompressionMethod::None); 62 | 63 | #undef DECLARE_FIELD 64 | }; 65 | 66 | std::ostream& operator<<(std::ostream& os, const ClientOptions& options); 67 | 68 | /** 69 | * 70 | */ 71 | class Client { 72 | public: 73 | Client(const ClientOptions& opts); 74 | ~Client(); 75 | 76 | /// Intends for execute arbitrary queries. 77 | void Execute(const Query& query); 78 | 79 | /// Intends for execute select queries. Data will be returned with 80 | /// one or more call of \p cb. 81 | void Select(const std::string& query, SelectCallback cb); 82 | 83 | /// Executes a select query which can be canceled by returning false from 84 | /// the data handler function \p cb. 85 | void SelectCancelable(const std::string& query, SelectCancelableCallback cb); 86 | 87 | /// Alias for Execute. 88 | void Select(const Query& query); 89 | 90 | /// Intends for insert block of data into a table \p table_name. 91 | void Insert(const std::string& table_name, const Block& block); 92 | 93 | void InsertQuery(const std::string& query, SelectCallback cb); 94 | 95 | void InsertData(const Block& block); 96 | 97 | void InsertDataEnd(); 98 | 99 | /// Ping server for aliveness. 100 | void Ping(); 101 | 102 | /// Reset connection with initial params. 103 | void ResetConnection(); 104 | 105 | private: 106 | ClientOptions options_; 107 | 108 | class Impl; 109 | std::unique_ptr impl_; 110 | }; 111 | 112 | } 113 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/array.cpp: -------------------------------------------------------------------------------- 1 | #include "array.h" 2 | 3 | #include 4 | 5 | namespace clickhouse { 6 | 7 | ColumnArray::ColumnArray(ColumnRef data) 8 | : Column(Type::CreateArray(data->Type())) 9 | , data_(data) 10 | , offsets_(std::make_shared()) 11 | { 12 | } 13 | 14 | void ColumnArray::AppendAsColumn(ColumnRef array) { 15 | if (!data_->Type()->IsEqual(array->Type())) { 16 | throw std::runtime_error( 17 | "can't append column of type " + array->Type()->GetName() + " " 18 | "to column type " + data_->Type()->GetName()); 19 | } 20 | 21 | if (offsets_->Size() == 0) { 22 | offsets_->Append(array->Size()); 23 | } else { 24 | offsets_->Append((*offsets_)[offsets_->Size() - 1] + array->Size()); 25 | } 26 | 27 | data_->Append(array); 28 | } 29 | 30 | ColumnRef ColumnArray::GetAsColumn(size_t n) const { 31 | return data_->Slice(GetOffset(n), GetSize(n)); 32 | } 33 | 34 | void ColumnArray::Append(ColumnRef column) { 35 | if (auto col = column->As()) { 36 | if (!col->data_->Type()->IsEqual(data_->Type())) { 37 | return; 38 | } 39 | 40 | for (size_t i = 0; i < col->Size(); ++i) { 41 | AppendAsColumn(col->GetAsColumn(i)); 42 | } 43 | } 44 | } 45 | 46 | bool ColumnArray::Load(CodedInputStream* input, size_t rows) { 47 | if (!offsets_->Load(input, rows)) { 48 | return false; 49 | } 50 | if (!data_->Load(input, (*offsets_)[rows - 1])) { 51 | return false; 52 | } 53 | return true; 54 | } 55 | 56 | void ColumnArray::Save(CodedOutputStream* output) { 57 | offsets_->Save(output); 58 | data_->Save(output); 59 | } 60 | 61 | void ColumnArray::Clear() { 62 | offsets_->Clear(); 63 | data_->Clear(); 64 | } 65 | 66 | size_t ColumnArray::Size() const { 67 | return offsets_->Size(); 68 | } 69 | 70 | size_t ColumnArray::GetOffset(size_t n) const { 71 | return (n == 0) ? 0 : (*offsets_)[n - 1]; 72 | } 73 | 74 | size_t ColumnArray::GetSize(size_t n) const { 75 | return (n == 0) ? (*offsets_)[n] : ((*offsets_)[n] - (*offsets_)[n - 1]); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/array.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "numeric.h" 4 | 5 | namespace clickhouse { 6 | 7 | /** 8 | * Represents column of Array(T). 9 | */ 10 | class ColumnArray : public Column { 11 | public: 12 | ColumnArray(ColumnRef data); 13 | 14 | /// Converts input column to array and appends 15 | /// as one row to the current column. 16 | void AppendAsColumn(ColumnRef array); 17 | 18 | /// Convets array at pos n to column. 19 | /// Type of element of result column same as type of array element. 20 | ColumnRef GetAsColumn(size_t n) const; 21 | 22 | public: 23 | /// Appends content of given column to the end of current one. 24 | void Append(ColumnRef column) override; 25 | 26 | /// Loads column data from input stream. 27 | bool Load(CodedInputStream* input, size_t rows) override; 28 | 29 | /// Saves column data to output stream. 30 | void Save(CodedOutputStream* output) override; 31 | 32 | /// Clear column data . 33 | void Clear() override; 34 | 35 | /// Returns count of rows in the column. 36 | size_t Size() const override; 37 | 38 | /// Makes slice of the current column. 39 | ColumnRef Slice(size_t, size_t) override { return ColumnRef(); } 40 | 41 | private: 42 | size_t GetOffset(size_t n) const; 43 | 44 | size_t GetSize(size_t n) const; 45 | 46 | private: 47 | ColumnRef data_; 48 | std::shared_ptr offsets_; 49 | }; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/column.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../base/input.h" 4 | #include "../base/coded.h" 5 | #include "../types/types.h" 6 | 7 | namespace clickhouse { 8 | 9 | using ColumnRef = std::shared_ptr; 10 | 11 | /** 12 | * An abstract base of all columns classes. 13 | */ 14 | class Column : public std::enable_shared_from_this 15 | { 16 | public: 17 | explicit inline Column(TypeRef type) 18 | : type_(type) 19 | { 20 | } 21 | 22 | virtual ~Column() 23 | { } 24 | 25 | /// Downcast pointer to the specific culumn's subtype. 26 | template 27 | inline std::shared_ptr As() { 28 | return std::dynamic_pointer_cast(shared_from_this()); 29 | } 30 | 31 | /// Downcast pointer to the specific culumn's subtype. 32 | template 33 | inline std::shared_ptr As() const { 34 | return std::dynamic_pointer_cast(shared_from_this()); 35 | } 36 | 37 | /// Get type object of the column. 38 | inline TypeRef Type() const { return type_; } 39 | 40 | /// Appends content of given column to the end of current one. 41 | virtual void Append(ColumnRef column) = 0; 42 | 43 | /// Loads column data from input stream. 44 | virtual bool Load(CodedInputStream* input, size_t rows) = 0; 45 | 46 | /// Saves column data to output stream. 47 | virtual void Save(CodedOutputStream* output) = 0; 48 | 49 | /// Clear column data . 50 | virtual void Clear() = 0; 51 | 52 | /// Returns count of rows in the column. 53 | virtual size_t Size() const = 0; 54 | 55 | /// Makes slice of the current column. 56 | virtual ColumnRef Slice(size_t begin, size_t len) = 0; 57 | 58 | protected: 59 | TypeRef type_; 60 | }; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/date.cpp: -------------------------------------------------------------------------------- 1 | #include "date.h" 2 | 3 | namespace clickhouse { 4 | 5 | ColumnDate::ColumnDate() 6 | : Column(Type::CreateDate()) 7 | , data_(std::make_shared()) 8 | { 9 | } 10 | 11 | void ColumnDate::Append(const std::time_t& value) { 12 | data_->Append(static_cast(value / 86400)); 13 | } 14 | 15 | void ColumnDate::Clear() { 16 | data_->Clear(); 17 | } 18 | 19 | std::time_t ColumnDate::At(size_t n) const { 20 | return data_->At(n) * 86400; 21 | } 22 | 23 | void ColumnDate::Append(ColumnRef column) { 24 | if (auto col = column->As()) { 25 | data_->Append(col->data_); 26 | } 27 | } 28 | 29 | bool ColumnDate::Load(CodedInputStream* input, size_t rows) { 30 | return data_->Load(input, rows); 31 | } 32 | 33 | void ColumnDate::Save(CodedOutputStream* output) { 34 | data_->Save(output); 35 | } 36 | 37 | size_t ColumnDate::Size() const { 38 | return data_->Size(); 39 | } 40 | 41 | ColumnRef ColumnDate::Slice(size_t begin, size_t len) { 42 | auto col = data_->Slice(begin, len)->As(); 43 | auto result = std::make_shared(); 44 | 45 | result->data_->Append(col); 46 | 47 | return result; 48 | } 49 | 50 | 51 | ColumnDateTime::ColumnDateTime() 52 | : Column(Type::CreateDateTime()) 53 | , data_(std::make_shared()) 54 | { 55 | } 56 | 57 | void ColumnDateTime::Append(const std::time_t& value) { 58 | data_->Append(static_cast(value)); 59 | } 60 | 61 | std::time_t ColumnDateTime::At(size_t n) const { 62 | return data_->At(n); 63 | } 64 | 65 | void ColumnDateTime::Append(ColumnRef column) { 66 | if (auto col = column->As()) { 67 | data_->Append(col->data_); 68 | } 69 | } 70 | 71 | bool ColumnDateTime::Load(CodedInputStream* input, size_t rows) { 72 | return data_->Load(input, rows); 73 | } 74 | 75 | void ColumnDateTime::Save(CodedOutputStream* output) { 76 | data_->Save(output); 77 | } 78 | 79 | size_t ColumnDateTime::Size() const { 80 | return data_->Size(); 81 | } 82 | 83 | void ColumnDateTime::Clear() { 84 | data_->Clear(); 85 | } 86 | 87 | ColumnRef ColumnDateTime::Slice(size_t begin, size_t len) { 88 | auto col = data_->Slice(begin, len)->As(); 89 | auto result = std::make_shared(); 90 | 91 | result->data_->Append(col); 92 | 93 | return result; 94 | } 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/date.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "numeric.h" 4 | 5 | #include 6 | 7 | namespace clickhouse { 8 | 9 | /** */ 10 | class ColumnDate : public Column { 11 | public: 12 | ColumnDate(); 13 | 14 | /// Appends one element to the end of column. 15 | void Append(const std::time_t& value); 16 | 17 | /// Returns element at given row number. 18 | std::time_t At(size_t n) const; 19 | 20 | public: 21 | /// Appends content of given column to the end of current one. 22 | void Append(ColumnRef column) override; 23 | 24 | /// Loads column data from input stream. 25 | bool Load(CodedInputStream* input, size_t rows) override; 26 | 27 | /// Saves column data to output stream. 28 | void Save(CodedOutputStream* output) override; 29 | 30 | /// Clear column data . 31 | void Clear() override; 32 | 33 | /// Returns count of rows in the column. 34 | size_t Size() const override; 35 | 36 | /// Makes slice of the current column. 37 | ColumnRef Slice(size_t begin, size_t len) override; 38 | 39 | private: 40 | std::shared_ptr data_; 41 | }; 42 | 43 | /** */ 44 | class ColumnDateTime : public Column { 45 | public: 46 | ColumnDateTime(); 47 | 48 | /// Appends one element to the end of column. 49 | void Append(const std::time_t& value); 50 | 51 | /// Returns element at given row number. 52 | std::time_t At(size_t n) const; 53 | 54 | public: 55 | /// Appends content of given column to the end of current one. 56 | void Append(ColumnRef column) override; 57 | 58 | /// Loads column data from input stream. 59 | bool Load(CodedInputStream* input, size_t rows) override; 60 | 61 | /// Clear column data . 62 | void Clear() override; 63 | 64 | /// Saves column data to output stream. 65 | void Save(CodedOutputStream* output) override; 66 | 67 | /// Returns count of rows in the column. 68 | size_t Size() const override; 69 | 70 | /// Makes slice of the current column. 71 | ColumnRef Slice(size_t begin, size_t len) override; 72 | 73 | private: 74 | std::shared_ptr data_; 75 | }; 76 | 77 | } 78 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/enum.cpp: -------------------------------------------------------------------------------- 1 | #include "enum.h" 2 | #include "utils.h" 3 | 4 | namespace clickhouse { 5 | 6 | template 7 | ColumnEnum::ColumnEnum(TypeRef type) 8 | : Column(type) 9 | { 10 | } 11 | 12 | template 13 | ColumnEnum::ColumnEnum(TypeRef type, const std::vector& data) 14 | : Column(type) 15 | , data_(data) 16 | { 17 | } 18 | 19 | template 20 | void ColumnEnum::Append(const T& value, bool checkValue) { 21 | if (checkValue) { 22 | // TODO type_->HasEnumValue(value), "Enum type doesn't have value " + std::to_string(value); 23 | } 24 | data_.push_back(value); 25 | } 26 | 27 | template 28 | void ColumnEnum::Append(const std::string& name) { 29 | data_.push_back(EnumType(type_).GetEnumValue(name)); 30 | } 31 | 32 | template 33 | void ColumnEnum::Clear() { 34 | data_.clear(); 35 | } 36 | 37 | template 38 | const T& ColumnEnum::At(size_t n) const { 39 | return data_.at(n); 40 | } 41 | 42 | template 43 | const std::string ColumnEnum::NameAt(size_t n) const { 44 | return EnumType(type_).GetEnumName(data_.at(n)); 45 | } 46 | 47 | template 48 | const T& ColumnEnum::operator[] (size_t n) const { 49 | return data_[n]; 50 | } 51 | 52 | template 53 | void ColumnEnum::SetAt(size_t n, const T& value, bool checkValue) { 54 | if (checkValue) { 55 | // TODO: type_->HasEnumValue(value), "Enum type doesn't have value " + std::to_string(value); 56 | } 57 | data_.at(n) = value; 58 | } 59 | 60 | template 61 | void ColumnEnum::SetNameAt(size_t n, const std::string& name) { 62 | data_.at(n) = EnumType(type_).GetEnumValue(name); 63 | } 64 | 65 | template 66 | void ColumnEnum::Append(ColumnRef column) { 67 | if (auto col = column->As>()) { 68 | data_.insert(data_.end(), col->data_.begin(), col->data_.end()); 69 | } 70 | } 71 | 72 | template 73 | bool ColumnEnum::Load(CodedInputStream* input, size_t rows) { 74 | data_.resize(rows); 75 | return input->ReadRaw(data_.data(), data_.size() * sizeof(T)); 76 | } 77 | 78 | template 79 | void ColumnEnum::Save(CodedOutputStream* output) { 80 | output->WriteRaw(data_.data(), data_.size() * sizeof(T)); 81 | } 82 | 83 | template 84 | size_t ColumnEnum::Size() const { 85 | return data_.size(); 86 | } 87 | 88 | template 89 | ColumnRef ColumnEnum::Slice(size_t begin, size_t len) { 90 | return std::make_shared>(type_, SliceVector(data_, begin, len)); 91 | } 92 | 93 | template class ColumnEnum; 94 | template class ColumnEnum; 95 | 96 | } 97 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/enum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "column.h" 4 | 5 | namespace clickhouse { 6 | 7 | 8 | template 9 | class ColumnEnum : public Column { 10 | public: 11 | ColumnEnum(TypeRef type); 12 | ColumnEnum(TypeRef type, const std::vector& data); 13 | 14 | /// Appends one element to the end of column. 15 | void Append(const T& value, bool checkValue = false); 16 | void Append(const std::string& name); 17 | 18 | /// Returns element at given row number. 19 | const T& At(size_t n) const; 20 | const std::string NameAt(size_t n) const; 21 | 22 | /// Returns element at given row number. 23 | const T& operator[] (size_t n) const; 24 | 25 | /// Set element at given row number. 26 | void SetAt(size_t n, const T& value, bool checkValue = false); 27 | void SetNameAt(size_t n, const std::string& name); 28 | 29 | public: 30 | /// Appends content of given column to the end of current one. 31 | void Append(ColumnRef column) override; 32 | 33 | /// Loads column data from input stream. 34 | bool Load(CodedInputStream* input, size_t rows) override; 35 | 36 | /// Saves column data to output stream. 37 | void Save(CodedOutputStream* output) override; 38 | 39 | /// Clear column data . 40 | void Clear() override; 41 | 42 | /// Returns count of rows in the column. 43 | size_t Size() const override; 44 | 45 | /// Makes slice of the current column. 46 | ColumnRef Slice(size_t begin, size_t len) override; 47 | 48 | private: 49 | std::vector data_; 50 | }; 51 | 52 | using ColumnEnum8 = ColumnEnum; 53 | using ColumnEnum16 = ColumnEnum; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/factory.cpp: -------------------------------------------------------------------------------- 1 | #include "factory.h" 2 | 3 | #include "array.h" 4 | #include "date.h" 5 | #include "enum.h" 6 | #include "nullable.h" 7 | #include "numeric.h" 8 | #include "string.h" 9 | #include "tuple.h" 10 | #include "uuid.h" 11 | 12 | #include "../types/type_parser.h" 13 | 14 | namespace clickhouse { 15 | namespace { 16 | 17 | static ColumnRef CreateTerminalColumn(const TypeAst& ast) { 18 | switch (ast.code) { 19 | case Type::UInt8: 20 | return std::make_shared(); 21 | case Type::UInt16: 22 | return std::make_shared(); 23 | case Type::UInt32: 24 | return std::make_shared(); 25 | case Type::UInt64: 26 | return std::make_shared(); 27 | 28 | case Type::Int8: 29 | return std::make_shared(); 30 | case Type::Int16: 31 | return std::make_shared(); 32 | case Type::Int32: 33 | return std::make_shared(); 34 | case Type::Int64: 35 | return std::make_shared(); 36 | 37 | case Type::UUID: 38 | return std::make_shared(); 39 | 40 | case Type::Float32: 41 | return std::make_shared(); 42 | case Type::Float64: 43 | return std::make_shared(); 44 | 45 | case Type::String: 46 | return std::make_shared(); 47 | case Type::FixedString: 48 | return std::make_shared(ast.elements.front().value); 49 | 50 | case Type::DateTime: 51 | return std::make_shared(); 52 | case Type::Date: 53 | return std::make_shared(); 54 | 55 | default: 56 | return nullptr; 57 | } 58 | } 59 | 60 | static ColumnRef CreateColumnFromAst(const TypeAst& ast) { 61 | switch (ast.meta) { 62 | case TypeAst::Array: { 63 | return std::make_shared( 64 | CreateColumnFromAst(ast.elements.front()) 65 | ); 66 | } 67 | 68 | case TypeAst::Nullable: { 69 | return std::make_shared( 70 | CreateColumnFromAst(ast.elements.front()), 71 | std::make_shared() 72 | ); 73 | } 74 | 75 | case TypeAst::Terminal: { 76 | return CreateTerminalColumn(ast); 77 | } 78 | 79 | case TypeAst::Tuple: { 80 | std::vector columns; 81 | 82 | for (const auto& elem : ast.elements) { 83 | if (auto col = CreateColumnFromAst(elem)) { 84 | columns.push_back(col); 85 | } else { 86 | return nullptr; 87 | } 88 | } 89 | 90 | return std::make_shared(columns); 91 | } 92 | 93 | case TypeAst::Enum: { 94 | std::vector enum_items; 95 | 96 | for (const auto& elem : ast.elements) { 97 | enum_items.push_back( 98 | Type::EnumItem{elem.name, (int16_t)elem.value}); 99 | } 100 | 101 | if (ast.code == Type::Enum8) { 102 | return std::make_shared( 103 | Type::CreateEnum8(enum_items) 104 | ); 105 | } else if (ast.code == Type::Enum16) { 106 | return std::make_shared( 107 | Type::CreateEnum16(enum_items) 108 | ); 109 | } 110 | break; 111 | } 112 | 113 | case TypeAst::Null: 114 | case TypeAst::Number: 115 | break; 116 | } 117 | 118 | return nullptr; 119 | } 120 | 121 | } // namespace 122 | 123 | 124 | ColumnRef CreateColumnByType(const std::string& type_name) { 125 | auto ast = ParseTypeName(type_name); 126 | if (ast != nullptr) { 127 | return CreateColumnFromAst(*ast); 128 | } 129 | 130 | return nullptr; 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/factory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "column.h" 4 | 5 | namespace clickhouse { 6 | 7 | ColumnRef CreateColumnByType(const std::string& type_name); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/nullable.cpp: -------------------------------------------------------------------------------- 1 | #include "nullable.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace clickhouse { 7 | 8 | ColumnNullable::ColumnNullable(ColumnRef nested, ColumnRef nulls) 9 | : Column(Type::CreateNullable(nested->Type())) 10 | , nested_(nested) 11 | , nulls_(nulls->As()) 12 | { 13 | if (nested_->Size() != nulls->Size()) { 14 | throw std::runtime_error("count of elements in nested and nulls should be the same"); 15 | } 16 | } 17 | 18 | bool ColumnNullable::IsNull(size_t n) const { 19 | return nulls_->At(n) != 0; 20 | } 21 | 22 | ColumnRef ColumnNullable::Nested() const { 23 | return nested_; 24 | } 25 | 26 | void ColumnNullable::Append(ColumnRef column) { 27 | if (auto col = column->As()) { 28 | if (!col->nested_->Type()->IsEqual(nested_->Type())) { 29 | return; 30 | } 31 | 32 | nested_->Append(col->nested_); 33 | nulls_->Append(col->nulls_); 34 | } 35 | } 36 | 37 | void ColumnNullable::Clear() { 38 | nested_->Clear(); 39 | nulls_->Clear(); 40 | } 41 | 42 | bool ColumnNullable::Load(CodedInputStream* input, size_t rows) { 43 | if (!nulls_->Load(input, rows)) { 44 | return false; 45 | } 46 | if (!nested_->Load(input, rows)) { 47 | return false; 48 | } 49 | return true; 50 | } 51 | 52 | void ColumnNullable::Save(CodedOutputStream* output) { 53 | nulls_->Save(output); 54 | nested_->Save(output); 55 | } 56 | 57 | size_t ColumnNullable::Size() const { 58 | assert(nested_->Size() == nulls_->Size()); 59 | return nulls_->Size(); 60 | } 61 | 62 | ColumnRef ColumnNullable::Slice(size_t begin, size_t len) { 63 | return std::make_shared(nested_->Slice(begin, len), nulls_->Slice(begin, len)); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/nullable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "column.h" 4 | #include "numeric.h" 5 | 6 | namespace clickhouse { 7 | 8 | /** 9 | * Represents column of Nullable(T). 10 | */ 11 | class ColumnNullable : public Column { 12 | public: 13 | ColumnNullable(ColumnRef nested, ColumnRef nulls); 14 | 15 | /// Returns null flag at given row number. 16 | bool IsNull(size_t n) const; 17 | 18 | /// Returns nested column. 19 | ColumnRef Nested() const; 20 | 21 | public: 22 | /// Appends content of given column to the end of current one. 23 | void Append(ColumnRef column) override; 24 | 25 | /// Loads column data from input stream. 26 | bool Load(CodedInputStream* input, size_t rows) override; 27 | 28 | /// Saves column data to output stream. 29 | void Save(CodedOutputStream* output) override; 30 | 31 | /// Clear column data . 32 | void Clear() override; 33 | 34 | /// Returns count of rows in the column. 35 | size_t Size() const override; 36 | 37 | /// Makes slice of the current column. 38 | ColumnRef Slice(size_t begin, size_t len) override; 39 | 40 | private: 41 | ColumnRef nested_; 42 | std::shared_ptr nulls_; 43 | }; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/numeric.cpp: -------------------------------------------------------------------------------- 1 | #include "numeric.h" 2 | #include "utils.h" 3 | 4 | namespace clickhouse { 5 | 6 | template 7 | ColumnVector::ColumnVector() 8 | : Column(Type::CreateSimple()) 9 | { 10 | } 11 | 12 | template 13 | ColumnVector::ColumnVector(const std::vector& data) 14 | : Column(Type::CreateSimple()) 15 | , data_(data) 16 | { 17 | } 18 | 19 | template 20 | void ColumnVector::Append(const T& value) { 21 | data_.push_back(value); 22 | } 23 | 24 | template 25 | void ColumnVector::Clear() { 26 | data_.clear(); 27 | } 28 | 29 | template 30 | const T& ColumnVector::At(size_t n) const { 31 | return data_.at(n); 32 | } 33 | 34 | template 35 | const T& ColumnVector::operator [] (size_t n) const { 36 | return data_[n]; 37 | } 38 | 39 | template 40 | void ColumnVector::Append(ColumnRef column) { 41 | if (auto col = column->As>()) { 42 | data_.insert(data_.end(), col->data_.begin(), col->data_.end()); 43 | } 44 | } 45 | 46 | template 47 | bool ColumnVector::Load(CodedInputStream* input, size_t rows) { 48 | data_.resize(rows); 49 | 50 | return input->ReadRaw(data_.data(), data_.size() * sizeof(T)); 51 | } 52 | 53 | template 54 | void ColumnVector::Save(CodedOutputStream* output) { 55 | output->WriteRaw(data_.data(), data_.size() * sizeof(T)); 56 | } 57 | 58 | template 59 | size_t ColumnVector::Size() const { 60 | return data_.size(); 61 | } 62 | 63 | template 64 | ColumnRef ColumnVector::Slice(size_t begin, size_t len) { 65 | return std::make_shared>(SliceVector(data_, begin, len)); 66 | } 67 | 68 | template class ColumnVector; 69 | template class ColumnVector; 70 | template class ColumnVector; 71 | template class ColumnVector; 72 | 73 | template class ColumnVector; 74 | template class ColumnVector; 75 | template class ColumnVector; 76 | template class ColumnVector; 77 | 78 | template class ColumnVector; 79 | template class ColumnVector; 80 | 81 | } 82 | 83 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/numeric.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "column.h" 4 | 5 | namespace clickhouse { 6 | 7 | /** 8 | * Represents various numeric columns. 9 | */ 10 | template 11 | class ColumnVector : public Column { 12 | public: 13 | ColumnVector(); 14 | 15 | explicit ColumnVector(const std::vector& data); 16 | 17 | /// Appends one element to the end of column. 18 | void Append(const T& value); 19 | 20 | /// Returns element at given row number. 21 | const T& At(size_t n) const; 22 | 23 | /// Returns element at given row number. 24 | const T& operator [] (size_t n) const; 25 | 26 | public: 27 | /// Appends content of given column to the end of current one. 28 | void Append(ColumnRef column) override; 29 | 30 | /// Loads column data from input stream. 31 | bool Load(CodedInputStream* input, size_t rows) override; 32 | 33 | /// Saves column data to output stream. 34 | void Save(CodedOutputStream* output) override; 35 | 36 | /// Clear column data . 37 | void Clear() override; 38 | 39 | /// Returns count of rows in the column. 40 | size_t Size() const override; 41 | 42 | /// Makes slice of the current column. 43 | ColumnRef Slice(size_t begin, size_t len) override; 44 | 45 | private: 46 | std::vector data_; 47 | }; 48 | 49 | using ColumnUInt8 = ColumnVector; 50 | using ColumnUInt16 = ColumnVector; 51 | using ColumnUInt32 = ColumnVector; 52 | using ColumnUInt64 = ColumnVector; 53 | 54 | using ColumnInt8 = ColumnVector; 55 | using ColumnInt16 = ColumnVector; 56 | using ColumnInt32 = ColumnVector; 57 | using ColumnInt64 = ColumnVector; 58 | 59 | using ColumnFloat32 = ColumnVector; 60 | using ColumnFloat64 = ColumnVector; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/string.cpp: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | #include "utils.h" 3 | 4 | #include "../base/wire_format.h" 5 | 6 | namespace clickhouse { 7 | 8 | ColumnFixedString::ColumnFixedString(size_t n) 9 | : Column(Type::CreateString(n)) 10 | , string_size_(n) 11 | { 12 | } 13 | 14 | void ColumnFixedString::Append(const std::string& str) { 15 | data_.push_back(str); 16 | data_.back().resize(string_size_); 17 | } 18 | 19 | void ColumnFixedString::Clear() { 20 | data_.clear(); 21 | } 22 | 23 | const std::string& ColumnFixedString::At(size_t n) const { 24 | return data_.at(n); 25 | } 26 | 27 | const std::string& ColumnFixedString::operator [] (size_t n) const { 28 | return data_[n]; 29 | } 30 | 31 | void ColumnFixedString::Append(ColumnRef column) { 32 | if (auto col = column->As()) { 33 | if (string_size_ == col->string_size_) { 34 | data_.insert(data_.end(), col->data_.begin(), col->data_.end()); 35 | } 36 | } 37 | } 38 | 39 | bool ColumnFixedString::Load(CodedInputStream* input, size_t rows) { 40 | for (size_t i = 0; i < rows; ++i) { 41 | std::string s; 42 | s.resize(string_size_); 43 | 44 | if (!WireFormat::ReadBytes(input, &s[0], s.size())) { 45 | return false; 46 | } 47 | 48 | data_.push_back(s); 49 | } 50 | 51 | return true; 52 | } 53 | 54 | void ColumnFixedString::Save(CodedOutputStream* output) { 55 | for (size_t i = 0; i < data_.size(); ++i) { 56 | WireFormat::WriteBytes(output, data_[i].data(), string_size_); 57 | } 58 | } 59 | 60 | size_t ColumnFixedString::Size() const { 61 | return data_.size(); 62 | } 63 | 64 | ColumnRef ColumnFixedString::Slice(size_t begin, size_t len) { 65 | auto result = std::make_shared(string_size_); 66 | 67 | if (begin < data_.size()) { 68 | result->data_ = SliceVector(data_, begin, len); 69 | } 70 | 71 | return result; 72 | } 73 | 74 | 75 | ColumnString::ColumnString() 76 | : Column(Type::CreateString()) 77 | { 78 | } 79 | 80 | ColumnString::ColumnString(const std::vector& data) 81 | : Column(Type::CreateString()) 82 | , data_(data) 83 | { 84 | } 85 | 86 | void ColumnString::Append(const std::string& str) { 87 | data_.push_back(str); 88 | } 89 | 90 | void ColumnString::Clear() { 91 | data_.clear(); 92 | } 93 | 94 | const std::string& ColumnString::At(size_t n) const { 95 | return data_.at(n); 96 | } 97 | 98 | const std::string& ColumnString::operator [] (size_t n) const { 99 | return data_[n]; 100 | } 101 | 102 | void ColumnString::Append(ColumnRef column) { 103 | if (auto col = column->As()) { 104 | data_.insert(data_.end(), col->data_.begin(), col->data_.end()); 105 | } 106 | } 107 | 108 | bool ColumnString::Load(CodedInputStream* input, size_t rows) { 109 | for (size_t i = 0; i < rows; ++i) { 110 | std::string s; 111 | 112 | if (!WireFormat::ReadString(input, &s)) { 113 | return false; 114 | } 115 | 116 | data_.push_back(s); 117 | } 118 | 119 | return true; 120 | } 121 | 122 | void ColumnString::Save(CodedOutputStream* output) { 123 | for (auto si = data_.begin(); si != data_.end(); ++si) { 124 | WireFormat::WriteString(output, *si); 125 | } 126 | } 127 | 128 | size_t ColumnString::Size() const { 129 | return data_.size(); 130 | } 131 | 132 | ColumnRef ColumnString::Slice(size_t begin, size_t len) { 133 | return std::make_shared(SliceVector(data_, begin, len)); 134 | } 135 | 136 | } 137 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/string.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "column.h" 4 | 5 | namespace clickhouse { 6 | 7 | /** 8 | * Represents column of fixed-length strings. 9 | */ 10 | class ColumnFixedString : public Column { 11 | public: 12 | explicit ColumnFixedString(size_t n); 13 | 14 | /// Appends one element to the column. 15 | void Append(const std::string& str); 16 | 17 | /// Returns element at given row number. 18 | const std::string& At(size_t n) const; 19 | 20 | /// Returns element at given row number. 21 | const std::string& operator [] (size_t n) const; 22 | 23 | public: 24 | /// Appends content of given column to the end of current one. 25 | void Append(ColumnRef column) override; 26 | 27 | /// Loads column data from input stream. 28 | bool Load(CodedInputStream* input, size_t rows) override; 29 | 30 | /// Saves column data to output stream. 31 | void Save(CodedOutputStream* output) override; 32 | 33 | /// Clear column data . 34 | void Clear() override; 35 | 36 | /// Returns count of rows in the column. 37 | size_t Size() const override; 38 | 39 | /// Makes slice of the current column. 40 | ColumnRef Slice(size_t begin, size_t len) override; 41 | 42 | private: 43 | const size_t string_size_; 44 | std::vector data_; 45 | }; 46 | 47 | 48 | /** 49 | * Represents column of variable-length strings. 50 | */ 51 | class ColumnString : public Column { 52 | public: 53 | ColumnString(); 54 | explicit ColumnString(const std::vector& data); 55 | 56 | /// Appends one element to the column. 57 | void Append(const std::string& str); 58 | 59 | /// Returns element at given row number. 60 | const std::string& At(size_t n) const; 61 | 62 | /// Returns element at given row number. 63 | const std::string& operator [] (size_t n) const; 64 | 65 | public: 66 | /// Appends content of given column to the end of current one. 67 | void Append(ColumnRef column) override; 68 | 69 | /// Loads column data from input stream. 70 | bool Load(CodedInputStream* input, size_t rows) override; 71 | 72 | /// Saves column data to output stream. 73 | void Save(CodedOutputStream* output) override; 74 | 75 | /// Clear column data . 76 | void Clear() override; 77 | 78 | /// Returns count of rows in the column. 79 | size_t Size() const override; 80 | 81 | /// Makes slice of the current column. 82 | ColumnRef Slice(size_t begin, size_t len) override; 83 | 84 | private: 85 | std::vector data_; 86 | }; 87 | 88 | } 89 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/tuple.cpp: -------------------------------------------------------------------------------- 1 | #include "tuple.h" 2 | 3 | namespace clickhouse { 4 | 5 | static std::vector CollectTypes(const std::vector& columns) { 6 | std::vector types; 7 | for (const auto& col : columns) { 8 | types.push_back(col->Type()); 9 | } 10 | return types; 11 | } 12 | 13 | ColumnTuple::ColumnTuple(const std::vector& columns) 14 | : Column(Type::CreateTuple(CollectTypes(columns))) 15 | , columns_(columns) 16 | { 17 | } 18 | 19 | size_t ColumnTuple::Size() const { 20 | return columns_.empty() ? 0 : columns_[0]->Size(); 21 | } 22 | 23 | size_t ColumnTuple::tupleSize() { 24 | return columns_.empty() ? 0 : columns_.size(); 25 | } 26 | 27 | bool ColumnTuple::Load(CodedInputStream* input, size_t rows) { 28 | for (auto ci = columns_.begin(); ci != columns_.end(); ++ci) { 29 | if (!(*ci)->Load(input, rows)) { 30 | return false; 31 | } 32 | } 33 | 34 | return true; 35 | } 36 | 37 | void ColumnTuple::Save(CodedOutputStream* output) { 38 | for (auto ci = columns_.begin(); ci != columns_.end(); ++ci) { 39 | (*ci)->Save(output); 40 | } 41 | } 42 | 43 | void ColumnTuple::Clear() { 44 | columns_.clear(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/tuple.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "column.h" 4 | 5 | #include 6 | 7 | namespace clickhouse { 8 | 9 | /** 10 | * Represents column of Tuple([T]). 11 | */ 12 | class ColumnTuple : public Column { 13 | public: 14 | ColumnTuple(const std::vector& columns); 15 | 16 | ColumnRef operator [] (size_t n) const { 17 | return columns_[n]; 18 | } 19 | 20 | size_t tupleSize(); 21 | 22 | public: 23 | /// Appends content of given column to the end of current one. 24 | void Append(ColumnRef) override { } 25 | 26 | /// Loads column data from input stream. 27 | bool Load(CodedInputStream* input, size_t rows) override; 28 | 29 | /// Saves column data to output stream. 30 | void Save(CodedOutputStream* output) override; 31 | 32 | /// Clear column data . 33 | void Clear() override; 34 | 35 | /// Returns count of rows in the column. 36 | size_t Size() const override; 37 | 38 | /// Makes slice of the current column. 39 | ColumnRef Slice(size_t, size_t) override { return ColumnRef(); } 40 | 41 | private: 42 | std::vector columns_; 43 | }; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace clickhouse { 7 | 8 | template 9 | std::vector SliceVector(const std::vector& vec, size_t begin, size_t len) { 10 | std::vector result; 11 | 12 | if (begin < vec.size()) { 13 | len = std::min(len, vec.size() - begin); 14 | result.assign(vec.begin() + begin, vec.begin() + (begin + len)); 15 | } 16 | 17 | return result; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/uuid.cpp: -------------------------------------------------------------------------------- 1 | #include "uuid.h" 2 | #include "utils.h" 3 | 4 | #include 5 | 6 | namespace clickhouse { 7 | 8 | ColumnUUID::ColumnUUID() 9 | : Column(Type::CreateUUID()) 10 | , data_(std::make_shared()) 11 | { 12 | } 13 | 14 | ColumnUUID::ColumnUUID(ColumnRef data) 15 | : Column(Type::CreateUUID()) 16 | , data_(data->As()) 17 | { 18 | if (data_->Size()%2 != 0) { 19 | throw std::runtime_error("number of entries must be even (two 64-bit numbers for each UUID)"); 20 | } 21 | } 22 | 23 | void ColumnUUID::Append(const UInt128& value) { 24 | data_->Append(value.first); 25 | data_->Append(value.second); 26 | } 27 | 28 | void ColumnUUID::Clear() { 29 | data_->Clear(); 30 | } 31 | 32 | const UInt128 ColumnUUID::At(size_t n) const { 33 | return UInt128(data_->At(n * 2), data_->At(n * 2 + 1)); 34 | } 35 | 36 | const UInt128 ColumnUUID::operator [] (size_t n) const { 37 | return UInt128((*data_)[n * 2], (*data_)[n * 2 + 1]); 38 | } 39 | 40 | void ColumnUUID::Append(ColumnRef column) { 41 | if (auto col = column->As()) { 42 | data_->Append(data_); 43 | } 44 | } 45 | 46 | bool ColumnUUID::Load(CodedInputStream* input, size_t rows) { 47 | return data_->Load(input, rows * 2); 48 | } 49 | 50 | void ColumnUUID::Save(CodedOutputStream* output) { 51 | data_->Save(output); 52 | } 53 | 54 | size_t ColumnUUID::Size() const { 55 | return data_->Size() / 2; 56 | } 57 | 58 | ColumnRef ColumnUUID::Slice(size_t begin, size_t len) { 59 | return std::make_shared(data_->Slice(begin * 2, len * 2)); 60 | } 61 | 62 | } 63 | 64 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/columns/uuid.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "column.h" 4 | #include "numeric.h" 5 | 6 | namespace clickhouse { 7 | 8 | using UInt128 = std::pair; 9 | 10 | /** 11 | * Represents a UUID column. 12 | */ 13 | class ColumnUUID : public Column { 14 | public: 15 | ColumnUUID(); 16 | 17 | explicit ColumnUUID(ColumnRef data); 18 | 19 | /// Appends one element to the end of column. 20 | void Append(const UInt128& value); 21 | 22 | /// Returns element at given row number. 23 | const UInt128 At(size_t n) const; 24 | 25 | /// Returns element at given row number. 26 | const UInt128 operator [] (size_t n) const; 27 | 28 | public: 29 | /// Appends content of given column to the end of current one. 30 | void Append(ColumnRef column) override; 31 | 32 | /// Loads column data from input stream. 33 | bool Load(CodedInputStream* input, size_t rows) override; 34 | 35 | /// Saves column data to output stream. 36 | void Save(CodedOutputStream* output) override; 37 | 38 | /// Clear column data . 39 | void Clear() override; 40 | 41 | /// Returns count of rows in the column. 42 | size_t Size() const override; 43 | 44 | /// Makes slice of the current column. 45 | ColumnRef Slice(size_t begin, size_t len) override; 46 | 47 | private: 48 | std::shared_ptr data_; 49 | }; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/error_codes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace clickhouse { 4 | 5 | enum ErrorCodes { 6 | CHECKSUM_DOESNT_MATCH = 40, 7 | CANNOT_PARSE_DATETIME = 41, 8 | UNKNOWN_FUNCTION = 46, 9 | UNKNOWN_IDENTIFIER = 47, 10 | TABLE_ALREADY_EXISTS = 57, 11 | UNKNOWN_TABLE = 60, 12 | SYNTAX_ERROR = 62, 13 | UNKNOWN_DATABASE = 81, 14 | DATABASE_ALREADY_EXISTS = 82, 15 | UNKNOWN_PACKET_FROM_CLIENT = 99, 16 | UNEXPECTED_PACKET_FROM_CLIENT = 101, 17 | RECEIVED_DATA_FOR_WRONG_QUERY_ID = 103, 18 | ENGINE_REQUIRED = 119, 19 | READONLY = 164, 20 | UNKNOWN_USER = 192, 21 | WRONG_PASSWORD = 193, 22 | REQUIRED_PASSWORD = 194, 23 | IP_ADDRESS_NOT_ALLOWED = 195, 24 | LIMIT_EXCEEDED = 290, 25 | UNKNOWN_DATABASE_ENGINE = 336, 26 | UNKNOWN_EXCEPTION = 1002, 27 | }; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/exceptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "query.h" 4 | 5 | #include 6 | 7 | namespace clickhouse { 8 | 9 | class ServerException : public std::runtime_error { 10 | public: 11 | ServerException(std::unique_ptr e) 12 | : runtime_error(std::string()) 13 | , exception_(std::move(e)) 14 | { 15 | } 16 | 17 | int GetCode() const { 18 | return exception_->code; 19 | } 20 | 21 | const Exception& GetException() const { 22 | return *exception_; 23 | } 24 | 25 | const char* what() const noexcept override { 26 | return exception_->display_text.c_str(); 27 | } 28 | 29 | private: 30 | std::unique_ptr exception_; 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/protocol.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace clickhouse { 4 | 5 | /// То, что передаёт сервер. 6 | namespace ServerCodes { 7 | enum { 8 | Hello = 0, /// Имя, версия, ревизия. 9 | Data = 1, /// Блок данных со сжатием или без. 10 | Exception = 2, /// Исключение во время обработки запроса. 11 | Progress = 3, /// Прогресс выполнения запроса: строк считано, байт считано. 12 | Pong = 4, /// Ответ на Ping. 13 | EndOfStream = 5, /// Все пакеты были переданы. 14 | ProfileInfo = 6, /// Пакет с профайлинговой информацией. 15 | Totals = 7, /// Блок данных с тотальными значениями, со сжатием или без. 16 | Extremes = 8, /// Блок данных с минимумами и максимумами, аналогично. 17 | }; 18 | } 19 | 20 | /// То, что передаёт клиент. 21 | namespace ClientCodes { 22 | enum { 23 | Hello = 0, /// Имя, версия, ревизия, БД по-умолчанию. 24 | Query = 1, /** Идентификатор запроса, настройки на отдельный запрос, 25 | * информация, до какой стадии исполнять запрос, 26 | * использовать ли сжатие, текст запроса (без данных для INSERT-а). 27 | */ 28 | Data = 2, /// Блок данных со сжатием или без. 29 | Cancel = 3, /// Отменить выполнение запроса. 30 | Ping = 4, /// Проверка живости соединения с сервером. 31 | }; 32 | } 33 | 34 | /// Использовать ли сжатие. 35 | namespace CompressionState { 36 | enum { 37 | Disable = 0, 38 | Enable = 1, 39 | }; 40 | } 41 | 42 | namespace Stages { 43 | enum { 44 | Complete = 2, 45 | }; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/query.cpp: -------------------------------------------------------------------------------- 1 | #include "query.h" 2 | 3 | namespace clickhouse { 4 | 5 | Query::Query() 6 | { } 7 | 8 | Query::Query(const char* query) 9 | : query_(query) 10 | { 11 | } 12 | 13 | Query::Query(const std::string& query) 14 | : query_(query) 15 | { 16 | } 17 | 18 | Query::~Query() 19 | { } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/query.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "block.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace clickhouse { 11 | 12 | /** 13 | * Settings of individual query. 14 | */ 15 | struct QuerySettings { 16 | /// Максимальное количество потоков выполнения запроса. По-умолчанию - определять автоматически. 17 | int max_threads = 0; 18 | /// Считать минимумы и максимумы столбцов результата. 19 | bool extremes = false; 20 | /// Тихо пропускать недоступные шарды. 21 | bool skip_unavailable_shards = false; 22 | /// Write statistics about read rows, bytes, time elapsed, etc. 23 | bool output_format_write_statistics = true; 24 | /// Use client timezone for interpreting DateTime string values, instead of adopting server timezone. 25 | bool use_client_time_zone = false; 26 | 27 | // connect_timeout 28 | // max_block_size 29 | // distributed_group_by_no_merge = false 30 | // strict_insert_defaults = 0 31 | // network_compression_method = LZ4 32 | // priority = 0 33 | }; 34 | 35 | 36 | struct Exception { 37 | int code = 0; 38 | std::string name; 39 | std::string display_text; 40 | std::string stack_trace; 41 | /// Pointer to nested exception. 42 | std::unique_ptr nested; 43 | }; 44 | 45 | 46 | struct Profile { 47 | uint64_t rows = 0; 48 | uint64_t blocks = 0; 49 | uint64_t bytes = 0; 50 | uint64_t rows_before_limit = 0; 51 | bool applied_limit = false; 52 | bool calculated_rows_before_limit = false; 53 | }; 54 | 55 | 56 | struct Progress { 57 | uint64_t rows = 0; 58 | uint64_t bytes = 0; 59 | uint64_t total_rows = 0; 60 | }; 61 | 62 | 63 | class QueryEvents { 64 | public: 65 | virtual ~QueryEvents() 66 | { } 67 | 68 | /// Some data was received. 69 | virtual void OnData(const Block& block) = 0; 70 | virtual bool OnDataCancelable(const Block& block) = 0; 71 | 72 | virtual void OnServerException(const Exception& e) = 0; 73 | 74 | virtual void OnProfile(const Profile& profile) = 0; 75 | 76 | virtual void OnProgress(const Progress& progress) = 0; 77 | 78 | virtual void OnFinish() = 0; 79 | }; 80 | 81 | 82 | using ExceptionCallback = std::function; 83 | using ProgressCallback = std::function; 84 | using SelectCallback = std::function; 85 | using SelectCancelableCallback = std::function; 86 | 87 | 88 | class Query : public QueryEvents { 89 | public: 90 | Query(); 91 | Query(const char* query); 92 | Query(const std::string& query); 93 | ~Query(); 94 | 95 | /// 96 | inline std::string GetText() const { 97 | return query_; 98 | } 99 | 100 | /// Set handler for receiving result data. 101 | inline Query& OnData(SelectCallback cb) { 102 | select_cb_ = cb; 103 | return *this; 104 | } 105 | 106 | inline Query& OnDataCancelable(SelectCancelableCallback cb) { 107 | select_cancelable_cb_ = cb; 108 | return *this; 109 | } 110 | 111 | /// Set handler for receiving server's exception. 112 | inline Query& OnException(ExceptionCallback cb) { 113 | exception_cb_ = cb; 114 | return *this; 115 | } 116 | 117 | 118 | /// Set handler for receiving a progress of query exceution. 119 | inline Query& OnProgress(ProgressCallback cb) { 120 | progress_cb_ = cb; 121 | return *this; 122 | } 123 | 124 | private: 125 | void OnData(const Block& block) override { 126 | if (select_cb_) { 127 | select_cb_(block); 128 | } 129 | } 130 | 131 | bool OnDataCancelable(const Block& block) override { 132 | if (select_cancelable_cb_) { 133 | return select_cancelable_cb_(block); 134 | } else { 135 | return true; 136 | } 137 | } 138 | 139 | void OnServerException(const Exception& e) override { 140 | if (exception_cb_) { 141 | exception_cb_(e); 142 | } 143 | } 144 | 145 | void OnProfile(const Profile& profile) override { 146 | (void)profile; 147 | } 148 | 149 | void OnProgress(const Progress& progress) override { 150 | if (progress_cb_) { 151 | progress_cb_(progress); 152 | } 153 | } 154 | 155 | void OnFinish() override { 156 | } 157 | 158 | private: 159 | std::string query_; 160 | ExceptionCallback exception_cb_; 161 | ProgressCallback progress_cb_; 162 | SelectCallback select_cb_; 163 | SelectCancelableCallback select_cancelable_cb_; 164 | }; 165 | 166 | } 167 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/types/type_parser.cpp: -------------------------------------------------------------------------------- 1 | #include "type_parser.h" 2 | #include "../base/string_utils.h" 3 | 4 | #include 5 | 6 | namespace clickhouse { 7 | 8 | static const std::unordered_map kTypeCode = { 9 | { "Int8", Type::Int8 }, 10 | { "Int16", Type::Int16 }, 11 | { "Int32", Type::Int32 }, 12 | { "Int64", Type::Int64 }, 13 | { "UInt8", Type::UInt8 }, 14 | { "UInt16", Type::UInt16 }, 15 | { "UInt32", Type::UInt32 }, 16 | { "UInt64", Type::UInt64 }, 17 | { "Float32", Type::Float32 }, 18 | { "Float64", Type::Float64 }, 19 | { "String", Type::String }, 20 | { "FixedString", Type::FixedString }, 21 | { "DateTime", Type::DateTime }, 22 | { "Date", Type::Date }, 23 | { "Array", Type::Array }, 24 | { "Nullable", Type::Nullable }, 25 | { "Tuple", Type::Tuple }, 26 | { "Enum8", Type::Enum8 }, 27 | { "Enum16", Type::Enum16 }, 28 | { "UUID", Type::UUID }, 29 | }; 30 | 31 | static Type::Code GetTypeCode(const std::string& name) { 32 | auto it = kTypeCode.find(name); 33 | if (it != kTypeCode.end()) { 34 | return it->second; 35 | } 36 | return Type::Void; 37 | } 38 | 39 | static TypeAst::Meta GetTypeMeta(const StringView& name) { 40 | if (name == "Array") { 41 | return TypeAst::Array; 42 | } 43 | 44 | if (name == "Null") { 45 | return TypeAst::Null; 46 | } 47 | 48 | if (name == "Nullable") { 49 | return TypeAst::Nullable; 50 | } 51 | 52 | if (name == "Tuple") { 53 | return TypeAst::Tuple; 54 | } 55 | 56 | if (name == "Enum8" || name == "Enum16") { 57 | return TypeAst::Enum; 58 | } 59 | 60 | return TypeAst::Terminal; 61 | } 62 | 63 | 64 | TypeParser::TypeParser(const StringView& name) 65 | : cur_(name.data()) 66 | , end_(name.data() + name.size()) 67 | , type_(nullptr) 68 | { 69 | } 70 | 71 | TypeParser::~TypeParser() = default; 72 | 73 | bool TypeParser::Parse(TypeAst* type) { 74 | type_ = type; 75 | open_elements_.push(type_); 76 | 77 | do { 78 | const Token& token = NextToken(); 79 | 80 | switch (token.type) { 81 | case Token::Name: 82 | type_->meta = GetTypeMeta(token.value); 83 | type_->name = token.value.to_string(); 84 | type_->code = GetTypeCode(type_->name); 85 | break; 86 | case Token::Number: 87 | type_->meta = TypeAst::Number; 88 | type_->value = std::stol(token.value.to_string()); 89 | break; 90 | case Token::LPar: 91 | type_->elements.emplace_back(TypeAst()); 92 | open_elements_.push(type_); 93 | type_ = &type_->elements.back(); 94 | break; 95 | case Token::RPar: 96 | type_ = open_elements_.top(); 97 | open_elements_.pop(); 98 | break; 99 | case Token::Comma: 100 | type_ = open_elements_.top(); 101 | open_elements_.pop(); 102 | type_->elements.emplace_back(TypeAst()); 103 | open_elements_.push(type_); 104 | type_ = &type_->elements.back(); 105 | break; 106 | case Token::EOS: 107 | return true; 108 | case Token::Invalid: 109 | return false; 110 | } 111 | } while (true); 112 | } 113 | 114 | TypeParser::Token TypeParser::NextToken() { 115 | for (; cur_ < end_; ++cur_) { 116 | switch (*cur_) { 117 | case ' ': 118 | case '\n': 119 | case '\t': 120 | case '\0': 121 | continue; 122 | 123 | case '=': 124 | case '\'': 125 | continue; 126 | 127 | case '(': 128 | return Token{Token::LPar, StringView(cur_++, 1)}; 129 | case ')': 130 | return Token{Token::RPar, StringView(cur_++, 1)}; 131 | case ',': 132 | return Token{Token::Comma, StringView(cur_++, 1)}; 133 | 134 | default: { 135 | const char* st = cur_; 136 | 137 | if (isalpha(*cur_) || *cur_ == '_') { 138 | for (; cur_ < end_; ++cur_) { 139 | if (!isalpha(*cur_) && !isdigit(*cur_) && *cur_ != '_') { 140 | break; 141 | } 142 | } 143 | 144 | return Token{Token::Name, StringView(st, cur_)}; 145 | } 146 | 147 | if (isdigit(*cur_) || *cur_ == '-') { 148 | for (++cur_; cur_ < end_; ++cur_) { 149 | if (!isdigit(*cur_)) { 150 | break; 151 | } 152 | } 153 | 154 | return Token{Token::Number, StringView(st, cur_)}; 155 | } 156 | 157 | return Token{Token::Invalid, StringView()}; 158 | } 159 | } 160 | } 161 | 162 | return Token{Token::EOS, StringView()}; 163 | } 164 | 165 | 166 | const TypeAst* ParseTypeName(const std::string& type_name) { 167 | // Cache for type_name. 168 | // Usually we won't have too many type names in the cache, so do not try to 169 | // limit cache size. 170 | static std::unordered_map ast_cache; 171 | 172 | auto it = ast_cache.find(type_name); 173 | if (it != ast_cache.end()) { 174 | return &it->second; 175 | } 176 | 177 | auto& ast = ast_cache[type_name]; 178 | if (TypeParser(type_name).Parse(&ast)) { 179 | return * 180 | } 181 | ast_cache.erase(type_name); 182 | return nullptr; 183 | } 184 | 185 | } 186 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/types/type_parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../base/string_view.h" 4 | #include "types.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace clickhouse { 11 | 12 | struct TypeAst { 13 | enum Meta { 14 | Array, 15 | Null, 16 | Nullable, 17 | Number, 18 | Terminal, 19 | Tuple, 20 | Enum 21 | }; 22 | 23 | /// Type's category. 24 | Meta meta; 25 | Type::Code code; 26 | /// Type's name. 27 | /// Need to cache TypeAst, so can't use StringView for name. 28 | std::string name; 29 | /// Value associated with the node, 30 | /// used for fixed-width types and enum values. 31 | int64_t value = 0; 32 | /// Subelements of the type. 33 | /// Used to store enum's names and values as well. 34 | std::list elements; 35 | }; 36 | 37 | 38 | class TypeParser { 39 | 40 | struct Token { 41 | enum Type { 42 | Invalid = 0, 43 | Name, 44 | Number, 45 | LPar, 46 | RPar, 47 | Comma, 48 | EOS, 49 | }; 50 | 51 | Type type; 52 | StringView value; 53 | }; 54 | 55 | public: 56 | explicit TypeParser(const StringView& name); 57 | ~TypeParser(); 58 | 59 | bool Parse(TypeAst* type); 60 | 61 | private: 62 | Token NextToken(); 63 | 64 | private: 65 | const char* cur_; 66 | const char* end_; 67 | 68 | TypeAst* type_; 69 | std::stack open_elements_; 70 | }; 71 | 72 | 73 | const TypeAst* ParseTypeName(const std::string& type_name); 74 | 75 | } 76 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/types/types.cpp: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | 3 | #include 4 | 5 | namespace clickhouse { 6 | 7 | Type::Type(const Code code) 8 | : code_(code) 9 | { 10 | if (code_ == Array) { 11 | array_ = new ArrayImpl; 12 | } else if (code_ == Tuple) { 13 | tuple_ = new TupleImpl; 14 | } else if (code_ == Nullable) { 15 | nullable_ = new NullableImpl; 16 | } else if (code_ == Enum8 || code_ == Enum16) { 17 | enum_ = new EnumImpl; 18 | } 19 | } 20 | 21 | Type::~Type() { 22 | if (code_ == Array) { 23 | delete array_; 24 | } else if (code_ == Tuple) { 25 | delete tuple_; 26 | } else if (code_ == Nullable) { 27 | delete nullable_; 28 | } else if (code_ == Enum8 || code_ == Enum16) { 29 | delete enum_; 30 | } 31 | } 32 | 33 | Type::Code Type::GetCode() const { 34 | return code_; 35 | } 36 | 37 | TypeRef Type::GetItemType() const { 38 | if (code_ == Array) { 39 | return array_->item_type; 40 | } 41 | return TypeRef(); 42 | } 43 | 44 | TypeRef Type::GetNestedType() const { 45 | if (code_ == Nullable) { 46 | return nullable_->nested_type; 47 | } 48 | return TypeRef(); 49 | } 50 | 51 | std::vector Type::GetTupleType() const { 52 | return tuple_->item_types; 53 | } 54 | 55 | std::string Type::GetName() const { 56 | switch (code_) { 57 | case Void: 58 | return "Void"; 59 | case Int8: 60 | return "Int8"; 61 | case Int16: 62 | return "Int16"; 63 | case Int32: 64 | return "Int32"; 65 | case Int64: 66 | return "Int64"; 67 | case UInt8: 68 | return "UInt8"; 69 | case UInt16: 70 | return "UInt16"; 71 | case UInt32: 72 | return "UInt32"; 73 | case UInt64: 74 | return "UInt64"; 75 | case UUID: 76 | return "UUID"; 77 | case Float32: 78 | return "Float32"; 79 | case Float64: 80 | return "Float64"; 81 | case String: 82 | return "String"; 83 | case FixedString: 84 | return "FixedString(" + std::to_string(string_size_) + ")"; 85 | case DateTime: 86 | return "DateTime"; 87 | case Date: 88 | return "Date"; 89 | case Array: 90 | return std::string("Array(") + array_->item_type->GetName() +")"; 91 | case Nullable: 92 | return std::string("Nullable(") + nullable_->nested_type->GetName() + ")"; 93 | case Tuple: { 94 | std::string result("Tuple("); 95 | for (size_t i = 0; i < tuple_->item_types.size(); ++i) { 96 | result += tuple_->item_types[i]->GetName(); 97 | 98 | if (i + 1 != tuple_->item_types.size()) { 99 | result += ", "; 100 | } 101 | } 102 | result += ")"; 103 | return result; 104 | } 105 | case Enum8: 106 | case Enum16: { 107 | std::string result; 108 | if (code_ == Enum8) { 109 | result = "Enum8("; 110 | } else { 111 | result = "Enum16("; 112 | } 113 | for (auto ei = enum_->value_to_name.begin(); ; ) { 114 | result += "'"; 115 | result += ei->second; 116 | result += "' = "; 117 | result += std::to_string(ei->first); 118 | 119 | if (++ei != enum_->value_to_name.end()) { 120 | result += ", "; 121 | } else { 122 | break; 123 | } 124 | } 125 | result += ")"; 126 | return result; 127 | } 128 | } 129 | 130 | return std::string(); 131 | } 132 | 133 | bool Type::IsEqual(const TypeRef& other) const { 134 | return this->GetName() == other->GetName(); 135 | } 136 | 137 | TypeRef Type::CreateArray(TypeRef item_type) { 138 | TypeRef type(new Type(Type::Array)); 139 | type->array_->item_type = item_type; 140 | return type; 141 | } 142 | 143 | TypeRef Type::CreateDate() { 144 | return TypeRef(new Type(Type::Date)); 145 | } 146 | 147 | TypeRef Type::CreateDateTime() { 148 | return TypeRef(new Type(Type::DateTime)); 149 | } 150 | 151 | TypeRef Type::CreateNullable(TypeRef nested_type) { 152 | TypeRef type(new Type(Type::Nullable)); 153 | type->nullable_->nested_type = nested_type; 154 | return type; 155 | } 156 | 157 | TypeRef Type::CreateString() { 158 | return TypeRef(new Type(Type::String)); 159 | } 160 | 161 | TypeRef Type::CreateString(size_t n) { 162 | TypeRef type(new Type(Type::FixedString)); 163 | type->string_size_ = n; 164 | return type; 165 | } 166 | 167 | TypeRef Type::CreateTuple(const std::vector& item_types) { 168 | TypeRef type(new Type(Type::Tuple)); 169 | type->tuple_->item_types.assign(item_types.begin(), item_types.end()); 170 | return type; 171 | } 172 | 173 | TypeRef Type::CreateEnum8(const std::vector& enum_items) { 174 | TypeRef type(new Type(Type::Enum8)); 175 | for (const auto& item : enum_items) { 176 | type->enum_->value_to_name[item.value] = item.name; 177 | type->enum_->name_to_value[item.name] = item.value; 178 | } 179 | return type; 180 | } 181 | 182 | TypeRef Type::CreateEnum16(const std::vector& enum_items) { 183 | TypeRef type(new Type(Type::Enum16)); 184 | for (const auto& item : enum_items) { 185 | type->enum_->value_to_name[item.value] = item.name; 186 | type->enum_->name_to_value[item.name] = item.value; 187 | } 188 | return type; 189 | } 190 | 191 | TypeRef Type::CreateUUID() { 192 | return TypeRef(new Type(Type::UUID)); 193 | } 194 | 195 | 196 | EnumType::EnumType(const TypeRef& type) 197 | : type_(type) 198 | { 199 | assert(type_->GetCode() == Type::Enum8 || 200 | type_->GetCode() == Type::Enum16); 201 | } 202 | 203 | const std::string& EnumType::GetEnumName(int16_t value) const { 204 | return type_->enum_->value_to_name[value]; 205 | } 206 | 207 | int16_t EnumType::GetEnumValue(const std::string& name) const { 208 | return type_->enum_->name_to_value[name]; 209 | } 210 | 211 | bool EnumType::HasEnumName(const std::string& name) const { 212 | return type_->enum_->name_to_value.find(name) != type_->enum_->name_to_value.end(); 213 | } 214 | 215 | bool EnumType::HasEnumValue(int16_t value) const { 216 | return type_->enum_->value_to_name.find(value) != type_->enum_->value_to_name.end(); 217 | } 218 | 219 | EnumType::ValueToNameIterator EnumType::BeginValueToName() const { 220 | return type_->enum_->value_to_name.begin(); 221 | } 222 | 223 | EnumType::ValueToNameIterator EnumType::EndValueToName() const { 224 | return type_->enum_->value_to_name.end(); 225 | } 226 | 227 | } 228 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/clickhouse/types/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace clickhouse { 9 | 10 | using TypeRef = std::shared_ptr; 11 | 12 | class Type { 13 | public: 14 | enum Code { 15 | Void = 0, 16 | Int8, 17 | Int16, 18 | Int32, 19 | Int64, 20 | UInt8, 21 | UInt16, 22 | UInt32, 23 | UInt64, 24 | Float32, 25 | Float64, 26 | String, 27 | FixedString, 28 | DateTime, 29 | Date, 30 | Array, 31 | Nullable, 32 | Tuple, 33 | Enum8, 34 | Enum16, 35 | UUID, 36 | }; 37 | 38 | struct EnumItem { 39 | std::string name; 40 | int16_t value; 41 | }; 42 | 43 | /// Destructor 44 | ~Type(); 45 | 46 | /// Type's code. 47 | Code GetCode() const; 48 | 49 | /// Type of array's elements. 50 | TypeRef GetItemType() const; 51 | 52 | /// Type of nested nullable element. 53 | TypeRef GetNestedType() const; 54 | 55 | /// Type of nested Tuple element type. 56 | std::vector GetTupleType() const; 57 | 58 | /// String representation of the type. 59 | std::string GetName() const; 60 | 61 | /// Is given type same as current one. 62 | bool IsEqual(const TypeRef& other) const; 63 | 64 | public: 65 | static TypeRef CreateArray(TypeRef item_type); 66 | 67 | static TypeRef CreateDate(); 68 | 69 | static TypeRef CreateDateTime(); 70 | 71 | static TypeRef CreateNullable(TypeRef nested_type); 72 | 73 | template 74 | static TypeRef CreateSimple(); 75 | 76 | static TypeRef CreateString(); 77 | 78 | static TypeRef CreateString(size_t n); 79 | 80 | static TypeRef CreateTuple(const std::vector& item_types); 81 | 82 | static TypeRef CreateEnum8(const std::vector& enum_items); 83 | 84 | static TypeRef CreateEnum16(const std::vector& enum_items); 85 | 86 | static TypeRef CreateUUID(); 87 | 88 | private: 89 | Type(const Code code); 90 | 91 | struct ArrayImpl { 92 | TypeRef item_type; 93 | }; 94 | 95 | struct NullableImpl { 96 | TypeRef nested_type; 97 | }; 98 | 99 | struct TupleImpl { 100 | std::vector item_types; 101 | }; 102 | 103 | struct EnumImpl { 104 | using ValueToNameType = std::map; 105 | using NameToValueType = std::map; 106 | ValueToNameType value_to_name; 107 | NameToValueType name_to_value; 108 | }; 109 | 110 | friend class EnumType; 111 | 112 | 113 | const Code code_; 114 | union { 115 | ArrayImpl* array_; 116 | NullableImpl* nullable_; 117 | TupleImpl* tuple_; 118 | EnumImpl* enum_; 119 | int string_size_; 120 | }; 121 | }; 122 | 123 | class EnumType { 124 | public: 125 | explicit EnumType(const TypeRef& type); 126 | 127 | std::string GetName() const { 128 | return type_->GetName(); 129 | } 130 | /// Methods to work with enum types. 131 | const std::string& GetEnumName(int16_t value) const; 132 | int16_t GetEnumValue(const std::string& name) const; 133 | bool HasEnumName(const std::string& name) const; 134 | bool HasEnumValue(int16_t value) const; 135 | 136 | /// Iterator for enum elements. 137 | using ValueToNameIterator = Type::EnumImpl::ValueToNameType::const_iterator; 138 | ValueToNameIterator BeginValueToName() const; 139 | ValueToNameIterator EndValueToName() const; 140 | 141 | private: 142 | TypeRef type_; 143 | }; 144 | 145 | template <> 146 | inline TypeRef Type::CreateSimple() { 147 | return TypeRef(new Type(Int8)); 148 | } 149 | 150 | template <> 151 | inline TypeRef Type::CreateSimple() { 152 | return TypeRef(new Type(Int16)); 153 | } 154 | 155 | template <> 156 | inline TypeRef Type::CreateSimple() { 157 | return TypeRef(new Type(Int32)); 158 | } 159 | 160 | template <> 161 | inline TypeRef Type::CreateSimple() { 162 | return TypeRef(new Type(Int64)); 163 | } 164 | 165 | template <> 166 | inline TypeRef Type::CreateSimple() { 167 | return TypeRef(new Type(UInt8)); 168 | } 169 | 170 | template <> 171 | inline TypeRef Type::CreateSimple() { 172 | return TypeRef(new Type(UInt16)); 173 | } 174 | 175 | template <> 176 | inline TypeRef Type::CreateSimple() { 177 | return TypeRef(new Type(UInt32)); 178 | } 179 | 180 | template <> 181 | inline TypeRef Type::CreateSimple() { 182 | return TypeRef(new Type(UInt64)); 183 | } 184 | 185 | template <> 186 | inline TypeRef Type::CreateSimple() { 187 | return TypeRef(new Type(Float32)); 188 | } 189 | 190 | template <> 191 | inline TypeRef Type::CreateSimple() { 192 | return TypeRef(new Type(Float64)); 193 | } 194 | 195 | } 196 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/cmake/cpp11.cmake: -------------------------------------------------------------------------------- 1 | MACRO (USE_CXX11) 2 | IF (CMAKE_VERSION VERSION_LESS "3.1") 3 | SET (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") 4 | ELSE () 5 | SET (CMAKE_CXX_STANDARD 11) 6 | SET (CMAKE_CXX_STANDARD_REQUIRED ON) 7 | ENDIF () 8 | ENDMACRO (USE_CXX11) 9 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/cmake/subdirs.cmake: -------------------------------------------------------------------------------- 1 | FUNCTION (SUBDIRS) 2 | FOREACH (dir ${ARGV}) 3 | ADD_SUBDIRECTORY (${dir}) 4 | ENDFOREACH(dir) 5 | ENDFUNCTION (SUBDIRS) -------------------------------------------------------------------------------- /lib/clickhouse-cpp/contrib/cityhash/BUCK: -------------------------------------------------------------------------------- 1 | cxx_library( 2 | name = 'cityhash', 3 | header_namespace = 'cityhash', 4 | exported_headers = subdir_glob([ 5 | ('', '*.h'), 6 | ]), 7 | srcs = glob([ 8 | '*.cc', 9 | ]), 10 | visibility = [ 11 | '//...', 12 | ], 13 | ) 14 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/contrib/cityhash/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_LIBRARY (cityhash-lib STATIC 2 | city.cc 3 | ) 4 | 5 | set_property(TARGET cityhash-lib PROPERTY POSITION_INDEPENDENT_CODE ON) 6 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/contrib/cityhash/COPYING: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 Google, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/contrib/cityhash/city.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 Google, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | // 21 | // CityHash, by Geoff Pike and Jyrki Alakuijala 22 | // 23 | // This file provides a few functions for hashing strings. On x86-64 24 | // hardware in 2011, CityHash64() is faster than other high-quality 25 | // hash functions, such as Murmur. This is largely due to higher 26 | // instruction-level parallelism. CityHash64() and CityHash128() also perform 27 | // well on hash-quality tests. 28 | // 29 | // CityHash128() is optimized for relatively long strings and returns 30 | // a 128-bit hash. For strings more than about 2000 bytes it can be 31 | // faster than CityHash64(). 32 | // 33 | // Functions in the CityHash family are not suitable for cryptography. 34 | // 35 | // WARNING: This code has not been tested on big-endian platforms! 36 | // It is known to work well on little-endian platforms that have a small penalty 37 | // for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs. 38 | // 39 | // By the way, for some hash functions, given strings a and b, the hash 40 | // of a+b is easily derived from the hashes of a and b. This property 41 | // doesn't hold for any hash functions in this file. 42 | 43 | #ifndef CITY_HASH_H_ 44 | #define CITY_HASH_H_ 45 | 46 | #include // for size_t. 47 | #include 48 | #include 49 | 50 | typedef uint8_t uint8; 51 | typedef uint32_t uint32; 52 | typedef uint64_t uint64; 53 | typedef std::pair uint128; 54 | 55 | inline uint64 Uint128Low64(const uint128& x) { return x.first; } 56 | inline uint64 Uint128High64(const uint128& x) { return x.second; } 57 | 58 | // Hash function for a byte array. 59 | uint64 CityHash64(const char *buf, size_t len); 60 | 61 | // Hash function for a byte array. For convenience, a 64-bit seed is also 62 | // hashed into the result. 63 | uint64 CityHash64WithSeed(const char *buf, size_t len, uint64 seed); 64 | 65 | // Hash function for a byte array. For convenience, two seeds are also 66 | // hashed into the result. 67 | uint64 CityHash64WithSeeds(const char *buf, size_t len, 68 | uint64 seed0, uint64 seed1); 69 | 70 | // Hash function for a byte array. 71 | uint128 CityHash128(const char *s, size_t len); 72 | 73 | // Hash function for a byte array. For convenience, a 128-bit seed is also 74 | // hashed into the result. 75 | uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed); 76 | 77 | // Hash 128 input bits down to 64 bits of output. 78 | // This is intended to be a reasonably good hash function. 79 | inline uint64 Hash128to64(const uint128& x) { 80 | // Murmur-inspired hashing. 81 | const uint64 kMul = 0x9ddfea08eb382d69ULL; 82 | uint64 a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; 83 | a ^= (a >> 47); 84 | uint64 b = (Uint128High64(x) ^ a) * kMul; 85 | b ^= (b >> 47); 86 | b *= kMul; 87 | return b; 88 | } 89 | 90 | #endif // CITY_HASH_H_ 91 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/contrib/cityhash/citycrc.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 Google, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | // 21 | // CityHash, by Geoff Pike and Jyrki Alakuijala 22 | // 23 | // This file declares the subset of the CityHash functions that require 24 | // _mm_crc32_u64(). See the CityHash README for details. 25 | // 26 | // Functions in the CityHash family are not suitable for cryptography. 27 | 28 | #ifndef CITY_HASH_CRC_H_ 29 | #define CITY_HASH_CRC_H_ 30 | 31 | #include "city.h" 32 | 33 | // Hash function for a byte array. 34 | uint128 CityHashCrc128(const char *s, size_t len); 35 | 36 | // Hash function for a byte array. For convenience, a 128-bit seed is also 37 | // hashed into the result. 38 | uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed); 39 | 40 | // Hash function for a byte array. Sets result[0] ... result[3]. 41 | void CityHashCrc256(const char *s, size_t len, uint64 *result); 42 | 43 | #endif // CITY_HASH_CRC_H_ 44 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/contrib/cityhash/config.h: -------------------------------------------------------------------------------- 1 | /* config.h. Generated from config.h.in by configure. */ 2 | /* config.h.in. Generated from configure.ac by autoheader. */ 3 | 4 | /* Define if building universal (internal helper macro) */ 5 | /* #undef AC_APPLE_UNIVERSAL_BUILD */ 6 | 7 | /* Define to 1 if the compiler supports __builtin_expect. */ 8 | #if WIN32 || WIN64 9 | # define HAVE_BUILTIN_EXPECT 0 10 | #else 11 | # define HAVE_BUILTIN_EXPECT 1 12 | #endif 13 | 14 | /* Define to 1 if you have the header file. */ 15 | #define HAVE_DLFCN_H 1 16 | 17 | /* Define to 1 if you have the header file. */ 18 | #define HAVE_INTTYPES_H 1 19 | 20 | /* Define to 1 if you have the header file. */ 21 | #define HAVE_MEMORY_H 1 22 | 23 | /* Define to 1 if you have the header file. */ 24 | #define HAVE_STDINT_H 1 25 | 26 | /* Define to 1 if you have the header file. */ 27 | #define HAVE_STDLIB_H 1 28 | 29 | /* Define to 1 if you have the header file. */ 30 | #define HAVE_STRINGS_H 1 31 | 32 | /* Define to 1 if you have the header file. */ 33 | #define HAVE_STRING_H 1 34 | 35 | /* Define to 1 if you have the header file. */ 36 | #define HAVE_SYS_STAT_H 1 37 | 38 | /* Define to 1 if you have the header file. */ 39 | #define HAVE_SYS_TYPES_H 1 40 | 41 | /* Define to 1 if you have the header file. */ 42 | #define HAVE_UNISTD_H 1 43 | 44 | /* Define to the sub-directory in which libtool stores uninstalled libraries. 45 | */ 46 | #define LT_OBJDIR ".libs/" 47 | 48 | /* Define to the address where bug reports for this package should be sent. */ 49 | #define PACKAGE_BUGREPORT "cityhash-discuss@googlegroups.com" 50 | 51 | /* Define to the full name of this package. */ 52 | #define PACKAGE_NAME "CityHash" 53 | 54 | /* Define to the full name and version of this package. */ 55 | #define PACKAGE_STRING "CityHash 1.0.2" 56 | 57 | /* Define to the one symbol short name of this package. */ 58 | #define PACKAGE_TARNAME "cityhash" 59 | 60 | /* Define to the home page for this package. */ 61 | #define PACKAGE_URL "" 62 | 63 | /* Define to the version of this package. */ 64 | #define PACKAGE_VERSION "1.0.2" 65 | 66 | /* Define to 1 if you have the ANSI C header files. */ 67 | #define STDC_HEADERS 1 68 | 69 | /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most 70 | significant byte first (like Motorola and SPARC, unlike Intel). */ 71 | #if defined AC_APPLE_UNIVERSAL_BUILD 72 | # if defined __BIG_ENDIAN__ 73 | # define WORDS_BIGENDIAN 1 74 | # endif 75 | #else 76 | # ifndef WORDS_BIGENDIAN 77 | /* # undef WORDS_BIGENDIAN */ 78 | # endif 79 | #endif 80 | 81 | /* Define for Solaris 2.5.1 so the uint32_t typedef from , 82 | , or is not used. If the typedef were allowed, the 83 | #define below would cause a syntax error. */ 84 | /* #undef _UINT32_T */ 85 | 86 | /* Define for Solaris 2.5.1 so the uint64_t typedef from , 87 | , or is not used. If the typedef were allowed, the 88 | #define below would cause a syntax error. */ 89 | /* #undef _UINT64_T */ 90 | 91 | /* Define for Solaris 2.5.1 so the uint8_t typedef from , 92 | , or is not used. If the typedef were allowed, the 93 | #define below would cause a syntax error. */ 94 | /* #undef _UINT8_T */ 95 | 96 | /* Define to `__inline__' or `__inline' if that's what the C compiler 97 | calls it, or to nothing if 'inline' is not supported under any name. */ 98 | #ifndef __cplusplus 99 | /* #undef inline */ 100 | #endif 101 | 102 | /* Define to `unsigned int' if does not define. */ 103 | /* #undef size_t */ 104 | 105 | /* Define to `int' if does not define. */ 106 | /* #undef ssize_t */ 107 | 108 | /* Define to the type of an unsigned integer type of width exactly 32 bits if 109 | such a type exists and the standard includes do not define it. */ 110 | /* #undef uint32_t */ 111 | 112 | /* Define to the type of an unsigned integer type of width exactly 64 bits if 113 | such a type exists and the standard includes do not define it. */ 114 | /* #undef uint64_t */ 115 | 116 | /* Define to the type of an unsigned integer type of width exactly 8 bits if 117 | such a type exists and the standard includes do not define it. */ 118 | /* #undef uint8_t */ 119 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/contrib/gtest/BUCK: -------------------------------------------------------------------------------- 1 | cxx_library( 2 | name = 'gtest', 3 | # This is a bit weird, but this is how the tests use the headers... 4 | header_namespace = 'contrib/gtest', 5 | exported_headers = subdir_glob([ 6 | ('', '*.h'), 7 | ]), 8 | srcs = glob([ 9 | '*.cc', 10 | ]), 11 | visibility = [ 12 | '//...', 13 | ], 14 | ) 15 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/contrib/gtest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_LIBRARY (gtest-lib STATIC 2 | gtest-all.cc 3 | ) 4 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/contrib/lz4/BUCK: -------------------------------------------------------------------------------- 1 | cxx_library( 2 | name = 'lz4', 3 | header_namespace = 'lz4', 4 | exported_headers = subdir_glob([ 5 | ('', '*.h'), 6 | ]), 7 | srcs = glob([ 8 | '*.c', 9 | ]), 10 | visibility = [ 11 | '//...', 12 | ], 13 | ) 14 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/contrib/lz4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_LIBRARY (lz4-lib STATIC 2 | lz4.c 3 | lz4hc.c 4 | ) 5 | 6 | set_property(TARGET lz4-lib PROPERTY POSITION_INDEPENDENT_CODE ON) 7 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/contrib/lz4/LICENSE: -------------------------------------------------------------------------------- 1 | LZ4 Library 2 | Copyright (c) 2011-2014, Yann Collet 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, this 12 | list of conditions and the following disclaimer in the documentation and/or 13 | other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/tests/simple/BUCK: -------------------------------------------------------------------------------- 1 | cxx_binary( 2 | name = 'simple', 3 | srcs = [ 4 | 'main.cpp', 5 | ], 6 | compiler_flags = [ 7 | '-std=c++11', 8 | ], 9 | deps = [ 10 | '//:clickhouse-cpp', 11 | ], 12 | ) 13 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/tests/simple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_EXECUTABLE (simple-test 2 | main.cpp 3 | ) 4 | 5 | TARGET_LINK_LIBRARIES (simple-test 6 | clickhouse-cpp-lib 7 | ) -------------------------------------------------------------------------------- /lib/clickhouse-cpp/ut/BUCK: -------------------------------------------------------------------------------- 1 | cxx_test( 2 | name = 'ut', 3 | srcs = glob([ 4 | '*.cpp', 5 | ]), 6 | compiler_flags = [ 7 | '-std=c++11', 8 | ], 9 | deps = [ 10 | '//:clickhouse-cpp', 11 | ], 12 | ) 13 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/ut/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_EXECUTABLE (clickhouse-cpp-ut 2 | main.cpp 3 | 4 | columns_ut.cpp 5 | types_ut.cpp 6 | type_parser_ut.cpp 7 | client_ut.cpp 8 | ) 9 | 10 | TARGET_LINK_LIBRARIES (clickhouse-cpp-ut 11 | clickhouse-cpp-lib 12 | gtest-lib 13 | ) 14 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/ut/columns_ut.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | using namespace clickhouse; 12 | 13 | static std::vector MakeNumbers() { 14 | return std::vector 15 | {1, 2, 3, 7, 11, 13, 17, 19, 23, 29, 31}; 16 | } 17 | 18 | static std::vector MakeBools() { 19 | return std::vector 20 | {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0}; 21 | } 22 | 23 | static std::vector MakeFixedStrings() { 24 | return std::vector 25 | {"aaa", "bbb", "ccc", "ddd"}; 26 | } 27 | 28 | static std::vector MakeStrings() { 29 | return std::vector 30 | {"a", "ab", "abc", "abcd"}; 31 | } 32 | 33 | static std::vector MakeUUIDs() { 34 | return std::vector 35 | {0xbb6a8c699ab2414cllu, 0x86697b7fd27f0825llu, 36 | 0x84b9f24bc26b49c6llu, 0xa03b4ab723341951llu, 37 | 0x3507213c178649f9llu, 0x9faf035d662f60aellu}; 38 | } 39 | 40 | 41 | TEST(ColumnsCase, NumericInit) { 42 | auto col = std::make_shared(MakeNumbers()); 43 | 44 | ASSERT_EQ(col->Size(), 11u); 45 | ASSERT_EQ(col->At(3), 7u); 46 | ASSERT_EQ(col->At(10), 31u); 47 | 48 | auto sun = std::make_shared(MakeNumbers()); 49 | } 50 | 51 | TEST(ColumnsCase, NumericSlice) { 52 | auto col = std::make_shared(MakeNumbers()); 53 | auto sub = col->Slice(3, 3)->As(); 54 | 55 | ASSERT_EQ(sub->Size(), 3u); 56 | ASSERT_EQ(sub->At(0), 7u); 57 | ASSERT_EQ(sub->At(2), 13u); 58 | } 59 | 60 | 61 | TEST(ColumnsCase, FixedStringInit) { 62 | auto col = std::make_shared(3); 63 | for (const auto& s : MakeFixedStrings()) { 64 | col->Append(s); 65 | } 66 | 67 | ASSERT_EQ(col->Size(), 4u); 68 | ASSERT_EQ(col->At(1), "bbb"); 69 | ASSERT_EQ(col->At(3), "ddd"); 70 | } 71 | 72 | TEST(ColumnsCase, StringInit) { 73 | auto col = std::make_shared(MakeStrings()); 74 | 75 | ASSERT_EQ(col->Size(), 4u); 76 | ASSERT_EQ(col->At(1), "ab"); 77 | ASSERT_EQ(col->At(3), "abcd"); 78 | } 79 | 80 | 81 | TEST(ColumnsCase, ArrayAppend) { 82 | auto arr1 = std::make_shared(std::make_shared()); 83 | auto arr2 = std::make_shared(std::make_shared()); 84 | 85 | auto id = std::make_shared(); 86 | id->Append(1); 87 | arr1->AppendAsColumn(id); 88 | 89 | id->Append(3); 90 | arr2->AppendAsColumn(id); 91 | 92 | arr1->Append(arr2); 93 | 94 | auto col = arr1->GetAsColumn(1); 95 | 96 | ASSERT_EQ(arr1->Size(), 2u); 97 | //ASSERT_EQ(col->As()->At(0), 1u); 98 | //ASSERT_EQ(col->As()->At(1), 3u); 99 | } 100 | 101 | TEST(ColumnsCase, DateAppend) { 102 | auto col1 = std::make_shared(); 103 | auto col2 = std::make_shared(); 104 | auto now = std::time(nullptr); 105 | 106 | col1->Append(now); 107 | col2->Append(col1); 108 | 109 | ASSERT_EQ(col2->Size(), 1u); 110 | ASSERT_EQ(col2->At(0), (now / 86400) * 86400); 111 | } 112 | 113 | TEST(ColumnsCase, EnumTest) { 114 | std::vector enum_items = {{"Hi", 1}, {"Hello", 2}}; 115 | 116 | auto col = std::make_shared(Type::CreateEnum8(enum_items)); 117 | ASSERT_TRUE(col->Type()->IsEqual(Type::CreateEnum8(enum_items))); 118 | 119 | col->Append(1); 120 | ASSERT_EQ(col->Size(), 1u); 121 | ASSERT_EQ(col->At(0), 1); 122 | ASSERT_EQ(col->NameAt(0), "Hi"); 123 | 124 | col->Append("Hello"); 125 | ASSERT_EQ(col->Size(), 2u); 126 | ASSERT_EQ(col->At(1), 2); 127 | ASSERT_EQ(col->NameAt(1), "Hello"); 128 | 129 | auto col16 = std::make_shared(Type::CreateEnum16(enum_items)); 130 | ASSERT_TRUE(col16->Type()->IsEqual(Type::CreateEnum16(enum_items))); 131 | } 132 | 133 | TEST(ColumnsCase, NullableSlice) { 134 | auto data = std::make_shared(MakeNumbers()); 135 | auto nulls = std::make_shared(MakeBools()); 136 | auto col = std::make_shared(data, nulls); 137 | auto sub = col->Slice(3, 4)->As(); 138 | auto subData = sub->Nested()->As(); 139 | 140 | ASSERT_EQ(sub->Size(), 4u); 141 | ASSERT_FALSE(sub->IsNull(0)); 142 | ASSERT_EQ(subData->At(0), 7u); 143 | ASSERT_TRUE(sub->IsNull(1)); 144 | ASSERT_FALSE(sub->IsNull(3)); 145 | ASSERT_EQ(subData->At(3), 17u); 146 | } 147 | 148 | TEST(ColumnsCase, UUIDInit) { 149 | auto col = std::make_shared(std::make_shared(MakeUUIDs())); 150 | 151 | ASSERT_EQ(col->Size(), 3u); 152 | ASSERT_EQ(col->At(0), UInt128(0xbb6a8c699ab2414cllu, 0x86697b7fd27f0825llu)); 153 | ASSERT_EQ(col->At(2), UInt128(0x3507213c178649f9llu, 0x9faf035d662f60aellu)); 154 | } 155 | 156 | TEST(ColumnsCase, UUIDSlice) { 157 | auto col = std::make_shared(std::make_shared(MakeUUIDs())); 158 | auto sub = col->Slice(1, 2)->As(); 159 | 160 | ASSERT_EQ(sub->Size(), 2u); 161 | ASSERT_EQ(sub->At(0), UInt128(0x84b9f24bc26b49c6llu, 0xa03b4ab723341951llu)); 162 | ASSERT_EQ(sub->At(1), UInt128(0x3507213c178649f9llu, 0x9faf035d662f60aellu)); 163 | } 164 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/ut/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) { 4 | ::testing::InitGoogleTest(&argc, argv); 5 | return RUN_ALL_TESTS(); 6 | } 7 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/ut/type_parser_ut.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace clickhouse; 5 | 6 | TEST(TypeParserCase, ParseTerminals) { 7 | TypeAst ast; 8 | TypeParser("UInt8").Parse(&ast); 9 | 10 | ASSERT_EQ(ast.meta, TypeAst::Terminal); 11 | ASSERT_EQ(ast.name, "UInt8"); 12 | ASSERT_EQ(ast.code, Type::UInt8); 13 | } 14 | 15 | TEST(TypeParserCase, ParseFixedString) { 16 | TypeAst ast; 17 | TypeParser("FixedString(24)").Parse(&ast); 18 | 19 | ASSERT_EQ(ast.meta, TypeAst::Terminal); 20 | ASSERT_EQ(ast.name, "FixedString"); 21 | ASSERT_EQ(ast.code, Type::FixedString); 22 | ASSERT_EQ(ast.elements.front().value, 24U); 23 | } 24 | 25 | TEST(TypeParserCase, ParseArray) { 26 | TypeAst ast; 27 | TypeParser("Array(Int32)").Parse(&ast); 28 | 29 | ASSERT_EQ(ast.meta, TypeAst::Array); 30 | ASSERT_EQ(ast.name, "Array"); 31 | ASSERT_EQ(ast.code, Type::Array); 32 | ASSERT_EQ(ast.elements.front().meta, TypeAst::Terminal); 33 | ASSERT_EQ(ast.elements.front().name, "Int32"); 34 | } 35 | 36 | TEST(TypeParserCase, ParseNullable) { 37 | TypeAst ast; 38 | TypeParser("Nullable(Date)").Parse(&ast); 39 | 40 | ASSERT_EQ(ast.meta, TypeAst::Nullable); 41 | ASSERT_EQ(ast.name, "Nullable"); 42 | ASSERT_EQ(ast.code, Type::Nullable); 43 | ASSERT_EQ(ast.elements.front().meta, TypeAst::Terminal); 44 | ASSERT_EQ(ast.elements.front().name, "Date"); 45 | } 46 | 47 | TEST(TypeParserCase, ParseEnum) { 48 | TypeAst ast; 49 | TypeParser( 50 | "Enum8('COLOR_red_10_T' = -12, 'COLOR_green_20_T'=-25, 'COLOR_blue_30_T'= 53, 'COLOR_black_30_T' = 107") 51 | .Parse(&ast); 52 | ASSERT_EQ(ast.meta, TypeAst::Enum); 53 | ASSERT_EQ(ast.name, "Enum8"); 54 | ASSERT_EQ(ast.code, Type::Enum8); 55 | ASSERT_EQ(ast.elements.size(), 4u); 56 | 57 | std::vector names = {"COLOR_red_10_T", "COLOR_green_20_T", "COLOR_blue_30_T", "COLOR_black_30_T"}; 58 | std::vector values = {-12, -25, 53, 107}; 59 | 60 | auto element = ast.elements.begin(); 61 | for (size_t i = 0; i < 4; ++i) { 62 | ASSERT_EQ(element->name, names[i]); 63 | ASSERT_EQ(element->code, Type::Void); 64 | ASSERT_EQ(element->value, values[i]); 65 | ++element; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/clickhouse-cpp/ut/types_ut.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace clickhouse; 5 | 6 | TEST(TypesCase, TypeName) { 7 | ASSERT_EQ( 8 | Type::CreateDate()->GetName(), 9 | "Date" 10 | ); 11 | 12 | ASSERT_EQ( 13 | Type::CreateArray(Type::CreateSimple())->GetName(), 14 | "Array(Int32)" 15 | ); 16 | 17 | ASSERT_EQ( 18 | Type::CreateNullable(Type::CreateSimple())->GetName(), 19 | "Nullable(Int32)" 20 | ); 21 | 22 | ASSERT_EQ( 23 | Type::CreateArray(Type::CreateSimple())->GetItemType()->GetCode(), 24 | Type::Int32 25 | ); 26 | 27 | ASSERT_EQ( 28 | Type::CreateTuple({ 29 | Type::CreateSimple(), 30 | Type::CreateString()})->GetName(), 31 | "Tuple(Int32, String)" 32 | ); 33 | } 34 | 35 | TEST(TypesCase, NullableType) { 36 | TypeRef nested = Type::CreateSimple(); 37 | ASSERT_EQ( 38 | Type::CreateNullable(nested)->GetNestedType(), 39 | nested 40 | ); 41 | } 42 | 43 | TEST(TypesCase, EnumTypes) { 44 | EnumType enum8(Type::CreateEnum8({{"One", 1}, {"Two", 2}})); 45 | ASSERT_EQ(enum8.GetName(), "Enum8('One' = 1, 'Two' = 2)"); 46 | ASSERT_TRUE(enum8.HasEnumValue(1)); 47 | ASSERT_TRUE(enum8.HasEnumName("Two")); 48 | ASSERT_FALSE(enum8.HasEnumValue(10)); 49 | ASSERT_FALSE(enum8.HasEnumName("Ten")); 50 | ASSERT_EQ(enum8.GetEnumName(2), "Two"); 51 | ASSERT_EQ(enum8.GetEnumValue("Two"), 2); 52 | 53 | EnumType enum16(Type::CreateEnum16({{"Green", 1}, {"Red", 2}, {"Yellow", 3}})); 54 | ASSERT_EQ(enum16.GetName(), "Enum16('Green' = 1, 'Red' = 2, 'Yellow' = 3)"); 55 | ASSERT_TRUE(enum16.HasEnumValue(3)); 56 | ASSERT_TRUE(enum16.HasEnumName("Green")); 57 | ASSERT_FALSE(enum16.HasEnumValue(10)); 58 | ASSERT_FALSE(enum16.HasEnumName("Black")); 59 | ASSERT_EQ(enum16.GetEnumName(2), "Red"); 60 | ASSERT_EQ(enum16.GetEnumValue("Green"), 1); 61 | 62 | ASSERT_EQ(std::distance(enum16.BeginValueToName(), enum16.EndValueToName()), 3u); 63 | ASSERT_EQ((*enum16.BeginValueToName()).first, 1); 64 | ASSERT_EQ((*enum16.BeginValueToName()).second, "Green"); 65 | ASSERT_EQ((*(++enum16.BeginValueToName())).first, 2); 66 | ASSERT_EQ((*(++enum16.BeginValueToName())).second, "Red"); 67 | } 68 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | SeasClick 4 | pecl.php.net 5 | An Yandex ClickHouse client driven extension for PHP. 6 | 7 | PHP client for Yandex ClickHouse,Based on ClickHouse C++ client. 8 | 9 | 10 | Chitao Gao 11 | neeke 12 | neeke@php.net 13 | yes 14 | 15 | 2023-02-24 16 | 17 | 18 | 0.1.1 19 | 0.1.1 20 | 21 | 22 | stable 23 | stable 24 | 25 | PHP3.01 26 | 27 | - Support PHP8.X version for pecl.net 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 7.0.0 159 | 160 | 161 | 1.4.0 162 | 163 | 164 | 165 | SeasClick 166 | 167 | 168 | - Support PHP8.X version for pecl.net 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /php7_wrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | SeasClick | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2018 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: SeasX Group | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | 20 | // PHP7.4 + 21 | #if !defined(ZEND_ACC_IMPLICIT_PUBLIC) 22 | # define ZEND_ACC_IMPLICIT_PUBLIC ZEND_ACC_PUBLIC 23 | #endif 24 | 25 | 26 | // PHP8+ 27 | #if !defined(ZEND_ACC_DTOR) 28 | #define ZEND_ACC_DTOR 0x4000 29 | #endif 30 | 31 | // PHP5+ 32 | #if PHP_MAJOR_VERSION <7 33 | 34 | #if PHP_VERSION_ID < 50500 35 | #define sc_zend_throw_exception(a, b, c) zend_throw_exception(a, (char *)b, c) 36 | #else 37 | #define sc_zend_throw_exception zend_throw_exception 38 | #endif 39 | 40 | #define sc_zend_throw_exception_tsrmls_cc sc_zend_throw_exception 41 | #define IS_TRUE 1 42 | #define SC_MAKE_STD_ZVAL(p) MAKE_STD_ZVAL(p) 43 | #define SC_RETURN_STRINGL(k, l) RETURN_STRINGL(k, l, 1) 44 | #define sc_zval_ptr_dtor zval_ptr_dtor 45 | #define sc_zval_add_ref(a) zval_add_ref(&a) 46 | static inline int sc_add_assoc_long_ex(zval *arg, const char *key, size_t key_len, long value) 47 | { 48 | return add_assoc_long_ex(arg, key, key_len + 1, value); 49 | } 50 | 51 | static inline int sc_add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double value) 52 | { 53 | return add_assoc_double_ex(arg, key, key_len + 1, value); 54 | } 55 | 56 | static inline int sc_add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval* value) 57 | { 58 | return add_assoc_zval_ex(arg, key, key_len + 1, value); 59 | } 60 | 61 | static inline int sc_add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, char *str, size_t length, int __duplicate) 62 | { 63 | return add_assoc_stringl_ex(arg, key, key_len + 1, str, length, __duplicate); 64 | } 65 | 66 | static inline int sc_add_assoc_null_ex(zval *arg, const char *key, size_t key_len) 67 | { 68 | return add_assoc_null_ex(arg, key, key_len + 1); 69 | } 70 | 71 | static inline zval *sc_zend_hash_find(HashTable *ht, char *k, int len) 72 | { 73 | zval **tmp = NULL; 74 | if (zend_hash_find(ht, k, len + 1, (void **) &tmp) == SUCCESS) 75 | { 76 | return *tmp; 77 | } 78 | else 79 | { 80 | return NULL; 81 | } 82 | } 83 | 84 | static inline zval *sc_zend_hash_index_find(HashTable *ht, ulong h) 85 | { 86 | zval **tmp = NULL; 87 | if (zend_hash_index_find(ht, h, (void **) &tmp) == SUCCESS) 88 | { 89 | return *tmp; 90 | } 91 | else 92 | { 93 | return NULL; 94 | } 95 | } 96 | 97 | #define sc_zend_update_property_string zend_update_property_string 98 | 99 | #define sc_zend_read_property(a, b, c, d, e) zend_read_property(a, b, c, d, e TSRMLS_CC) 100 | 101 | #define SC_HASHTABLE_FOREACH_START2(ht, k, klen, ktype, entry)\ 102 | zval **tmp = NULL; ulong_t idx;\ 103 | for (zend_hash_internal_pointer_reset(ht); \ 104 | (ktype = zend_hash_get_current_key_ex(ht, &k, &klen, &idx, 0, NULL)) != HASH_KEY_NON_EXISTANT; \ 105 | zend_hash_move_forward(ht)\ 106 | ) { \ 107 | if (zend_hash_get_current_data(ht, (void**)&tmp) == FAILURE) {\ 108 | continue;\ 109 | }\ 110 | entry = *tmp;\ 111 | klen --; 112 | 113 | #define SC_HASHTABLE_FOREACH_END() } 114 | 115 | #define sc_add_next_index_stringl add_next_index_stringl 116 | #define sc_zend_hash_get_current_data zend_hash_get_current_data 117 | #else 118 | // PHP7 119 | #define sc_zend_throw_exception zend_throw_exception 120 | #define sc_zend_hash_find zend_hash_str_find 121 | #define sc_zend_hash_index_find zend_hash_index_find 122 | #define SC_MAKE_STD_ZVAL(p) zval _stack_zval_##p; p = &(_stack_zval_##p) 123 | #define SC_RETURN_STRINGL(k, l) RETURN_STRINGL(k, l) 124 | #define sc_zval_ptr_dtor(p) zval_ptr_dtor(*p) 125 | #define sc_zval_add_ref(p) Z_TRY_ADDREF_P(p) 126 | #define sc_add_assoc_long_ex add_assoc_long_ex 127 | #define sc_add_assoc_double_ex add_assoc_double_ex 128 | #define sc_add_assoc_zval_ex add_assoc_zval_ex 129 | #define sc_add_assoc_stringl_ex(a, b, c, d, e, f) add_assoc_stringl_ex(a, b, c, d, e) 130 | #define sc_add_assoc_null_ex(a, b, c) add_assoc_null_ex(a, b, c) 131 | 132 | 133 | 134 | #if PHP_VERSION_ID < 80000 135 | #define sc_zend_throw_exception_tsrmls_cc(a, b, c) sc_zend_throw_exception(a, b, c TSRMLS_CC) 136 | #else 137 | #define sc_zend_throw_exception_tsrmls_cc(a, b, c) sc_zend_throw_exception(a, b, c) 138 | #endif 139 | 140 | 141 | static inline zval* sc_zend_read_property(zend_class_entry *class_ptr, zval *obj, const char *s, int len, int silent) 142 | { 143 | zval rv; 144 | #if PHP_VERSION_ID < 80000 145 | return zend_read_property(class_ptr, obj, s, len, silent, &rv); 146 | #else 147 | zend_object *zendObject; 148 | zendObject=Z_OBJ_P(obj); 149 | return zend_read_property(class_ptr, zendObject, s, len, silent, &rv); 150 | #endif 151 | 152 | } 153 | 154 | 155 | static inline void sc_zend_update_property_string( zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value) 156 | { 157 | #if PHP_VERSION_ID < 80000 158 | return zend_update_property_string(scope, object, name, name_length, value TSRMLS_CC); 159 | #else 160 | zend_object *zendObject; 161 | zendObject=Z_OBJ_P(object); 162 | return zend_update_property_string(scope, zendObject, name, name_length, value); 163 | #endif 164 | } 165 | 166 | 167 | static inline void sc_zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value) 168 | { 169 | #if PHP_VERSION_ID < 80000 170 | return zend_update_property_long(scope, object, name, name_length, value TSRMLS_CC); 171 | #else 172 | zend_object *zendObject; 173 | zendObject=Z_OBJ_P(object); 174 | return zend_update_property_long(scope, zendObject, name, name_length, value); 175 | #endif 176 | } 177 | 178 | static inline void sc_zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value) /* {{{ */ 179 | { 180 | #if PHP_VERSION_ID < 80000 181 | return zend_update_property_bool(scope, object, name, name_length, value TSRMLS_CC); 182 | #else 183 | zend_object *zendObject; 184 | zendObject=Z_OBJ_P(object); 185 | return zend_update_property_bool(scope, zendObject, name, name_length, value); 186 | #endif 187 | } 188 | 189 | #define SC_HASHTABLE_FOREACH_START2(ht, k, klen, ktype, _val) zend_string *_foreach_key;\ 190 | ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _foreach_key, _val);\ 191 | if (!_foreach_key) {k = NULL; klen = 0; ktype = 0;}\ 192 | else {k = _foreach_key->val, klen=_foreach_key->len; ktype = 1;} { 193 | 194 | #define SC_HASHTABLE_FOREACH_END() } ZEND_HASH_FOREACH_END(); 195 | 196 | #define sc_add_next_index_stringl(arr, str, len, dup) add_next_index_stringl(arr, str, len) 197 | 198 | static inline int sc_zend_hash_get_current_data(HashTable *ht, void **v) 199 | { 200 | zval *value = zend_hash_get_current_data(ht); 201 | if (value == NULL) 202 | { 203 | return FAILURE; 204 | } 205 | else 206 | { 207 | *v = (void *) value; 208 | return SUCCESS; 209 | } 210 | } 211 | #endif 212 | 213 | #define php_array_get_value(ht, str, v) ((v = sc_zend_hash_find(ht, (char *)str, sizeof(str)-1)) && !ZVAL_IS_NULL(v)) 214 | 215 | /* 216 | * Local variables: 217 | * tab-width: 4 218 | * c-basic-offset: 4 219 | * End: 220 | * vim600: noet sw=4 ts=4 fdm=marker 221 | * vim<600: noet sw=4 ts=4 222 | */ 223 | -------------------------------------------------------------------------------- /php_SeasClick.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | SeasClick | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2018 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: SeasX Group | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | #ifdef __cplusplus 19 | #define __STDC_FORMAT_MACROS 20 | #endif 21 | 22 | #ifndef PHP_SEASCLICK_H 23 | #define PHP_SEASCLICK_H 24 | 25 | extern zend_module_entry SeasClick_module_entry; 26 | #define phpext_SeasClick_ptr &SeasClick_module_entry 27 | 28 | #define PHP_SEASCLICK_VERSION "0.1.1" 29 | 30 | #ifdef PHP_WIN32 31 | # define PHP_SEASCLICK_API __declspec(dllexport) 32 | #elif defined(__GNUC__) && __GNUC__ >= 4 33 | # define PHP_SEASCLICK_API __attribute__ ((visibility("default"))) 34 | #else 35 | # define PHP_SEASCLICK_API 36 | #endif 37 | 38 | extern "C" { 39 | #ifdef ZTS 40 | #include "TSRM.h" 41 | #endif 42 | } 43 | 44 | typedef unsigned long ulong_t; 45 | 46 | #ifdef ZTS 47 | #define SEASCLICK_G(v) TSRMG(SeasClick_globals_id, zend_SeasClick_globals *, v) 48 | #else 49 | #define SEASCLICK_G(v) (SeasClick_globals.v) 50 | #endif 51 | 52 | #define SEASCLICK_RES_NAME "SeasClick" 53 | 54 | #endif /* PHP_SEASCLICK_H */ 55 | 56 | /* 57 | * Local variables: 58 | * tab-width: 4 59 | * c-basic-offset: 4 60 | * End: 61 | * vim600: noet sw=4 ts=4 fdm=marker 62 | * vim<600: noet sw=4 ts=4 63 | */ 64 | -------------------------------------------------------------------------------- /tests/001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for SeasClick presence 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 20 | --EXPECT-- 21 | SeasClick extension is available 22 | -------------------------------------------------------------------------------- /tests/002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SeasClick testArray 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | "clickhouse", 9 | "port" => "9000", 10 | "compression" => true 11 | ]; 12 | 13 | clientTest($config); 14 | 15 | function clientTest($config) 16 | { 17 | $deleteTable = true; 18 | $client = new SeasClick($config); 19 | $client->execute("CREATE DATABASE IF NOT EXISTS test"); 20 | 21 | testArray($client, $deleteTable); 22 | } 23 | 24 | function testArray($client, $deleteTable = false) { 25 | $client->execute("CREATE TABLE IF NOT EXISTS test.array_test (string_c String, array_c Array(Int8), arraynull_c Array(Nullable(String))) ENGINE = Memory"); 26 | 27 | $client->insert("test.array_test", [ 28 | 'string_c', 'array_c', 'arraynull_c' 29 | ], [ 30 | [ 31 | 'string_c1', [1, 2, 3], ['string'] 32 | ], 33 | [ 34 | 'string_c2', [4, 5, 6], [null] 35 | ] 36 | ]); 37 | 38 | $result = $client->select("SELECT {select} FROM {table}", [ 39 | 'select' => 'string_c, array_c, arraynull_c', 40 | 'table' => 'test.array_test' 41 | ]); 42 | var_dump($result); 43 | 44 | if ($deleteTable) { 45 | $client->execute("DROP TABLE {table}", [ 46 | 'table' => 'test.array_test' 47 | ]); 48 | } 49 | } 50 | 51 | ?> 52 | --EXPECT-- 53 | array(2) { 54 | [0]=> 55 | array(3) { 56 | ["string_c"]=> 57 | string(9) "string_c1" 58 | ["array_c"]=> 59 | array(3) { 60 | [0]=> 61 | int(1) 62 | [1]=> 63 | int(2) 64 | [2]=> 65 | int(3) 66 | } 67 | ["arraynull_c"]=> 68 | array(1) { 69 | ["array"]=> 70 | string(6) "string" 71 | } 72 | } 73 | [1]=> 74 | array(3) { 75 | ["string_c"]=> 76 | string(9) "string_c2" 77 | ["array_c"]=> 78 | array(3) { 79 | [0]=> 80 | int(4) 81 | [1]=> 82 | int(5) 83 | [2]=> 84 | int(6) 85 | } 86 | ["arraynull_c"]=> 87 | array(1) { 88 | [0]=> 89 | NULL 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /tests/003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SeasClick testEnum 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | "clickhouse", 9 | "port" => "9000", 10 | "compression" => true 11 | ]; 12 | 13 | clientTest($config); 14 | 15 | function clientTest($config) 16 | { 17 | $deleteTable = true; 18 | $client = new SeasClick($config); 19 | $client->execute("CREATE DATABASE IF NOT EXISTS test"); 20 | 21 | testEnum($client, $deleteTable); 22 | } 23 | 24 | function testEnum($client, $deleteTable = false) { 25 | $client->execute("CREATE TABLE IF NOT EXISTS test.enum_test (enum8_c Enum8('One8' = 1, 'Two8' = 2), enum16_c Enum16('One16' = 1, 'Two16' = 2)) ENGINE = Memory"); 26 | 27 | $client->insert("test.enum_test", [ 28 | 'enum8_c', 'enum16_c' 29 | ],[ 30 | [1, 'Two16'], 31 | ['Two8', 1] 32 | ]); 33 | 34 | $result = $client->select("SELECT {select} FROM {table}", [ 35 | 'select' => 'enum8_c, enum16_c', 36 | 'table' => 'test.enum_test' 37 | ]); 38 | var_dump($result); 39 | 40 | if ($deleteTable) { 41 | $client->execute("DROP TABLE {table}", [ 42 | 'table' => 'test.enum_test' 43 | ]); 44 | } 45 | } 46 | 47 | ?> 48 | --EXPECT-- 49 | array(2) { 50 | [0]=> 51 | array(2) { 52 | ["enum8_c"]=> 53 | string(4) "One8" 54 | ["enum16_c"]=> 55 | string(5) "Two16" 56 | } 57 | [1]=> 58 | array(2) { 59 | ["enum8_c"]=> 60 | string(4) "Two8" 61 | ["enum16_c"]=> 62 | string(5) "One16" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tests/004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SeasClick testString 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | "clickhouse", 9 | "port" => "9000", 10 | "compression" => true 11 | ]; 12 | 13 | clientTest($config); 14 | 15 | function clientTest($config) 16 | { 17 | $deleteTable = true; 18 | $client = new SeasClick($config); 19 | $client->execute("CREATE DATABASE IF NOT EXISTS test"); 20 | 21 | testString($client, $deleteTable); 22 | } 23 | 24 | function testString($client, $deleteTable = false) { 25 | $client->execute("CREATE TABLE IF NOT EXISTS test.string_test (string_c String, fixedstring_c FixedString(50)) ENGINE = Memory"); 26 | 27 | $client->insert("test.string_test", [ 28 | 'string_c', 'fixedstring_c' 29 | ], [ 30 | [ 31 | 'string_c1', 32 | 'fixedstring_c1' 33 | ], 34 | [ 35 | 'string_c2', 36 | 'fixedstring_c2' 37 | ] 38 | ]); 39 | 40 | $result = $client->select("SELECT {select} FROM {table}", [ 41 | 'select' => 'string_c, fixedstring_c', 42 | 'table' => 'test.string_test' 43 | ]); 44 | var_dump($result); 45 | 46 | if ($deleteTable) { 47 | $client->execute("DROP TABLE {table}", [ 48 | 'table' => 'test.string_test' 49 | ]); 50 | } 51 | } 52 | 53 | ?> 54 | --EXPECT-- 55 | array(2) { 56 | [0]=> 57 | array(2) { 58 | ["string_c"]=> 59 | string(9) "string_c1" 60 | ["fixedstring_c"]=> 61 | string(14) "fixedstring_c1" 62 | } 63 | [1]=> 64 | array(2) { 65 | ["string_c"]=> 66 | string(9) "string_c2" 67 | ["fixedstring_c"]=> 68 | string(14) "fixedstring_c2" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SeasClick testNullAble 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | "clickhouse", 9 | "port" => "9000", 10 | "compression" => true 11 | ]; 12 | 13 | clientTest($config); 14 | 15 | function clientTest($config) 16 | { 17 | $deleteTable = true; 18 | $client = new SeasClick($config); 19 | $client->execute("CREATE DATABASE IF NOT EXISTS test"); 20 | 21 | testNullAble($client, $deleteTable); 22 | } 23 | 24 | function testNullAble($client, $deleteTable = false) { 25 | $client->execute("CREATE TABLE IF NOT EXISTS test.nullable_test (int8null_c Nullable(Int8), stringnull_c Nullable(String), enumnull_c Nullable(Enum8('One8' = 1, 'Two8' = 2)), float32null_c Nullable(Float32), uuidnull_c Nullable(UUID)) ENGINE = Memory"); 26 | 27 | $client->insert("test.nullable_test",[ 28 | 'int8null_c', 29 | 'stringnull_c', 30 | 'enumnull_c', 31 | 'float32null_c', 32 | 'uuidnull_c' 33 | ], [ 34 | [8, 'string', 'One8', 32, '31249a1b7b0542709f37c609b48a9bb2'], 35 | [null, null, null, null, null], 36 | ]); 37 | 38 | $result = $client->select("SELECT {select} FROM {table}", [ 39 | 'select' => 'int8null_c, stringnull_c, enumnull_c, float32null_c, uuidnull_c', 40 | 'table' => 'test.nullable_test' 41 | ]); 42 | var_dump($result); 43 | 44 | if ($deleteTable) { 45 | $client->execute("DROP TABLE {table}", [ 46 | 'table' => 'test.nullable_test' 47 | ]); 48 | } 49 | } 50 | 51 | ?> 52 | --EXPECT-- 53 | array(2) { 54 | [0]=> 55 | array(5) { 56 | ["int8null_c"]=> 57 | int(8) 58 | ["stringnull_c"]=> 59 | string(6) "string" 60 | ["enumnull_c"]=> 61 | string(4) "One8" 62 | ["float32null_c"]=> 63 | float(32) 64 | ["uuidnull_c"]=> 65 | string(32) "31249a1b7b0542709f37c609b48a9bb2" 66 | } 67 | [1]=> 68 | array(5) { 69 | ["int8null_c"]=> 70 | NULL 71 | ["stringnull_c"]=> 72 | NULL 73 | ["enumnull_c"]=> 74 | NULL 75 | ["float32null_c"]=> 76 | NULL 77 | ["uuidnull_c"]=> 78 | NULL 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tests/006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SeasClick testInt 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | "clickhouse", 9 | "port" => "9000", 10 | "compression" => true 11 | ]; 12 | 13 | clientTest($config); 14 | 15 | function clientTest($config) 16 | { 17 | $deleteTable = true; 18 | $client = new SeasClick($config); 19 | $client->execute("CREATE DATABASE IF NOT EXISTS test"); 20 | 21 | testUInt($client, $deleteTable); 22 | } 23 | 24 | function testUInt($client, $deleteTable = false) { 25 | $client->execute("CREATE TABLE IF NOT EXISTS test.int_test (int8_c Int8, int16_c Int16, uint8_c UInt8, uint16_c UInt16) ENGINE = Memory"); 26 | 27 | $client->insert("test.int_test",[ 28 | 'int8_c','int16_c','uint8_c','uint16_c' 29 | ], [ 30 | [8, 8, 8, 8], 31 | [9, 9, 9, 9], 32 | ]); 33 | 34 | $client->writeStart("test.int_test", [ 35 | 'int8_c','int16_c','uint8_c' 36 | ]); 37 | $client->write([ 38 | [8, 8, 8], 39 | [9, 9, 9], 40 | ]); 41 | $client->writeEnd(); 42 | 43 | $result = $client->select("SELECT {select} FROM {table}", [ 44 | 'select' => 'int8_c, int16_c, uint8_c, uint16_c', 45 | 'table' => 'test.int_test' 46 | ]); 47 | var_dump($result); 48 | 49 | if ($deleteTable) { 50 | $client->execute("DROP TABLE {table}", [ 51 | 'table' => 'test.int_test' 52 | ]); 53 | } 54 | } 55 | 56 | ?> 57 | --EXPECT-- 58 | array(4) { 59 | [0]=> 60 | array(4) { 61 | ["int8_c"]=> 62 | int(8) 63 | ["int16_c"]=> 64 | int(8) 65 | ["uint8_c"]=> 66 | int(8) 67 | ["uint16_c"]=> 68 | int(8) 69 | } 70 | [1]=> 71 | array(4) { 72 | ["int8_c"]=> 73 | int(9) 74 | ["int16_c"]=> 75 | int(9) 76 | ["uint8_c"]=> 77 | int(9) 78 | ["uint16_c"]=> 79 | int(9) 80 | } 81 | [2]=> 82 | array(4) { 83 | ["int8_c"]=> 84 | int(8) 85 | ["int16_c"]=> 86 | int(8) 87 | ["uint8_c"]=> 88 | int(8) 89 | ["uint16_c"]=> 90 | int(0) 91 | } 92 | [3]=> 93 | array(4) { 94 | ["int8_c"]=> 95 | int(9) 96 | ["int16_c"]=> 97 | int(9) 98 | ["uint8_c"]=> 99 | int(9) 100 | ["uint16_c"]=> 101 | int(0) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /tests/007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SeasClick testFloat 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | "clickhouse", 9 | "port" => "9000", 10 | "compression" => true 11 | ]; 12 | 13 | clientTest($config); 14 | 15 | function clientTest($config) 16 | { 17 | $deleteTable = true; 18 | $client = new SeasClick($config); 19 | $client->execute("CREATE DATABASE IF NOT EXISTS test"); 20 | 21 | testFloat($client, $deleteTable); 22 | } 23 | 24 | function testFloat($client, $deleteTable = false) { 25 | $client->execute("CREATE TABLE IF NOT EXISTS test.float_test (float32_c Float32, float64_c Float64) ENGINE = Memory"); 26 | 27 | $client->insert("test.float_test",[ 28 | 'float32_c', 'float64_c' 29 | ], [ 30 | [32.32, 64.64], 31 | [32.31, 64.68] 32 | ]); 33 | 34 | $client->writeStart("test.float_test", [ 35 | 'float32_c' 36 | ]); 37 | $client->write([ 38 | [32.32], 39 | [32.31] 40 | ]); 41 | $client->writeEnd(); 42 | 43 | $result = $client->select("SELECT {select} FROM {table}", [ 44 | 'select' => 'float32_c, float64_c', 45 | 'table' => 'test.float_test' 46 | ]); 47 | var_dump($result); 48 | 49 | if ($deleteTable) { 50 | $client->execute("DROP TABLE {table}", [ 51 | 'table' => 'test.float_test' 52 | ]); 53 | } 54 | } 55 | 56 | ?> 57 | --EXPECT-- 58 | array(4) { 59 | [0]=> 60 | array(2) { 61 | ["float32_c"]=> 62 | float(32.32) 63 | ["float64_c"]=> 64 | float(64.64) 65 | } 66 | [1]=> 67 | array(2) { 68 | ["float32_c"]=> 69 | float(32.31) 70 | ["float64_c"]=> 71 | float(64.68) 72 | } 73 | [2]=> 74 | array(2) { 75 | ["float32_c"]=> 76 | float(32.32) 77 | ["float64_c"]=> 78 | float(0) 79 | } 80 | [3]=> 81 | array(2) { 82 | ["float32_c"]=> 83 | float(32.31) 84 | ["float64_c"]=> 85 | float(0) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tests/008.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SeasClick testUUID 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | "clickhouse", 9 | "port" => "9000", 10 | "compression" => true 11 | ]; 12 | 13 | clientTest($config); 14 | 15 | function clientTest($config) 16 | { 17 | $deleteTable = true; 18 | $client = new SeasClick($config); 19 | $client->execute("CREATE DATABASE IF NOT EXISTS test"); 20 | 21 | testUUID($client, $deleteTable); 22 | } 23 | 24 | function testUUID($client, $deleteTable = false) { 25 | $client->execute("CREATE TABLE IF NOT EXISTS test.uuid_test (uuid_c UUID, uuid2_c UUID) ENGINE = Memory"); 26 | 27 | $client->insert("test.uuid_test",[ 28 | 'uuid_c', 'uuid2_c' 29 | ], [ 30 | ['31249a1b-7b05-4270-9f37-c609b48a9bb2', '31249a1b7b0542709f37c609b48a9bb2'], 31 | ['31249a1b-7b05-4270-9f37-c609b48a9bb2', null], 32 | ]); 33 | 34 | $client->writeStart("test.uuid_test", [ 35 | 'uuid_c' 36 | ]); 37 | $client->write([ 38 | ['00000000-0000-0000-9f37-c609b48a9bb2'], 39 | ['31249a1b-7b05-4270-9f37-c609b48a9bb2'], 40 | ]); 41 | $client->writeEnd(); 42 | 43 | $result = $client->select("SELECT {select} FROM {table}", [ 44 | 'select' => 'uuid_c, uuid2_c', 45 | 'table' => 'test.uuid_test' 46 | ]); 47 | var_dump($result); 48 | 49 | if ($deleteTable) { 50 | $client->execute("DROP TABLE {table}", [ 51 | 'table' => 'test.uuid_test' 52 | ]); 53 | } 54 | } 55 | 56 | ?> 57 | --EXPECT-- 58 | array(4) { 59 | [0]=> 60 | array(2) { 61 | ["uuid_c"]=> 62 | string(32) "31249a1b7b0542709f37c609b48a9bb2" 63 | ["uuid2_c"]=> 64 | string(32) "31249a1b7b0542709f37c609b48a9bb2" 65 | } 66 | [1]=> 67 | array(2) { 68 | ["uuid_c"]=> 69 | string(32) "31249a1b7b0542709f37c609b48a9bb2" 70 | ["uuid2_c"]=> 71 | string(32) "00000000000000000000000000000000" 72 | } 73 | [2]=> 74 | array(2) { 75 | ["uuid_c"]=> 76 | string(32) "00000000000000009f37c609b48a9bb2" 77 | ["uuid2_c"]=> 78 | string(32) "00000000000000000000000000000000" 79 | } 80 | [3]=> 81 | array(2) { 82 | ["uuid_c"]=> 83 | string(32) "31249a1b7b0542709f37c609b48a9bb2" 84 | ["uuid2_c"]=> 85 | string(32) "00000000000000000000000000000000" 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tests/009.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SeasClick testDate 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | "clickhouse", 9 | "port" => "9000", 10 | "compression" => true 11 | ]; 12 | 13 | clientTest($config); 14 | 15 | function clientTest($config) 16 | { 17 | $deleteTable = true; 18 | $client = new SeasClick($config); 19 | $client->execute("CREATE DATABASE IF NOT EXISTS test"); 20 | 21 | testDate($client, $deleteTable); 22 | } 23 | 24 | function testDate($client, $deleteTable = false) { 25 | $client->execute("CREATE TABLE IF NOT EXISTS test.date_test (date_c Date, datetime_c DateTime) ENGINE = Memory"); 26 | 27 | $time1 = strtotime(date('Y-m-d H:i:s', 1548633600)); 28 | $time2 = strtotime(date('Y-m-d H:i:s', 1548687925)); 29 | 30 | $client->insert("test.date_test", [ 31 | 'date_c', 'datetime_c' 32 | ], [ 33 | [$time1, $time2], 34 | [$time1, $time2] 35 | ]); 36 | 37 | $result = $client->select("SELECT {select} FROM {table}", [ 38 | 'select' => 'date_c, datetime_c', 39 | 'table' => 'test.date_test' 40 | ]); 41 | var_dump($result); 42 | 43 | if ($deleteTable) { 44 | $client->execute("DROP TABLE {table}", [ 45 | 'table' => 'test.date_test' 46 | ]); 47 | } 48 | } 49 | 50 | ?> 51 | --EXPECT-- 52 | array(2) { 53 | [0]=> 54 | array(2) { 55 | ["date_c"]=> 56 | int(1548633600) 57 | ["datetime_c"]=> 58 | int(1548687925) 59 | } 60 | [1]=> 61 | array(2) { 62 | ["date_c"]=> 63 | int(1548633600) 64 | ["datetime_c"]=> 65 | int(1548687925) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tests/010.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SeasClick testDate 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | "clickhouse", 9 | "port" => "9000", 10 | "compression" => true 11 | ]; 12 | 13 | clientTest($config); 14 | 15 | function clientTest($config) 16 | { 17 | $deleteTable = true; 18 | $client = new SeasClick($config); 19 | $client->execute("CREATE DATABASE IF NOT EXISTS test"); 20 | 21 | testTuple($client, $deleteTable); 22 | } 23 | 24 | function testTuple($client, $deleteTable = false) { 25 | $client->execute("CREATE TABLE IF NOT EXISTS test.tuple_test (tuple_c Tuple(id UInt64, name String), int_c UInt64, string_c String) ENGINE = Memory"); 26 | 27 | $client->insert("test.tuple_test", [ 28 | 'tuple_c', 'int_c', 'string_c' 29 | ], [ 30 | [[1, 'one'], 1, 'one'], 31 | [[2, 'two'], 2, 'two'], 32 | ]); 33 | $result = $client->select("SELECT {select} FROM {table}", [ 34 | 'select' => 'tuple_c, int_c, string_c', 35 | 'table' => 'test.tuple_test' 36 | ]); 37 | var_dump($result); 38 | 39 | if ($deleteTable) { 40 | $client->execute("DROP TABLE {table}", [ 41 | 'table' => 'test.tuple_test' 42 | ]); 43 | } 44 | } 45 | 46 | ?> 47 | --EXPECT-- 48 | array(2) { 49 | [0]=> 50 | array(3) { 51 | ["tuple_c"]=> 52 | array(2) { 53 | [0]=> 54 | int(1) 55 | [1]=> 56 | string(3) "one" 57 | } 58 | ["int_c"]=> 59 | int(1) 60 | ["string_c"]=> 61 | string(3) "one" 62 | } 63 | [1]=> 64 | array(3) { 65 | ["tuple_c"]=> 66 | array(2) { 67 | [0]=> 68 | int(2) 69 | [1]=> 70 | string(3) "two" 71 | } 72 | ["int_c"]=> 73 | int(2) 74 | ["string_c"]=> 75 | string(3) "two" 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tests/bench_mark/README.md: -------------------------------------------------------------------------------- 1 | SeasClick 2 | ===== 3 | performance test 4 | 5 | ### Test 6 | ```ssh 7 | composer install 8 | vim bench_mark.php 9 | php bench_mark.php 10 | ``` 11 | -------------------------------------------------------------------------------- /tests/bench_mark/bench_mark.php: -------------------------------------------------------------------------------- 1 | $value) { 27 | list($dataCount, $seletCount, $limit) = $value; 28 | $insertData = initData($dataCount); 29 | $insertOneCkData = initOneCkData($dataCount); 30 | 31 | echo "\n##### dataCount: {$dataCount}, seletCount: {$seletCount}, limit: {$limit} #####\n"; 32 | 33 | $t0 = $t = start_test(); 34 | testPhpClickhouse($insertData, $seletCount, $limit); 35 | $t = end_test($t, "PhpClickhouse"); 36 | 37 | testSeasClickNonCompression($insertData, $seletCount, $limit); 38 | $t = end_test($t, "SeasClickNonCompression"); 39 | 40 | testSeasClickCompression($insertData, $seletCount, $limit); 41 | $t = end_test($t, "SeasClickCompression"); 42 | 43 | testOneCk($insertOneCkData, $seletCount, $limit); 44 | $t = end_test($t, "OneCk"); 45 | 46 | total($t0, "Total"); 47 | } 48 | 49 | function start_test() 50 | { 51 | return getmicrotime(); 52 | } 53 | 54 | function getmicrotime() 55 | { 56 | $t = gettimeofday(); 57 | 58 | return ($t['sec'] + $t['usec'] / 1000000); 59 | } 60 | 61 | function end_test($start, $name) 62 | { 63 | global $total; 64 | $end = getmicrotime(); 65 | $total += $end - $start; 66 | $num = number_format($end - $start, 3); 67 | $pad = str_repeat(" ", 60 - strlen($name) - strlen($num)); 68 | 69 | echo $name . $pad . $num . "\n"; 70 | 71 | return getmicrotime(); 72 | } 73 | 74 | function total() 75 | { 76 | global $total; 77 | $pad = str_repeat("-", 32); 78 | echo $pad . "\n"; 79 | $num = number_format($total, 3); 80 | $pad = str_repeat(" ", 32 - strlen("Total") - strlen($num)); 81 | echo "Total" . $pad . $num . "\n"; 82 | } 83 | 84 | function testSeasClickNonCompression($insertData, $num, $limit) 85 | { 86 | $config = [ 87 | "host" => "clickhouse", 88 | "port" => "9000", 89 | "compression" => false 90 | ]; 91 | 92 | $db = new SeasClick($config); 93 | $db->execute("CREATE DATABASE IF NOT EXISTS test"); 94 | 95 | $db->execute(' 96 | CREATE TABLE IF NOT EXISTS test.summing_url_views ( 97 | event_date Date DEFAULT toDate(event_time), 98 | event_time DateTime, 99 | site_id Int32, 100 | site_key String, 101 | views Int32, 102 | v_00 Int32, 103 | v_55 Int32 104 | ) 105 | ENGINE = SummingMergeTree(event_date, (site_id, site_key, event_time, event_date), 8192) 106 | '); 107 | 108 | $db->insert("test.summing_url_views", 109 | ['event_time', 'site_key', 'site_id', 'views', 'v_00', 'v_55'], 110 | $insertData 111 | ); 112 | 113 | $a = $num; 114 | while ($a--) { 115 | $db->select('SELECT * FROM test.summing_url_views LIMIT ' . $limit); 116 | } 117 | 118 | $db->execute("DROP TABLE {table}", [ 119 | 'table' => 'test.summing_url_views' 120 | ]); 121 | } 122 | 123 | function testSeasClickCompression($insertData, $num, $limit) 124 | { 125 | $config = [ 126 | "host" => "clickhouse", 127 | "port" => "9000", 128 | "compression" => true 129 | ]; 130 | 131 | $db = new SeasClick($config); 132 | $db->execute("CREATE DATABASE IF NOT EXISTS test"); 133 | 134 | $db->execute(' 135 | CREATE TABLE IF NOT EXISTS test.summing_url_views ( 136 | event_date Date DEFAULT toDate(event_time), 137 | event_time DateTime, 138 | site_id Int32, 139 | site_key String, 140 | views Int32, 141 | v_00 Int32, 142 | v_55 Int32 143 | ) 144 | ENGINE = SummingMergeTree(event_date, (site_id, site_key, event_time, event_date), 8192) 145 | '); 146 | 147 | $db->insert("test.summing_url_views", 148 | ['event_time', 'site_key', 'site_id', 'views', 'v_00', 'v_55'], 149 | $insertData 150 | ); 151 | 152 | $a = $num; 153 | while ($a--) { 154 | $db->select('SELECT * FROM test.summing_url_views LIMIT ' . $limit); 155 | } 156 | 157 | $db->execute("DROP TABLE {table}", [ 158 | 'table' => 'test.summing_url_views' 159 | ]); 160 | } 161 | 162 | function testPhpClickhouse($insertData, $num, $limit) 163 | { 164 | $config = [ 165 | 'host' => 'clickhouse', 166 | 'port' => '8123', 167 | 'username' => 'default', 168 | 'password' => '' 169 | ]; 170 | $db = new ClickHouseDB\Client($config); 171 | $db->write("CREATE DATABASE IF NOT EXISTS test"); 172 | 173 | $db->database('test'); 174 | $db->setTimeout(1.5); // 1500 ms 175 | $db->setTimeout(10); // 10 seconds 176 | $db->setConnectTimeOut(5); // 5 seconds 177 | 178 | $db->write(' 179 | CREATE TABLE IF NOT EXISTS summing_url_views ( 180 | event_date Date DEFAULT toDate(event_time), 181 | event_time DateTime, 182 | site_id Int32, 183 | site_key String, 184 | views Int32, 185 | v_00 Int32, 186 | v_55 Int32 187 | ) 188 | ENGINE = SummingMergeTree(event_date, (site_id, site_key, event_time, event_date), 8192) 189 | '); 190 | 191 | $db->insert("summing_url_views", 192 | $insertData, 193 | ['event_time', 'site_key', 'site_id', 'views', 'v_00', 'v_55'] 194 | ); 195 | 196 | $a = $num; 197 | while ($a--) { 198 | $db->select('SELECT * FROM summing_url_views LIMIT ' . $limit)->rows(); 199 | } 200 | 201 | $db->write('DROP TABLE IF EXISTS summing_url_views'); 202 | } 203 | 204 | function testOneCk($insertData, $num, $limit) 205 | { 206 | $db = new Client('tcp://clickhouse:9000', 'default', '', ''); 207 | 208 | $db->query('CREATE DATABASE IF NOT EXISTS test'); 209 | 210 | $db->query(' 211 | CREATE TABLE IF NOT EXISTS summing_url_views ( 212 | event_date Date DEFAULT toDate(event_time), 213 | event_time DateTime, 214 | site_id Int32, 215 | site_key String, 216 | views Int32, 217 | v_00 Int32, 218 | v_55 Int32 219 | ) 220 | ENGINE = SummingMergeTree(event_date, (site_id, site_key, event_time, event_date), 8192) 221 | '); 222 | 223 | $data['insert data'] = $db->insert('summing_url_views', $insertData); 224 | 225 | $a = $num; 226 | while ($a--) { 227 | $db->query('SELECT * FROM summing_url_views LIMIT ' . $limit); 228 | } 229 | 230 | $db->query('DROP TABLE IF EXISTS summing_url_views'); 231 | } 232 | 233 | function initOneCkData($num = 100) 234 | { 235 | $insertData = []; 236 | while ($num--) { 237 | $insertData[] = [ 238 | 'event_time' => time(), 239 | 'site_key' => 'HASH2', 240 | 'site_id' => 2345, 241 | 'views' => 12, 242 | 'v_00' => 9, 243 | 'v_55' => 3 244 | ]; 245 | } 246 | return $insertData; 247 | } 248 | 249 | function initData($num = 100) 250 | { 251 | $insertData = []; 252 | while ($num--) { 253 | $insertData[] = [time(), 'HASH2', 2345, 12, 9, 3]; 254 | } 255 | return $insertData; 256 | } 257 | -------------------------------------------------------------------------------- /tests/bench_mark/bench_mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeasX/SeasClick/46299d761096e7e62ea8c6a4717eea82492fd4cd/tests/bench_mark/bench_mark.png -------------------------------------------------------------------------------- /tests/bench_mark/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "smi2/phpclickhouse": "^1.1", 4 | "lizhichao/one-ck": "^0.1.8" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/bench_mark/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "5ce62d7da7b75f43d0dabe3f2766147a", 8 | "packages": [ 9 | { 10 | "name": "lizhichao/one-ck", 11 | "version": "0.1.9", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/lizhichao/one-ck.git", 15 | "reference": "0b1de9b6f5527e81023a677e39aa0f62e2fc0193" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/lizhichao/one-ck/zipball/0b1de9b6f5527e81023a677e39aa0f62e2fc0193", 20 | "reference": "0b1de9b6f5527e81023a677e39aa0f62e2fc0193", 21 | "shasum": "", 22 | "mirrors": [ 23 | { 24 | "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", 25 | "preferred": true 26 | } 27 | ] 28 | }, 29 | "require": { 30 | "ext-bcmath": "*", 31 | "ext-json": "*", 32 | "php": ">=7.1" 33 | }, 34 | "type": "library", 35 | "autoload": { 36 | "psr-4": { 37 | "OneCk\\": "src/" 38 | } 39 | }, 40 | "notification-url": "https://packagist.org/downloads/", 41 | "license": [ 42 | "Apache-2.0" 43 | ], 44 | "authors": [ 45 | { 46 | "name": "tanszhe", 47 | "email": "1018595261@qq.com" 48 | } 49 | ], 50 | "description": "clickhouse tcp client", 51 | "keywords": [ 52 | "clickhouse", 53 | "client", 54 | "php", 55 | "tcp" 56 | ], 57 | "time": "2020-09-09T07:30:08+00:00" 58 | }, 59 | { 60 | "name": "smi2/phpclickhouse", 61 | "version": "1.1.2", 62 | "source": { 63 | "type": "git", 64 | "url": "https://github.com/smi2/phpClickHouse.git", 65 | "reference": "ecf411b3b493e12bfe64873dac94456245d6c45c" 66 | }, 67 | "dist": { 68 | "type": "zip", 69 | "url": "https://api.github.com/repos/smi2/phpClickHouse/zipball/ecf411b3b493e12bfe64873dac94456245d6c45c", 70 | "reference": "ecf411b3b493e12bfe64873dac94456245d6c45c", 71 | "shasum": "", 72 | "mirrors": [ 73 | { 74 | "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", 75 | "preferred": true 76 | } 77 | ] 78 | }, 79 | "require": { 80 | "ext-curl": "*", 81 | "php": ">=5.6" 82 | }, 83 | "require-dev": { 84 | "doctrine/coding-standard": "^4.0", 85 | "php": "^7.1", 86 | "phpstan/phpstan": "^0.9.2", 87 | "phpunit/phpunit": "^7.0" 88 | }, 89 | "type": "library", 90 | "autoload": { 91 | "psr-4": { 92 | "ClickHouseDB\\": "src/" 93 | } 94 | }, 95 | "notification-url": "https://packagist.org/downloads/", 96 | "license": [ 97 | "MIT" 98 | ], 99 | "authors": [ 100 | { 101 | "name": "Igor Strykhar", 102 | "email": "isublimity@gmail.com", 103 | "homepage": "https://github.com/isublimity" 104 | } 105 | ], 106 | "description": "PHP ClickHouse Client", 107 | "homepage": "https://github.com/smi2/phpClickHouse", 108 | "keywords": [ 109 | "clickhouse", 110 | "client", 111 | "curl", 112 | "driver", 113 | "http", 114 | "http client", 115 | "php" 116 | ], 117 | "time": "2018-07-03T18:04:38+00:00" 118 | } 119 | ], 120 | "packages-dev": [], 121 | "aliases": [], 122 | "minimum-stability": "stable", 123 | "stability-flags": [], 124 | "prefer-stable": false, 125 | "prefer-lowest": false, 126 | "platform": [], 127 | "platform-dev": [] 128 | } 129 | -------------------------------------------------------------------------------- /travis/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | TEST_DIR="`pwd`/tests/" 3 | 4 | make test 5 | 6 | for file in `find $TEST_DIR -name "*.diff" 2>/dev/null` 7 | do 8 | grep "\-\-XFAIL--" ${file/%diff/phpt} >/dev/null 2>&1 9 | if [ $? -gt 0 ] 10 | then 11 | FAILS[${#FAILS[@]}]="$file" 12 | fi 13 | done 14 | 15 | if [ ${#FAILS[@]} -gt 0 ] 16 | then 17 | for fail in "${FAILS[@]}" 18 | do 19 | sh -xc "cat $fail" 20 | done 21 | exit 1 22 | else 23 | exit 0 24 | fi -------------------------------------------------------------------------------- /typesToPhp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | SeasClick | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2018 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: SeasX Group | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | using namespace clickhouse; 19 | using namespace std; 20 | 21 | ColumnRef createColumn(TypeRef type); 22 | 23 | ColumnRef insertColumn(TypeRef type, zval *value_zval); 24 | 25 | void convertToZval(zval *arr, const ColumnRef& columnRef, int row, string column_name, int8_t is_array); 26 | 27 | void zvalToBlock(Block& blockDes, Block& blockSrc, zend_ulong num_key, zval *value_zval); 28 | 29 | /* 30 | * Local variables: 31 | * tab-width: 4 32 | * c-basic-offset: 4 33 | * End: 34 | * vim600: noet sw=4 ts=4 fdm=marker 35 | * vim<600: noet sw=4 ts=4 36 | */ 37 | --------------------------------------------------------------------------------