├── .DS_Store ├── .gitignore ├── .gitmodules ├── API.md ├── CMakeLists.txt ├── LICENSE ├── README.md ├── README.zh_Hans.md ├── a.cpp ├── config.json ├── file_controller.cc ├── file_controller.h ├── flypen.jpeg ├── flypen.srctrlbm ├── flypen.srctrldb ├── flypen.srctrlprj ├── jwt_controller.cc ├── jwt_controller.h ├── libpqxx ├── .circleci │ └── config.yml ├── .clang-format ├── .clang-tidy ├── .cmake-format ├── .github │ └── workflows │ │ ├── codeql.yml │ │ └── stale.yml ├── .gitignore ├── .lgtm.yml ├── .lift │ └── ignoreFiles ├── .mdl_style.rb ├── .mdlrc ├── .readthedocs.yaml ├── AUTHORS ├── BUILDING-cmake.md ├── BUILDING-configure.md ├── CMakeLists.txt ├── COPYING ├── INSTALL ├── Makefile.am ├── Makefile.in ├── NEWS ├── README.md ├── VERSION ├── aclocal.m4 ├── appveyor.yml ├── autogen.sh ├── cmake │ ├── config.cmake │ ├── libpqxx-config.cmake │ └── pqxx_cxx_feature_checks.cmake ├── compile_flags.in ├── config-tests │ ├── PQXX_HAVE_CHARCONV_FLOAT.cxx │ ├── PQXX_HAVE_CHARCONV_INT.cxx │ ├── PQXX_HAVE_CMP.cxx │ ├── PQXX_HAVE_CONCEPTS.cxx │ ├── PQXX_HAVE_CXA_DEMANGLE.cxx │ ├── PQXX_HAVE_GCC_PURE.cxx │ ├── PQXX_HAVE_GCC_VISIBILITY.cxx │ ├── PQXX_HAVE_LIKELY.cxx │ ├── PQXX_HAVE_MULTIDIM.cxx │ ├── PQXX_HAVE_PATH.cxx │ ├── PQXX_HAVE_POLL.cxx │ ├── PQXX_HAVE_SLEEP_FOR.cxx │ ├── PQXX_HAVE_SOURCE_LOCATION.cxx │ ├── PQXX_HAVE_SPAN.cxx │ ├── PQXX_HAVE_SSIZE.cxx │ ├── PQXX_HAVE_STRERROR_R.cxx │ ├── PQXX_HAVE_STRERROR_S.cxx │ ├── PQXX_HAVE_THREAD_LOCAL.cxx │ ├── PQXX_HAVE_UNREACHABLE.cxx │ ├── PQXX_HAVE_YEAR_MONTH_DAY.cxx │ ├── README.md │ └── no_need_fslib.cxx ├── config │ ├── Makefile.am │ ├── Makefile.in │ ├── compile │ ├── config.guess │ ├── config.sub │ ├── depcomp │ ├── install-sh │ ├── ltmain.sh │ ├── m4 │ │ ├── Makefile.am │ │ ├── libtool.m4 │ │ ├── ltoptions.m4 │ │ ├── ltsugar.m4 │ │ ├── ltversion.m4 │ │ └── lt~obsolete.m4 │ ├── missing │ ├── mkinstalldirs │ └── test-driver ├── configitems ├── configure ├── configure.ac ├── cxx_features.txt ├── doc │ ├── CMakeLists.txt │ ├── Doxyfile.in │ ├── Makefile.am │ ├── Makefile.in │ ├── _static │ │ └── readme.txt │ ├── conf.py │ └── index.rst ├── include │ ├── CMakeLists.txt │ ├── CMakeLists.txt.template │ ├── Makefile.am │ ├── Makefile.in │ └── pqxx │ │ ├── Makefile.am │ │ ├── Makefile.in │ │ ├── array │ │ ├── array.hxx │ │ ├── binarystring │ │ ├── binarystring.hxx │ │ ├── blob │ │ ├── blob.hxx │ │ ├── composite │ │ ├── composite.hxx │ │ ├── config.h.in │ │ ├── connection │ │ ├── connection.hxx │ │ ├── cursor │ │ ├── cursor.hxx │ │ ├── dbtransaction │ │ ├── dbtransaction.hxx │ │ ├── doc │ │ ├── accessing-results.md │ │ ├── binary-data.md │ │ ├── datatypes.md │ │ ├── escaping.md │ │ ├── getting-started.md │ │ ├── mainpage.md │ │ ├── mainpage.md.template │ │ ├── parameters.md │ │ ├── performance.md │ │ ├── prepared-statement.md │ │ ├── streams.md │ │ └── thread-safety.md │ │ ├── errorhandler │ │ ├── errorhandler.hxx │ │ ├── except │ │ ├── except.hxx │ │ ├── field │ │ ├── field.hxx │ │ ├── internal │ │ ├── array-composite.hxx │ │ ├── callgate.hxx │ │ ├── concat.hxx │ │ ├── conversions.hxx │ │ ├── encoding_group.hxx │ │ ├── encodings.hxx │ │ ├── gates │ │ │ ├── connection-errorhandler.hxx │ │ │ ├── connection-largeobject.hxx │ │ │ ├── connection-notification_receiver.hxx │ │ │ ├── connection-pipeline.hxx │ │ │ ├── connection-sql_cursor.hxx │ │ │ ├── connection-stream_from.hxx │ │ │ ├── connection-stream_to.hxx │ │ │ ├── connection-transaction.hxx │ │ │ ├── errorhandler-connection.hxx │ │ │ ├── icursor_iterator-icursorstream.hxx │ │ │ ├── icursorstream-icursor_iterator.hxx │ │ │ ├── result-connection.hxx │ │ │ ├── result-creation.hxx │ │ │ ├── result-pipeline.hxx │ │ │ ├── result-sql_cursor.hxx │ │ │ ├── transaction-sql_cursor.hxx │ │ │ └── transaction-transaction_focus.hxx │ │ ├── header-post.hxx │ │ ├── header-pre.hxx │ │ ├── ignore-deprecated-post.hxx │ │ ├── ignore-deprecated-pre.hxx │ │ ├── libpq-forward.hxx │ │ ├── result_iter.hxx │ │ ├── result_iterator.hxx │ │ ├── sql_cursor.hxx │ │ ├── statement_parameters.hxx │ │ ├── stream_iterator.hxx │ │ ├── stream_query.hxx │ │ ├── stream_query_impl.hxx │ │ └── wait.hxx │ │ ├── isolation │ │ ├── isolation.hxx │ │ ├── largeobject │ │ ├── largeobject.hxx │ │ ├── nontransaction │ │ ├── nontransaction.hxx │ │ ├── notification │ │ ├── notification.hxx │ │ ├── params │ │ ├── params.hxx │ │ ├── pipeline │ │ ├── pipeline.hxx │ │ ├── pqxx │ │ ├── prepared_statement │ │ ├── prepared_statement.hxx │ │ ├── range │ │ ├── range.hxx │ │ ├── result │ │ ├── result.hxx │ │ ├── robusttransaction │ │ ├── robusttransaction.hxx │ │ ├── row │ │ ├── row.hxx │ │ ├── separated_list │ │ ├── separated_list.hxx │ │ ├── strconv │ │ ├── strconv.hxx │ │ ├── stream_from │ │ ├── stream_from.hxx │ │ ├── stream_to │ │ ├── stream_to.hxx │ │ ├── subtransaction │ │ ├── subtransaction.hxx │ │ ├── time │ │ ├── time.hxx │ │ ├── transaction │ │ ├── transaction.hxx │ │ ├── transaction_base │ │ ├── transaction_base.hxx │ │ ├── transaction_focus │ │ ├── transaction_focus.hxx │ │ ├── transactor │ │ ├── transactor.hxx │ │ ├── types │ │ ├── types.hxx │ │ ├── util │ │ ├── util.hxx │ │ ├── version │ │ ├── version.hxx │ │ ├── version.hxx.template │ │ ├── zview │ │ └── zview.hxx ├── libpqxx.pc.in ├── pqxx_cxx_feature_checks.ac ├── requirements.json ├── src │ ├── CMakeLists.txt │ ├── Makefile.am │ ├── Makefile.in │ ├── array.cxx │ ├── binarystring.cxx │ ├── blob.cxx │ ├── connection.cxx │ ├── cursor.cxx │ ├── encodings.cxx │ ├── errorhandler.cxx │ ├── except.cxx │ ├── field.cxx │ ├── largeobject.cxx │ ├── notification.cxx │ ├── params.cxx │ ├── pipeline.cxx │ ├── pqxx-source.hxx │ ├── result.cxx │ ├── robusttransaction.cxx │ ├── row.cxx │ ├── sql_cursor.cxx │ ├── strconv.cxx │ ├── stream_from.cxx │ ├── stream_to.cxx │ ├── subtransaction.cxx │ ├── time.cxx │ ├── transaction.cxx │ ├── transaction_base.cxx │ ├── util.cxx │ ├── version.cxx │ └── wait.cxx ├── test │ ├── CMakeLists.txt │ ├── Makefile.am │ ├── Makefile.am.template │ ├── Makefile.in │ ├── runner.cxx │ ├── test00.cxx │ ├── test01.cxx │ ├── test02.cxx │ ├── test04.cxx │ ├── test07.cxx │ ├── test10.cxx │ ├── test11.cxx │ ├── test13.cxx │ ├── test14.cxx │ ├── test16.cxx │ ├── test17.cxx │ ├── test18.cxx │ ├── test20.cxx │ ├── test21.cxx │ ├── test26.cxx │ ├── test29.cxx │ ├── test30.cxx │ ├── test32.cxx │ ├── test37.cxx │ ├── test39.cxx │ ├── test46.cxx │ ├── test56.cxx │ ├── test60.cxx │ ├── test61.cxx │ ├── test62.cxx │ ├── test69.cxx │ ├── test70.cxx │ ├── test71.cxx │ ├── test72.cxx │ ├── test74.cxx │ ├── test75.cxx │ ├── test76.cxx │ ├── test77.cxx │ ├── test78.cxx │ ├── test79.cxx │ ├── test82.cxx │ ├── test84.cxx │ ├── test87.cxx │ ├── test88.cxx │ ├── test89.cxx │ ├── test90.cxx │ ├── test_helpers.hxx │ ├── test_types.hxx │ └── unit │ │ ├── CMakeLists.txt │ │ ├── test_array.cxx │ │ ├── test_binarystring.cxx │ │ ├── test_blob.cxx │ │ ├── test_cancel_query.cxx │ │ ├── test_column.cxx │ │ ├── test_composite.cxx │ │ ├── test_connection.cxx │ │ ├── test_cursor.cxx │ │ ├── test_encodings.cxx │ │ ├── test_error_verbosity.cxx │ │ ├── test_errorhandler.cxx │ │ ├── test_escape.cxx │ │ ├── test_exceptions.cxx │ │ ├── test_field.cxx │ │ ├── test_float.cxx │ │ ├── test_largeobject.cxx │ │ ├── test_nonblocking_connect.cxx │ │ ├── test_notification.cxx │ │ ├── test_pipeline.cxx │ │ ├── test_prepared_statement.cxx │ │ ├── test_range.cxx │ │ ├── test_read_transaction.cxx │ │ ├── test_result_iteration.cxx │ │ ├── test_result_slicing.cxx │ │ ├── test_row.cxx │ │ ├── test_separated_list.cxx │ │ ├── test_simultaneous_transactions.cxx │ │ ├── test_sql_cursor.cxx │ │ ├── test_stateless_cursor.cxx │ │ ├── test_strconv.cxx │ │ ├── test_stream_from.cxx │ │ ├── test_stream_query.cxx │ │ ├── test_stream_to.cxx │ │ ├── test_string_conversion.cxx │ │ ├── test_subtransaction.cxx │ │ ├── test_test_helpers.cxx │ │ ├── test_thread_safety_model.cxx │ │ ├── test_time.cxx │ │ ├── test_transaction.cxx │ │ ├── test_transaction_base.cxx │ │ ├── test_transaction_focus.cxx │ │ ├── test_transactor.cxx │ │ ├── test_type_name.cxx │ │ └── test_zview.cxx └── tools │ ├── Makefile.am │ ├── Makefile.in │ ├── deprecations │ ├── extract_version │ ├── format │ ├── generate_check_config.py │ ├── generate_cxx_checks.py │ ├── lint │ ├── m4esc.py │ ├── pqxxthreadsafety.cxx │ ├── rmlo.cxx │ ├── splitconfig.py │ ├── template2mak.py │ ├── test_all.py │ ├── todo │ └── update-copyright ├── localhost.sql ├── main.cc ├── models └── model.json ├── msg_controller.cc ├── msg_controller.h ├── package-lock.json ├── pgsql.cc ├── pgsql.h ├── root ├── 123 ├── 12121 ├── bwb ├── lglglgly │ └── lgylgy ├── lgy ├── lgylgy ├── rubbish_lj └── sdfsadf ├── run.sh ├── user_controller.cc └── user_controller.h /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stepbystepcode/flypen/81fb7cd80ca59798991db363564ca844a835bfeb/.DS_Store -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "drogon"] 2 | path = drogon 3 | url = https://github.com/drogonframework/drogon 4 | [submodule "jwt-cpp"] 5 | path = jwt-cpp 6 | url = https://github.com/Thalhammer/jwt-cpp 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Jing Li 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | if(sodium_init() < 0) { 8 | cerr << "Error: sodium Library Initialized Error\n"; 9 | exit(0); 10 | } 11 | /** 12 | * 一、前期处理 13 | * 1.生成两个密钥对A与B 14 | * 2.A与B各自保存自己的私钥 15 | * 3.将PkA和PkB存入数据库中 16 | * 4.生成加密密钥K(Nonce生成) 17 | * 18 | * 二、加密(假设A给B发送消息) 19 | * A用自己的私钥,B的公钥和K,以及明文m加密 20 | * 21 | * 三、传输 22 | * 传输。。。 23 | * 24 | * 四、解密 25 | * B用自己的私钥、A的公钥和K,以及密文解密 26 | * 27 | * 五、 28 | * 删除加密密钥K 29 | */ 30 | return 0; 31 | } -------------------------------------------------------------------------------- /file_controller.h: -------------------------------------------------------------------------------- 1 | #ifndef _FILE_CONTROLLER_H_ 2 | #define _FILE_CONTROLLER_H_ 3 | #include 4 | #include 5 | using namespace drogon; 6 | 7 | void saveFile(const HttpRequestPtr &req, std::function &&callback); 8 | void imageUpload(const HttpRequestPtr &req, std::function &&callback); 9 | void getPicture(const HttpRequestPtr &req, std::function &&callback); 10 | void commandsCtrl(const HttpRequestPtr &req, std::function &&callback); 11 | void add_lock(const HttpRequestPtr &req, std::function &&callback); 12 | std::string return_status(std::string result, const std::string& command,Json::Value &res_json); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /flypen.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stepbystepcode/flypen/81fb7cd80ca59798991db363564ca844a835bfeb/flypen.jpeg -------------------------------------------------------------------------------- /flypen.srctrlbm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stepbystepcode/flypen/81fb7cd80ca59798991db363564ca844a835bfeb/flypen.srctrlbm -------------------------------------------------------------------------------- /flypen.srctrldb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stepbystepcode/flypen/81fb7cd80ca59798991db363564ca844a835bfeb/flypen.srctrldb -------------------------------------------------------------------------------- /flypen.srctrlprj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | gnu++17 6 | 7 | 8 | unknown 9 | x86_64 10 | unknown 11 | unknown 12 | 13 | 0 14 | 15 | 16 | mysql-connector 17 | jwt-cpp 18 | drogon 19 | 20 | C++ Source Group 21 | 22 | 1 23 | 24 | 25 | .cpp 26 | .cxx 27 | .cc 28 | 29 | 30 | ./ 31 | mysql-connector/include 32 | 33 | enabled 34 | C++ Source Group 35 | 36 | 37 | 8 38 | 39 | -------------------------------------------------------------------------------- /jwt_controller.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "jwt_controller.h" 6 | 7 | using namespace jwt; 8 | 9 | std::string jwtGen(const Json::Value &req_json) 10 | { 11 | auto now = std::chrono::system_clock::now(); 12 | auto ms = std::chrono::duration_cast(now.time_since_epoch()).count(); 13 | std::string timestamp = std::to_string(ms); 14 | auto token = jwt::create() 15 | .set_type("JWS") 16 | .set_payload_claim("name", jwt::claim(req_json["username"].asString())) 17 | .set_payload_claim("time", jwt::claim(timestamp)) 18 | .sign(jwt::algorithm::hs256{"secret"}); 19 | return std::string(token); 20 | } 21 | 22 | std::string jwtDecrypt(const std::string &token) 23 | { 24 | try 25 | { 26 | auto decoded_token = jwt::decode(token); 27 | auto verifier = jwt::verify() 28 | .allow_algorithm(jwt::algorithm::hs256{"secret"}) 29 | .with_type("JWS"); 30 | verifier.verify(decoded_token); 31 | return decoded_token.get_payload_claim("name").as_string(); 32 | } 33 | catch (const std::exception &e) 34 | { 35 | // std::cout << "Failed to decrypt JWT: " + std::string(e.what()) << std::endl; 36 | throw std::runtime_error("Failed to decrypt JWT"); 37 | } 38 | } 39 | 40 | bool jwtVerify(const drogon::HttpRequestPtr &req) 41 | { 42 | std::string authHeader = req->getHeader("Authorization"); 43 | if (authHeader.substr(0, 7) == "Bearer ") 44 | { 45 | std::string bearerToken = authHeader.substr(7); 46 | try 47 | { 48 | std::string sender = jwtDecrypt(bearerToken); 49 | return true; 50 | } 51 | catch (const std::exception &e) 52 | { 53 | // std::cout << "Wrong token" << std::endl; 54 | return false; 55 | } 56 | } 57 | else 58 | { 59 | std::cout << "No Authorization" << std::endl; 60 | return false; 61 | } 62 | } -------------------------------------------------------------------------------- /jwt_controller.h: -------------------------------------------------------------------------------- 1 | #ifndef _JWT_CONTROLLER_H_ 2 | #define _JWT_CONTROLLER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | std::string jwtGen(const Json::Value &req_json); 9 | std::string jwtDecrypt(const std::string &token); 10 | bool jwtVerify(const drogon::HttpRequestPtr &req); 11 | 12 | #endif -------------------------------------------------------------------------------- /libpqxx/.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # CircleCI config for automated test builds triggered from Github. 2 | version: 2 3 | jobs: 4 | build: 5 | docker: 6 | - image: debian:unstable 7 | environment: 8 | - PGHOST: "/tmp" 9 | steps: 10 | - checkout 11 | - run: 12 | name: Configure apt archives 13 | command: apt update 14 | - run: 15 | name: Install 16 | command: apt install -y lsb-release python3 cmake postgresql libpq-dev 17 | postgresql-server-dev-all build-essential autoconf dh-autoreconf 18 | autoconf-archive automake cppcheck clang shellcheck 19 | python3-virtualenv 20 | - run: 21 | name: Identify 22 | command: lsb_release -a && c++ --version && clang++ --version 23 | - run: 24 | name: Prepare postgres 25 | command: | 26 | mkdir /tmp/db && 27 | chown postgres /tmp/db && 28 | su postgres -c '/usr/lib/postgresql/*/bin/initdb --pgdata /tmp/db --auth trust --nosync' 29 | - run: 30 | name: Run postgres 31 | command: (su postgres -c '/usr/lib/postgresql/*/bin/postgres -D /tmp/db -k /tmp' 32 | &) && sleep 5 33 | - run: 34 | name: Create postgres user 35 | command: su postgres -c "createuser -w -d root" 36 | - run: 37 | name: Set up database 38 | command: createdb --template=template0 --encoding=UNICODE root 39 | - run: 40 | name: Autogen 41 | command: ./autogen.sh 42 | - run: 43 | name: Configure 44 | command: | 45 | ./configure \ 46 | --disable-documentation \ 47 | --enable-maintainer-mode \ 48 | --enable-audit \ 49 | --enable-shared --disable-static \ 50 | CXXFLAGS='-O3 -std=c++17' \ 51 | CXX=clang++ 52 | - store_artifacts: 53 | path: config.log 54 | - run: 55 | name: Make 56 | command: make -j$(nproc) 57 | - run: 58 | name: Test 59 | command: PGDATA=db/data make -j$(nproc) check 60 | - run: 61 | name: Analyse 62 | command: ./tools/lint --full >lint.log 63 | - store_artifacts: 64 | path: lint.log 65 | # The resource_class feature allows configuring CPU and RAM resources for each job. Different resource classes are available for different executors. https://circleci.com/docs/2.0/configuration-reference/#resourceclass 66 | resource_class: large 67 | -------------------------------------------------------------------------------- /libpqxx/.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | 3 | AlignAfterOpenBracket: AlwaysBreak 4 | # AllowAllArgumentsOnNextLine: true 5 | # AllowAllConstructorInitializersOnNextLine: true 6 | AllowAllParametersOfDeclarationOnNextLine: true 7 | AllowShortBlocksOnASingleLine: true 8 | AllowShortCaseLabelsOnASingleLine: true 9 | AllowShortFunctionsOnASingleLine: Inline 10 | # AllowShortIfStatementsOnASingleLine: WithoutElse 11 | # AllowShortLambdasOnASingleLine: All 12 | AllowShortLoopsOnASingleLine: true 13 | AlwaysBreakAfterReturnType: None 14 | AlwaysBreakBeforeMultilineStrings: true 15 | # AlwaysBreakTemplateDeclarations: No 16 | BinPackArguments: true 17 | BinPackParameters: true 18 | BreakBeforeBraces: Custom 19 | BraceWrapping: 20 | # AfterCaseLabel: true 21 | AfterClass: true 22 | AfterControlStatement: true 23 | AfterEnum: true 24 | AfterExternBlock: true 25 | AfterFunction: true 26 | AfterNamespace: true 27 | AfterStruct: true 28 | BeforeCatch: true 29 | BeforeElse: true 30 | IndentBraces: false 31 | SplitEmptyFunction: false 32 | SplitEmptyNamespace: false 33 | SplitEmptyRecord: false 34 | BreakBeforeBinaryOperators: None 35 | BreakBeforeTernaryOperators: false 36 | BreakConstructorInitializers: AfterColon 37 | # BreakInheritanceList: AfterColon 38 | BreakStringLiterals: true 39 | ColumnLimit: 79 40 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 41 | ConstructorInitializerIndentWidth: 8 42 | ContinuationIndentWidth: 2 43 | Cpp11BracedListStyle: true 44 | FixNamespaceComments: true 45 | IncludeBlocks: Preserve 46 | IndentCaseLabels: false 47 | IndentPPDirectives: AfterHash 48 | IndentWidth: 2 49 | IndentWrappedFunctionNames: false 50 | KeepEmptyLinesAtTheStartOfBlocks: false 51 | MaxEmptyLinesToKeep: 2 52 | # NamespaceIndentation: All 53 | SortIncludes: true 54 | SortUsingDeclarations: true 55 | SpaceAfterCStyleCast: false 56 | SpaceAfterTemplateKeyword: false 57 | SpaceBeforeAssignmentOperators: true 58 | # SpaceBeforeCpp11BracedList: false 59 | # SpaceBeforeCtorInitializerColon: true 60 | # SpaceBeforeInheritanceColon: true 61 | # SpaceBeforeParents: ControlStatements 62 | # SpaceBeforeRangedBasedForLoopColon: true 63 | SpaceInEmptyParentheses: false 64 | SpacesInAngles: false 65 | SpacesInCStyleCastParentheses: false 66 | SpacesInContainerLiterals: false 67 | SpacesInParentheses: false 68 | SpacesInSquareBrackets: false 69 | Standard: Cpp11 70 | UseTab: Never 71 | --- 72 | -------------------------------------------------------------------------------- /libpqxx/.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | schedule: 9 | - cron: "33 21 * * 6" 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | permissions: 16 | actions: read 17 | contents: read 18 | security-events: write 19 | 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | language: [ python, cpp ] 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v2 31 | with: 32 | languages: ${{ matrix.language }} 33 | queries: +security-and-quality 34 | 35 | # For some reason, this seems to detect neither the configure script or the 36 | # CMake setup. 37 | # 38 | # - name: Autobuild 39 | # uses: github/codeql-action/autobuild@v2 40 | # 41 | # Instead, we'll have to build manually: 42 | - name: Build 43 | run: | 44 | gcc --version 45 | sudo apt-get install -y postgresql virtualenv 46 | sudo service postgresql start 47 | sudo su postgres -c "createuser --createdb $(whoami)" 48 | createdb "$(whoami)" 49 | # Using clang because currently the gcc build fails with an 50 | # address sanitizer (asan) link error. 51 | ./configure --enable-maintainer-mode --enable-audit --disable-documentation --disable-static CXXFLAGS='-O1 -std=c++17' CXX=clang++ 52 | make -j4 check || (cat test-suite.log && exit 1) 53 | 54 | - name: Perform CodeQL Analysis 55 | uses: github/codeql-action/analyze@v2 56 | with: 57 | category: "/language:${{ matrix.language }}" 58 | -------------------------------------------------------------------------------- /libpqxx/.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues and pull requests 2 | 3 | on: 4 | schedule: 5 | - cron: "30 1 * * *" 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | stale: 12 | 13 | permissions: 14 | issues: write # for actions/stale to close stale issues 15 | pull-requests: write # for actions/stale to close stale PRs 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/stale@v1 20 | with: 21 | repo-token: ${{ secrets.GITHUB_TOKEN }} 22 | stale-issue-message: 'There has been no activity on this ticket. Consider closing it.' 23 | stale-pr-message: 'There has been no activity on this pull request. Complete it or drop it.' 24 | stale-issue-label: 'no-issue-activity' 25 | stale-pr-label: 'no-pr-activity' 26 | -------------------------------------------------------------------------------- /libpqxx/.gitignore: -------------------------------------------------------------------------------- 1 | autom4te.cache 2 | build-*.out 3 | ChangeLog 4 | CMakeFiles/CMakeTmp 5 | confdefs.h 6 | config.log 7 | config.status 8 | conftest 9 | conftest.cpp 10 | conftest.err 11 | doc/_build 12 | doc/Doxyfile 13 | doc/html/Reference/*.css 14 | doc/html/Reference/*.html 15 | doc/html/Reference/*.js 16 | doc/html/Reference/*.png 17 | doc/html/Reference/*.map 18 | doc/html/Reference/*.md5 19 | doc/reference-stamp 20 | include/pqxx/config-*-*.h 21 | include/pqxx/config.h 22 | include/pqxx/stamp-h1 23 | libpqxx.pc 24 | libpqxx-*.tar.gz 25 | libtool 26 | pqxx-config 27 | pqxxlo.txt 28 | test/pqxxlo.txt 29 | tools/pqxxthreadsafety 30 | tools/rmlo 31 | README 32 | win32/common 33 | **/Makefile 34 | **/*.la 35 | **/*.lo 36 | **/*.o 37 | **/*.out 38 | **/.*.swp 39 | **/.swp 40 | **/*.tmp 41 | **/.deps 42 | **/.libs 43 | **/*~ 44 | **/lint.log 45 | **/lint.trs 46 | **/runner 47 | **/runner.log 48 | **/runner.trs 49 | **/test-suite.log 50 | -------------------------------------------------------------------------------- /libpqxx/.lgtm.yml: -------------------------------------------------------------------------------- 1 | # Config file for lgtm.com static analysis. 2 | 3 | path_classifiers: 4 | test: 5 | - test 6 | generated: 7 | - aclocal.m4 8 | - configure 9 | - ltmain.sh 10 | -------------------------------------------------------------------------------- /libpqxx/.lift/ignoreFiles: -------------------------------------------------------------------------------- 1 | # Make Sonatype Lift ignore these generated files. 2 | configure 3 | config/* 4 | -------------------------------------------------------------------------------- /libpqxx/.mdl_style.rb: -------------------------------------------------------------------------------- 1 | all 2 | 3 | # Allow mixing of header styles, within reason. 4 | # I use "setext" style when I can, but have to switch to "atx" (hash marks) 5 | # for the more fine-grained sections which setext does not support. 6 | rule 'MD003', :style => :setext_with_atx 7 | 8 | # Multiple consecutive blank lines. Sorry, but I want my Markdown to look 9 | # nice. And there does not seem to be an option for "allow a maximum of 2." 10 | exclude_rule 'MD012' 11 | 12 | # What joker came up with this? There may be some sense to warning about 13 | # trailing punctuation, but not when it's a question mark or exclamantion mark! 14 | rule 'MD026', :punctuation => '.,;:' 15 | 16 | # In an ordered list, I like to start each item with the right number, not with 17 | # "1." 18 | rule 'MD029', :style => :ordered 19 | 20 | # Allow bare URLs. Hate to have to disable this, but mainpage.md has some 21 | # special syntax which requires bare URLs. 22 | exclude_rule 'MD034' 23 | -------------------------------------------------------------------------------- /libpqxx/.mdlrc: -------------------------------------------------------------------------------- 1 | # Markdownlint config. Basically it's code, not config. :-( 2 | # Also, it seems all we can really do in this file is point to another file 3 | # containing our actual configuration. 4 | style '.mdl_style.rb' 5 | -------------------------------------------------------------------------------- /libpqxx/.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | version: 2 5 | 6 | # Set the version of Python and other tools you might need 7 | build: 8 | os: ubuntu-22.04 9 | tools: 10 | python: "3.10" 11 | apt_packages: 12 | - doxygen 13 | - graphviz 14 | 15 | # Build documentation in the docs/ directory with Sphinx 16 | sphinx: 17 | #builder: html 18 | configuration: doc/conf.py 19 | fail_on_warning: true 20 | 21 | # We recommend specifying your dependencies to enable reproducible builds: 22 | # https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 23 | # python: 24 | # install: 25 | # - requirements: docs/requirements.txt 26 | 27 | -------------------------------------------------------------------------------- /libpqxx/AUTHORS: -------------------------------------------------------------------------------- 1 | Jeroen T. Vermeulen. Wrote the code. 2 | Ray Dassen. Did most of the autoconf etc. stuff. 3 | 4 | Lots of others helped with various other contributions. 5 | -------------------------------------------------------------------------------- /libpqxx/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | 3 | file(READ VERSION VER_FILE_CONTENT) 4 | string(STRIP ${VER_FILE_CONTENT} VER_FILE_CONTENT) 5 | 6 | project( 7 | libpqxx 8 | VERSION ${VER_FILE_CONTENT} 9 | LANGUAGES CXX 10 | ) 11 | 12 | if(NOT "${CMAKE_CXX_STANDARD}") 13 | set(CMAKE_CXX_STANDARD 17) 14 | endif() 15 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 16 | set(CMAKE_CXX_EXTENSIONS OFF) 17 | set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) 18 | 19 | option(BUILD_DOC "Build documentation" OFF) 20 | 21 | if(NOT SKIP_BUILD_TEST) 22 | option(BUILD_TEST "Build all test cases" ON) 23 | endif() 24 | 25 | include(GNUInstallDirs) 26 | include(CMakePackageConfigHelpers) 27 | include(config) 28 | 29 | add_subdirectory(src) 30 | add_subdirectory(include) 31 | if(BUILD_DOC) 32 | add_subdirectory(doc) 33 | endif() 34 | if(BUILD_TEST) 35 | add_subdirectory(test) 36 | endif() 37 | 38 | # installation 39 | write_basic_package_version_file( 40 | "${CMAKE_CURRENT_BINARY_DIR}/libpqxx-config-version.cmake" 41 | VERSION ${PROJECT_VERSION} 42 | COMPATIBILITY SameMajorVersion 43 | ) 44 | install(FILES cmake/libpqxx-config.cmake 45 | "${CMAKE_CURRENT_BINARY_DIR}/libpqxx-config-version.cmake" 46 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libpqxx 47 | ) 48 | install( 49 | EXPORT libpqxx-targets 50 | NAMESPACE libpqxx:: 51 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libpqxx 52 | ) 53 | # Build tree export 54 | export( 55 | EXPORT libpqxx-targets 56 | NAMESPACE libpqxx:: 57 | FILE ${CMAKE_CURRENT_BINARY_DIR}/libpqxx-targets.cmake 58 | ) 59 | configure_file( 60 | cmake/libpqxx-config.cmake ${CMAKE_CURRENT_BINARY_DIR}/libpqxx-config.cmake 61 | COPYONLY 62 | ) 63 | # Package generation 64 | set(CPACK_GENERATOR TGZ) 65 | set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) 66 | include(CPack) 67 | -------------------------------------------------------------------------------- /libpqxx/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2000-2024 Jeroen T. Vermeulen. 2 | 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 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | * Neither the name of the author, nor the names of other contributors may be 14 | used to endorse or promote products derived from this software without 15 | specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | -------------------------------------------------------------------------------- /libpqxx/INSTALL: -------------------------------------------------------------------------------- 1 | For installation instructions, see `BUILDING-configure.md` (for the `configure` 2 | build) and `BUILDING-cmake.md` (for the CMake build). 3 | -------------------------------------------------------------------------------- /libpqxx/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = include src test tools config doc 2 | EXTRA_DIST = autogen.sh configitems README.md VERSION requirements.json 3 | 4 | MAINTAINERCLEANFILES = \ 5 | Makefile.in aclocal.m4 config.h.in config.log configure stamp-h.in 6 | 7 | pkgconfigdir = $(libdir)/pkgconfig 8 | pkgconfig_DATA = libpqxx.pc 9 | 10 | TESTS = tools/lint 11 | 12 | 13 | # Generate ChangeLog from git history. It goes all the way back through 14 | # the project's git, bzr, svn, and cvs days. 15 | dist-hook: ChangeLog 16 | 17 | ChangeLog: configure.ac 18 | git log --stat --name-only --date=short --abbrev-commit >$@ 19 | 20 | 21 | # We use README.md, but automake expects plain README. 22 | README: README.md 23 | ln -s $< $@ 24 | -------------------------------------------------------------------------------- /libpqxx/VERSION: -------------------------------------------------------------------------------- 1 | 7.9.0 2 | -------------------------------------------------------------------------------- /libpqxx/appveyor.yml: -------------------------------------------------------------------------------- 1 | # Configuration for test runs in Appveyor. 2 | version: 1.0.{build} 3 | image: Visual Studio 2022 4 | services: postgresql13 5 | # Run CMake to build libpqxx.sln. 6 | before_build: 7 | - cmd: >- 8 | call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" 9 | 10 | cmake -DBUILD_SHARED_LIBS=1 -DCMAKE_CXX_STANDARD=23 11 | configuration: Release 12 | build: 13 | parallel: true 14 | project: libpqxx.sln 15 | test_script: 16 | - ps: >- 17 | $env:Path += ";.\src\Release;C:\Program Files\PostgreSQL\13\bin" 18 | 19 | $env:PGUSER = "postgres" 20 | 21 | $env:PGPASSWORD = "Password12!" 22 | 23 | .\test\Release\runner.exe 24 | notifications: 25 | - provider: Email 26 | subject: 'libpqxx: AppVeyor build failure' 27 | message: The libpqxx AppVeyor build has failed. 28 | on_build_success: false 29 | on_build_failure: true 30 | on_build_status_changed: false 31 | -------------------------------------------------------------------------------- /libpqxx/autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Run this to generate the configure script etc. 3 | 4 | set -eu 5 | 6 | PQXXVERSION=$(./tools/extract_version) 7 | PQXX_ABI=$(./tools/extract_version --abi) 8 | PQXX_MAJOR=$(./tools/extract_version --major) 9 | PQXX_MINOR=$(./tools/extract_version --minor) 10 | echo "libpqxx version $PQXXVERSION" 11 | echo "libpqxx ABI version $PQXX_ABI" 12 | 13 | substitute() { 14 | sed -e "s/@PQXXVERSION@/$PQXXVERSION/g" \ 15 | -e "s/@PQXX_MAJOR@/$PQXX_MAJOR/g" \ 16 | -e "s/@PQXX_MINOR@/$PQXX_MINOR/g" \ 17 | -e "s/@PQXX_ABI@/$PQXX_ABI/g" \ 18 | "$1" 19 | } 20 | 21 | 22 | # Use templating system to generate various Makefiles. 23 | expand_templates() { 24 | for template in "$@" 25 | do 26 | ./tools/template2mak.py "$template" "${template%.template}" 27 | done 28 | } 29 | 30 | 31 | # We have two kinds of templates. One uses our custom templating tool. And 32 | # a few others simply have some substitutions done. 33 | # shellcheck disable=SC2046 34 | expand_templates $(find . -name \*.template) 35 | substitute include/pqxx/version.hxx.template >include/pqxx/version.hxx 36 | substitute include/pqxx/doc/mainpage.md.template >include/pqxx/doc/mainpage.md 37 | 38 | # Generate feature test snippets for C++ features that we simply detect by 39 | # checking a C++ feature test macro. 40 | ./tools/generate_cxx_checks.py 41 | 42 | # Generate autoconf and CMake configuration for our feature test snippets. 43 | ./tools/generate_check_config.py 44 | 45 | autoheader 46 | libtoolize --force --automake --copy 47 | aclocal -I . -I config/m4 48 | automake --add-missing --copy 49 | autoconf 50 | 51 | echo "Done." 52 | -------------------------------------------------------------------------------- /libpqxx/cmake/libpqxx-config.cmake: -------------------------------------------------------------------------------- 1 | include(CMakeFindDependencyMacro) 2 | find_dependency(PostgreSQL) 3 | 4 | include("${CMAKE_CURRENT_LIST_DIR}/libpqxx-targets.cmake") 5 | -------------------------------------------------------------------------------- /libpqxx/compile_flags.in: -------------------------------------------------------------------------------- 1 | @CPPFLAGS@ @CXXFLAGS@ 2 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_CHARCONV_FLOAT.cxx: -------------------------------------------------------------------------------- 1 | // Test for std::to_string/std::from_string for floating-point types. 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | char z[100]; 8 | auto rt = std::to_chars(std::begin(z), std::end(z), 3.14159L); 9 | if (rt.ec != std::errc{}) 10 | return 1; 11 | long double n; 12 | auto rf = std::from_chars(std::cbegin(z), std::cend(z), n); 13 | if (rf.ec != std::errc{}) 14 | return 2; 15 | return (n > 3 and n < 4) ? 0 : 1; 16 | } 17 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_CHARCONV_INT.cxx: -------------------------------------------------------------------------------- 1 | // Test for std::to_string/std::from_string for integral types. 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | char z[100]; 8 | auto rt = std::to_chars(std::begin(z), std::end(z), 9ULL); 9 | if (rt.ec != std::errc{}) 10 | return 1; 11 | unsigned long long n; 12 | auto rf = std::from_chars(std::cbegin(z), std::cend(z), n); 13 | if (rf.ec != std::errc{}) 14 | return 2; 15 | return (n == 9ULL) ? 0 : 1; 16 | } 17 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_CMP.cxx: -------------------------------------------------------------------------------- 1 | // Test for C++20 std::cmp_greater etc. support. 2 | // C++20: Assume support. 3 | #include 4 | 5 | 6 | int main() 7 | { 8 | return std::cmp_greater(-1, 2u) && std::cmp_less_equal(3, 0); 9 | } 10 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_CONCEPTS.cxx: -------------------------------------------------------------------------------- 1 | // Feature check for 'PQXX_HAVE_CONCEPTS'. 2 | // Generated by generate_cxx_checks.py. 3 | #include 4 | #if !defined(__cpp_concepts) 5 | # error "No PQXX_HAVE_CONCEPTS: __cpp_concepts is not set." 6 | #endif 7 | #if !__cpp_concepts 8 | # error "No PQXX_HAVE_CONCEPTS: __cpp_concepts is false." 9 | #endif 10 | 11 | int main() {} 12 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_CXA_DEMANGLE.cxx: -------------------------------------------------------------------------------- 1 | // Test for cross-vendor C++ ABI's __cxa_demangle function. 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | int main() 10 | { 11 | int status = 0; 12 | char *name = 13 | abi::__cxa_demangle(typeid(10).name(), nullptr, nullptr, &status); 14 | if (status != 0) 15 | throw std::runtime_error("Demangle failed!"); 16 | int result = std::strcmp(name, "int"); 17 | std::free(name); 18 | return result; 19 | } 20 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_GCC_PURE.cxx: -------------------------------------------------------------------------------- 1 | // Test for gcc-style "pure" attribute. 2 | int __attribute__((pure)) f() 3 | { 4 | return 0; 5 | } 6 | 7 | int main() 8 | { 9 | return f(); 10 | } 11 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_GCC_VISIBILITY.cxx: -------------------------------------------------------------------------------- 1 | // Test for gcc-style "visibility" attribute. 2 | struct __attribute__((visibility("hidden"))) D 3 | { 4 | D() {} 5 | int f() { return 0; } 6 | }; 7 | 8 | int main() 9 | { 10 | D d; 11 | return d.f(); 12 | } 13 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_LIKELY.cxx: -------------------------------------------------------------------------------- 1 | // Test for C++20 [[likely]] and [[unlikely]] attributes. 2 | // C++20: Assume support. 3 | 4 | int main(int argc, char **) 5 | { 6 | #if __cplusplus < 202002L 7 | deliberately_fail(because, older, C++, standard); 8 | #endif 9 | 10 | int x = 0; 11 | if (argc == 1) [[likely]] 12 | x = 0; 13 | else 14 | x = 1; 15 | return x; 16 | } 17 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_MULTIDIM.cxx: -------------------------------------------------------------------------------- 1 | // Feature check for 'PQXX_HAVE_MULTIDIM'. 2 | // Generated by generate_cxx_checks.py. 3 | #include 4 | #if !defined(__cpp_multidimensional_subscript) 5 | # error "No PQXX_HAVE_MULTIDIM: __cpp_multidimensional_subscript is not set." 6 | #endif 7 | #if !__cpp_multidimensional_subscript 8 | # error "No PQXX_HAVE_MULTIDIM: __cpp_multidimensional_subscript is false." 9 | #endif 10 | 11 | int main() {} 12 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_PATH.cxx: -------------------------------------------------------------------------------- 1 | // Check for working std::filesystem support. 2 | #include 3 | 4 | 5 | int main() 6 | { 7 | // Apparently some versions of MinGW lack this comparison operator. 8 | return std::filesystem::path{} != std::filesystem::path{}; 9 | } 10 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_POLL.cxx: -------------------------------------------------------------------------------- 1 | // Test for poll(). 2 | #include 3 | 4 | int main() 5 | { 6 | return poll(nullptr, 0, 0); 7 | } 8 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_SLEEP_FOR.cxx: -------------------------------------------------------------------------------- 1 | // Test for std::this_thread::sleep_for(). 2 | /* For some reason MinGW's header seems to be broken. 3 | * 4 | * But it gets worse. It looks as if we can include without problems 5 | * in this configuration test. Why does it break when MinGW users try to build 6 | * the library, but succeed when we try it here? 7 | * 8 | * To try and get close to the situation in the library code itself, we try 9 | * including some standard headers and OS headers that we don't strictly need 10 | * here. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | #if __has_include() 23 | # include 24 | #endif 25 | #if __has_include() 26 | # include 27 | #endif 28 | #if __has_include() 29 | # include 30 | #endif 31 | 32 | 33 | int main() 34 | { 35 | std::this_thread::sleep_for(std::chrono::microseconds{10u}); 36 | } 37 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_SOURCE_LOCATION.cxx: -------------------------------------------------------------------------------- 1 | // Feature check for 'PQXX_HAVE_SOURCE_LOCATION'. 2 | // Generated by generate_cxx_checks.py. 3 | #include 4 | #if !defined(__cpp_lib_source_location) 5 | # error "No PQXX_HAVE_SOURCE_LOCATION: __cpp_lib_source_location is not set." 6 | #endif 7 | #if !__cpp_lib_source_location 8 | # error "No PQXX_HAVE_SOURCE_LOCATION: __cpp_lib_source_location is false." 9 | #endif 10 | 11 | int main() {} 12 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_SPAN.cxx: -------------------------------------------------------------------------------- 1 | // Feature check for 'PQXX_HAVE_SPAN'. 2 | // Generated by generate_cxx_checks.py. 3 | #include 4 | #if !defined(__cpp_lib_span) 5 | # error "No PQXX_HAVE_SPAN: __cpp_lib_span is not set." 6 | #endif 7 | #if !__cpp_lib_span 8 | # error "No PQXX_HAVE_SPAN: __cpp_lib_span is false." 9 | #endif 10 | 11 | int main() {} 12 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_SSIZE.cxx: -------------------------------------------------------------------------------- 1 | // Feature check for 'PQXX_HAVE_SSIZE'. 2 | // Generated by generate_cxx_checks.py. 3 | #include 4 | #if !defined(__cpp_lib_ssize) 5 | # error "No PQXX_HAVE_SSIZE: __cpp_lib_ssize is not set." 6 | #endif 7 | #if !__cpp_lib_ssize 8 | # error "No PQXX_HAVE_SSIZE: __cpp_lib_ssize is false." 9 | #endif 10 | 11 | int main() {} 12 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_STRERROR_R.cxx: -------------------------------------------------------------------------------- 1 | // Check for strerror_r. 2 | // It can be either the POSIX version (which returns int) or the GNU version 3 | // (which returns char *). 4 | 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | char buffer[200]; 11 | auto res{strerror_r(1, buffer, 200)}; 12 | // Sidestep type differences. We don't really care what the value is. 13 | return not not res; 14 | } 15 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_STRERROR_S.cxx: -------------------------------------------------------------------------------- 1 | // Test for strerror_s, as defined in Windows and C11. 2 | // Presumably this'll be part of the C++ standard some day. 3 | 4 | #include 5 | 6 | int main() 7 | { 8 | using namespace std; 9 | char buf[200]; 10 | return strerror_s(buf, 200, 1); 11 | } 12 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_THREAD_LOCAL.cxx: -------------------------------------------------------------------------------- 1 | // Test for std::to_string/std::from_string for floating-point types. 2 | // TODO: Probably no longer needed once we always have float std::charconv. 3 | #include 4 | #include 5 | 6 | int main(int argc, char **) 7 | { 8 | #if defined(__MINGW32__) && defined(__GNUC__) 9 | # if __GNUC__ < 11 || ((__GNUC__ == 11) && (__GNU_MINOR__ == 0)) 10 | # error "On MinGW before gcc 11.1, thread_local breaks at run time." 11 | # endif 12 | #endif 13 | thread_local std::stringstream s; 14 | s << argc; 15 | std::cout << s.str(); 16 | } 17 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_UNREACHABLE.cxx: -------------------------------------------------------------------------------- 1 | // Feature check for 'PQXX_HAVE_UNREACHABLE'. 2 | // Generated by generate_cxx_checks.py. 3 | #include 4 | #if !defined(__cpp_lib_unreachable) 5 | # error "No PQXX_HAVE_UNREACHABLE: __cpp_lib_unreachable is not set." 6 | #endif 7 | #if !__cpp_lib_unreachable 8 | # error "No PQXX_HAVE_UNREACHABLE: __cpp_lib_unreachable is false." 9 | #endif 10 | 11 | int main() {} 12 | -------------------------------------------------------------------------------- /libpqxx/config-tests/PQXX_HAVE_YEAR_MONTH_DAY.cxx: -------------------------------------------------------------------------------- 1 | // Test for std::chrono::year_month_day etc. 2 | #include 3 | 4 | int main() 5 | { 6 | return int(std::chrono::year{1}); 7 | } 8 | -------------------------------------------------------------------------------- /libpqxx/config-tests/README.md: -------------------------------------------------------------------------------- 1 | Configuration tests 2 | =================== 3 | 4 | Libpqxx comes with support for two different build systems: the GNU autotools, 5 | and CMake. 6 | 7 | We need to teach both of these to test things like "does this compiler 8 | environment support `std::to_chars` for floating-point types?" 9 | 10 | In both build systems we test these things by trying to compile a particular 11 | snippet of code, found in this directry, and seeing whether that succeeds. 12 | 13 | To avoid duplicating those snippets for multiple build systems, we put them 14 | here. Both the autotools configuration and the CMake configuration can refer to 15 | them that way. We generate autoconf and cmake configuration automatically to 16 | inject those checks, avoiding tedious repetition. 17 | 18 | Some of the checks are based on C++20 feature test macros. We generate those 19 | automatically using `tools/generate_cxx_checks.py`. 20 | 21 | It took a bit of nasty magic to read a C++ source file into m4 for the autoconf 22 | side and treat it as a string literal, without macro expansion. There is every 23 | chance that I missed something, so be prepared for tests failing for unexpected 24 | reasons! Some C++ syntax may end up having an unforeseen meaning in m4, and 25 | screw up the handling of the code snippet. Re-configure, and read your logs 26 | carefully after editing these snippets. 27 | -------------------------------------------------------------------------------- /libpqxx/config-tests/no_need_fslib.cxx: -------------------------------------------------------------------------------- 1 | // Check whether we need to link to the stdc++fs library. 2 | // 3 | // We assume that the presence of the header means that we have 4 | // support for the basics of std::filesystem. This check will succeed if 5 | // either there is no header, or there is one and it works without 6 | // any special options. If the link fails, we assume that -lstdc++fs will fix 7 | // it for us. 8 | 9 | #include 10 | 11 | #if __has_include() 12 | # include 13 | #endif 14 | 15 | 16 | int main() 17 | { 18 | #if __has_include() 19 | std::cout << std::filesystem::path{"foo.bar"}.c_str() << '\n'; 20 | #endif 21 | } 22 | -------------------------------------------------------------------------------- /libpqxx/config/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST=m4/Makefile.am sample-headers 2 | MAINTAINERCLEANFILES=Makefile.in config.guess config.sub install-sh \ 3 | ltmain.sh missing mkinstalldirs 4 | 5 | dist-hook: 6 | find "${distdir}" -type d -name CVS -print0 | xargs -0 rm -rf 7 | find "${distdir}" -type d -name .svn -print0 | xargs -0 rm -rf 8 | 9 | -------------------------------------------------------------------------------- /libpqxx/config/m4/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES=Makefile.in config.guess config.sub install-sh \ 2 | ltmain.sh missing mkinstalldirs 3 | 4 | -------------------------------------------------------------------------------- /libpqxx/config/m4/ltversion.m4: -------------------------------------------------------------------------------- 1 | # ltversion.m4 -- version numbers -*- Autoconf -*- 2 | # 3 | # Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation, 4 | # Inc. 5 | # Written by Scott James Remnant, 2004 6 | # 7 | # This file is free software; the Free Software Foundation gives 8 | # unlimited permission to copy and/or distribute it, with or without 9 | # modifications, as long as this notice is preserved. 10 | 11 | # @configure_input@ 12 | 13 | # serial 4245 ltversion.m4 14 | # This file is part of GNU Libtool 15 | 16 | m4_define([LT_PACKAGE_VERSION], [2.4.7]) 17 | m4_define([LT_PACKAGE_REVISION], [2.4.7]) 18 | 19 | AC_DEFUN([LTVERSION_VERSION], 20 | [macro_version='2.4.7' 21 | macro_revision='2.4.7' 22 | _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) 23 | _LT_DECL(, macro_revision, 0) 24 | ]) 25 | -------------------------------------------------------------------------------- /libpqxx/configitems: -------------------------------------------------------------------------------- 1 | PACKAGE internal autotools 2 | PACKAGE_BUGREPORT internal autotools 3 | PACKAGE_NAME internal autotools 4 | PACKAGE_STRING internal autotools 5 | PACKAGE_TARNAME internal autotools 6 | PACKAGE_VERSION internal autotools 7 | PQXX_HAVE_CHARCONV_INT internal compiler 8 | PQXX_HAVE_CHARCONV_FLOAT internal compiler 9 | PQXX_HAVE_CMP public compiler 10 | PQXX_HAVE_CONCEPTS public compiler 11 | PQXX_HAVE_CXA_DEMANGLE internal compiler 12 | PQXX_HAVE_GCC_PURE public compiler 13 | PQXX_HAVE_GCC_VISIBILITY public compiler 14 | PQXX_HAVE_MULTIDIM public compiler 15 | PQXX_HAVE_LIKELY public compiler 16 | PQXX_HAVE_PATH public compiler 17 | PQXX_HAVE_POLL internal compiler 18 | PQXX_HAVE_SLEEP_FOR internal compiler 19 | PQXX_HAVE_SOURCE_LOCATION public compiler 20 | PQXX_HAVE_SPAN public compiler 21 | PQXX_HAVE_SSIZE public compiler 22 | PQXX_HAVE_STRERROR_R public compiler 23 | PQXX_HAVE_STRERROR_S public compiler 24 | PQXX_HAVE_THREAD_LOCAL internal compiler 25 | PQXX_HAVE_UNREACHABLE public compiler 26 | PQXX_HAVE_YEAR_MONTH_DAY public compiler 27 | VERSION internal autotools 28 | -------------------------------------------------------------------------------- /libpqxx/cxx_features.txt: -------------------------------------------------------------------------------- 1 | # Feature checks that we can perform simply by testing a C++ feature 2 | # test macro. 3 | # 4 | # Each (non-empty, non-comment) line consists of a libpqxx feature macro 5 | # and the corresponding C++ feature test macro that we need to check in 6 | # order to detect that feature. 7 | # 8 | # From these, the autogen script generates code snippets that the build 9 | # configuration step can try to compile, as well as the bits of config 10 | # to do that in the supported build systems. 11 | # 12 | # Remember to enter each of these in configitems as well, or they won't 13 | # end up in the actual configuration headers. 14 | 15 | PQXX_HAVE_CONCEPTS __cpp_concepts 16 | PQXX_HAVE_MULTIDIM __cpp_multidimensional_subscript 17 | PQXX_HAVE_SOURCE_LOCATION __cpp_lib_source_location 18 | PQXX_HAVE_SPAN __cpp_lib_span 19 | PQXX_HAVE_SSIZE __cpp_lib_ssize 20 | PQXX_HAVE_UNREACHABLE __cpp_lib_unreachable 21 | -------------------------------------------------------------------------------- /libpqxx/doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_program(HAVE_DOXYGEN doxygen) 2 | 3 | if(NOT HAVE_DOXYGEN) 4 | message(FATAL_ERROR "***************************************************** 5 | Doxygen not found. 6 | Install it, or configure with -DBUILD_DOC=OFF 7 | *****************************************************" 8 | ) 9 | endif() 10 | 11 | set(PQXXVERSION "${CMAKE_PROJECT_VERSION}") 12 | set(top_srcdir "${PROJECT_SOURCE_DIR}") 13 | set(PQXX_ABI "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") 14 | set(PQXX_MAJOR "${PROJECT_VERSION_MAJOR}") 15 | set(PQXX_MINOR "${PROJECT_VERSION_MINOR}") 16 | 17 | find_program(HAVE_DOT dot) 18 | if(HAVE_DOT) 19 | set(HAVE_DOT YES) 20 | else() 21 | set(HAVE_DOT NO) 22 | endif() 23 | 24 | configure_file(Doxyfile.in Doxyfile) 25 | 26 | if(HAVE_DOXYGEN) 27 | file( 28 | GLOB DOXYGEN_SOURCES 29 | "${PROJECT_SOURCE_DIR}/include/pqxx/*.hxx" 30 | "${PROJECT_SOURCE_DIR}/include/pqxx/doc/*.md" 31 | "${PROJECT_SOURCE_DIR}/*.cxx" 32 | ) 33 | set(DOXYGEN_STAMP_FILE "${CMAKE_CURRENT_BINARY_DIR}/doxygen.stamp") 34 | add_custom_command(OUTPUT ${DOXYGEN_STAMP_FILE} 35 | COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/html 36 | COMMAND doxygen Doxyfile 37 | COMMAND ${CMAKE_COMMAND} -E touch ${DOXYGEN_STAMP_FILE} 38 | DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile ${DOXYGEN_SOURCES} 39 | COMMENT "Generate API documentation" 40 | VERBATIM 41 | ) 42 | add_custom_target(doxygen ALL 43 | DEPENDS ${DOXYGEN_STAMP_FILE} 44 | SOURCES ${DOXYGEN_SOURCES} 45 | ) 46 | install( 47 | DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html 48 | DESTINATION ${CMAKE_INSTALL_DOCDIR}/html 49 | ) 50 | endif() 51 | -------------------------------------------------------------------------------- /libpqxx/doc/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = Makefile.in 2 | 3 | maintainer-clean-local: 4 | $(RM) -rf html 5 | $(RM) reference-stamp 6 | $(MKDIR) html 7 | 8 | EXTRA_DIST= Doxyfile.in libpqxx.xml reference-stamp 9 | 10 | all-local: docs 11 | 12 | if BUILD_REFERENCE 13 | DOCS = reference 14 | else 15 | DOCS = 16 | endif 17 | 18 | if MAINTAINER_MODE 19 | REFERENCE_STAMP_DEP = ../src/libpqxx.la 20 | else 21 | REFERENCE_STAMP_DEP = 22 | endif 23 | 24 | docs: $(DOCS) 25 | 26 | reference: reference-stamp 27 | reference-stamp: Doxyfile.in $(REFERENCE_STAMP_DEP) 28 | if [ -x "$(DOXYGEN)" ]; then \ 29 | $(MKDIR_P) html; \ 30 | $(DOXYGEN) Doxyfile; \ 31 | touch $@; \ 32 | else \ 33 | echo >&2; \ 34 | echo >&2 "*****************************************************"; \ 35 | echo >&2; \ 36 | echo >&2 "Doxygen not found."; \ 37 | echo >&2 "Install it, or configure with --disable-documentation"; \ 38 | echo >&2; \ 39 | echo >&2 "*****************************************************"; \ 40 | exit 1; \ 41 | fi 42 | 43 | ../src/libpqxx.la: 44 | cd ../src; \ 45 | $(MAKE) libpqxx.la 46 | 47 | 48 | dist-hook: reference 49 | if [ -d $(srcdir)/html ]; then \ 50 | cp -pR html $(distdir)/ ; \ 51 | fi 52 | -------------------------------------------------------------------------------- /libpqxx/doc/_static/readme.txt: -------------------------------------------------------------------------------- 1 | Static HTML files for documentation go here. 2 | -------------------------------------------------------------------------------- /libpqxx/doc/index.rst: -------------------------------------------------------------------------------- 1 | .. x documentation master file, created by 2 | sphinx-quickstart on Sun Dec 3 01:30:12 2017. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | libpqxx 7 | ======= 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | 14 | 15 | Indices and tables 16 | ================== 17 | 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | -------------------------------------------------------------------------------- /libpqxx/include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ############################################################################## 2 | # AUTOMATICALLY GENERATED FILE -- DO NOT EDIT. 3 | # 4 | # This file is generated automatically by libpqxx's template2mak.py script, and 5 | # will be rewritten from time to time. 6 | # 7 | # If you modify this file, chances are your modifications will be lost. 8 | # 9 | # The template2mak.py script should be available in the tools directory of the 10 | # libpqxx source archive. 11 | # 12 | # Generated from template './include/CMakeLists.txt.template'. 13 | # ############################################################################## 14 | install( 15 | DIRECTORY pqxx "${PROJECT_BINARY_DIR}/include/pqxx" 16 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 17 | FILES_MATCHING 18 | # For each X.hxx, install both X.hxx itself and plain X. 19 | PATTERN *.hxx 20 | # TODO: Is there any way to do this with CMake's globbing? 21 | PATTERN array 22 | PATTERN binarystring 23 | PATTERN blob 24 | PATTERN composite 25 | PATTERN connection 26 | PATTERN cursor 27 | PATTERN dbtransaction 28 | PATTERN errorhandler 29 | PATTERN except 30 | PATTERN field 31 | PATTERN isolation 32 | PATTERN largeobject 33 | PATTERN nontransaction 34 | PATTERN notification 35 | PATTERN params 36 | PATTERN pipeline 37 | PATTERN prepared_statement 38 | PATTERN range 39 | PATTERN result 40 | PATTERN robusttransaction 41 | PATTERN row 42 | PATTERN separated_list 43 | PATTERN strconv 44 | PATTERN stream_from 45 | PATTERN stream_to 46 | PATTERN subtransaction 47 | PATTERN time 48 | PATTERN transaction 49 | PATTERN transaction_base 50 | PATTERN transaction_focus 51 | PATTERN transactor 52 | PATTERN types 53 | PATTERN util 54 | PATTERN version 55 | PATTERN zview 56 | PATTERN internal/*.hxx 57 | PATTERN internal/gates/*.hxx 58 | PATTERN config-public-compiler.h 59 | PATTERN pqxx 60 | PATTERN doc EXCLUDE 61 | ) 62 | 63 | install( 64 | DIRECTORY pqxx/doc/ 65 | DESTINATION ${CMAKE_INSTALL_DOCDIR} 66 | FILES_MATCHING 67 | PATTERN *.md 68 | ) 69 | -------------------------------------------------------------------------------- /libpqxx/include/CMakeLists.txt.template: -------------------------------------------------------------------------------- 1 | install( 2 | DIRECTORY pqxx "${PROJECT_BINARY_DIR}/include/pqxx" 3 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 4 | FILES_MATCHING 5 | # For each X.hxx, install both X.hxx itself and plain X. 6 | PATTERN *.hxx 7 | # TODO: Is there any way to do this with CMake's globbing? 8 | ###MAKTEMPLATE:FOREACH include/pqxx/*.hxx 9 | PATTERN ###BASENAME### 10 | ###MAKTEMPLATE:ENDFOREACH 11 | PATTERN internal/*.hxx 12 | PATTERN internal/gates/*.hxx 13 | PATTERN config-public-compiler.h 14 | PATTERN pqxx 15 | PATTERN doc EXCLUDE 16 | ) 17 | 18 | install( 19 | DIRECTORY pqxx/doc/ 20 | DESTINATION ${CMAKE_INSTALL_DOCDIR} 21 | FILES_MATCHING 22 | PATTERN *.md 23 | ) 24 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES=Makefile.in stamp-h.in 2 | 3 | noinst_HEADERS = \ 4 | config-internal-autotools.h 5 | 6 | nodist_noinst_HEADERS = \ 7 | config.h \ 8 | config-internal-compiler.h 9 | 10 | DISTCLEANFILES = \ 11 | config-internal-autotools.h \ 12 | config-internal-compiler.h \ 13 | config-public-compiler.h 14 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/array: -------------------------------------------------------------------------------- 1 | /** Handling of SQL arrays. 2 | */ 3 | // Actual definitions in .hxx file so editors and such recognize file type. 4 | #include "pqxx/internal/header-pre.hxx" 5 | #include "pqxx/array.hxx" 6 | #include "pqxx/internal/header-post.hxx" 7 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/binarystring: -------------------------------------------------------------------------------- 1 | /** BYTEA (binary string) conversions. 2 | */ 3 | // Actual definitions in .hxx file so editors and such recognize file type. 4 | #include "pqxx/internal/header-pre.hxx" 5 | #include "pqxx/binarystring.hxx" 6 | #include "pqxx/internal/header-post.hxx" 7 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/blob: -------------------------------------------------------------------------------- 1 | /** Binary Large Objects interface. 2 | */ 3 | // Actual definitions in .hxx file so editors and such recognize file type. 4 | #include "pqxx/internal/header-pre.hxx" 5 | #include "pqxx/blob.hxx" 6 | #include "pqxx/internal/header-post.hxx" 7 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/composite: -------------------------------------------------------------------------------- 1 | /** Handling of SQL "composite types." 2 | */ 3 | // Actual definitions in .hxx file so editors and such recognize file type. 4 | #include "pqxx/internal/header-pre.hxx" 5 | #include "pqxx/composite.hxx" 6 | #include "pqxx/internal/header-post.hxx" 7 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/connection: -------------------------------------------------------------------------------- 1 | /** pqxx::connection class. 2 | * 3 | * pqxx::connection encapsulates a connection to a database. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/connection.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/cursor: -------------------------------------------------------------------------------- 1 | /** Definition of the iterator/container-style cursor classes. 2 | * 3 | * C++-style wrappers for SQL cursors 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/cursor.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/dbtransaction: -------------------------------------------------------------------------------- 1 | /** pqxx::dbtransaction abstract base class. 2 | * 3 | * pqxx::dbransaction defines a real transaction on the database. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/dbtransaction.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/doc/binary-data.md: -------------------------------------------------------------------------------- 1 | Binary data {#binary} 2 | =========== 3 | 4 | The database has two ways of storing binary data: `BYTEA` is like a string, but 5 | containing bytes rather than text characters. And _large objects_ are more 6 | like a separate table containing binary objects. 7 | 8 | Generally you'll want to use `BYTEA` for reasonably-sized values, and large 9 | objects for very large values. 10 | 11 | That's the database side. On the C++ side, in libpqxx, all binary data must be 12 | either `pqxx::bytes` or `pqxx::bytes_view`; or if you're building in C++20 or 13 | better, anything that's a block of contiguous `std::byte` in memory. 14 | 15 | So for example, if you want to write a large object, you'd create a 16 | `pqxx::blob` object. And you might use that to write data in the form of 17 | `pqxx::bytes_view`. 18 | 19 | Your particular binary data may look different though. You may have it in a 20 | `std::string`, or a `std::vector`, or a pointer to `char` 21 | accompanied by a size (which could be signed or unsigned, and of any of a few 22 | different widths). Sometimes that's your choice, or sometimes some other 23 | library will dictate what form it takes. 24 | 25 | So long as it's _basically_ still a block of bytes though, you can use 26 | `pqxx::binary_cast` to construct a `pqxx::bytes_view` from it. 27 | 28 | There are two forms of `binary_cast`. One takes a single argument that must 29 | support `std::data()` and `std::size()`: 30 | 31 | ```cxx 32 | std::string hi{"Hello binary world"}; 33 | my_blob.write(pqxx::binary_cast(hi); 34 | ``` 35 | 36 | The other takes a pointer and a size: 37 | 38 | ```cxx 39 | char const greeting[] = "Hello binary world"; 40 | char const *hi = greeting; 41 | my_blob.write(pqxx::binary_cast(hi, sizeof(greeting))); 42 | ``` 43 | 44 | 45 | Caveats 46 | ------- 47 | 48 | There are some restrictions on `binary_cast` that you must be aware of. 49 | 50 | First, your data must of a type that gives us _bytes._ So: `char`, 51 | `unsigned char`, `signed char`, `int8_t`, `uint8_t`, or of course `std::byte`. 52 | You can't feed in a vector of `double`, or anything like that. 53 | 54 | Second, the data must be laid out as a contiguous block in memory. If there's 55 | no `std::data()` implementation for your type, it's not suitable. 56 | 57 | Third, `binary_cast` only constructs something like a `std::string_view`. It 58 | does not make a copy of your actual data. So, make sure that your data remains 59 | alive and in the same place while you're using it. 60 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/doc/mainpage.md: -------------------------------------------------------------------------------- 1 | libpqxx {#mainpage} 2 | ======= 3 | 4 | @version 7.9.0 5 | @author Jeroen T. Vermeulen 6 | @see http://pqxx.org 7 | @see https://github.com/jtv/libpqxx 8 | 9 | Welcome to libpqxx, the C++ API to the PostgreSQL database management system. 10 | 11 | Compiling this package requires PostgreSQL to be installed -- including the 12 | C headers for client development. The library builds on top of PostgreSQL's 13 | standard C API, libpq. The libpq headers are not needed to compile client 14 | programs, however. 15 | 16 | For a quick introduction to installing and using libpqxx, see the README.md 17 | file. The latest information can be found at 18 | [http://pqxx.org/](http://pqxx.org/). 19 | 20 | 21 | Some links that should help you find your bearings: 22 | 23 | * @ref getting-started 24 | * @ref thread-safety 25 | * @ref connections 26 | * @ref transactions 27 | * @ref escaping 28 | * @ref performance 29 | * @ref transactor 30 | * @ref datatypes 31 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/doc/mainpage.md.template: -------------------------------------------------------------------------------- 1 | libpqxx {#mainpage} 2 | ======= 3 | 4 | @version @PQXXVERSION@ 5 | @author Jeroen T. Vermeulen 6 | @see http://pqxx.org 7 | @see https://github.com/jtv/libpqxx 8 | 9 | Welcome to libpqxx, the C++ API to the PostgreSQL database management system. 10 | 11 | Compiling this package requires PostgreSQL to be installed -- including the 12 | C headers for client development. The library builds on top of PostgreSQL's 13 | standard C API, libpq. The libpq headers are not needed to compile client 14 | programs, however. 15 | 16 | For a quick introduction to installing and using libpqxx, see the README.md 17 | file. The latest information can be found at 18 | [http://pqxx.org/](http://pqxx.org/). 19 | 20 | 21 | Some links that should help you find your bearings: 22 | 23 | * @ref getting-started 24 | * @ref thread-safety 25 | * @ref connections 26 | * @ref transactions 27 | * @ref escaping 28 | * @ref performance 29 | * @ref transactor 30 | * @ref datatypes 31 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/doc/performance.md: -------------------------------------------------------------------------------- 1 | Performance features {#performance} 2 | ==================== 3 | 4 | If your program's database interaction is not as efficient as it needs to be, 5 | the first place to look is usually the SQL you're executing. But libpqxx 6 | has a few specialized features to help you squeeze more performance out 7 | of how you issue commands and retrieve data: 8 | 9 | * @ref streams. Use these as a faster way to transfer data between your 10 | code and the database. 11 | * `std::string_view` and `pqxx::zview`. In places where traditional C++ worked 12 | with `std::string`, see whether `std::string_view` or `pqxx::zview` will 13 | do. Of course that means that you'll have to look at the data's lifetime 14 | more carefully, but it'll save the computer a lot of copying. 15 | * @ref prepared. These can be executed many times without the server 16 | parsing and planning them anew each time. They also save you having to 17 | escape string parameters. 18 | * `pqxx::pipeline` lets you send queries to the database in batches, and 19 | continue other processing while they are executing. 20 | * `pqxx::connecting` lets you start setting up a database connection, but 21 | without blocking the thread. 22 | 23 | As always of course, don't risk the quality of your code for optimizations 24 | that you don't need! 25 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/doc/thread-safety.md: -------------------------------------------------------------------------------- 1 | Thread safety {#thread-safety} 2 | ============= 3 | 4 | This library does not contain any locking code to protect objects against 5 | simultaneous modification in multi-threaded programs. Therefore it is up 6 | to you, the user of the library, to ensure that your threaded client 7 | programs perform no conflicting operations concurrently. 8 | 9 | Most of the time this isn't hard. Result sets are immutable, so you can 10 | share them between threads without problem. The main rule is: 11 | 12 | @li Treat a connection, together with any and all objects related to it, as 13 | a "world" of its own. You should generally make sure that the same "world" 14 | is never accessed by another thread while you're doing anything non-const 15 | in there. 16 | 17 | That means: don't issue a query on a transaction while you're also opening 18 | a subtransaction, don't access a cursor while you may also be committing, 19 | and so on. 20 | 21 | In particular, cursors are tricky. It's easy to perform a non-const 22 | operation without noticing. So, if you're going to share cursors or 23 | cursor-related objects between threads, lock very conservatively! 24 | 25 | Use `pqxx::describe_thread_safety` to find out at runtime what level of 26 | thread safety is implemented in your build and version of libpqxx. It 27 | returns a `pqxx::thread_safety_model` describing what you can and cannot rely 28 | on. A command-line utility `tools/pqxxthreadsafety` prints out the same 29 | information. 30 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/errorhandler: -------------------------------------------------------------------------------- 1 | /** pqxx::errorhandler class. 2 | * 3 | * Callbacks for handling errors and warnings. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/errorhandler.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/except: -------------------------------------------------------------------------------- 1 | /** libpqxx exception classes. 2 | * 3 | * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ... 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/except.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/field: -------------------------------------------------------------------------------- 1 | /** pqxx::field class. 2 | * 3 | * pqxx::field refers to a field in a query result. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/field.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/callgate.hxx: -------------------------------------------------------------------------------- 1 | #ifndef PQXX_H_CALLGATE 2 | #define PQXX_H_CALLGATE 3 | 4 | /* 5 | Here's what a typical gate class definition looks like: 6 | 7 | ```cxx 8 | #include 9 | 10 | namespace pqxx::internal::gate 11 | { 12 | class PQXX_PRIVATE @gateclass@ : callgate<@host@> 13 | { 14 | friend class @client@; 15 | 16 | @gateclass@(reference x) : super(x) {} 17 | 18 | // Methods here. Use home() to access the host-class object. 19 | }; 20 | } // namespace pqxx::internal::gate 21 | ``` 22 | */ 23 | 24 | namespace pqxx::internal 25 | { 26 | /// Base class for call gates. 27 | /** 28 | * A call gate defines a limited, private interface on the host class that 29 | * specified client classes can access. 30 | * 31 | * The metaphor works as follows: the gate stands in front of a "home," which 32 | * is really a class, and only lets specific friends in. 33 | * 34 | * To implement a call gate that gives client C access to host H, 35 | * * derive a gate class from callgate; 36 | * * make the gate class a friend of H; 37 | * * make C a friend of the gate class; and 38 | * * implement "stuff C can do with H" as private members in the gate class. 39 | * 40 | * This special kind of "gated" friendship gives C private access to H, but 41 | * only through an expressly limited interface. The gate class can access its 42 | * host object as home(). 43 | * 44 | * Keep gate classes entirely stateless. They should be ultra-lightweight 45 | * wrappers for their host classes, and be optimized away as much as possible 46 | * by the compiler. Once you start adding state, you're on a slippery slope 47 | * away from the pure, clean, limited interface pattern that gate classes are 48 | * meant to implement. 49 | * 50 | * Ideally, all member functions of the gate class should be one-liners passing 51 | * calls straight on to the host class. It can be useful however to break this 52 | * rule temporarily during inter-class refactoring. 53 | */ 54 | template class PQXX_PRIVATE callgate 55 | { 56 | protected: 57 | /// This class, to keep constructors easy. 58 | using super = callgate; 59 | /// A reference to the host class. Helps keep constructors easy. 60 | using reference = HOME &; 61 | 62 | callgate(reference x) : m_home(x) {} 63 | 64 | /// The home object. The gate class has full "private" access. 65 | reference home() const noexcept { return m_home; } 66 | 67 | private: 68 | reference m_home; 69 | }; 70 | } // namespace pqxx::internal 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/concat.hxx: -------------------------------------------------------------------------------- 1 | #if !defined(PQXX_CONCAT_HXX) 2 | # define PQXX_CONCAT_HXX 3 | 4 | # include 5 | # include 6 | 7 | # include "pqxx/strconv.hxx" 8 | 9 | namespace pqxx::internal 10 | { 11 | /// Convert item to a string, write it into [here, end). 12 | template 13 | void render_item(TYPE const &item, char *&here, char *end) 14 | { 15 | here = string_traits::into_buf(here, end, item) - 1; 16 | } 17 | 18 | 19 | // C++20: Support non-random_access_range ranges. 20 | /// Efficiently combine a bunch of items into one big string. 21 | /** Use this as an optimised version of string concatentation. It takes just 22 | * about any type; it will represent each item as a string according to its 23 | * @ref string_traits. 24 | * 25 | * This is a simpler, more specialised version of @ref separated_list for a 26 | * statically known series of items, possibly of different types. 27 | */ 28 | template 29 | [[nodiscard]] inline std::string concat(TYPE... item) 30 | { 31 | std::string buf; 32 | // Size to accommodate string representations of all inputs, minus their 33 | // terminating zero bytes. 34 | buf.resize(size_buffer(item...)); 35 | 36 | char *const data{buf.data()}; 37 | char *here = data; 38 | char *end = data + std::size(buf); 39 | (render_item(item, here, end), ...); 40 | 41 | buf.resize(static_cast(here - data)); 42 | return buf; 43 | } 44 | } // namespace pqxx::internal 45 | #endif 46 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/encoding_group.hxx: -------------------------------------------------------------------------------- 1 | /** Enum type for supporting encodings in libpqxx 2 | * 3 | * Copyright (c) 2000-2024, Jeroen T. Vermeulen. 4 | * 5 | * See COPYING for copyright license. If you did not receive a file called 6 | * COPYING with this source code, please notify the distributor of this 7 | * mistake, or contact the author. 8 | */ 9 | #ifndef PQXX_H_ENCODING_GROUP 10 | #define PQXX_H_ENCODING_GROUP 11 | 12 | #include 13 | 14 | namespace pqxx::internal 15 | { 16 | // Types of encodings supported by PostgreSQL, see 17 | // https://www.postgresql.org/docs/current/static/multibyte.html#CHARSET-TABLE 18 | enum class encoding_group 19 | { 20 | // Handles all single-byte fixed-width encodings 21 | MONOBYTE, 22 | 23 | // Multibyte encodings. 24 | // Many of these can embed ASCII-like bytes inside multibyte characters, 25 | // notably Big5, SJIS, SHIFT_JIS_2004, GP18030, GBK, JOHAB, UHC. 26 | BIG5, 27 | EUC_CN, 28 | EUC_JP, 29 | EUC_KR, 30 | EUC_TW, 31 | GB18030, 32 | GBK, 33 | JOHAB, 34 | MULE_INTERNAL, 35 | SJIS, 36 | UHC, 37 | UTF8, 38 | }; 39 | 40 | 41 | // TODO: Get rid of these. Specialise at higher level. 42 | /// Function type: "find the end of the current glyph." 43 | /** This type of function takes a text buffer, and a location in that buffer, 44 | * and returns the location one byte past the end of the current glyph. 45 | * 46 | * The start offset marks the beginning of the current glyph. It must fall 47 | * within the buffer. 48 | * 49 | * There are multiple different glyph scanner implementations, for different 50 | * kinds of encodings. 51 | */ 52 | using glyph_scanner_func = 53 | std::size_t(char const buffer[], std::size_t buffer_len, std::size_t start); 54 | 55 | 56 | /// Function type: "find first occurrence of specific any of ASCII characters." 57 | /** This type of function takes a text buffer, and a location in that buffer, 58 | * and returns the location of the first occurrence within that string of any 59 | * of a specific set of ASCII characters. 60 | * 61 | * For efficiency, it's up to the function to know which those special ASCII 62 | * characters are. 63 | * 64 | * The start offset marks the beginning of the current glyph. It must fall 65 | * within the buffer. 66 | * 67 | * Returns the offset of the first matching character, or if there is none, the 68 | * end of `haystack`. 69 | */ 70 | using char_finder_func = 71 | std::size_t(std::string_view haystack, std::size_t start); 72 | } // namespace pqxx::internal 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/connection-errorhandler.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace pqxx 4 | { 5 | class connection; 6 | class errorhandler; 7 | } // namespace pqxx 8 | 9 | namespace pqxx::internal::gate 10 | { 11 | class PQXX_PRIVATE connection_errorhandler : callgate 12 | { 13 | friend class pqxx::errorhandler; 14 | 15 | connection_errorhandler(reference x) : super(x) {} 16 | 17 | void register_errorhandler(errorhandler *h) 18 | { 19 | home().register_errorhandler(h); 20 | } 21 | void unregister_errorhandler(errorhandler *h) 22 | { 23 | home().unregister_errorhandler(h); 24 | } 25 | }; 26 | } // namespace pqxx::internal::gate 27 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/connection-largeobject.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace pqxx 7 | { 8 | class blob; 9 | class largeobject; 10 | } // namespace pqxx 11 | 12 | 13 | namespace pqxx::internal::gate 14 | { 15 | class PQXX_PRIVATE connection_largeobject : callgate 16 | { 17 | friend class pqxx::blob; 18 | friend class pqxx::largeobject; 19 | 20 | connection_largeobject(reference x) : super(x) {} 21 | 22 | pq::PGconn *raw_connection() const { return home().raw_connection(); } 23 | }; 24 | 25 | 26 | class PQXX_PRIVATE const_connection_largeobject : callgate 27 | { 28 | friend class pqxx::blob; 29 | friend class pqxx::largeobject; 30 | 31 | const_connection_largeobject(reference x) : super(x) {} 32 | 33 | std::string error_message() const { return home().err_msg(); } 34 | }; 35 | } // namespace pqxx::internal::gate 36 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/connection-notification_receiver.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "pqxx/connection.hxx" 4 | 5 | 6 | namespace pqxx 7 | { 8 | class notification_receiver; 9 | } 10 | 11 | 12 | namespace pqxx::internal::gate 13 | { 14 | class PQXX_PRIVATE connection_notification_receiver : callgate 15 | { 16 | friend class pqxx::notification_receiver; 17 | 18 | connection_notification_receiver(reference x) : super(x) {} 19 | 20 | void add_receiver(notification_receiver *receiver) 21 | { 22 | home().add_receiver(receiver); 23 | } 24 | void remove_receiver(notification_receiver *receiver) noexcept 25 | { 26 | home().remove_receiver(receiver); 27 | } 28 | }; 29 | } // namespace pqxx::internal::gate 30 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/connection-pipeline.hxx: -------------------------------------------------------------------------------- 1 | #include "pqxx/internal/libpq-forward.hxx" 2 | #include 3 | 4 | #include "pqxx/pipeline.hxx" 5 | 6 | namespace pqxx::internal::gate 7 | { 8 | class PQXX_PRIVATE connection_pipeline : callgate 9 | { 10 | friend class pqxx::pipeline; 11 | 12 | connection_pipeline(reference x) : super(x) {} 13 | 14 | void start_exec(char const query[]) { home().start_exec(query); } 15 | pqxx::internal::pq::PGresult *get_result() { return home().get_result(); } 16 | void cancel_query() { home().cancel_query(); } 17 | 18 | bool consume_input() noexcept { return home().consume_input(); } 19 | bool is_busy() const noexcept { return home().is_busy(); } 20 | 21 | int encoding_id() { return home().encoding_id(); } 22 | }; 23 | } // namespace pqxx::internal::gate 24 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/connection-sql_cursor.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace pqxx::internal 4 | { 5 | class sql_cursor; 6 | } 7 | 8 | 9 | namespace pqxx::internal::gate 10 | { 11 | class PQXX_PRIVATE connection_sql_cursor : callgate 12 | { 13 | friend class pqxx::internal::sql_cursor; 14 | 15 | connection_sql_cursor(reference x) : super(x) {} 16 | 17 | result exec(char const query[]) { return home().exec(query); } 18 | }; 19 | } // namespace pqxx::internal::gate 20 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/connection-stream_from.hxx: -------------------------------------------------------------------------------- 1 | #if !defined(PQXX_H_CONNECTION_STREAM_FROM) 2 | # define PQXX_H_CONNECTION_STREAM_FROM 3 | 4 | # include 5 | 6 | # include "pqxx/connection.hxx" 7 | 8 | namespace pqxx::internal::gate 9 | { 10 | // Not publicising this call gate to specific classes. We also use it in 11 | // stream_query, which is a template. 12 | struct PQXX_PRIVATE connection_stream_from : callgate 13 | { 14 | connection_stream_from(reference x) : super{x} {} 15 | 16 | auto read_copy_line() { return home().read_copy_line(); } 17 | }; 18 | } // namespace pqxx::internal::gate 19 | #endif 20 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/connection-stream_to.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "pqxx/stream_to.hxx" 4 | 5 | 6 | namespace pqxx::internal::gate 7 | { 8 | class PQXX_PRIVATE connection_stream_to : callgate 9 | { 10 | friend class pqxx::stream_to; 11 | 12 | connection_stream_to(reference x) : super(x) {} 13 | 14 | void write_copy_line(std::string_view line) { home().write_copy_line(line); } 15 | void end_copy_write() { home().end_copy_write(); } 16 | }; 17 | } // namespace pqxx::internal::gate 18 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/connection-transaction.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace pqxx 4 | { 5 | class connection; 6 | } 7 | 8 | namespace pqxx::internal::gate 9 | { 10 | class PQXX_PRIVATE connection_transaction : callgate 11 | { 12 | friend class pqxx::transaction_base; 13 | 14 | connection_transaction(reference x) : super(x) {} 15 | 16 | template result exec(STRING query, std::string_view desc) 17 | { 18 | return home().exec(query, desc); 19 | } 20 | 21 | void register_transaction(transaction_base *t) 22 | { 23 | home().register_transaction(t); 24 | } 25 | void unregister_transaction(transaction_base *t) noexcept 26 | { 27 | home().unregister_transaction(t); 28 | } 29 | 30 | auto read_copy_line() { return home().read_copy_line(); } 31 | void write_copy_line(std::string_view line) { home().write_copy_line(line); } 32 | void end_copy_write() { home().end_copy_write(); } 33 | 34 | result exec_prepared(zview statement, internal::c_params const &args) 35 | { 36 | return home().exec_prepared(statement, args); 37 | } 38 | 39 | result exec_params(zview query, internal::c_params const &args) 40 | { 41 | return home().exec_params(query, args); 42 | } 43 | }; 44 | } // namespace pqxx::internal::gate 45 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/errorhandler-connection.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace pqxx::internal::gate 4 | { 5 | class PQXX_PRIVATE errorhandler_connection : callgate 6 | { 7 | friend class pqxx::connection; 8 | 9 | errorhandler_connection(reference x) : super(x) {} 10 | 11 | void unregister() noexcept { home().unregister(); } 12 | }; 13 | } // namespace pqxx::internal::gate 14 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace pqxx::internal::gate 4 | { 5 | class PQXX_PRIVATE icursor_iterator_icursorstream : callgate 6 | { 7 | friend class pqxx::icursorstream; 8 | 9 | icursor_iterator_icursorstream(reference x) : super(x) {} 10 | 11 | icursor_iterator::difference_type pos() const noexcept 12 | { 13 | return home().pos(); 14 | } 15 | 16 | icursor_iterator *get_prev() { return home().m_prev; } 17 | void set_prev(icursor_iterator *i) { home().m_prev = i; } 18 | 19 | icursor_iterator *get_next() { return home().m_next; } 20 | void set_next(icursor_iterator *i) { home().m_next = i; } 21 | 22 | void fill(result const &r) { home().fill(r); } 23 | }; 24 | } // namespace pqxx::internal::gate 25 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace pqxx::internal::gate 4 | { 5 | class PQXX_PRIVATE icursorstream_icursor_iterator : callgate 6 | { 7 | friend class pqxx::icursor_iterator; 8 | 9 | icursorstream_icursor_iterator(reference x) : super(x) {} 10 | 11 | void insert_iterator(icursor_iterator *i) noexcept 12 | { 13 | home().insert_iterator(i); 14 | } 15 | 16 | void remove_iterator(icursor_iterator *i) const noexcept 17 | { 18 | home().remove_iterator(i); 19 | } 20 | 21 | icursorstream::size_type forward() { return home().forward(); } 22 | icursorstream::size_type forward(icursorstream::size_type n) 23 | { 24 | return home().forward(n); 25 | } 26 | 27 | void service_iterators(icursorstream::difference_type p) 28 | { 29 | home().service_iterators(p); 30 | } 31 | }; 32 | } // namespace pqxx::internal::gate 33 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/result-connection.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace pqxx::internal::gate 4 | { 5 | class PQXX_PRIVATE result_connection : callgate 6 | { 7 | friend class pqxx::connection; 8 | 9 | result_connection(reference x) : super(x) {} 10 | 11 | operator bool() const { return bool(home()); } 12 | bool operator!() const { return not home(); } 13 | }; 14 | } // namespace pqxx::internal::gate 15 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/result-creation.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace pqxx::internal::gate 4 | { 5 | class PQXX_PRIVATE result_creation : callgate 6 | { 7 | friend class pqxx::connection; 8 | friend class pqxx::pipeline; 9 | 10 | result_creation(reference x) : super(x) {} 11 | 12 | static result create( 13 | std::shared_ptr rhs, 14 | std::shared_ptr const &query, encoding_group enc) 15 | { 16 | return result(rhs, query, enc); 17 | } 18 | 19 | void check_status(std::string_view desc = ""sv) const 20 | { 21 | return home().check_status(desc); 22 | } 23 | }; 24 | } // namespace pqxx::internal::gate 25 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/result-pipeline.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace pqxx::internal::gate 4 | { 5 | class PQXX_PRIVATE result_pipeline : callgate 6 | { 7 | friend class pqxx::pipeline; 8 | 9 | result_pipeline(reference x) : super(x) {} 10 | 11 | std::shared_ptr query_ptr() const 12 | { 13 | return home().query_ptr(); 14 | } 15 | }; 16 | } // namespace pqxx::internal::gate 17 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/result-sql_cursor.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace pqxx::internal::gate 4 | { 5 | class PQXX_PRIVATE result_sql_cursor : callgate 6 | { 7 | friend class pqxx::internal::sql_cursor; 8 | 9 | result_sql_cursor(reference x) : super(x) {} 10 | 11 | char const *cmd_status() const noexcept { return home().cmd_status(); } 12 | }; 13 | } // namespace pqxx::internal::gate 14 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/transaction-sql_cursor.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace pqxx::internal::gate 4 | { 5 | class PQXX_PRIVATE transaction_sql_cursor : callgate 6 | { 7 | friend class pqxx::internal::sql_cursor; 8 | transaction_sql_cursor(reference x) : super(x) {} 9 | }; 10 | } // namespace pqxx::internal::gate 11 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/gates/transaction-transaction_focus.hxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "pqxx/transaction_base.hxx" 4 | 5 | namespace pqxx::internal::gate 6 | { 7 | class PQXX_PRIVATE transaction_transaction_focus : callgate 8 | { 9 | friend class pqxx::transaction_focus; 10 | 11 | transaction_transaction_focus(reference x) : super(x) {} 12 | 13 | void register_focus(transaction_focus *focus) 14 | { 15 | home().register_focus(focus); 16 | } 17 | void unregister_focus(transaction_focus *focus) noexcept 18 | { 19 | home().unregister_focus(focus); 20 | } 21 | void register_pending_error(zview error) 22 | { 23 | home().register_pending_error(error); 24 | } 25 | void register_pending_error(std::string &&error) 26 | { 27 | home().register_pending_error(std::move(error)); 28 | } 29 | }; 30 | } // namespace pqxx::internal::gate 31 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/header-post.hxx: -------------------------------------------------------------------------------- 1 | /* Compiler deficiency workarounds for compiling libpqxx headers. 2 | * 3 | * To be included at the end of each libpqxx header, in order to restore the 4 | * client program's settings. 5 | * 6 | * Copyright (c) 2000-2024, Jeroen T. Vermeulen. 7 | * 8 | * See COPYING for copyright license. If you did not receive a file called 9 | * COPYING with this source code, please notify the distributor of this 10 | * mistake, or contact the author. 11 | */ 12 | // NO GUARDS HERE! This code should be executed every time! 13 | 14 | #if defined(_MSC_VER) 15 | # pragma warning(pop) // Restore compiler's warning state 16 | #endif 17 | 18 | #if !defined(PQXX_HEADER_PRE) 19 | # error "Include pqxx/internal/header-post.hxx AFTER its 'pre' counterpart." 20 | #endif 21 | 22 | #undef PQXX_HEADER_PRE 23 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/ignore-deprecated-post.hxx: -------------------------------------------------------------------------------- 1 | /// End a code block started by "ignore-deprecated-pre.hxx". 2 | 3 | #if !defined(PQXX_IGNORING_DEPRECATED) 4 | # error "Ended an 'ignore-deprecated' block while none was active." 5 | #endif 6 | 7 | #if defined(__GNUC__) 8 | # pragma GCC diagnostic pop 9 | #endif // __GNUC__ 10 | 11 | #ifdef _MSC_VER 12 | # pragma warning(pop) 13 | #endif 14 | 15 | #undef PQXX_IGNORING_DEPRECATED 16 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/ignore-deprecated-pre.hxx: -------------------------------------------------------------------------------- 1 | /** Start a block of deprecated code which may call other deprecated code. 2 | * 3 | * Most compilers will emit warnings when deprecated code is invoked from 4 | * non-deprecated code. But some compilers (notably gcc) will always emit the 5 | * warning even when the calling code is also deprecated. 6 | * 7 | * This header starts a block where those warnings are suppressed. It can be 8 | * included inside a code block. 9 | * 10 | * Always match the #include with a closing #include of 11 | * "ignore-deprecated-post.hxx". To avoid mistakes, keep the enclosed area as 12 | * small as possible. 13 | */ 14 | #if defined(PQXX_IGNORING_DEPRECATED) 15 | # error "Started an 'ignore-deprecated' block inside another." 16 | #endif 17 | 18 | #define PQXX_IGNORING_DEPRECATED 19 | 20 | #if defined(__GNUC__) 21 | # pragma GCC diagnostic push 22 | # pragma GCC diagnostic ignored "-Wdeprecated-declarations" 23 | #endif // __GNUC__ 24 | 25 | #ifdef _MSC_VER 26 | # pragma warning(push) 27 | # pragma warning(disable : 4996) 28 | #endif 29 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/libpq-forward.hxx: -------------------------------------------------------------------------------- 1 | /** Minimal forward declarations of libpq types needed in libpqxx headers. 2 | * 3 | * DO NOT INCLUDE THIS FILE when building client programs. 4 | * 5 | * Copyright (c) 2000-2024, Jeroen T. Vermeulen. 6 | * 7 | * See COPYING for copyright license. If you did not receive a file called 8 | * COPYING with this source code, please notify the distributor of this 9 | * mistake, or contact the author. 10 | */ 11 | #if !defined(PQXX_H_LIBPQ_FORWARD) 12 | # define PQXX_H_LIBPQ_FORWARD 13 | 14 | extern "C" 15 | { 16 | struct pg_conn; 17 | struct pg_result; 18 | struct pgNotify; 19 | } 20 | 21 | /// Forward declarations of libpq types as needed in libpqxx headers. 22 | namespace pqxx::internal::pq 23 | { 24 | using PGconn = pg_conn; 25 | using PGresult = pg_result; 26 | using PGnotify = pgNotify; 27 | using PQnoticeProcessor = void (*)(void *, char const *); 28 | } // namespace pqxx::internal::pq 29 | 30 | namespace pqxx 31 | { 32 | /// PostgreSQL database row identifier. 33 | using oid = unsigned int; 34 | } // namespace pqxx 35 | #endif 36 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/internal/wait.hxx: -------------------------------------------------------------------------------- 1 | #if !defined(PQXX_WAIT_HXX) 2 | # define PQXX_WAIT_HXX 3 | 4 | namespace pqxx::internal 5 | { 6 | /// Wait. 7 | /** This is normally `std::this_thread::sleep_for()`. But MinGW's `thread` 8 | * header doesn't work, so we must be careful about including it. 9 | */ 10 | void PQXX_LIBEXPORT wait_for(unsigned int microseconds); 11 | 12 | 13 | /// Wait for a socket to be ready for reading/writing, or timeout. 14 | PQXX_LIBEXPORT void wait_fd( 15 | int fd, bool for_read, bool for_write, unsigned seconds = 1, 16 | unsigned microseconds = 0); 17 | } // namespace pqxx::internal 18 | #endif 19 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/isolation: -------------------------------------------------------------------------------- 1 | /** Transaction isolation levels. 2 | * 3 | * Policies and traits describing SQL transaction isolation levels 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/isolation.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/largeobject: -------------------------------------------------------------------------------- 1 | /** Large Objects interface. 2 | * 3 | * Supports direct access to large objects, as well as through I/O streams 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/largeobject.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/nontransaction: -------------------------------------------------------------------------------- 1 | /** pqxx::nontransaction class. 2 | * 3 | * pqxx::nontransaction provides nontransactional database access. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/nontransaction.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/notification: -------------------------------------------------------------------------------- 1 | /** pqxx::notification_receiver functor interface. 2 | * 3 | * pqxx::notification_receiver handles incoming notifications. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/notification.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/params: -------------------------------------------------------------------------------- 1 | /** Helper classes for passing statement parameters. 2 | * 3 | * Use these for prepared statements and parameterised statements. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/params.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/pipeline: -------------------------------------------------------------------------------- 1 | /** pqxx::pipeline class. 2 | * 3 | * Throughput-optimized query interface. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/pipeline.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/pqxx: -------------------------------------------------------------------------------- 1 | /// Convenience header: include all libpqxx definitions. 2 | #include "pqxx/internal/header-pre.hxx" 3 | 4 | #include "pqxx/array.hxx" 5 | #include "pqxx/binarystring.hxx" 6 | #include "pqxx/blob.hxx" 7 | #include "pqxx/connection.hxx" 8 | #include "pqxx/cursor.hxx" 9 | #include "pqxx/errorhandler.hxx" 10 | #include "pqxx/except.hxx" 11 | #include "pqxx/largeobject.hxx" 12 | #include "pqxx/nontransaction.hxx" 13 | #include "pqxx/notification.hxx" 14 | #include "pqxx/params.hxx" 15 | #include "pqxx/pipeline.hxx" 16 | #include "pqxx/prepared_statement.hxx" 17 | #include "pqxx/range.hxx" 18 | #include "pqxx/result.hxx" 19 | #include "pqxx/internal/result_iterator.hxx" 20 | #include "pqxx/internal/result_iter.hxx" 21 | #include "pqxx/robusttransaction.hxx" 22 | #include "pqxx/row.hxx" 23 | #include "pqxx/stream_from.hxx" 24 | #include "pqxx/stream_to.hxx" 25 | #include "pqxx/subtransaction.hxx" 26 | #include "pqxx/time.hxx" 27 | #include "pqxx/transaction.hxx" 28 | #include "pqxx/transactor.hxx" 29 | 30 | #include "pqxx/internal/header-post.hxx" 31 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/prepared_statement: -------------------------------------------------------------------------------- 1 | /// @deprecated Include @c instead. 2 | 3 | #include "params.hxx" 4 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/prepared_statement.hxx: -------------------------------------------------------------------------------- 1 | /// @deprecated Include @c instead. 2 | 3 | #include "params.hxx" 4 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/range: -------------------------------------------------------------------------------- 1 | /** Client-side support for SQL range types. 2 | */ 3 | // Actual definitions in .hxx file so editors and such recognize file type. 4 | #include "pqxx/internal/header-pre.hxx" 5 | #include "pqxx/range.hxx" 6 | #include "pqxx/internal/header-post.hxx" 7 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/result: -------------------------------------------------------------------------------- 1 | /** pqxx::result class and support classes. 2 | * 3 | * pqxx::result represents the set of result rows from a database query. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | 8 | #include "pqxx/result.hxx" 9 | 10 | // Now include some types which depend on result, but which the user will 11 | // expect to see defined after including this header. 12 | #include "pqxx/internal/result_iterator.hxx" 13 | #include "pqxx/field.hxx" 14 | #include "pqxx/internal/result_iter.hxx" 15 | 16 | #include "pqxx/internal/header-post.hxx" 17 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/robusttransaction: -------------------------------------------------------------------------------- 1 | /** pqxx::robusttransaction class. 2 | * 3 | * pqxx::robusttransaction is a slower but safer transaction class. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/robusttransaction.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/row: -------------------------------------------------------------------------------- 1 | /** pqxx::row class. 2 | * 3 | * pqxx::row refers to a row in a result. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | 8 | #include "pqxx/result.hxx" 9 | #include "pqxx/row.hxx" 10 | 11 | #include "pqxx/internal/header-post.hxx" 12 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/separated_list: -------------------------------------------------------------------------------- 1 | /** Helper similar to Python's @c str.join(). 2 | */ 3 | // Actual definitions in .hxx file so editors and such recognize file type. 4 | #include "pqxx/internal/header-pre.hxx" 5 | #include "pqxx/separated_list.hxx" 6 | #include "pqxx/internal/header-post.hxx" 7 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/strconv: -------------------------------------------------------------------------------- 1 | /** String conversion definitions. 2 | */ 3 | // Actual definitions in .hxx file so editors and such recognize file type. 4 | #include "pqxx/internal/header-pre.hxx" 5 | #include "pqxx/strconv.hxx" 6 | #include "pqxx/internal/header-post.hxx" 7 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/stream_from: -------------------------------------------------------------------------------- 1 | /** pqxx::stream_from class. 2 | * 3 | * pqxx::stream_from enables optimized batch reads from a database table. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/stream_from.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/stream_to: -------------------------------------------------------------------------------- 1 | /** pqxx::stream_to class. 2 | * 3 | * pqxx::stream_to enables optimized batch updates to a database table. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/stream_to.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/subtransaction: -------------------------------------------------------------------------------- 1 | /** pqxx::subtransaction class. 2 | * 3 | * pqxx::subtransaction is a nested transaction, i.e. one inside a transaction. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/subtransaction.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/time: -------------------------------------------------------------------------------- 1 | /** Date/time string conversions. 2 | */ 3 | // Actual definitions in .hxx file so editors and such recognize file type. 4 | #include "pqxx/internal/header-pre.hxx" 5 | #include "pqxx/time.hxx" 6 | #include "pqxx/internal/header-post.hxx" 7 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/transaction: -------------------------------------------------------------------------------- 1 | /** pqxx::transaction class. 2 | * 3 | * pqxx::transaction represents a standard database transaction. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/transaction.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/transaction_base: -------------------------------------------------------------------------------- 1 | /** Base for the transaction classes. 2 | * 3 | * pqxx::transaction_base defines the interface for any abstract class that 4 | * represents a database transaction. 5 | */ 6 | // Actual definitions in .hxx file so editors and such recognize file type. 7 | #include "pqxx/internal/header-pre.hxx" 8 | #include "pqxx/transaction_base.hxx" 9 | #include "pqxx/internal/header-post.hxx" 10 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/transaction_focus: -------------------------------------------------------------------------------- 1 | /** 2 | * Transaction focus: types which monopolise a transaction's attention. 3 | */ 4 | // Actual definitions in .hxx file so editors and such recognize file type. 5 | #include "pqxx/internal/header-pre.hxx" 6 | #include "pqxx/types.hxx" 7 | #include "pqxx/internal/header-post.hxx" 8 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/transactor: -------------------------------------------------------------------------------- 1 | /** pqxx::transactor class. 2 | * 3 | * pqxx::transactor is a framework-style wrapper for safe transactions. 4 | */ 5 | // Actual definitions in .hxx file so editors and such recognize file type. 6 | #include "pqxx/internal/header-pre.hxx" 7 | #include "pqxx/transactor.hxx" 8 | #include "pqxx/internal/header-post.hxx" 9 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/types: -------------------------------------------------------------------------------- 1 | /** 2 | * Basic typedefs and forward declarations. 3 | */ 4 | // Actual definitions in .hxx file so editors and such recognize file type. 5 | #include "pqxx/internal/header-pre.hxx" 6 | #include "pqxx/types.hxx" 7 | #include "pqxx/internal/header-post.hxx" 8 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/util: -------------------------------------------------------------------------------- 1 | /** Various utility definitions for libpqxx. 2 | */ 3 | // Actual definitions in .hxx file so editors and such recognize file type 4 | #include "pqxx/internal/header-pre.hxx" 5 | #include "pqxx/util.hxx" 6 | #include "pqxx/internal/header-post.hxx" 7 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/version: -------------------------------------------------------------------------------- 1 | /** libpqxx version info. 2 | */ 3 | // Actual definitions in .hxx file so editors and such recognize file type. 4 | #include "pqxx/internal/header-pre.hxx" 5 | #include "pqxx/version.hxx" 6 | #include "pqxx/internal/header-post.hxx" 7 | 8 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/version.hxx: -------------------------------------------------------------------------------- 1 | /* Version info for libpqxx. 2 | * 3 | * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead. 4 | * 5 | * Copyright (c) 2000-2024, Jeroen T. Vermeulen. 6 | * 7 | * See COPYING for copyright license. If you did not receive a file called 8 | * COPYING with this source code, please notify the distributor of this 9 | * mistake, or contact the author. 10 | */ 11 | #if !defined(PQXX_H_VERSION) 12 | # define PQXX_H_VERSION 13 | 14 | # if !defined(PQXX_HEADER_PRE) 15 | # error "Include libpqxx headers as , not ." 16 | # endif 17 | 18 | /// Full libpqxx version string. 19 | # define PQXX_VERSION "7.9.0" 20 | /// Library ABI version. 21 | # define PQXX_ABI "7.9" 22 | 23 | /// Major version number. 24 | # define PQXX_VERSION_MAJOR 7 25 | /// Minor version number. 26 | # define PQXX_VERSION_MINOR 9 27 | 28 | # define PQXX_VERSION_CHECK check_pqxx_version_7_9 29 | 30 | namespace pqxx::internal 31 | { 32 | /// Library version check stub. 33 | /** Helps detect version mismatches between libpqxx headers and the libpqxx 34 | * library binary. 35 | * 36 | * Sometimes users run into trouble linking their code against libpqxx because 37 | * they build their own libpqxx, but the system also has a different version 38 | * installed. The declarations in the headers against which they compile their 39 | * code will differ from the ones used to build the libpqxx version they're 40 | * using, leading to confusing link errors. The solution is to generate a link 41 | * error when the libpqxx binary is not the same version as the libpqxx headers 42 | * used to compile the code. 43 | * 44 | * This function's definition is in the libpqxx binary, so it's based on the 45 | * version as found in the binary. The headers contain a call to the function, 46 | * whose name contains the libpqxx version as found in the headers. (The 47 | * library build process will use its own local headers even if another version 48 | * of the headers is installed on the system.) 49 | * 50 | * If the libpqxx binary was compiled for a different version than the user's 51 | * code, linking will fail with an error: `check_pqxx_version_*_*` will not 52 | * exist for the given version number. 53 | */ 54 | PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept; 55 | } // namespace pqxx::internal 56 | #endif 57 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/version.hxx.template: -------------------------------------------------------------------------------- 1 | /* Version info for libpqxx. 2 | * 3 | * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead. 4 | * 5 | * Copyright (c) 2000-2024, Jeroen T. Vermeulen. 6 | * 7 | * See COPYING for copyright license. If you did not receive a file called 8 | * COPYING with this source code, please notify the distributor of this 9 | * mistake, or contact the author. 10 | */ 11 | #if !defined(PQXX_H_VERSION) 12 | # define PQXX_H_VERSION 13 | 14 | # if !defined(PQXX_HEADER_PRE) 15 | # error "Include libpqxx headers as , not ." 16 | # endif 17 | 18 | /// Full libpqxx version string. 19 | # define PQXX_VERSION "@PQXXVERSION@" 20 | /// Library ABI version. 21 | # define PQXX_ABI "@PQXX_ABI@" 22 | 23 | /// Major version number. 24 | # define PQXX_VERSION_MAJOR @PQXX_MAJOR@ 25 | /// Minor version number. 26 | # define PQXX_VERSION_MINOR @PQXX_MINOR@ 27 | 28 | # define PQXX_VERSION_CHECK check_pqxx_version_@PQXX_MAJOR@_@PQXX_MINOR@ 29 | 30 | namespace pqxx::internal 31 | { 32 | /// Library version check stub. 33 | /** Helps detect version mismatches between libpqxx headers and the libpqxx 34 | * library binary. 35 | * 36 | * Sometimes users run into trouble linking their code against libpqxx because 37 | * they build their own libpqxx, but the system also has a different version 38 | * installed. The declarations in the headers against which they compile their 39 | * code will differ from the ones used to build the libpqxx version they're 40 | * using, leading to confusing link errors. The solution is to generate a link 41 | * error when the libpqxx binary is not the same version as the libpqxx headers 42 | * used to compile the code. 43 | * 44 | * This function's definition is in the libpqxx binary, so it's based on the 45 | * version as found in the binary. The headers contain a call to the function, 46 | * whose name contains the libpqxx version as found in the headers. (The 47 | * library build process will use its own local headers even if another version 48 | * of the headers is installed on the system.) 49 | * 50 | * If the libpqxx binary was compiled for a different version than the user's 51 | * code, linking will fail with an error: `check_pqxx_version_*_*` will not 52 | * exist for the given version number. 53 | */ 54 | PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept; 55 | } // namespace pqxx::internal 56 | #endif 57 | -------------------------------------------------------------------------------- /libpqxx/include/pqxx/zview: -------------------------------------------------------------------------------- 1 | /** Zero-terminated string view class. 2 | */ 3 | // Actual definitions in .hxx file so editors and such recognize file type. 4 | #include "pqxx/internal/header-pre.hxx" 5 | #include "pqxx/zview.hxx" 6 | #include "pqxx/internal/header-post.hxx" 7 | -------------------------------------------------------------------------------- /libpqxx/libpqxx.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libpqxx 7 | Description: C++ client API for the PostgreSQL database management system. 8 | Version: @VERSION@ 9 | Libs: -L${libdir} -lpqxx 10 | Cflags: -I${includedir} 11 | -------------------------------------------------------------------------------- /libpqxx/requirements.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Minimum versions needed of various things.", 3 | "c++": "17", 4 | "libpq": "10.0", 5 | "postgresql": "10.0", 6 | "gcc": "8", 7 | "clang": "11", 8 | "msvc": "2019" 9 | } 10 | -------------------------------------------------------------------------------- /libpqxx/src/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libpqxx.la 2 | libpqxx_la_SOURCES = \ 3 | array.cxx \ 4 | binarystring.cxx \ 5 | blob.cxx \ 6 | connection.cxx \ 7 | cursor.cxx \ 8 | encodings.cxx \ 9 | errorhandler.cxx \ 10 | except.cxx \ 11 | field.cxx \ 12 | largeobject.cxx \ 13 | notification.cxx \ 14 | params.cxx \ 15 | pipeline.cxx \ 16 | result.cxx \ 17 | robusttransaction.cxx \ 18 | sql_cursor.cxx \ 19 | strconv.cxx \ 20 | stream_from.cxx \ 21 | stream_to.cxx \ 22 | subtransaction.cxx \ 23 | time.cxx \ 24 | transaction.cxx \ 25 | transaction_base.cxx \ 26 | row.cxx \ 27 | util.cxx \ 28 | version.cxx \ 29 | wait.cxx 30 | 31 | libpqxx_version = -release $(PQXX_ABI) 32 | 33 | libpqxx_la_LDFLAGS = $(libpqxx_version) \ 34 | -rpath $(libdir) \ 35 | ${POSTGRES_LIB} 36 | 37 | AM_CPPFLAGS = \ 38 | -I$(top_srcdir)/include -I$(top_builddir)/include ${POSTGRES_INCLUDE} 39 | 40 | # Override automatically generated list of default includes. It contains only 41 | # unnecessary entries, and incorrectly mentions include/pqxx directly. 42 | DEFAULT_INCLUDES= 43 | 44 | MAINTAINERCLEANFILES=Makefile.in 45 | -------------------------------------------------------------------------------- /libpqxx/src/errorhandler.cxx: -------------------------------------------------------------------------------- 1 | /** Implementation of pqxx::errorhandler and helpers. 2 | * 3 | * pqxx::errorhandler allows programs to receive errors and warnings. 4 | * 5 | * Copyright (c) 2000-2024, Jeroen T. Vermeulen. 6 | * 7 | * See COPYING for copyright license. If you did not receive a file called 8 | * COPYING with this source code, please notify the distributor of this 9 | * mistake, or contact the author. 10 | */ 11 | #include "pqxx-source.hxx" 12 | 13 | #include "pqxx/internal/header-pre.hxx" 14 | 15 | #include "pqxx/connection.hxx" 16 | #include "pqxx/errorhandler.hxx" 17 | #include "pqxx/internal/gates/connection-errorhandler.hxx" 18 | 19 | #include "pqxx/internal/header-post.hxx" 20 | 21 | 22 | pqxx::errorhandler::errorhandler(connection &conn) : m_home{&conn} 23 | { 24 | pqxx::internal::gate::connection_errorhandler{*m_home}.register_errorhandler( 25 | this); 26 | } 27 | 28 | 29 | pqxx::errorhandler::~errorhandler() 30 | { 31 | unregister(); 32 | } 33 | 34 | 35 | void pqxx::errorhandler::unregister() noexcept 36 | { 37 | if (m_home != nullptr) 38 | { 39 | pqxx::internal::gate::connection_errorhandler connection_gate{*m_home}; 40 | m_home = nullptr; 41 | connection_gate.unregister_errorhandler(this); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /libpqxx/src/field.cxx: -------------------------------------------------------------------------------- 1 | /** Implementation of the pqxx::field class. 2 | * 3 | * pqxx::field refers to a field in a query result. 4 | * 5 | * Copyright (c) 2000-2024, Jeroen T. Vermeulen. 6 | * 7 | * See COPYING for copyright license. If you did not receive a file called 8 | * COPYING with this source code, please notify the distributor of this 9 | * mistake, or contact the author. 10 | */ 11 | #include "pqxx-source.hxx" 12 | 13 | #include 14 | 15 | #include "pqxx/internal/header-pre.hxx" 16 | 17 | #include "pqxx/field.hxx" 18 | #include "pqxx/internal/libpq-forward.hxx" 19 | #include "pqxx/result.hxx" 20 | #include "pqxx/row.hxx" 21 | 22 | #include "pqxx/internal/header-post.hxx" 23 | 24 | 25 | pqxx::field::field(pqxx::row const &r, pqxx::row::size_type c) noexcept : 26 | m_col{c}, m_home{r.m_result}, m_row{r.m_index} 27 | {} 28 | 29 | 30 | bool PQXX_COLD pqxx::field::operator==(field const &rhs) const noexcept 31 | { 32 | if (is_null() and rhs.is_null()) 33 | return true; 34 | if (is_null() != rhs.is_null()) 35 | return false; 36 | auto const s{size()}; 37 | return (s == std::size(rhs)) and (std::memcmp(c_str(), rhs.c_str(), s) == 0); 38 | } 39 | 40 | 41 | char const *pqxx::field::name() const & 42 | { 43 | return home().column_name(col()); 44 | } 45 | 46 | 47 | pqxx::oid pqxx::field::type() const 48 | { 49 | return home().column_type(col()); 50 | } 51 | 52 | 53 | pqxx::oid pqxx::field::table() const 54 | { 55 | return home().column_table(col()); 56 | } 57 | 58 | 59 | pqxx::row::size_type pqxx::field::table_column() const 60 | { 61 | return home().table_column(col()); 62 | } 63 | 64 | 65 | char const *pqxx::field::c_str() const & 66 | { 67 | return home().get_value(idx(), col()); 68 | } 69 | 70 | 71 | bool pqxx::field::is_null() const noexcept 72 | { 73 | return home().get_is_null(idx(), col()); 74 | } 75 | 76 | 77 | pqxx::field::size_type pqxx::field::size() const noexcept 78 | { 79 | return home().get_length(idx(), col()); 80 | } 81 | -------------------------------------------------------------------------------- /libpqxx/src/notification.cxx: -------------------------------------------------------------------------------- 1 | /** Implementation of the pqxx::notification_receiever class. 2 | * 3 | * pqxx::notification_receiver processes notifications. 4 | * 5 | * Copyright (c) 2000-2024, Jeroen T. Vermeulen. 6 | * 7 | * See COPYING for copyright license. If you did not receive a file called 8 | * COPYING with this source code, please notify the distributor of this 9 | * mistake, or contact the author. 10 | */ 11 | #include "pqxx-source.hxx" 12 | 13 | #include 14 | 15 | #include "pqxx/internal/header-pre.hxx" 16 | 17 | #include "pqxx/internal/gates/connection-notification_receiver.hxx" 18 | #include "pqxx/notification.hxx" 19 | 20 | #include "pqxx/internal/header-post.hxx" 21 | 22 | 23 | pqxx::notification_receiver::notification_receiver( 24 | connection &c, std::string_view channel) : 25 | m_conn{c}, m_channel{channel} 26 | { 27 | pqxx::internal::gate::connection_notification_receiver{c}.add_receiver(this); 28 | } 29 | 30 | 31 | pqxx::notification_receiver::~notification_receiver() 32 | { 33 | pqxx::internal::gate::connection_notification_receiver{this->conn()} 34 | .remove_receiver(this); 35 | } 36 | -------------------------------------------------------------------------------- /libpqxx/src/pqxx-source.hxx: -------------------------------------------------------------------------------- 1 | /* Compiler settings for compiling libpqxx itself. 2 | * 3 | * Include this header in every source file that goes into the libpqxx library 4 | * binary, and nowhere else. 5 | * 6 | * To ensure this, include this file once, as the very first header, in each 7 | * compilation unit for the library. 8 | * 9 | * DO NOT INCLUDE THIS FILE when building client programs. 10 | * 11 | * Copyright (c) 2000-2024, Jeroen T. Vermeulen. 12 | * 13 | * See COPYING for copyright license. If you did not receive a file called 14 | * COPYING with this source code, please notify the distributor of this 15 | * mistake, or contact the author. 16 | */ 17 | 18 | // Workarounds & definitions needed to compile libpqxx into a library. 19 | #include "pqxx/config-internal-compiler.h" 20 | 21 | #ifdef _WIN32 22 | 23 | # ifdef PQXX_SHARED 24 | // We're building libpqxx as a shared library. 25 | # undef PQXX_LIBEXPORT 26 | # define PQXX_LIBEXPORT __declspec(dllexport) 27 | # define PQXX_PRIVATE __declspec() 28 | # endif // PQXX_SHARED 29 | 30 | #endif // _WIN32 31 | -------------------------------------------------------------------------------- /libpqxx/src/subtransaction.cxx: -------------------------------------------------------------------------------- 1 | /** Implementation of the pqxx::subtransaction class. 2 | * 3 | * pqxx::transaction is a nested transaction, i.e. one within a transaction 4 | * 5 | * Copyright (c) 2000-2024, Jeroen T. Vermeulen. 6 | * 7 | * See COPYING for copyright license. If you did not receive a file called 8 | * COPYING with this source code, please notify the distributor of this 9 | * mistake, or contact the author. 10 | */ 11 | #include "pqxx-source.hxx" 12 | 13 | #include 14 | #include 15 | 16 | #include "pqxx/internal/header-pre.hxx" 17 | 18 | #include "pqxx/connection.hxx" 19 | #include "pqxx/internal/concat.hxx" 20 | #include "pqxx/subtransaction.hxx" 21 | 22 | #include "pqxx/internal/header-post.hxx" 23 | 24 | 25 | namespace 26 | { 27 | using namespace std::literals; 28 | constexpr std::string_view class_name{"subtransaction"sv}; 29 | } // namespace 30 | 31 | 32 | pqxx::subtransaction::subtransaction( 33 | dbtransaction &t, std::string_view tname) : 34 | transaction_focus{t, class_name, t.conn().adorn_name(tname)}, 35 | // We can't initialise the rollback command here, because we don't yet 36 | // have a full object to implement quoted_name(). 37 | dbtransaction{t.conn(), tname, std::shared_ptr{}} 38 | { 39 | set_rollback_cmd(std::make_shared( 40 | internal::concat("ROLLBACK TO SAVEPOINT ", quoted_name()))); 41 | direct_exec(std::make_shared( 42 | internal::concat("SAVEPOINT ", quoted_name()))); 43 | } 44 | 45 | 46 | namespace 47 | { 48 | using dbtransaction_ref = pqxx::dbtransaction &; 49 | } // namespace 50 | 51 | 52 | pqxx::subtransaction::subtransaction( 53 | subtransaction &t, std::string_view tname) : 54 | subtransaction(dbtransaction_ref(t), tname) 55 | {} 56 | 57 | 58 | pqxx::subtransaction::~subtransaction() noexcept 59 | { 60 | close(); 61 | } 62 | 63 | 64 | void pqxx::subtransaction::do_commit() 65 | { 66 | direct_exec(std::make_shared( 67 | internal::concat("RELEASE SAVEPOINT ", quoted_name()))); 68 | } 69 | -------------------------------------------------------------------------------- /libpqxx/src/version.cxx: -------------------------------------------------------------------------------- 1 | /** Version check. 2 | * 3 | * Copyright (c) 2000-2024, Jeroen T. Vermeulen. 4 | * 5 | * See COPYING for copyright license. If you did not receive a file called 6 | * COPYING with this source code, please notify the distributor of this 7 | * mistake, or contact the author. 8 | */ 9 | #include "pqxx-source.hxx" 10 | 11 | #include "pqxx/internal/header-pre.hxx" 12 | 13 | #include "pqxx/version.hxx" 14 | 15 | #include "pqxx/internal/header-post.hxx" 16 | 17 | 18 | namespace pqxx::internal 19 | { 20 | // One, single definition of this function. If a call fails to link, and 21 | // (some) other calls do link, then the libpqxx binary was built against a 22 | // different libpqxx version than the code which is being linked against it. 23 | PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept 24 | { 25 | return 0; 26 | } 27 | } // namespace pqxx::internal 28 | -------------------------------------------------------------------------------- /libpqxx/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | enable_testing() 2 | 3 | if(NOT PostgreSQL_FOUND) 4 | find_package(PostgreSQL REQUIRED) 5 | endif() 6 | 7 | file(GLOB TEST_SOURCES test*.cxx unit/test_*.cxx runner.cxx) 8 | 9 | add_executable(runner ${TEST_SOURCES}) 10 | target_link_libraries(runner PUBLIC pqxx) 11 | target_include_directories(runner PRIVATE ${PostgreSQL_INCLUDE_DIRS}) 12 | add_test( 13 | NAME runner 14 | WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} 15 | COMMAND runner 16 | ) 17 | 18 | if(INSTALL_TEST) 19 | install( 20 | PROGRAMS runner 21 | TYPE BIN 22 | RENAME libpqxx-test-runner 23 | ) 24 | endif() 25 | -------------------------------------------------------------------------------- /libpqxx/test/Makefile.am.template: -------------------------------------------------------------------------------- 1 | # Makefile.am is generated automatically for automake whenever test programs are 2 | # added to libpqxx. 3 | 4 | EXTRA_DIST = Makefile.am.template 5 | 6 | # Use the serial test runner, so tests don't get run in parallel. Otherwise, 7 | # output from test failures will be hidden away in log files where we can't 8 | # see them when running in a build slave. 9 | AUTOMAKE_OPTIONS=serial-tests 10 | 11 | 12 | AM_CPPFLAGS=-I$(top_builddir)/include -I$(top_srcdir)/include 13 | 14 | # Override automatically generated list of default includes. It contains only 15 | # unnecessary entries, and incorrectly mentions include/pqxx directly. 16 | DEFAULT_INCLUDES= 17 | 18 | noinst_HEADERS = test_helpers.hxx 19 | 20 | CLEANFILES=pqxxlo.txt 21 | MAINTAINERCLEANFILES=Makefile.in 22 | 23 | #TESTS_ENVIRONMENT=PGDATABASE=libpqxx 24 | # PGDATABASE, PGHOST, PGPORT, PGUSER 25 | 26 | runner_SOURCES = \ 27 | ###MAKTEMPLATE:FOREACH test/test*.cxx 28 | ###BASENAME###.cxx \ 29 | ###MAKTEMPLATE:ENDFOREACH 30 | ###MAKTEMPLATE:FOREACH test/unit/test_*.cxx 31 | unit/###BASENAME###.cxx \ 32 | ###MAKTEMPLATE:ENDFOREACH 33 | runner.cxx 34 | 35 | runner_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} 36 | 37 | TESTS = runner 38 | check_PROGRAMS = ${TESTS} 39 | -------------------------------------------------------------------------------- /libpqxx/test/test01.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "test_helpers.hxx" 6 | 7 | using namespace pqxx; 8 | 9 | 10 | namespace 11 | { 12 | // Simple test program for libpqxx. Open connection to database, start 13 | // a transaction, and perform a query inside it. 14 | void test_001() 15 | { 16 | connection conn; 17 | 18 | // Begin a transaction acting on our current connection. Give it a human- 19 | // readable name so the library can include it in error messages. 20 | work tx{conn, "test1"}; 21 | 22 | // Perform a query on the database, storing result rows in R. 23 | result r(tx.exec("SELECT * FROM pg_tables")); 24 | 25 | // We're expecting to find some tables... 26 | PQXX_CHECK(not std::empty(r), "No tables found."); 27 | 28 | tx.commit(); 29 | } 30 | 31 | 32 | PQXX_REGISTER_TEST(test_001); 33 | } // namespace 34 | -------------------------------------------------------------------------------- /libpqxx/test/test02.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "test_helpers.hxx" 4 | 5 | using namespace pqxx; 6 | 7 | 8 | // Example/test program for libpqxx. Perform a query and enumerate its output 9 | // using array indexing. 10 | 11 | namespace 12 | { 13 | void bad_connect() 14 | { 15 | connection conn{"totally#invalid@connect$string!?"}; 16 | } 17 | 18 | void test_002() 19 | { 20 | // Before we really connect, test the expected behaviour of the default 21 | // connection type, where a failure to connect results in an immediate 22 | // exception rather than a silent retry. 23 | PQXX_CHECK_THROWS_EXCEPTION( 24 | bad_connect(), "Invalid connection string did not cause exception."); 25 | 26 | // Set up connection to database 27 | std::string ConnectString; 28 | connection C{ConnectString}; 29 | 30 | // Start transaction within context of connection. 31 | work T{C, "test2"}; 32 | 33 | // Perform query within transaction. 34 | result R(T.exec("SELECT * FROM pg_tables")); 35 | 36 | // Let's keep the database waiting as briefly as possible: commit now, 37 | // before we start processing results. We could do this later, or since 38 | // we're not making any changes in the database that need to be committed, 39 | // we could in this case even omit it altogether. 40 | T.commit(); 41 | 42 | // Ah, this version of postgres will tell you which table a column in a 43 | // result came from. Let's just test that functionality... 44 | oid const rtable{R.column_table(0)}; 45 | PQXX_CHECK_EQUAL( 46 | rtable, R.column_table(pqxx::row::size_type(0)), 47 | "Inconsistent answers from column_table()"); 48 | 49 | std::string const rcol{R.column_name(0)}; 50 | oid const crtable{R.column_table(rcol)}; 51 | PQXX_CHECK_EQUAL( 52 | crtable, rtable, "Field looked up by name gives different origin."); 53 | 54 | // Now we've got all that settled, let's process our results. 55 | for (auto const &f : R) 56 | { 57 | oid const ftable{f[0].table()}; 58 | PQXX_CHECK_EQUAL(ftable, rtable, "field::table() is broken."); 59 | 60 | oid const ttable{f.column_table(0)}; 61 | 62 | PQXX_CHECK_EQUAL( 63 | ttable, f.column_table(pqxx::row::size_type(0)), 64 | "Inconsistent pqxx::row::column_table()."); 65 | 66 | PQXX_CHECK_EQUAL(ttable, rtable, "Inconsistent result::column_table()."); 67 | 68 | oid const cttable{f.column_table(rcol)}; 69 | 70 | PQXX_CHECK_EQUAL(cttable, rtable, "pqxx::row::column_table() is broken."); 71 | } 72 | } 73 | 74 | 75 | PQXX_REGISTER_TEST(test_002); 76 | } // namespace 77 | -------------------------------------------------------------------------------- /libpqxx/test/test04.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "test_helpers.hxx" 17 | 18 | using namespace pqxx; 19 | 20 | // Example program for libpqxx. Send notification to self. 21 | 22 | namespace 23 | { 24 | int Backend_PID{0}; 25 | 26 | 27 | // Sample implementation of notification receiver. 28 | class TestListener final : public notification_receiver 29 | { 30 | bool m_done; 31 | 32 | public: 33 | explicit TestListener(connection &conn) : 34 | notification_receiver(conn, "listen"), m_done(false) 35 | {} 36 | 37 | virtual void operator()(std::string const &, int be_pid) override 38 | { 39 | m_done = true; 40 | PQXX_CHECK_EQUAL( 41 | be_pid, Backend_PID, "Notification came from wrong backend process."); 42 | } 43 | 44 | bool done() const { return m_done; } 45 | }; 46 | 47 | 48 | void test_004() 49 | { 50 | connection conn; 51 | 52 | TestListener L{conn}; 53 | // Trigger our notification receiver. 54 | perform([&conn, &L] { 55 | work tx(conn); 56 | tx.exec0("NOTIFY " + conn.quote_name(L.channel())); 57 | Backend_PID = conn.backendpid(); 58 | tx.commit(); 59 | }); 60 | 61 | int notifs{0}; 62 | for (int i{0}; (i < 20) and not L.done(); ++i) 63 | { 64 | PQXX_CHECK_EQUAL(notifs, 0, "Got unexpected notifications."); 65 | // Sleep for one second. I'm not proud of this, but how does one inject 66 | // a change to the built-in clock in a static language? 67 | pqxx::internal::wait_for(1000u); 68 | notifs = conn.get_notifs(); 69 | } 70 | 71 | PQXX_CHECK_NOT_EQUAL(L.done(), false, "No notification received."); 72 | PQXX_CHECK_EQUAL(notifs, 1, "Got too many notifications."); 73 | } 74 | 75 | 76 | PQXX_REGISTER_TEST(test_004); 77 | } // namespace 78 | -------------------------------------------------------------------------------- /libpqxx/test/test11.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "test_helpers.hxx" 8 | 9 | using namespace pqxx; 10 | 11 | 12 | // Test program for libpqxx. Query a table and report its metadata. 13 | namespace 14 | { 15 | void test_011() 16 | { 17 | connection conn; 18 | work tx{conn}; 19 | std::string const Table{"pg_tables"}; 20 | 21 | result R(tx.exec("SELECT * FROM " + Table)); 22 | 23 | // Print column names 24 | for (pqxx::row::size_type c{0}; c < R.columns(); ++c) 25 | { 26 | std::string N{R.column_name(c)}; 27 | PQXX_CHECK_EQUAL(R.column_number(N), c, "Inconsistent column numbers."); 28 | } 29 | 30 | // If there are rows in R, compare their metadata to R's. 31 | if (not std::empty(R)) 32 | { 33 | PQXX_CHECK_EQUAL(R[0].rownumber(), 0, "Row 0 has wrong number."); 34 | 35 | if (std::size(R) >= 2) 36 | PQXX_CHECK_EQUAL(R[1].rownumber(), 1, "Row 1 has wrong number."); 37 | 38 | // Test result::iterator::swap() 39 | pqxx::result::const_iterator const T1(R[0]), T2(R[1]); 40 | PQXX_CHECK_NOT_EQUAL(T1, T2, "Values are identical--can't test swap()."); 41 | pqxx::result::const_iterator T1s(T1), T2s(T2); 42 | PQXX_CHECK_EQUAL(T1s, T1, "Result iterator copy-construction is wrong."); 43 | PQXX_CHECK_EQUAL( 44 | T2s, T2, "Result iterator copy-construction is inconsistently wrong."); 45 | T1s.swap(T2s); 46 | PQXX_CHECK_NOT_EQUAL(T1s, T1, "Result iterator swap doesn't work."); 47 | PQXX_CHECK_NOT_EQUAL( 48 | T2s, T2, "Result iterator swap inconsistently wrong."); 49 | PQXX_CHECK_EQUAL(T2s, T1, "Result iterator swap is asymmetric."); 50 | PQXX_CHECK_EQUAL( 51 | T1s, T2, "Result iterator swap is inconsistently asymmetric."); 52 | 53 | for (pqxx::row::size_type c{0}; c < std::size(R[0]); ++c) 54 | { 55 | std::string N{R.column_name(c)}; 56 | 57 | PQXX_CHECK_EQUAL( 58 | std::string{R[0].at(c).c_str()}, R[0].at(N).c_str(), 59 | "Field by name != field by number."); 60 | 61 | PQXX_CHECK_EQUAL( 62 | std::string{R[0][c].c_str()}, R[0][N].c_str(), 63 | "at() is inconsistent with operator[]."); 64 | 65 | PQXX_CHECK_EQUAL(R[0][c].name(), N, "Field names are inconsistent."); 66 | 67 | PQXX_CHECK_EQUAL( 68 | std::size(R[0][c]), strlen(R[0][c].c_str()), 69 | "Field size is not what we expected."); 70 | } 71 | } 72 | } 73 | 74 | 75 | PQXX_REGISTER_TEST(test_011); 76 | } // namespace 77 | -------------------------------------------------------------------------------- /libpqxx/test/test13.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "test_helpers.hxx" 5 | 6 | using namespace pqxx; 7 | 8 | 9 | // Test program for libpqxx. Verify abort behaviour of transactor. 10 | // 11 | // The program will attempt to add an entry to a table called "pqxxevents", 12 | // with a key column called "year"--and then abort the change. 13 | // 14 | // Note for the superstitious: the numbering for this test program is pure 15 | // coincidence. 16 | namespace 17 | { 18 | // Let's take a boring year that is not going to be in the "pqxxevents" table 19 | constexpr unsigned int BoringYear = 1977; 20 | 21 | 22 | // Count events and specifically events occurring in Boring Year, leaving the 23 | // former count in the result pair's first member, and the latter in second. 24 | std::pair count_events(connection &conn, std::string const &table) 25 | { 26 | work tx{conn}; 27 | std::string const count_query{"SELECT count(*) FROM " + table}; 28 | return std::make_pair( 29 | tx.query_value(count_query), 30 | tx.query_value(count_query + " WHERE year=" + to_string(BoringYear))); 31 | } 32 | 33 | 34 | struct deliberate_error : std::exception 35 | {}; 36 | 37 | 38 | void failed_insert(connection &C, std::string const &table) 39 | { 40 | work tx(C); 41 | result R = tx.exec0( 42 | "INSERT INTO " + table + " VALUES (" + to_string(BoringYear) + 43 | ", " 44 | "'yawn')"); 45 | 46 | PQXX_CHECK_EQUAL(R.affected_rows(), 1, "Bad affected_rows()."); 47 | throw deliberate_error(); 48 | } 49 | 50 | 51 | void test_013() 52 | { 53 | connection conn; 54 | { 55 | work tx{conn}; 56 | test::create_pqxxevents(tx); 57 | tx.commit(); 58 | } 59 | 60 | std::string const Table{"pqxxevents"}; 61 | 62 | auto const Before{ 63 | perform([&conn, &Table] { return count_events(conn, Table); })}; 64 | PQXX_CHECK_EQUAL( 65 | Before.second, 0, 66 | "Already have event for " + to_string(BoringYear) + "--can't test."); 67 | 68 | quiet_errorhandler d(conn); 69 | PQXX_CHECK_THROWS( 70 | perform([&conn, &Table] { failed_insert(conn, Table); }), deliberate_error, 71 | "Failing transactor failed to throw correct exception."); 72 | 73 | auto const After{ 74 | perform([&conn, &Table] { return count_events(conn, Table); })}; 75 | 76 | PQXX_CHECK_EQUAL( 77 | After.first, Before.first, "abort() didn't reset event count."); 78 | 79 | PQXX_CHECK_EQUAL( 80 | After.second, Before.second, 81 | "abort() didn't reset event count for " + to_string(BoringYear)); 82 | } 83 | 84 | 85 | PQXX_REGISTER_TEST(test_013); 86 | } // namespace 87 | -------------------------------------------------------------------------------- /libpqxx/test/test14.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "test_helpers.hxx" 6 | 7 | using namespace pqxx; 8 | 9 | 10 | // Test nontransaction. 11 | 12 | namespace 13 | { 14 | void test_014() 15 | { 16 | connection conn; 17 | 18 | // Begin a "non-transaction" acting on our current connection. This is 19 | // really all the transactional integrity we need since we're only 20 | // performing one query which does not modify the database. 21 | nontransaction tx{conn, "test14"}; 22 | 23 | // The transaction class family also has process_notice() functions. 24 | // These simply pass the notice through to their connection, but this may 25 | // be more convenient in some cases. All process_notice() functions accept 26 | // C++ strings as well as C strings. 27 | tx.process_notice(std::string{"Started nontransaction\n"}); 28 | 29 | // "Commit" the non-transaction. This doesn't really do anything since 30 | // nontransaction doesn't start a backend transaction. 31 | tx.commit(); 32 | } 33 | 34 | 35 | PQXX_REGISTER_TEST(test_014); 36 | } // namespace 37 | -------------------------------------------------------------------------------- /libpqxx/test/test16.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "test_helpers.hxx" 7 | 8 | using namespace pqxx; 9 | 10 | 11 | // Test robusttransaction. 12 | namespace 13 | { 14 | void test_016() 15 | { 16 | connection conn; 17 | robusttransaction<> tx{conn}; 18 | result R{tx.exec("SELECT * FROM pg_tables")}; 19 | 20 | result::const_iterator c; 21 | for (c = std::begin(R); c != std::end(R); ++c) 22 | ; 23 | 24 | // See if back() and row comparison work properly 25 | PQXX_CHECK( 26 | std::size(R) >= 2, "Not enough rows in pg_tables to test, sorry!"); 27 | 28 | --c; 29 | 30 | PQXX_CHECK_EQUAL( 31 | c->size(), std::size(R.back()), 32 | "Size mismatch between row iterator and back()."); 33 | 34 | std::string const nullstr; 35 | for (pqxx::row::size_type i{0}; i < c->size(); ++i) 36 | PQXX_CHECK_EQUAL( 37 | c[i].as(nullstr), R.back()[i].as(nullstr), "Value mismatch in back()."); 38 | PQXX_CHECK(*c == R.back(), "Row equality is broken."); 39 | PQXX_CHECK(not(*c != R.back()), "Row inequality is broken."); 40 | 41 | tx.commit(); 42 | } 43 | 44 | 45 | PQXX_REGISTER_TEST(test_016); 46 | } // namespace 47 | -------------------------------------------------------------------------------- /libpqxx/test/test17.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "test_helpers.hxx" 8 | 9 | using namespace pqxx; 10 | 11 | 12 | // Simple test program for libpqxx. Open connection to database, start 13 | // a dummy transaction to gain nontransactional access, and perform a query. 14 | namespace 15 | { 16 | void test_017() 17 | { 18 | connection conn; 19 | perform([&conn] { 20 | nontransaction tx{conn}; 21 | auto const r{tx.exec("SELECT * FROM generate_series(1, 4)")}; 22 | PQXX_CHECK_EQUAL(std::size(r), 4, "Weird query result."); 23 | tx.commit(); 24 | }); 25 | } 26 | 27 | 28 | PQXX_REGISTER_TEST(test_017); 29 | } // namespace 30 | -------------------------------------------------------------------------------- /libpqxx/test/test18.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "test_helpers.hxx" 7 | 8 | using namespace pqxx; 9 | 10 | 11 | // Test program for libpqxx. Verify abort behaviour of RobustTransaction. 12 | // 13 | // The program will attempt to add an entry to a table called "pqxxevents", 14 | // with a key column called "year"--and then abort the change. 15 | namespace 16 | { 17 | // Let's take a boring year that is not going to be in the "pqxxevents" table 18 | constexpr long BoringYear{1977}; 19 | 20 | 21 | // Count events and specifically events occurring in Boring Year, leaving the 22 | // former count in the result pair's first member, and the latter in second. 23 | std::pair count_events(connection &conn, std::string const &table) 24 | { 25 | nontransaction tx{conn}; 26 | std::string const count_query{"SELECT count(*) FROM " + table}; 27 | return std::make_pair( 28 | tx.query_value(count_query), 29 | tx.query_value(count_query + " WHERE year=" + to_string(BoringYear))); 30 | } 31 | 32 | 33 | struct deliberate_error : std::exception 34 | {}; 35 | 36 | 37 | void test_018() 38 | { 39 | connection conn; 40 | { 41 | work tx{conn}; 42 | test::create_pqxxevents(tx); 43 | tx.commit(); 44 | } 45 | 46 | std::string const Table{"pqxxevents"}; 47 | 48 | auto const Before{ 49 | perform([&conn, &Table] { return count_events(conn, Table); })}; 50 | PQXX_CHECK_EQUAL( 51 | Before.second, 0, 52 | "Already have event for " + to_string(BoringYear) + ", cannot run."); 53 | 54 | { 55 | quiet_errorhandler d{conn}; 56 | PQXX_CHECK_THROWS( 57 | perform([&conn, Table] { 58 | robusttransaction tx{conn}; 59 | tx.exec0( 60 | "INSERT INTO " + Table + " VALUES (" + to_string(BoringYear) + 61 | ", '" + tx.esc("yawn") + "')"); 62 | 63 | throw deliberate_error(); 64 | }), 65 | deliberate_error, 66 | "Not getting expected exception from failing transactor."); 67 | } 68 | 69 | auto const After{ 70 | perform([&conn, &Table] { return count_events(conn, Table); })}; 71 | 72 | PQXX_CHECK_EQUAL(After.first, Before.first, "Event count changed."); 73 | PQXX_CHECK_EQUAL( 74 | After.second, Before.second, 75 | "Event count for " + to_string(BoringYear) + " changed."); 76 | } 77 | 78 | 79 | PQXX_REGISTER_TEST(test_018); 80 | } // namespace 81 | -------------------------------------------------------------------------------- /libpqxx/test/test21.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "test_helpers.hxx" 7 | 8 | using namespace pqxx; 9 | 10 | 11 | // Simple test program for libpqxx. Open a connection to database, start a 12 | // transaction, and perform a query inside it. 13 | namespace 14 | { 15 | void test_021() 16 | { 17 | connection conn; 18 | 19 | std::string const HostName{ 20 | ((conn.hostname() == nullptr) ? "" : conn.hostname())}; 21 | conn.process_notice( 22 | std::string{} + "database=" + conn.dbname() + 23 | ", " 24 | "username=" + 25 | conn.username() + 26 | ", " 27 | "hostname=" + 28 | HostName + 29 | ", " 30 | "port=" + 31 | to_string(conn.port()) + 32 | ", " 33 | "backendpid=" + 34 | to_string(conn.backendpid()) + "\n"); 35 | 36 | work tx{conn, "test_021"}; 37 | 38 | // By now our connection should really have been created 39 | conn.process_notice("Printing details on actual connection\n"); 40 | conn.process_notice( 41 | std::string{} + "database=" + conn.dbname() + 42 | ", " 43 | "username=" + 44 | conn.username() + 45 | ", " 46 | "hostname=" + 47 | HostName + 48 | ", " 49 | "port=" + 50 | to_string(conn.port()) + 51 | ", " 52 | "backendpid=" + 53 | to_string(conn.backendpid()) + "\n"); 54 | 55 | std::string P; 56 | from_string(conn.port(), P); 57 | PQXX_CHECK_EQUAL( 58 | P, to_string(conn.port()), "Port string conversion is broken."); 59 | PQXX_CHECK_EQUAL(to_string(P), P, "Port string conversion is broken."); 60 | 61 | result R(tx.exec("SELECT * FROM pg_tables")); 62 | 63 | tx.process_notice(pqxx::internal::concat( 64 | to_string(std::size(R)), " result row in transaction ", tx.name(), "\n")); 65 | tx.commit(); 66 | } 67 | 68 | 69 | PQXX_REGISTER_TEST(test_021); 70 | } // namespace 71 | -------------------------------------------------------------------------------- /libpqxx/test/test26.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "test_helpers.hxx" 9 | 10 | using namespace pqxx; 11 | 12 | 13 | // Example program for libpqxx. Modify the database, retaining transactional 14 | // integrity using the transactor framework. 15 | namespace 16 | { 17 | // Convert year to 4-digit format. 18 | int To4Digits(int Y) 19 | { 20 | int Result{Y}; 21 | 22 | PQXX_CHECK(Y >= 0, "Negative year: " + to_string(Y)); 23 | 24 | if (Y < 70) 25 | Result += 2000; 26 | else if (Y < 100) 27 | Result += 1900; 28 | else 29 | PQXX_CHECK(Y >= 1970, "Unexpected year: " + to_string(Y)); 30 | return Result; 31 | } 32 | 33 | 34 | // Transaction definition for year-field update. Returns conversions done. 35 | std::map update_years(connection &C) 36 | { 37 | std::map conversions; 38 | work tx{C}; 39 | 40 | // Note all different years currently occurring in the table, writing them 41 | // and their correct mappings to m_conversions 42 | for (auto const &[y] : 43 | tx.stream>("SELECT year FROM pqxxevents")) 44 | { 45 | // Read year, and if it is non-null, note its converted value 46 | if (bool(y)) 47 | conversions[y.value()] = To4Digits(y.value()); 48 | } 49 | 50 | // For each occurring year, write converted date back to whereever it may 51 | // occur in the table. Since we're in a transaction, any changes made by 52 | // others at the same time will not affect us. 53 | for (auto const &c : conversions) 54 | tx.exec0( 55 | "UPDATE pqxxevents " 56 | "SET year=" + 57 | to_string(c.second) + 58 | " " 59 | "WHERE year=" + 60 | to_string(c.first)); 61 | 62 | tx.commit(); 63 | 64 | return conversions; 65 | } 66 | 67 | 68 | void test_026() 69 | { 70 | connection conn; 71 | { 72 | nontransaction tx{conn}; 73 | test::create_pqxxevents(tx); 74 | tx.commit(); 75 | } 76 | 77 | // Perform (an instantiation of) the UpdateYears transactor we've defined 78 | // in the code above. This is where the work gets done. 79 | auto const conversions{perform([&conn] { return update_years(conn); })}; 80 | 81 | PQXX_CHECK(not std::empty(conversions), "No conversions done!"); 82 | } 83 | 84 | 85 | PQXX_REGISTER_TEST(test_026); 86 | } // namespace 87 | -------------------------------------------------------------------------------- /libpqxx/test/test30.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "test_helpers.hxx" 8 | 9 | using namespace pqxx; 10 | 11 | 12 | // Test program for libpqxx. Query a table and report its metadata. 13 | namespace 14 | { 15 | void test_030() 16 | { 17 | std::string const Table{"pg_tables"}; 18 | 19 | connection conn; 20 | work tx{conn, "test30"}; 21 | 22 | result R(tx.exec(("SELECT * FROM " + Table).c_str())); 23 | PQXX_CHECK(not std::empty(R), "Table " + Table + " is empty, cannot test."); 24 | 25 | // Print column names 26 | for (pqxx::row::size_type c{0}; c < R.columns(); ++c) 27 | { 28 | std::string N{R.column_name(c)}; 29 | 30 | PQXX_CHECK_EQUAL( 31 | R[0].column_number(N), R.column_number(N), 32 | "row::column_number() is inconsistent with result::column_number()."); 33 | 34 | PQXX_CHECK_EQUAL(R[0].column_number(N), c, "Inconsistent column numbers."); 35 | } 36 | 37 | // If there are rows in R, compare their metadata to R's. 38 | if (std::empty(R)) 39 | { 40 | std::cout << "(Table is empty.)\n"; 41 | return; 42 | } 43 | 44 | PQXX_CHECK_EQUAL(R[0].rownumber(), 0, "Row 0 reports wrong number."); 45 | 46 | if (std::size(R) < 2) 47 | std::cout << "(Only one row in table.)\n"; 48 | else 49 | PQXX_CHECK_EQUAL(R[1].rownumber(), 1, "Row 1 reports wrong number."); 50 | 51 | for (pqxx::row::size_type c{0}; c < std::size(R[0]); ++c) 52 | { 53 | std::string N{R.column_name(c)}; 54 | 55 | PQXX_CHECK_EQUAL( 56 | std::string{R[0].at(c).c_str()}, R[0].at(N).c_str(), 57 | "Different field values by name and by number."); 58 | 59 | PQXX_CHECK_EQUAL( 60 | std::string{R[0][c].c_str()}, R[0][N].c_str(), 61 | "at() is inconsistent with operator[]."); 62 | 63 | PQXX_CHECK_EQUAL(R[0][c].name(), N, "Inconsistent field names."); 64 | 65 | PQXX_CHECK_EQUAL( 66 | std::size(R[0][c]), std::strlen(R[0][c].c_str()), 67 | "Inconsistent field lengths."); 68 | } 69 | } 70 | 71 | 72 | PQXX_REGISTER_TEST(test_030); 73 | } // namespace 74 | -------------------------------------------------------------------------------- /libpqxx/test/test32.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "test_helpers.hxx" 6 | 7 | using namespace pqxx; 8 | 9 | 10 | // Test program for libpqxx. Verify abort behaviour of transactor. 11 | // 12 | // The program will attempt to add an entry to a table called "pqxxevents", 13 | // with a key column called "year"--and then abort the change. 14 | // 15 | // Note for the superstitious: the numbering for this test program is pure 16 | // coincidence. 17 | 18 | namespace 19 | { 20 | // Let's take a boring year that is not going to be in the "pqxxevents" table 21 | constexpr int BoringYear{1977}; 22 | 23 | std::pair count_events(connection &conn, std::string const &table) 24 | { 25 | std::string const count_query{"SELECT count(*) FROM " + table}; 26 | work tx{conn}; 27 | return std::make_pair( 28 | tx.query_value(count_query), 29 | tx.query_value(count_query + " WHERE year=" + to_string(BoringYear))); 30 | } 31 | 32 | 33 | struct deliberate_error : std::exception 34 | {}; 35 | 36 | 37 | void test_032() 38 | { 39 | connection conn; 40 | { 41 | nontransaction tx{conn}; 42 | test::create_pqxxevents(tx); 43 | } 44 | 45 | std::string const Table{"pqxxevents"}; 46 | 47 | std::pair const Before{ 48 | perform([&conn, &Table] { return count_events(conn, Table); })}; 49 | PQXX_CHECK_EQUAL( 50 | Before.second, 0, 51 | "Already have event for " + to_string(BoringYear) + ", cannot test."); 52 | 53 | { 54 | quiet_errorhandler d(conn); 55 | PQXX_CHECK_THROWS( 56 | perform([&conn, &Table] { 57 | work{conn}.exec0( 58 | "INSERT INTO " + Table + " VALUES (" + to_string(BoringYear) + 59 | ", " 60 | "'yawn')"); 61 | throw deliberate_error(); 62 | }), 63 | deliberate_error, 64 | "Did not get expected exception from failing transactor."); 65 | } 66 | 67 | std::pair const After{ 68 | perform([&conn, &Table] { return count_events(conn, Table); })}; 69 | 70 | PQXX_CHECK_EQUAL(After.first, Before.first, "Event count changed."); 71 | PQXX_CHECK_EQUAL( 72 | After.second, Before.second, 73 | "Event count for " + to_string(BoringYear) + " changed."); 74 | } 75 | 76 | 77 | PQXX_REGISTER_TEST(test_032); 78 | } // namespace 79 | -------------------------------------------------------------------------------- /libpqxx/test/test37.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "test_helpers.hxx" 6 | 7 | using namespace pqxx; 8 | 9 | 10 | // Test program for libpqxx. Verify abort behaviour of RobustTransaction. 11 | // 12 | // The program will attempt to add an entry to a table called "pqxxevents", 13 | // with a key column called "year"--and then abort the change. 14 | namespace 15 | { 16 | // Let's take a boring year that is not going to be in the "pqxxevents" table 17 | constexpr int BoringYear{1977}; 18 | 19 | // Count events and specifically events occurring in Boring Year, leaving the 20 | // former count in the result pair's first member, and the latter in second. 21 | std::pair count_events(connection &conn, std::string const &table) 22 | { 23 | std::string const count_query{"SELECT count(*) FROM " + table}; 24 | nontransaction tx{conn}; 25 | return std::make_pair( 26 | tx.query_value(count_query), 27 | tx.query_value(count_query + " WHERE year=" + to_string(BoringYear))); 28 | } 29 | 30 | 31 | struct deliberate_error : std::exception 32 | {}; 33 | 34 | 35 | void test_037() 36 | { 37 | connection conn; 38 | { 39 | nontransaction tx{conn}; 40 | test::create_pqxxevents(tx); 41 | } 42 | 43 | std::string const Table{"pqxxevents"}; 44 | 45 | auto const Before{ 46 | perform([&conn, &Table] { return count_events(conn, Table); })}; 47 | PQXX_CHECK_EQUAL( 48 | Before.second, 0, 49 | "Already have event for " + to_string(BoringYear) + ", cannot test."); 50 | 51 | { 52 | quiet_errorhandler d(conn); 53 | PQXX_CHECK_THROWS( 54 | perform([&conn, &Table] { 55 | robusttransaction<> tx{conn}; 56 | tx.exec0( 57 | "INSERT INTO " + Table + " VALUES (" + to_string(BoringYear) + 58 | ", " 59 | "'yawn')"); 60 | 61 | throw deliberate_error(); 62 | }), 63 | deliberate_error, 64 | "Did not get expected exception from failing transactor."); 65 | } 66 | 67 | auto const After{ 68 | perform([&conn, &Table] { return count_events(conn, Table); })}; 69 | 70 | PQXX_CHECK_EQUAL(After.first, Before.first, "Number of events changed."); 71 | PQXX_CHECK_EQUAL( 72 | After.second, Before.second, 73 | "Number of events for " + to_string(BoringYear) + " changed."); 74 | } 75 | 76 | 77 | PQXX_REGISTER_TEST(test_037); 78 | } // namespace 79 | -------------------------------------------------------------------------------- /libpqxx/test/test39.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "test_helpers.hxx" 4 | 5 | using namespace pqxx; 6 | 7 | 8 | // Test: nontransaction changes are committed immediately. 9 | namespace 10 | { 11 | int BoringYear{1977}; 12 | 13 | 14 | void test_039() 15 | { 16 | connection conn; 17 | nontransaction tx1{conn}; 18 | test::create_pqxxevents(tx1); 19 | std::string const Table{"pqxxevents"}; 20 | 21 | // Verify our start condition before beginning: there must not be a 1977 22 | // record already. 23 | result R(tx1.exec( 24 | "SELECT * FROM " + Table + 25 | " " 26 | "WHERE year=" + 27 | to_string(BoringYear))); 28 | 29 | PQXX_CHECK_EQUAL( 30 | std::size(R), 0, 31 | "Already have a row for " + to_string(BoringYear) + ", cannot test."); 32 | 33 | // (Not needed, but verify that clear() works on empty containers) 34 | R.clear(); 35 | PQXX_CHECK(std::empty(R), "Result is non-empty after clear()."); 36 | 37 | // OK. Having laid that worry to rest, add a record for 1977. 38 | tx1.exec0( 39 | "INSERT INTO " + Table + 40 | " VALUES" 41 | "(" + 42 | to_string(BoringYear) + 43 | "," 44 | "'Yawn'" 45 | ")"); 46 | 47 | // Abort tx1. Since tx1 is a nontransaction, which provides only the 48 | // transaction class interface without providing any form of transactional 49 | // integrity, this is not going to undo our work. 50 | tx1.abort(); 51 | 52 | // Verify that our record was added, despite the Abort() 53 | nontransaction tx2(conn, "tx2"); 54 | R = tx2.exec( 55 | "SELECT * FROM " + Table + 56 | " " 57 | "WHERE year=" + 58 | to_string(BoringYear)); 59 | PQXX_CHECK_EQUAL(std::size(R), 1, "Unexpected result size."); 60 | 61 | PQXX_CHECK(R.capacity() >= std::size(R), "Result's capacity is too small."); 62 | 63 | R.clear(); 64 | PQXX_CHECK(std::empty(R), "result::clear() is broken."); 65 | 66 | // Now remove our record again 67 | tx2.exec0( 68 | "DELETE FROM " + Table + 69 | " " 70 | "WHERE year=" + 71 | to_string(BoringYear)); 72 | 73 | tx2.commit(); 74 | 75 | // And again, verify results 76 | nontransaction tx3(conn, "tx3"); 77 | 78 | R = tx3.exec( 79 | "SELECT * FROM " + Table + 80 | " " 81 | "WHERE year=" + 82 | to_string(BoringYear)); 83 | 84 | PQXX_CHECK_EQUAL(std::size(R), 0, "Record is not gone as expected."); 85 | } 86 | 87 | 88 | PQXX_REGISTER_TEST(test_039); 89 | } // namespace 90 | -------------------------------------------------------------------------------- /libpqxx/test/test46.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "test_helpers.hxx" 8 | 9 | using namespace pqxx; 10 | 11 | 12 | // Streams test program for libpqxx. Insert a result field into various 13 | // types of streams. 14 | namespace 15 | { 16 | void test_046() 17 | { 18 | connection conn; 19 | work tx{conn}; 20 | 21 | row R{tx.exec1("SELECT count(*) FROM pg_tables")}; 22 | 23 | // Read the value into a stringstream. 24 | std::stringstream I; 25 | #include "pqxx/internal/ignore-deprecated-pre.hxx" 26 | I << R[0]; 27 | #include "pqxx/internal/ignore-deprecated-post.hxx" 28 | 29 | // Now convert the stringstream into a numeric type 30 | long L{}, L2{}; 31 | I >> L; 32 | 33 | R[0].to(L2); 34 | PQXX_CHECK_EQUAL(L, L2, "Inconsistency between conversion methods."); 35 | 36 | float F{}, F2{}; 37 | std::stringstream I2; 38 | #include "pqxx/internal/ignore-deprecated-pre.hxx" 39 | I2 << R[0]; 40 | #include "pqxx/internal/ignore-deprecated-post.hxx" 41 | I2 >> F; 42 | R[0].to(F2); 43 | PQXX_CHECK_BOUNDS(F2, F - 0.01, F + 0.01, "Bad floating-point result."); 44 | 45 | auto F3{from_string(R[0].c_str())}; 46 | PQXX_CHECK_BOUNDS(F3, F - 0.01, F + 0.01, "Bad float from from_string."); 47 | 48 | auto D{from_string(R[0].c_str())}; 49 | PQXX_CHECK_BOUNDS(D, F - 0.01, F + 0.01, "Bad double from from_string."); 50 | 51 | auto LD{from_string(R[0].c_str())}; 52 | PQXX_CHECK_BOUNDS( 53 | LD, F - 0.01, F + 0.01, "Bad long double from from_string."); 54 | 55 | auto S{from_string(R[0].c_str())}, 56 | S2{from_string(std::string{R[0].c_str()})}, 57 | S3{from_string(R[0])}; 58 | 59 | PQXX_CHECK_EQUAL( 60 | S2, S, 61 | "from_string(char const[], std::string &) " 62 | "is inconsistent with " 63 | "from_string(std::string const &, std::string &)."); 64 | 65 | PQXX_CHECK_EQUAL( 66 | S3, S2, 67 | "from_string(result::field const &, std::string &) " 68 | "is inconsistent with " 69 | "from_string(std::string const &, std::string &)."); 70 | 71 | PQXX_CHECK(tx.query_value("SELECT 1=1"), "1=1 doesn't yield 'true.'"); 72 | 73 | PQXX_CHECK(not tx.query_value("SELECT 2+2=5"), "2+2=5 yields 'true.'"); 74 | } 75 | 76 | 77 | PQXX_REGISTER_TEST(test_046); 78 | } // namespace 79 | -------------------------------------------------------------------------------- /libpqxx/test/test56.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "test_helpers.hxx" 4 | 5 | using namespace pqxx; 6 | 7 | 8 | // Simple test program for libpqxx. Issue invalid query and handle error. 9 | namespace 10 | { 11 | void test_056() 12 | { 13 | connection conn; 14 | work tx{conn}; 15 | quiet_errorhandler d(conn); 16 | 17 | PQXX_CHECK_THROWS( 18 | tx.exec("DELIBERATELY INVALID TEST QUERY..."), sql_error, 19 | "SQL syntax error did not raise expected exception."); 20 | } 21 | 22 | 23 | PQXX_REGISTER_TEST(test_056); 24 | } // namespace 25 | -------------------------------------------------------------------------------- /libpqxx/test/test60.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "test_helpers.hxx" 8 | 9 | using namespace pqxx; 10 | 11 | 12 | // Example program for libpqxx. Test session variable functionality. 13 | namespace 14 | { 15 | std::string GetDatestyle(connection &conn) 16 | { 17 | return conn.get_var("DATESTYLE"); 18 | } 19 | 20 | 21 | std::string SetDatestyle(connection &conn, std::string style) 22 | { 23 | conn.set_session_var("DATESTYLE", style); 24 | std::string const fullname{GetDatestyle(conn)}; 25 | PQXX_CHECK( 26 | not std::empty(fullname), 27 | "Setting datestyle to " + style + " makes it an empty string."); 28 | 29 | return fullname; 30 | } 31 | 32 | 33 | void CheckDatestyle(connection &conn, std::string expected) 34 | { 35 | PQXX_CHECK_EQUAL(GetDatestyle(conn), expected, "Got wrong datestyle."); 36 | } 37 | 38 | 39 | void RedoDatestyle( 40 | connection &conn, std::string const &style, std::string const &expected) 41 | { 42 | PQXX_CHECK_EQUAL( 43 | SetDatestyle(conn, style), expected, "Set wrong datestyle."); 44 | } 45 | 46 | 47 | void ActivationTest( 48 | connection &conn, std::string const &style, std::string const &expected) 49 | { 50 | RedoDatestyle(conn, style, expected); 51 | CheckDatestyle(conn, expected); 52 | } 53 | 54 | 55 | void test_060() 56 | { 57 | connection conn; 58 | 59 | PQXX_CHECK(not std::empty(GetDatestyle(conn)), "Initial datestyle not set."); 60 | 61 | std::string const ISOname{SetDatestyle(conn, "ISO")}; 62 | std::string const SQLname{SetDatestyle(conn, "SQL")}; 63 | 64 | PQXX_CHECK_NOT_EQUAL(ISOname, SQLname, "Same datestyle in SQL and ISO."); 65 | 66 | RedoDatestyle(conn, "SQL", SQLname); 67 | 68 | ActivationTest(conn, "ISO", ISOname); 69 | ActivationTest(conn, "SQL", SQLname); 70 | 71 | PQXX_CHECK_THROWS( 72 | conn.set_session_var("bonjour_name", std::optional{}), 73 | pqxx::variable_set_to_null, 74 | "Setting a variable to null did not report the error correctly."); 75 | 76 | // Prove that setting an unknown variable causes an error, as expected 77 | quiet_errorhandler d{conn}; 78 | PQXX_CHECK_THROWS( 79 | conn.set_session_var("NONEXISTENT_VARIABLE_I_HOPE", 1), sql_error, 80 | "Setting unknown variable failed to fail."); 81 | } 82 | 83 | 84 | PQXX_REGISTER_TEST(test_060); 85 | } // namespace 86 | -------------------------------------------------------------------------------- /libpqxx/test/test61.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "test_helpers.hxx" 6 | 7 | using namespace pqxx; 8 | 9 | 10 | // Example program for libpqxx. Test local variable functionality. 11 | namespace 12 | { 13 | std::string GetDatestyle(transaction_base &T) 14 | { 15 | return T.conn().get_var("DATESTYLE"); 16 | } 17 | 18 | 19 | std::string SetDatestyle(transaction_base &T, std::string style) 20 | { 21 | T.conn().set_session_var("DATESTYLE", style); 22 | std::string const fullname{GetDatestyle(T)}; 23 | PQXX_CHECK( 24 | not std::empty(fullname), 25 | "Setting datestyle to " + style + " makes it an empty string."); 26 | 27 | return fullname; 28 | } 29 | 30 | 31 | void RedoDatestyle( 32 | transaction_base &T, std::string const &style, std::string const &expected) 33 | { 34 | PQXX_CHECK_EQUAL(SetDatestyle(T, style), expected, "Set wrong datestyle."); 35 | } 36 | 37 | 38 | void test_061() 39 | { 40 | connection conn; 41 | work tx{conn}; 42 | 43 | PQXX_CHECK(not std::empty(GetDatestyle(tx)), "Initial datestyle not set."); 44 | 45 | std::string const ISOname{SetDatestyle(tx, "ISO")}; 46 | std::string const SQLname{SetDatestyle(tx, "SQL")}; 47 | 48 | PQXX_CHECK_NOT_EQUAL(ISOname, SQLname, "Same datestyle in SQL and ISO."); 49 | 50 | RedoDatestyle(tx, "SQL", SQLname); 51 | 52 | // Prove that setting an unknown variable causes an error, as expected 53 | quiet_errorhandler d(tx.conn()); 54 | PQXX_CHECK_THROWS( 55 | conn.set_session_var("NONEXISTENT_VARIABLE_I_HOPE", 1), sql_error, 56 | "Setting unknown variable failed to fail."); 57 | } 58 | 59 | 60 | PQXX_REGISTER_TEST(test_061); 61 | } // namespace 62 | -------------------------------------------------------------------------------- /libpqxx/test/test62.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "test_helpers.hxx" 7 | 8 | 9 | using namespace pqxx; 10 | 11 | 12 | // Example program for libpqxx. Test binary string functionality. 13 | namespace 14 | { 15 | void test_062() 16 | { 17 | connection conn; 18 | work tx{conn}; 19 | 20 | std::string const TestStr{ 21 | "Nasty\n\030Test\n\t String with \200\277 weird bytes " 22 | "\r\0 and Trailer\\\\\0"}; 23 | 24 | tx.exec0("CREATE TEMP TABLE pqxxbin (binfield bytea)"); 25 | 26 | std::string const Esc{tx.esc_raw(bytes{ 27 | reinterpret_cast(std::data(TestStr)), 28 | std::size(TestStr)})}; 29 | 30 | tx.exec0("INSERT INTO pqxxbin VALUES ('" + Esc + "')"); 31 | 32 | result R{tx.exec("SELECT * from pqxxbin")}; 33 | tx.exec0("DELETE FROM pqxxbin"); 34 | 35 | auto const B{R.at(0).at(0).as()}; 36 | 37 | PQXX_CHECK(not std::empty(B), "Binary string became empty in conversion."); 38 | 39 | PQXX_CHECK_EQUAL( 40 | std::size(B), std::size(TestStr), "Binary string was mangled."); 41 | 42 | bytes::const_iterator c; 43 | bytes::size_type i; 44 | for (i = 0, c = std::begin(B); i < std::size(B); ++i, ++c) 45 | { 46 | PQXX_CHECK(c != std::end(B), "Premature end to binary string."); 47 | 48 | char const x{TestStr.at(i)}, y{char(B.at(i))}, z{char(std::data(B)[i])}; 49 | 50 | PQXX_CHECK_EQUAL( 51 | std::string(&x, 1), std::string(&y, 1), "Binary string byte changed."); 52 | 53 | PQXX_CHECK_EQUAL( 54 | std::string(&y, 1), std::string(&z, 1), 55 | "Inconsistent byte at offset " + to_string(i) + "."); 56 | } 57 | } 58 | 59 | 60 | PQXX_REGISTER_TEST(test_062); 61 | } // namespace 62 | -------------------------------------------------------------------------------- /libpqxx/test/test69.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "test_helpers.hxx" 7 | 8 | using namespace pqxx; 9 | 10 | 11 | // Test program for libpqxx. Issue a query repeatedly through a pipeline, and 12 | // compare results. 13 | namespace 14 | { 15 | void TestPipeline(pipeline &P, int numqueries) 16 | { 17 | std::string const Q{"SELECT 99"}; 18 | 19 | for (int i{numqueries}; i > 0; --i) P.insert(Q); 20 | 21 | PQXX_CHECK( 22 | (numqueries == 0) or not std::empty(P), "pipeline::empty() is broken."); 23 | 24 | int res{0}; 25 | for (int i{numqueries}; i > 0; --i) 26 | { 27 | PQXX_CHECK( 28 | not std::empty(P), "Got wrong number of queries from pipeline."); 29 | 30 | auto R{P.retrieve()}; 31 | 32 | if (res != 0) 33 | PQXX_CHECK_EQUAL( 34 | R.second[0][0].as(), res, 35 | "Got unexpected result out of pipeline."); 36 | 37 | res = R.second[0][0].as(); 38 | } 39 | 40 | PQXX_CHECK(std::empty(P), "Pipeline not empty after retrieval."); 41 | } 42 | 43 | 44 | void test_069() 45 | { 46 | connection conn; 47 | work tx{conn}; 48 | pipeline P(tx); 49 | PQXX_CHECK(std::empty(P), "Pipeline is not empty initially."); 50 | for (int i{0}; i < 5; ++i) TestPipeline(P, i); 51 | } 52 | 53 | 54 | PQXX_REGISTER_TEST(test_069); 55 | } // namespace 56 | -------------------------------------------------------------------------------- /libpqxx/test/test71.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include "test_helpers.hxx" 8 | 9 | using namespace pqxx; 10 | 11 | 12 | // Test program for libpqxx. Issue queries through a pipeline, and retrieve 13 | // results both in-order and out-of-order. 14 | namespace 15 | { 16 | using Exp = std::map; 17 | 18 | template void checkresult(pipeline &P, PAIR c) 19 | { 20 | result const r{P.retrieve(c.first)}; 21 | int const val{r.at(0).at(0).as(int(0))}; 22 | PQXX_CHECK_EQUAL(val, c.second, "Wrong result from pipeline."); 23 | } 24 | 25 | 26 | void test_071() 27 | { 28 | connection conn; 29 | work tx{conn}; 30 | pipeline P(tx); 31 | 32 | // Keep expected result for every query we issue 33 | Exp values; 34 | 35 | // Insert queries returning various numbers. 36 | for (int i{1}; i < 10; ++i) values[P.insert("SELECT " + to_string(i))] = i; 37 | 38 | // Retrieve results in query_id order, and compare to expected values 39 | for (auto &c : values) checkresult(P, c); 40 | 41 | PQXX_CHECK(std::empty(P), "Pipeline was not empty retrieving all results."); 42 | 43 | values.clear(); 44 | 45 | // Insert more queries returning various numbers 46 | P.retain(20); 47 | for (int i{100}; i > 90; --i) values[P.insert("SELECT " + to_string(i))] = i; 48 | 49 | P.resume(); 50 | 51 | // Retrieve results in reverse order 52 | for (auto c{std::rbegin(values)}; c != std::rend(values); ++c) 53 | checkresult(P, *c); 54 | 55 | values.clear(); 56 | P.retain(10); 57 | for (int i{1010}; i > 1000; --i) 58 | values[P.insert("SELECT " + to_string(i))] = i; 59 | for (auto &c : values) 60 | { 61 | if (P.is_finished(c.first)) 62 | std::cout << "Query #" << c.first << " completed despite retain()" 63 | << std::endl; 64 | } 65 | 66 | // See that all results are retrieved by complete() 67 | P.complete(); 68 | for (auto &c : values) 69 | PQXX_CHECK(P.is_finished(c.first), "Query not finished after complete()."); 70 | } 71 | } // namespace 72 | 73 | 74 | PQXX_REGISTER_TEST(test_071); 75 | -------------------------------------------------------------------------------- /libpqxx/test/test72.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "test_helpers.hxx" 7 | 8 | using namespace pqxx; 9 | 10 | 11 | // Test program for libpqxx. Test error handling for pipeline. 12 | namespace 13 | { 14 | void test_072() 15 | { 16 | connection conn; 17 | work tx{conn}; 18 | pipeline P{tx}; 19 | 20 | // Ensure all queries are issued at once to make the test more interesting 21 | P.retain(); 22 | 23 | // The middle query should fail; the surrounding two should succeed 24 | auto const id_1{P.insert("SELECT 1")}; 25 | auto const id_f{P.insert("SELECT * FROM pg_nonexist")}; 26 | auto const id_2{P.insert("SELECT 2")}; 27 | 28 | // See that we can process the queries without stumbling over the error 29 | P.complete(); 30 | 31 | // We should be able to get the first result, which preceeds the error 32 | auto const res_1{P.retrieve(id_1).at(0).at(0).as()}; 33 | PQXX_CHECK_EQUAL(res_1, 1, "Got wrong result from pipeline."); 34 | 35 | // We should *not* get a result for the query behind the error 36 | { 37 | quiet_errorhandler d{conn}; 38 | PQXX_CHECK_THROWS( 39 | P.retrieve(id_2).at(0).at(0).as(), std::runtime_error, 40 | "Pipeline wrongly resumed after SQL error."); 41 | } 42 | 43 | // Now see that we get an exception when we touch the failed result 44 | { 45 | quiet_errorhandler d{conn}; 46 | PQXX_CHECK_THROWS( 47 | P.retrieve(id_f), sql_error, "Pipeline failed to register SQL error."); 48 | } 49 | } 50 | } // namespace 51 | 52 | 53 | PQXX_REGISTER_TEST(test_072); 54 | -------------------------------------------------------------------------------- /libpqxx/test/test74.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "test_helpers.hxx" 6 | 7 | using namespace pqxx; 8 | 9 | 10 | // Test program for libpqxx. Test fieldstream. 11 | namespace 12 | { 13 | void test_074() 14 | { 15 | #include "pqxx/internal/ignore-deprecated-pre.hxx" 16 | connection conn; 17 | work tx{conn}; 18 | 19 | result R{tx.exec("SELECT * FROM pg_tables")}; 20 | std::string const sval{R.at(0).at(1).c_str()}; 21 | std::string sval2; 22 | fieldstream fs1(R.front()[1]); 23 | fs1 >> sval2; 24 | PQXX_CHECK_EQUAL(sval2, sval, "fieldstream returned wrong value."); 25 | 26 | R = tx.exec("SELECT count(*) FROM pg_tables"); 27 | int ival; 28 | fieldstream fs2(R.at(0).at(0)); 29 | fs2 >> ival; 30 | PQXX_CHECK_EQUAL( 31 | ival, R.front().front().as(), "fieldstream::front() is broken."); 32 | 33 | double dval; 34 | (fieldstream(R.at(0).at(0))) >> dval; 35 | PQXX_CHECK_BOUNDS( 36 | dval, R[0][0].as() - 0.1, R[0][0].as() + 0.1, 37 | "Got wrong double from fieldstream."); 38 | 39 | auto const roughpi{static_cast(3.1415926435)}; 40 | R = tx.exec("SELECT " + to_string(roughpi)); 41 | float pival; 42 | (fieldstream(R.at(0).at(0))) >> pival; 43 | PQXX_CHECK_BOUNDS( 44 | pival, roughpi - 0.001, roughpi + 0.001, 45 | "Pi approximation came back wrong from fieldstream."); 46 | 47 | PQXX_CHECK_EQUAL( 48 | to_string(R[0][0]), R[0][0].c_str(), 49 | "to_string(result::field) is inconsistent with c_str()."); 50 | 51 | float float_pi; 52 | from_string(to_string(roughpi), float_pi); 53 | PQXX_CHECK_BOUNDS( 54 | float_pi, roughpi - 0.00001, roughpi + 0.00001, 55 | "Float changed in conversion."); 56 | 57 | double double_pi; 58 | pqxx::from_string(pqxx::to_string(static_cast(roughpi)), double_pi); 59 | PQXX_CHECK_BOUNDS( 60 | double_pi, roughpi - 0.00001, roughpi + 0.00001, 61 | "Double changed in conversion."); 62 | 63 | long double const ld{roughpi}; 64 | long double long_double_pi; 65 | from_string(to_string(ld), long_double_pi); 66 | PQXX_CHECK_BOUNDS( 67 | long_double_pi, roughpi - 0.00001, roughpi + 0.00001, 68 | "long double changed in conversion."); 69 | #include "pqxx/internal/ignore-deprecated-post.hxx" 70 | } 71 | } // namespace 72 | 73 | 74 | PQXX_REGISTER_TEST(test_074); 75 | -------------------------------------------------------------------------------- /libpqxx/test/test76.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "test_helpers.hxx" 4 | 5 | // Simple test program for libpqxx. Test string conversion routines. 6 | namespace 7 | { 8 | void test_076() 9 | { 10 | pqxx::connection conn; 11 | pqxx::nontransaction tx{conn}; 12 | 13 | auto RFalse{tx.exec1("SELECT 1=0")}, RTrue{tx.exec1("SELECT 1=1")}; 14 | auto False{pqxx::from_string(RFalse[0])}, 15 | True{pqxx::from_string(RTrue[0])}; 16 | PQXX_CHECK(not False, "False bool converted to true."); 17 | PQXX_CHECK(True, "True bool converted to false."); 18 | 19 | RFalse = tx.exec1("SELECT " + pqxx::to_string(False)); 20 | RTrue = tx.exec1("SELECT " + pqxx::to_string(True)); 21 | False = pqxx::from_string(RFalse[0]); 22 | True = pqxx::from_string(RTrue[0]); 23 | PQXX_CHECK(not False, "False bool converted to true."); 24 | PQXX_CHECK(True, "True bool converted to false."); 25 | 26 | short const svals[]{-1, 1, 999, -32767, -32768, 32767, 0}; 27 | for (int i{0}; svals[i] != 0; ++i) 28 | { 29 | auto s{pqxx::from_string(pqxx::to_string(svals[i]))}; 30 | PQXX_CHECK_EQUAL(s, svals[i], "short/string conversion not bijective."); 31 | s = pqxx::from_string( 32 | tx.exec1("SELECT " + pqxx::to_string(svals[i]))[0].c_str()); 33 | PQXX_CHECK_EQUAL(s, svals[i], "Roundtrip through backend changed short."); 34 | } 35 | 36 | unsigned short const uvals[]{1, 999, 32767, 32768, 65535, 0}; 37 | for (int i{0}; uvals[i] != 0; ++i) 38 | { 39 | auto u{pqxx::from_string(pqxx::to_string(uvals[i]))}; 40 | PQXX_CHECK_EQUAL( 41 | u, uvals[i], "unsigned short/string conversion not bijective."); 42 | 43 | u = pqxx::from_string( 44 | tx.exec1("SELECT " + pqxx::to_string(uvals[i]))[0].c_str()); 45 | PQXX_CHECK_EQUAL( 46 | u, uvals[i], "Roundtrip through backend changed unsigned short."); 47 | } 48 | } 49 | } // namespace 50 | 51 | 52 | PQXX_REGISTER_TEST(test_076); 53 | -------------------------------------------------------------------------------- /libpqxx/test/test77.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "test_helpers.hxx" 4 | 5 | 6 | // Test program for libpqxx. Test result::swap() 7 | namespace 8 | { 9 | void test_077() 10 | { 11 | pqxx::connection conn; 12 | pqxx::nontransaction tx{conn}; 13 | 14 | auto RFalse{tx.exec("SELECT 1=0")}, RTrue{tx.exec("SELECT 1=1")}; 15 | auto f{pqxx::from_string(RFalse[0][0])}; 16 | auto t{pqxx::from_string(RTrue[0][0])}; 17 | PQXX_CHECK( 18 | not f and t, "Booleans converted incorrectly; can't trust this test."); 19 | 20 | RFalse.swap(RTrue); 21 | f = pqxx::from_string(RFalse[0][0]); 22 | t = pqxx::from_string(RTrue[0][0]); 23 | PQXX_CHECK(f and not t, "result::swap() is broken."); 24 | } 25 | } // namespace 26 | 27 | 28 | PQXX_REGISTER_TEST(test_077); 29 | -------------------------------------------------------------------------------- /libpqxx/test/test78.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "test_helpers.hxx" 10 | 11 | 12 | // Example program for libpqxx. Send notification to self, using a 13 | // notification name with unusal characters, and without polling. 14 | namespace 15 | { 16 | // Sample implementation of notification receiver. 17 | class TestListener : public pqxx::notification_receiver 18 | { 19 | bool m_done; 20 | 21 | public: 22 | explicit TestListener(pqxx::connection &conn, std::string const &Name) : 23 | pqxx::notification_receiver(conn, Name), m_done(false) 24 | {} 25 | 26 | void operator()(std::string const &, int be_pid) override 27 | { 28 | m_done = true; 29 | PQXX_CHECK_EQUAL( 30 | be_pid, conn().backendpid(), 31 | "Got notification from wrong backend process."); 32 | 33 | std::cout << "Received notification: " << channel() << " pid=" << be_pid 34 | << std::endl; 35 | } 36 | 37 | bool done() const { return m_done; } 38 | }; 39 | 40 | 41 | void test_078() 42 | { 43 | pqxx::connection conn; 44 | 45 | std::string const NotifName{"my listener"}; 46 | TestListener L{conn, NotifName}; 47 | 48 | pqxx::perform([&conn, &L] { 49 | pqxx::work tx{conn}; 50 | tx.exec0("NOTIFY " + tx.quote_name(L.channel())); 51 | tx.commit(); 52 | }); 53 | 54 | int notifs{0}; 55 | for (int i{0}; (i < 20) and not L.done(); ++i) 56 | { 57 | PQXX_CHECK_EQUAL(notifs, 0, "Got unexpected notifications."); 58 | std::cout << "."; 59 | notifs = conn.await_notification(); 60 | } 61 | std::cout << std::endl; 62 | 63 | PQXX_CHECK(L.done(), "No notification received."); 64 | PQXX_CHECK_EQUAL(notifs, 1, "Got unexpected number of notifications."); 65 | } 66 | } // namespace 67 | 68 | 69 | PQXX_REGISTER_TEST(test_078); 70 | -------------------------------------------------------------------------------- /libpqxx/test/test79.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "test_helpers.hxx" 10 | 11 | 12 | // Example program for libpqxx. Test waiting for notification with timeout. 13 | namespace 14 | { 15 | // Sample implementation of notification receiver. 16 | class TestListener final : public pqxx::notification_receiver 17 | { 18 | bool m_done; 19 | 20 | public: 21 | explicit TestListener(pqxx::connection &conn, std::string const &Name) : 22 | pqxx::notification_receiver(conn, Name), m_done(false) 23 | {} 24 | 25 | void operator()(std::string const &, int be_pid) override 26 | { 27 | m_done = true; 28 | PQXX_CHECK_EQUAL( 29 | be_pid, conn().backendpid(), "Notification came from wrong backend."); 30 | 31 | std::cout << "Received notification: " << channel() << " pid=" << be_pid 32 | << std::endl; 33 | } 34 | 35 | bool done() const { return m_done; } 36 | }; 37 | 38 | 39 | void test_079() 40 | { 41 | pqxx::connection conn; 42 | 43 | std::string const NotifName{"mylistener"}; 44 | TestListener L(conn, NotifName); 45 | 46 | // First see if the timeout really works: we're not expecting any notifs 47 | int notifs{conn.await_notification(0, 1)}; 48 | PQXX_CHECK_EQUAL(notifs, 0, "Got unexpected notification."); 49 | 50 | pqxx::perform([&conn, &L] { 51 | pqxx::work tx{conn}; 52 | tx.exec0("NOTIFY " + L.channel()); 53 | tx.commit(); 54 | }); 55 | 56 | for (int i{0}; (i < 20) and not L.done(); ++i) 57 | { 58 | PQXX_CHECK_EQUAL(notifs, 0, "Got notifications, but no handler called."); 59 | std::cout << "."; 60 | notifs = conn.await_notification(1, 0); 61 | } 62 | std::cout << std::endl; 63 | 64 | PQXX_CHECK(L.done(), "No notifications received."); 65 | PQXX_CHECK_EQUAL(notifs, 1, "Got unexpected notifications."); 66 | } 67 | } // namespace 68 | 69 | 70 | PQXX_REGISTER_TEST(test_079); 71 | -------------------------------------------------------------------------------- /libpqxx/test/test87.cxx: -------------------------------------------------------------------------------- 1 | #include "pqxx/config-public-compiler.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "test_helpers.hxx" 19 | 20 | 21 | // Test program for libpqxx. Send notification to self, and wait on the 22 | // socket's connection for it to come in. In a simple situation you'd use 23 | // connection::await_notification() for this, but that won't let you wait for 24 | // multiple sockets. 25 | namespace 26 | { 27 | // Sample implementation of notification receiver. 28 | class TestListener final : public pqxx::notification_receiver 29 | { 30 | bool m_done; 31 | 32 | public: 33 | explicit TestListener(pqxx::connection &conn, std::string Name) : 34 | pqxx::notification_receiver(conn, Name), m_done(false) 35 | {} 36 | 37 | void operator()(std::string const &, int be_pid) override 38 | { 39 | m_done = true; 40 | PQXX_CHECK_EQUAL( 41 | be_pid, conn().backendpid(), 42 | "Notification came from wrong backend process."); 43 | 44 | std::cout << "Received notification: " << channel() << " pid=" << be_pid 45 | << std::endl; 46 | } 47 | 48 | bool done() const { return m_done; } 49 | }; 50 | 51 | 52 | void test_087() 53 | { 54 | pqxx::connection conn; 55 | 56 | std::string const NotifName{"my notification"}; 57 | TestListener L{conn, NotifName}; 58 | 59 | pqxx::perform([&conn, &L] { 60 | pqxx::work tx{conn}; 61 | tx.exec0("NOTIFY " + tx.quote_name(L.channel())); 62 | tx.commit(); 63 | }); 64 | 65 | int notifs{0}; 66 | for (int i{0}; (i < 20) and not L.done(); ++i) 67 | { 68 | PQXX_CHECK_EQUAL(notifs, 0, "Got unexpected notifications."); 69 | 70 | std::cout << "."; 71 | 72 | pqxx::internal::wait_fd(conn.sock(), true, false); 73 | notifs = conn.get_notifs(); 74 | } 75 | std::cout << std::endl; 76 | 77 | PQXX_CHECK(L.done(), "No notification received."); 78 | PQXX_CHECK_EQUAL(notifs, 1, "Got unexpected number of notifications."); 79 | } 80 | } // namespace 81 | 82 | 83 | PQXX_REGISTER_TEST(test_087); 84 | -------------------------------------------------------------------------------- /libpqxx/test/test89.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "test_helpers.hxx" 7 | 8 | // Test program for libpqxx. Attempt to perform nested queries on various 9 | // types of connections. 10 | namespace 11 | { 12 | void test_089() 13 | { 14 | pqxx::connection C; 15 | 16 | // Trivial test: create subtransactions, and commit/abort 17 | pqxx::work T0(C, "T0"); 18 | T0.exec1("SELECT 'T0 starts'"); 19 | pqxx::subtransaction T0a(T0, "T0a"); 20 | T0a.commit(); 21 | pqxx::subtransaction T0b(T0, "T0b"); 22 | T0b.abort(); 23 | T0.exec1("SELECT 'T0 ends'"); 24 | T0.commit(); 25 | 26 | // Basic functionality: perform query in subtransaction; abort, continue 27 | pqxx::work T1(C, "T1"); 28 | T1.exec1("SELECT 'T1 starts'"); 29 | pqxx::subtransaction T1a(T1, "T1a"); 30 | T1a.exec1("SELECT ' a'"); 31 | T1a.commit(); 32 | pqxx::subtransaction T1b(T1, "T1b"); 33 | T1b.exec1("SELECT ' b'"); 34 | T1b.abort(); 35 | pqxx::subtransaction T1c(T1, "T1c"); 36 | T1c.exec1("SELECT ' c'"); 37 | T1c.commit(); 38 | T1.exec1("SELECT 'T1 ends'"); 39 | T1.commit(); 40 | } 41 | } // namespace 42 | 43 | 44 | PQXX_REGISTER_TEST(test_089); 45 | -------------------------------------------------------------------------------- /libpqxx/test/test90.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "test_helpers.hxx" 4 | 5 | // Test program for libpqxx. Test adorn_name. 6 | 7 | namespace 8 | { 9 | void test_090() 10 | { 11 | pqxx::connection conn; 12 | 13 | // Test connection's adorn_name() function for uniqueness 14 | std::string const nametest{"basename"}; 15 | 16 | PQXX_CHECK_NOT_EQUAL( 17 | conn.adorn_name(nametest), conn.adorn_name(nametest), 18 | "\"Unique\" names are not unique."); 19 | } 20 | } // namespace 21 | 22 | 23 | PQXX_REGISTER_TEST(test_090); 24 | -------------------------------------------------------------------------------- /libpqxx/test/unit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(NOT PostgreSQL_FOUND) 2 | if(POLICY CMP0074) 3 | cmake_policy(PUSH) 4 | # CMP0074 is `OLD` by `cmake_minimum_required(VERSION 3.7)`, sets `NEW` 5 | # to enable support CMake variable `PostgreSQL_ROOT`. 6 | cmake_policy(SET CMP0074 NEW) 7 | endif() 8 | 9 | find_package(PostgreSQL REQUIRED) 10 | 11 | if(POLICY CMP0074) 12 | cmake_policy(POP) 13 | endif() 14 | endif() 15 | 16 | file(GLOB UNIT_TEST_SOURCES *.cxx) 17 | 18 | add_executable(unit_runner ${UNIT_TEST_SOURCES}) 19 | target_link_libraries(unit_runner PUBLIC pqxx) 20 | target_include_directories(unit_runner PRIVATE ${PostgreSQL_INCLUDE_DIRS}) 21 | add_test( 22 | NAME unit_runner 23 | WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} 24 | COMMAND unit_runner 25 | ) 26 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_cancel_query.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../test_helpers.hxx" 5 | 6 | namespace 7 | { 8 | void test_cancel_query() 9 | { 10 | pqxx::connection conn; 11 | pqxx::work tx{conn}; 12 | // Calling cancel_query() while none is in progress has no effect. 13 | conn.cancel_query(); 14 | 15 | // Nothing much is guaranteed about cancel_query, except that it doesn't make 16 | // the process die in flames. 17 | pqxx::pipeline p{tx, "test_cancel_query"}; 18 | p.retain(0); 19 | p.insert("SELECT pg_sleep(1)"); 20 | conn.cancel_query(); 21 | } 22 | 23 | 24 | PQXX_REGISTER_TEST(test_cancel_query); 25 | } // namespace 26 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_column.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../test_helpers.hxx" 4 | 5 | namespace 6 | { 7 | void test_table_column() 8 | { 9 | pqxx::connection conn; 10 | pqxx::work tx{conn}; 11 | 12 | tx.exec0("CREATE TEMP TABLE pqxxfoo (x varchar, y integer, z integer)"); 13 | tx.exec0("INSERT INTO pqxxfoo VALUES ('xx', 1, 2)"); 14 | auto R{tx.exec("SELECT z,y,x FROM pqxxfoo")}; 15 | auto X{tx.exec("SELECT x,y,z,99 FROM pqxxfoo")}; 16 | 17 | pqxx::row::size_type x{R.table_column(2)}, y{R.table_column(1)}, 18 | z{R.table_column(static_cast(0))}; 19 | 20 | PQXX_CHECK_EQUAL(x, 0, "Wrong column number."); 21 | PQXX_CHECK_EQUAL(y, 1, "Wrong column number."); 22 | PQXX_CHECK_EQUAL(z, 2, "Wrong column number."); 23 | 24 | x = R.table_column("x"); 25 | y = R.table_column("y"); 26 | z = R.table_column("z"); 27 | 28 | PQXX_CHECK_EQUAL(x, 0, "Wrong number for named column."); 29 | PQXX_CHECK_EQUAL(y, 1, "Wrong number for named column."); 30 | PQXX_CHECK_EQUAL(z, 2, "Wrong number for named column."); 31 | 32 | pqxx::row::size_type xx{X[0].table_column(static_cast(0))}, 33 | yx{X[0].table_column(pqxx::row::size_type(1))}, zx{X[0].table_column("z")}; 34 | 35 | PQXX_CHECK_EQUAL(xx, 0, "Bad result from table_column(int)."); 36 | PQXX_CHECK_EQUAL(yx, 1, "Bad result from table_column(size_type)."); 37 | PQXX_CHECK_EQUAL(zx, 2, "Bad result from table_column(string)."); 38 | 39 | for (pqxx::row::size_type i{0}; i < std::size(R[0]); ++i) 40 | PQXX_CHECK_EQUAL( 41 | R[0][i].table_column(), R.table_column(i), 42 | "Bad result from column_table()."); 43 | 44 | int col; 45 | PQXX_CHECK_THROWS_EXCEPTION( 46 | col = R.table_column(3), "table_column() with invalid index didn't fail."); 47 | pqxx::ignore_unused(col); 48 | 49 | PQXX_CHECK_THROWS_EXCEPTION( 50 | col = R.table_column("nonexistent"), 51 | "table_column() with invalid column name didn't fail."); 52 | pqxx::ignore_unused(col); 53 | 54 | PQXX_CHECK_THROWS_EXCEPTION( 55 | col = X.table_column(3), "table_column() on non-table didn't fail."); 56 | pqxx::ignore_unused(col); 57 | } 58 | } // namespace 59 | 60 | 61 | PQXX_REGISTER_TEST(test_table_column); 62 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_cursor.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../test_helpers.hxx" 5 | 6 | namespace 7 | { 8 | void test_stateless_cursor_provides_random_access(pqxx::connection &conn) 9 | { 10 | pqxx::work tx{conn}; 11 | pqxx::stateless_cursor< 12 | pqxx::cursor_base::read_only, pqxx::cursor_base::owned> 13 | c{tx, "SELECT * FROM generate_series(0, 3)", "count", false}; 14 | 15 | auto r{c.retrieve(1, 2)}; 16 | PQXX_CHECK_EQUAL(std::size(r), 1, "Wrong number of rows from retrieve()."); 17 | PQXX_CHECK_EQUAL(r[0][0].as(), 1, "Cursor retrieved wrong data."); 18 | 19 | r = c.retrieve(3, 10); 20 | PQXX_CHECK_EQUAL(std::size(r), 1, "Expected 1 row retrieving past end."); 21 | PQXX_CHECK_EQUAL(r[0][0].as(), 3, "Wrong data retrieved at end."); 22 | 23 | r = c.retrieve(0, 1); 24 | PQXX_CHECK_EQUAL(std::size(r), 1, "Wrong number of rows back at beginning."); 25 | PQXX_CHECK_EQUAL(r[0][0].as(), 0, "Wrong data back at beginning."); 26 | } 27 | 28 | 29 | void test_stateless_cursor_ignores_trailing_semicolon(pqxx::connection &conn) 30 | { 31 | pqxx::work tx{conn}; 32 | pqxx::stateless_cursor< 33 | pqxx::cursor_base::read_only, pqxx::cursor_base::owned> 34 | c{tx, "SELECT * FROM generate_series(0, 3) ;; ; \n \t ", "count", false}; 35 | 36 | auto r{c.retrieve(1, 2)}; 37 | PQXX_CHECK_EQUAL(std::size(r), 1, "Trailing semicolon confused retrieve()."); 38 | } 39 | 40 | 41 | void test_cursor() 42 | { 43 | pqxx::connection conn; 44 | test_stateless_cursor_provides_random_access(conn); 45 | test_stateless_cursor_ignores_trailing_semicolon(conn); 46 | } 47 | 48 | 49 | PQXX_REGISTER_TEST(test_cursor); 50 | } // namespace 51 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_error_verbosity.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../test_helpers.hxx" 4 | 5 | extern "C" 6 | { 7 | #include 8 | } 9 | 10 | namespace 11 | { 12 | void test_error_verbosity() 13 | { 14 | PQXX_CHECK_EQUAL( 15 | static_cast(pqxx::error_verbosity::terse), 16 | static_cast(PQERRORS_TERSE), 17 | "error_verbosity enum should match PGVerbosity."); 18 | PQXX_CHECK_EQUAL( 19 | static_cast(pqxx::error_verbosity::normal), 20 | static_cast(PQERRORS_DEFAULT), 21 | "error_verbosity enum should match PGVerbosity."); 22 | PQXX_CHECK_EQUAL( 23 | static_cast(pqxx::error_verbosity::verbose), 24 | static_cast(PQERRORS_VERBOSE), 25 | "error_verbosity enum should match PGVerbosity."); 26 | 27 | pqxx::connection conn; 28 | pqxx::work tx{conn}; 29 | conn.set_verbosity(pqxx::error_verbosity::terse); 30 | tx.exec1("SELECT 1"); 31 | conn.set_verbosity(pqxx::error_verbosity::verbose); 32 | tx.exec1("SELECT 2"); 33 | } 34 | 35 | 36 | PQXX_REGISTER_TEST(test_error_verbosity); 37 | } // namespace 38 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_exceptions.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../test_helpers.hxx" 5 | 6 | 7 | namespace 8 | { 9 | void test_exceptions() 10 | { 11 | std::string const broken_query{"SELECT HORRIBLE ERROR"}, 12 | err{"Error message"}; 13 | 14 | try 15 | { 16 | throw pqxx::sql_error{err, broken_query}; 17 | } 18 | catch (std::exception const &e) 19 | { 20 | PQXX_CHECK_EQUAL(e.what(), err, "Exception contains wrong message."); 21 | auto downcast{dynamic_cast(&e)}; 22 | PQXX_CHECK( 23 | downcast != nullptr, "exception-to-sql_error downcast is broken."); 24 | PQXX_CHECK_EQUAL( 25 | downcast->query(), broken_query, 26 | "Getting query from pqxx exception is broken."); 27 | } 28 | 29 | pqxx::connection conn; 30 | pqxx::work tx{conn}; 31 | try 32 | { 33 | tx.exec("INVALID QUERY HERE"); 34 | } 35 | catch (pqxx::syntax_error const &e) 36 | { 37 | // SQL syntax error has sqlstate error 42601. 38 | PQXX_CHECK_EQUAL( 39 | e.sqlstate(), "42601", "Unexpected sqlstate on syntax error."); 40 | } 41 | } 42 | 43 | 44 | PQXX_REGISTER_TEST(test_exceptions); 45 | } // namespace 46 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_field.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../test_helpers.hxx" 4 | 5 | namespace 6 | { 7 | void test_field() 8 | { 9 | pqxx::connection c; 10 | pqxx::work tx{c}; 11 | auto const r1{tx.exec1("SELECT 9")}; 12 | auto const &f1{r1[0]}; 13 | 14 | PQXX_CHECK_EQUAL(f1.as(), "9", "as() is broken."); 15 | PQXX_CHECK_EQUAL( 16 | f1.as("z"), "9", "as(string) is broken."); 17 | 18 | PQXX_CHECK_EQUAL(f1.as(), 9, "as() is broken."); 19 | PQXX_CHECK_EQUAL(f1.as(10), 9, "as(int) is broken."); 20 | 21 | std::string s; 22 | PQXX_CHECK(f1.to(s), "to(string) failed."); 23 | PQXX_CHECK_EQUAL(s, "9", "to(string) is broken."); 24 | s = "x"; 25 | PQXX_CHECK(f1.to(s, std::string{"7"}), "to(string, string) failed."); 26 | PQXX_CHECK_EQUAL(s, "9", "to(string, string) is broken."); 27 | 28 | int i{}; 29 | PQXX_CHECK(f1.to(i), "to(int) failed."); 30 | PQXX_CHECK_EQUAL(i, 9, "to(int) is broken."); 31 | i = 8; 32 | PQXX_CHECK(f1.to(i, 12), "to(int, int) failed."); 33 | PQXX_CHECK_EQUAL(i, 9, "to(int, int) is broken."); 34 | 35 | auto const r2{tx.exec1("SELECT NULL")}; 36 | auto const f2{r2[0]}; 37 | i = 100; 38 | PQXX_CHECK_THROWS( 39 | f2.as(), pqxx::conversion_error, "Null conversion failed to throw."); 40 | PQXX_CHECK_EQUAL(i, 100, "Null conversion touched its output."); 41 | 42 | PQXX_CHECK_EQUAL(f2.as(66), 66, "as default is broken."); 43 | 44 | PQXX_CHECK(!(f2.to(i)), "to(int) failed to report a null."); 45 | PQXX_CHECK(!(f2.to(i, 54)), "to(int, int) failed to report a null."); 46 | PQXX_CHECK_EQUAL(i, 54, "to(int, int) failed to default."); 47 | 48 | auto const r3{tx.exec("SELECT generate_series(1, 5)")}; 49 | PQXX_CHECK_EQUAL(r3.at(3, 0).as(), 4, "Two-argument at() went wrong."); 50 | #if defined(PQXX_HAVE_MULTIDIM) 51 | PQXX_CHECK_EQUAL((r3[3, 0].as()), 4, "Two-argument [] went wrong."); 52 | #endif // PQXX_HAVE_MULTIDIM 53 | } 54 | 55 | 56 | PQXX_REGISTER_TEST(test_field); 57 | } // namespace 58 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_largeobject.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include "../test_helpers.hxx" 8 | 9 | namespace 10 | { 11 | void test_stream_large_object() 12 | { 13 | pqxx::connection conn; 14 | 15 | // Construct a really nasty string. (Don't just construct a std::string from 16 | // a char[] constant, because it'll terminate at the embedded zero.) 17 | // 18 | // The crucial thing is the "ff" byte at the beginning. It tests for 19 | // possible conflation between "eof" (-1) and a char which just happens to 20 | // have the same bit pattern as an 8-bit value of -1. This conflation can be 21 | // a problem when it occurs at buffer boundaries. 22 | constexpr char bytes[]{"\xff\0end"}; 23 | std::string const contents{bytes, std::size(bytes)}; 24 | 25 | pqxx::work tx{conn}; 26 | #include "pqxx/internal/ignore-deprecated-pre.hxx" 27 | pqxx::largeobject new_obj{tx}; 28 | 29 | pqxx::olostream write{tx, new_obj}; 30 | write << contents; 31 | write.flush(); 32 | 33 | pqxx::largeobjectaccess check{tx, new_obj, std::ios::in | std::ios::binary}; 34 | std::array buf; 35 | std::size_t const len{ 36 | static_cast(check.read(std::data(buf), std::size(buf)))}; 37 | PQXX_CHECK_EQUAL(len, std::size(contents), "olostream truncated data."); 38 | std::string const check_str{std::data(buf), len}; 39 | PQXX_CHECK_EQUAL(check_str, contents, "olostream mangled data."); 40 | 41 | pqxx::ilostream read{tx, new_obj}; 42 | std::string read_back; 43 | std::string chunk; 44 | while (read >> chunk) read_back += chunk; 45 | 46 | new_obj.remove(tx); 47 | 48 | PQXX_CHECK_EQUAL(read_back, contents, "Got wrong data from ilostream."); 49 | PQXX_CHECK_EQUAL( 50 | std::size(read_back), std::size(contents), "ilostream truncated data."); 51 | PQXX_CHECK_EQUAL( 52 | std::size(read_back), std::size(bytes), "ilostream truncated data."); 53 | #include "pqxx/internal/ignore-deprecated-post.hxx" 54 | } 55 | 56 | 57 | PQXX_REGISTER_TEST(test_stream_large_object); 58 | } // namespace 59 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_nonblocking_connect.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "../test_helpers.hxx" 6 | 7 | 8 | namespace 9 | { 10 | void test_nonblocking_connect() 11 | { 12 | pqxx::connecting nbc; 13 | while (not nbc.done()) 14 | { 15 | pqxx::internal::wait_fd( 16 | nbc.sock(), nbc.wait_to_read(), nbc.wait_to_write()); 17 | nbc.process(); 18 | } 19 | 20 | pqxx::connection conn{std::move(nbc).produce()}; 21 | pqxx::work tx{conn}; 22 | PQXX_CHECK_EQUAL(tx.query_value("SELECT 10"), 10, "Bad value!?"); 23 | } 24 | 25 | 26 | PQXX_REGISTER_TEST(test_nonblocking_connect); 27 | } // namespace 28 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_notification.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include "../test_helpers.hxx" 13 | 14 | namespace 15 | { 16 | class TestReceiver final : public pqxx::notification_receiver 17 | { 18 | public: 19 | std::string payload; 20 | int backend_pid; 21 | 22 | TestReceiver(pqxx::connection &c, std::string const &channel_name) : 23 | pqxx::notification_receiver(c, channel_name), 24 | payload(), 25 | backend_pid(0) 26 | {} 27 | 28 | virtual void 29 | operator()(std::string const &payload_string, int backend) override 30 | { 31 | this->payload = payload_string; 32 | this->backend_pid = backend; 33 | } 34 | }; 35 | 36 | 37 | void test_receive( 38 | pqxx::transaction_base &t, std::string const &channel, 39 | char const payload[] = nullptr) 40 | { 41 | pqxx::connection &conn(t.conn()); 42 | 43 | std::string SQL{"NOTIFY \"" + channel + "\""}; 44 | if (payload != nullptr) 45 | SQL += ", " + t.quote(payload); 46 | 47 | TestReceiver receiver{t.conn(), channel}; 48 | 49 | // Clear out any previously pending notifications that might otherwise 50 | // confuse the test. 51 | conn.get_notifs(); 52 | 53 | // Notify, and receive. 54 | t.exec(SQL); 55 | t.commit(); 56 | 57 | int notifs{0}; 58 | for (int i{0}; (i < 10) and (notifs == 0); 59 | ++i, pqxx::internal::wait_for(1000u)) 60 | notifs = conn.get_notifs(); 61 | 62 | PQXX_CHECK_EQUAL(notifs, 1, "Got wrong number of notifications."); 63 | PQXX_CHECK_EQUAL(receiver.backend_pid, conn.backendpid(), "Bad pid."); 64 | if (payload == nullptr) 65 | PQXX_CHECK(std::empty(receiver.payload), "Unexpected payload."); 66 | else 67 | PQXX_CHECK_EQUAL(receiver.payload, payload, "Bad payload."); 68 | } 69 | 70 | 71 | void test_notification() 72 | { 73 | pqxx::connection conn; 74 | TestReceiver receiver(conn, "mychannel"); 75 | PQXX_CHECK_EQUAL(receiver.channel(), "mychannel", "Bad channel."); 76 | 77 | pqxx::work tx{conn}; 78 | test_receive(tx, "channel1"); 79 | 80 | pqxx::nontransaction u(conn); 81 | test_receive(u, "channel2", "payload"); 82 | } 83 | 84 | 85 | PQXX_REGISTER_TEST(test_notification); 86 | } // namespace 87 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_pipeline.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "../test_helpers.hxx" 7 | 8 | namespace 9 | { 10 | void test_pipeline() 11 | { 12 | pqxx::connection conn; 13 | pqxx::work tx{conn}; 14 | 15 | // A pipeline grabs transaction focus, blocking regular queries and such. 16 | pqxx::pipeline pipe(tx, "test_pipeline_detach"); 17 | PQXX_CHECK_THROWS( 18 | tx.exec("SELECT 1"), std::logic_error, 19 | "Pipeline does not block regular queries"); 20 | 21 | // Flushing a pipeline relinquishes transaction focus. 22 | pipe.flush(); 23 | auto r{tx.exec("SELECT 2")}; 24 | PQXX_CHECK_EQUAL( 25 | std::size(r), 1, "Wrong query result after flushing pipeline."); 26 | PQXX_CHECK_EQUAL( 27 | r[0][0].as(), 2, "Query returns wrong data after flushing pipeline."); 28 | 29 | // Inserting a query makes the pipeline grab transaction focus back. 30 | auto q{pipe.insert("SELECT 2")}; 31 | PQXX_CHECK_THROWS( 32 | tx.exec("SELECT 3"), std::logic_error, 33 | "Pipeline does not block regular queries"); 34 | 35 | // Invoking complete() also detaches the pipeline from the transaction. 36 | pipe.complete(); 37 | r = tx.exec("SELECT 4"); 38 | PQXX_CHECK_EQUAL(std::size(r), 1, "Wrong query result after complete()."); 39 | PQXX_CHECK_EQUAL( 40 | r[0][0].as(), 4, "Query returns wrong data after complete()."); 41 | 42 | // The complete() also received any pending query results from the backend. 43 | r = pipe.retrieve(q); 44 | PQXX_CHECK_EQUAL(std::size(r), 1, "Wrong result from pipeline."); 45 | PQXX_CHECK_EQUAL(r[0][0].as(), 2, "Pipeline returned wrong data."); 46 | 47 | // We can cancel while the pipe is empty, and things will still work. 48 | pipe.cancel(); 49 | 50 | // Issue a query and cancel it. Measure time to see that we don't really 51 | // wait. 52 | using clock = std::chrono::steady_clock; 53 | auto const start{clock::now()}; 54 | pipe.retain(0); 55 | pipe.insert("pg_sleep(10)"); 56 | pipe.cancel(); 57 | auto const finish{clock::now()}; 58 | auto const seconds{ 59 | std::chrono::duration_cast(finish - start).count()}; 60 | PQXX_CHECK_LESS(seconds, 5, "Canceling a sleep took suspiciously long."); 61 | } 62 | } // namespace 63 | 64 | PQXX_REGISTER_TEST(test_pipeline); 65 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_read_transaction.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../test_helpers.hxx" 4 | 5 | namespace 6 | { 7 | void test_read_transaction() 8 | { 9 | pqxx::connection conn; 10 | pqxx::read_transaction tx{conn}; 11 | PQXX_CHECK_EQUAL( 12 | tx.exec("SELECT 1")[0][0].as(), 1, 13 | "Bad result from read transaction."); 14 | 15 | PQXX_CHECK_THROWS( 16 | tx.exec("CREATE TABLE should_not_exist(x integer)"), pqxx::sql_error, 17 | "Read-only transaction allows database to be modified."); 18 | } 19 | 20 | 21 | PQXX_REGISTER_TEST(test_read_transaction); 22 | } // namespace 23 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_separated_list.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../test_helpers.hxx" 4 | 5 | // Test program for separated_list. 6 | 7 | namespace 8 | { 9 | void test_separated_list() 10 | { 11 | PQXX_CHECK_EQUAL( 12 | pqxx::separated_list(",", std::vector{}), "", 13 | "Empty list came out wrong."); 14 | 15 | PQXX_CHECK_EQUAL( 16 | pqxx::separated_list(",", std::vector{5}), "5", 17 | "Single-element list came out wrong."); 18 | 19 | PQXX_CHECK_EQUAL( 20 | pqxx::separated_list(",", std::vector{3, 6}), "3,6", 21 | "Things go wrong once separators come in."); 22 | 23 | std::vector const nums{1, 2, 3}; 24 | PQXX_CHECK_EQUAL( 25 | pqxx::separated_list( 26 | "+", std::begin(nums), std::end(nums), 27 | [](auto elt) { return *elt * 2; }), 28 | "2+4+6", "Accessors don't seem to work."); 29 | } 30 | 31 | 32 | PQXX_REGISTER_TEST(test_separated_list); 33 | } // namespace 34 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_simultaneous_transactions.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../test_helpers.hxx" 5 | 6 | namespace 7 | { 8 | void test_simultaneous_transactions() 9 | { 10 | pqxx::connection conn; 11 | 12 | pqxx::nontransaction n1{conn}; 13 | PQXX_CHECK_THROWS( 14 | pqxx::nontransaction n2{conn}, std::logic_error, 15 | "Allowed to open simultaneous nontransactions."); 16 | } 17 | 18 | 19 | PQXX_REGISTER_TEST(test_simultaneous_transactions); 20 | } // namespace 21 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_subtransaction.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../test_helpers.hxx" 5 | 6 | namespace 7 | { 8 | void make_table(pqxx::transaction_base &trans) 9 | { 10 | trans.exec0("CREATE TEMP TABLE foo (x INTEGER)"); 11 | } 12 | 13 | 14 | void insert_row(pqxx::transaction_base &trans) 15 | { 16 | trans.exec0("INSERT INTO foo(x) VALUES (1)"); 17 | } 18 | 19 | 20 | int count_rows(pqxx::transaction_base &trans) 21 | { 22 | return trans.query_value("SELECT count(*) FROM foo"); 23 | } 24 | 25 | 26 | void test_subtransaction_commits_if_commit_called(pqxx::connection &conn) 27 | { 28 | pqxx::work trans(conn); 29 | make_table(trans); 30 | { 31 | pqxx::subtransaction sub(trans); 32 | insert_row(sub); 33 | sub.commit(); 34 | } 35 | PQXX_CHECK_EQUAL( 36 | count_rows(trans), 1, "Work done in committed subtransaction was lost."); 37 | } 38 | 39 | 40 | void test_subtransaction_aborts_if_abort_called(pqxx::connection &conn) 41 | { 42 | pqxx::work trans(conn); 43 | make_table(trans); 44 | { 45 | pqxx::subtransaction sub(trans); 46 | insert_row(sub); 47 | sub.abort(); 48 | } 49 | PQXX_CHECK_EQUAL( 50 | count_rows(trans), 0, "Aborted subtransaction was not rolled back."); 51 | } 52 | 53 | 54 | void test_subtransaction_aborts_implicitly(pqxx::connection &conn) 55 | { 56 | pqxx::work trans(conn); 57 | make_table(trans); 58 | { 59 | pqxx::subtransaction sub(trans); 60 | insert_row(sub); 61 | } 62 | PQXX_CHECK_EQUAL( 63 | count_rows(trans), 0, 64 | "Uncommitted subtransaction was not rolled back uring destruction."); 65 | } 66 | 67 | 68 | void test_subtransaction() 69 | { 70 | pqxx::connection conn; 71 | test_subtransaction_commits_if_commit_called(conn); 72 | test_subtransaction_aborts_if_abort_called(conn); 73 | test_subtransaction_aborts_implicitly(conn); 74 | } 75 | 76 | 77 | PQXX_REGISTER_TEST(test_subtransaction); 78 | } // namespace 79 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_thread_safety_model.cxx: -------------------------------------------------------------------------------- 1 | #include "../test_helpers.hxx" 2 | 3 | #include 4 | 5 | namespace 6 | { 7 | void test_thread_safety_model() 8 | { 9 | auto const model{pqxx::describe_thread_safety()}; 10 | 11 | if (model.safe_libpq and model.safe_kerberos) 12 | PQXX_CHECK_EQUAL( 13 | model.description, "", 14 | "Thread-safety looks okay but model description is nonempty."); 15 | else 16 | PQXX_CHECK_NOT_EQUAL( 17 | model.description, "", 18 | "Thread-safety model is imperfect but lacks description."); 19 | } 20 | 21 | 22 | PQXX_REGISTER_TEST(test_thread_safety_model); 23 | } // namespace 24 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_transaction_focus.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../test_helpers.hxx" 5 | 6 | namespace 7 | { 8 | auto make_focus(pqxx::dbtransaction &tx) 9 | { 10 | #include "pqxx/internal/ignore-deprecated-pre.hxx" 11 | return pqxx::stream_from::query(tx, "SELECT * from generate_series(1, 10)"); 12 | #include "pqxx/internal/ignore-deprecated-post.hxx" 13 | } 14 | 15 | 16 | void test_cannot_run_statement_during_focus() 17 | { 18 | pqxx::connection conn; 19 | pqxx::transaction tx{conn}; 20 | tx.exec("SELECT 1"); 21 | auto focus{make_focus(tx)}; 22 | PQXX_CHECK_THROWS( 23 | tx.exec("SELECT 1"), pqxx::usage_error, 24 | "Command during focus did not throw expected error."); 25 | } 26 | 27 | 28 | void test_cannot_run_prepared_statement_during_focus() 29 | { 30 | pqxx::connection conn; 31 | conn.prepare("foo", "SELECT 1"); 32 | pqxx::transaction tx{conn}; 33 | tx.exec_prepared("foo"); 34 | auto focus{make_focus(tx)}; 35 | PQXX_CHECK_THROWS( 36 | tx.exec_prepared("foo"), pqxx::usage_error, 37 | "Prepared statement during focus did not throw expected error."); 38 | } 39 | 40 | void test_cannot_run_params_statement_during_focus() 41 | { 42 | pqxx::connection conn; 43 | pqxx::transaction tx{conn}; 44 | tx.exec_params("select $1", 10); 45 | auto focus{make_focus(tx)}; 46 | PQXX_CHECK_THROWS( 47 | tx.exec_params("select $1", 10), pqxx::usage_error, 48 | "Parameterized statement during focus did not throw expected error."); 49 | } 50 | 51 | 52 | PQXX_REGISTER_TEST(test_cannot_run_statement_during_focus); 53 | PQXX_REGISTER_TEST(test_cannot_run_prepared_statement_during_focus); 54 | PQXX_REGISTER_TEST(test_cannot_run_params_statement_during_focus); 55 | } // namespace 56 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_type_name.cxx: -------------------------------------------------------------------------------- 1 | #include "../test_helpers.hxx" 2 | 3 | namespace 4 | { 5 | void test_type_name() 6 | { 7 | // It's hard to test in more detail, because spellings may differ. 8 | // For instance, one compiler might call "const unsigned int*" what another 9 | // might call "unsigned const *". And Visual Studio prefixes "class" to 10 | // class types. 11 | std::string const i{pqxx::type_name}; 12 | PQXX_CHECK_LESS(std::size(i), 5u, "type_name is suspiciously long."); 13 | PQXX_CHECK_EQUAL( 14 | i.substr(0, 1), "i", "type_name does not start with 'i'."); 15 | } 16 | 17 | 18 | PQXX_REGISTER_TEST(test_type_name); 19 | } // namespace 20 | -------------------------------------------------------------------------------- /libpqxx/test/unit/test_zview.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../test_helpers.hxx" 4 | 5 | 6 | namespace 7 | { 8 | void test_zview_literal() 9 | { 10 | using pqxx::operator"" _zv; 11 | 12 | PQXX_CHECK_EQUAL(("foo"_zv), pqxx::zview{"foo"}, "zview literal is broken."); 13 | } 14 | 15 | 16 | void test_zview_converts_to_string() 17 | { 18 | using pqxx::operator"" _zv; 19 | using traits = pqxx::string_traits; 20 | 21 | PQXX_CHECK_EQUAL( 22 | pqxx::to_string("hello"_zv), std::string{"hello"}, 23 | "to_string on zview failed."); 24 | 25 | char buf[100]; 26 | 27 | auto const v{traits::to_buf(std::begin(buf), std::end(buf), "myview"_zv)}; 28 | PQXX_CHECK_EQUAL(std::string{v}, "myview", "to_buf on zview failed."); 29 | 30 | auto const p{ 31 | traits::into_buf(std::begin(buf), std::end(buf), "moreview"_zv)}; 32 | PQXX_CHECK_NOT_EQUAL( 33 | p, std::begin(buf), "into_buf on zview returns beginning of buffer."); 34 | PQXX_CHECK( 35 | p > std::begin(buf) and p < std::end(buf), 36 | "into_buf on zview did not store in buffer."); 37 | PQXX_CHECK(*(p - 1) == '\0', "into_buf on zview wasted space."); 38 | PQXX_CHECK(*(p - 2) == 'w', "into_buf on zview has extraneous data."); 39 | PQXX_CHECK_EQUAL(std::string(buf), "moreview", "into_buf on zview failed."); 40 | } 41 | 42 | 43 | PQXX_REGISTER_TEST(test_zview_literal); 44 | PQXX_REGISTER_TEST(test_zview_converts_to_string); 45 | } // namespace 46 | -------------------------------------------------------------------------------- /libpqxx/tools/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = \ 2 | deprecations \ 3 | extract_version \ 4 | format \ 5 | generate_check_config.py \ 6 | generate_cxx_checks.py \ 7 | lint \ 8 | m4esc.py \ 9 | pqxxthreadsafety.cxx \ 10 | rmlo.cxx \ 11 | splitconfig.py \ 12 | template2mak.py \ 13 | todo \ 14 | update-copyright 15 | 16 | AM_CPPFLAGS=-I$(top_builddir)/include -I$(top_srcdir)/include ${POSTGRES_INCLUDE} 17 | # Override automatically generated list of default includes. It contains only 18 | # unnecessary entries, and incorrectly mentions include/pqxx directly. 19 | DEFAULT_INCLUDES= 20 | 21 | noinst_PROGRAMS = rmlo pqxxthreadsafety 22 | 23 | rmlo_SOURCES = rmlo.cxx 24 | rmlo_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} 25 | 26 | pqxxthreadsafety_SOURCES = pqxxthreadsafety.cxx 27 | pqxxthreadsafety_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} 28 | -------------------------------------------------------------------------------- /libpqxx/tools/deprecations: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | set -eu 3 | 4 | MARKER='include.*ignore-deprecated-pre' 5 | grep -Ircl "$MARKER" src include tools/*.cxx test config-tests | sort 6 | -------------------------------------------------------------------------------- /libpqxx/tools/extract_version: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | set -eu 3 | 4 | ARG="${1:-}" 5 | 6 | # Source directory. In out-of-tree builds, Automake sets this for us. 7 | srcdir=${srcdir:-.} 8 | 9 | 10 | # Print usage information. 11 | usage() { 12 | cat <... 18 | 19 | Acceptable option values are: 20 | -h, --help Print this message, and exit. 21 | -a, --abi Show libpqxx ABI version; leave out revision number. 22 | -f, --full Show full libpqxx version string (the default). 23 | -M, --major Show major libpqxx version. 24 | -m, --minor Show minor libpqxx version (between major and revision). 25 | EOF 26 | } 27 | 28 | 29 | # Print "unknown argument" error. 30 | unknown_arg() { 31 | cat <&2 32 | Unknown argument: $1. 33 | Try 34 | 35 | $0 --help 36 | 37 | for usage information. 38 | EOF 39 | } 40 | 41 | 42 | case "$ARG" in 43 | ''|-f|--full) 44 | # Default: Print full version. 45 | cat "$srcdir/VERSION" 46 | ;; 47 | 48 | -h|--help) 49 | # Print usage information, and exit. 50 | usage 51 | exit 52 | ;; 53 | 54 | -a|--abi) 55 | # Print just the ABI version (major & minor). 56 | sed -e 's/^\([^.]*\.[^.]*\)\..*/\1/' "$srcdir/VERSION" 57 | ;; 58 | 59 | -M|--major) 60 | # Print the major version number. 61 | sed -e 's/^\([^.]*\)\..*/\1/' "$srcdir/VERSION" 62 | ;; 63 | 64 | -m|--minor) 65 | # Print the minor version number. 66 | sed -e 's/^[^.]*\.\([^.]*\)\..*/\1/' "$srcdir/VERSION" 67 | ;; 68 | 69 | *) 70 | unknown_arg "$ARG" 71 | exit 1 72 | ;; 73 | esac 74 | -------------------------------------------------------------------------------- /libpqxx/tools/format: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # Reformat source code using clang-format. 4 | # 5 | # This script is not portable: as of Ubuntu 21.04, virtualenv's "activate" 6 | # seems to rely on a non-POSIX variable, $OSTYPE. 7 | 8 | set -C -u -e 9 | 10 | # Reformat C++ files. 11 | find . -name '*.[ch]xx' -print0 | xargs -0 clang-format -i 12 | 13 | 14 | # Reformat CMake files. 15 | WORKDIR=$(mktemp -d) 16 | virtualenv -q --python="$(which python3)" "$WORKDIR/venv" 17 | # shellcheck disable=SC1091 18 | source "$WORKDIR"/venv/bin/activate 19 | pip install -q six pyaml cmake-format 20 | (find . -name '*.cmake' -print0 | xargs -0 -n1 cmake-format -i) || /bin/true 21 | rm -rf "$WORKDIR" 22 | -------------------------------------------------------------------------------- /libpqxx/tools/m4esc.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | """M4-quote text, for use as a literal in configure.ac. 4 | 5 | Produces M4 "code" which evaluates to the input text. 6 | 7 | It's not easy to read plain text from an input file in M4, without having it 8 | expanded as M4. Sometimes all we want is literal text! 9 | """ 10 | from __future__ import ( 11 | absolute_import, 12 | print_function, 13 | unicode_literals, 14 | ) 15 | 16 | from argparse import ArgumentParser 17 | from sys import ( 18 | stdin, 19 | stdout, 20 | ) 21 | 22 | 23 | def parse_args(): 24 | parser = ArgumentParser(description=__doc__) 25 | parser.add_argument( 26 | '--open', '-a', default='[[', help="Current open-quote symbol.") 27 | parser.add_argument( 28 | '--close', '-b', default=']]', help="Current close-quote symbol.") 29 | parser.add_argument( 30 | '--input', '-i', default='-', help="Input file, or '-' for stdin.") 31 | parser.add_argument( 32 | '--output', '-o', default='-', help="Output file, or '-' for stdout.") 33 | return parser.parse_args() 34 | 35 | 36 | def open_input(in_file): 37 | if in_file == '-': 38 | return stdin 39 | else: 40 | return open(in_file) 41 | 42 | 43 | def open_output(out_file): 44 | if out_file == '-': 45 | return stdout 46 | else: 47 | return open(out_file, 'w') 48 | 49 | 50 | def escape(line): 51 | return ( 52 | line 53 | .replace('[', '@<:@') 54 | .replace(']', '@:>@') 55 | .replace('#', '@%:@') 56 | .replace('$', '@S|@') 57 | ) 58 | 59 | 60 | def main(args): 61 | with open_input(args.input) as istr, open_output(args.output) as ostr: 62 | ostr.write(args.open) 63 | for line in istr: 64 | ostr.write(escape(line)) 65 | ostr.write('\n') 66 | ostr.write(args.close) 67 | 68 | 69 | if __name__ == '__main__': 70 | main(parse_args()) 71 | -------------------------------------------------------------------------------- /libpqxx/tools/pqxxthreadsafety.cxx: -------------------------------------------------------------------------------- 1 | // Print thread-safety information for present libpqxx build. 2 | #include 3 | 4 | #include "pqxx/util" 5 | 6 | 7 | int main() 8 | { 9 | std::cout << pqxx::describe_thread_safety().description << std::endl; 10 | } 11 | -------------------------------------------------------------------------------- /libpqxx/tools/rmlo.cxx: -------------------------------------------------------------------------------- 1 | // Remove large objects given on the command line from the default database. 2 | #include 3 | 4 | #include "pqxx/pqxx" 5 | 6 | 7 | int main(int, char *argv[]) 8 | { 9 | pqxx::connection conn; 10 | bool failures = false; 11 | 12 | try 13 | { 14 | for (int i{1}; argv[i]; ++i) 15 | { 16 | auto o{pqxx::from_string(argv[i])}; 17 | try 18 | { 19 | pqxx::perform([o, &conn] { 20 | pqxx::work tx{conn}; 21 | pqxx::blob::remove(tx, o); 22 | tx.commit(); 23 | }); 24 | } 25 | catch (std::exception const &e) 26 | { 27 | std::cerr << e.what() << std::endl; 28 | failures = true; 29 | } 30 | } 31 | } 32 | catch (std::exception const &e) 33 | { 34 | std::cerr << e.what() << std::endl; 35 | return 2; 36 | } 37 | 38 | return failures; 39 | } 40 | -------------------------------------------------------------------------------- /libpqxx/tools/todo: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # List "TODO" and "XXX" items in the given files, or throughout the source 4 | # code. 5 | 6 | set -e -u -o pipefail 7 | 8 | # TODO: Make location-independent? 9 | find_source() { 10 | echo configure.ac 11 | find . -name '*.[ch]xx' | sed -e 's|^\./||' | sort 12 | echo tools/* 13 | } 14 | 15 | 16 | FILES=${*:-$(find_source)} 17 | 18 | 19 | # Search for "$1:" in files $2. 20 | # (This function adds the colon. That way, the search statement itself won't 21 | # show up in the search.) 22 | search_for() { 23 | local key="$1:" 24 | shift 25 | find_source | xargs grep "$key" 26 | } 27 | 28 | 29 | search_for XXX "$FILES" || true 30 | search_for TODO "$FILES" || true 31 | -------------------------------------------------------------------------------- /libpqxx/tools/update-copyright: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # Update the libpqxx copyright strings in the current directory. 4 | # 5 | # Usage: update-copyright [year] 6 | # 7 | # Where "year" is the new copyright year. Defaults to the current year. 8 | # 9 | # Assumes GNU grep and GNU sed. 10 | set -eu -o pipefail 11 | 12 | # The regexes are a bit awkward because they must work in both grep and sed. 13 | # 14 | # F'rinstance, PREFIX can't include the dash because our replacement string in 15 | # sed would have a backreference (e.g. "\3") immediately followed by a year 16 | # (e.g. 2022), and there's no clear boundary between the backreference number 17 | # and the year: "\32022". 18 | PREFIX='Copyright (c),* 2000' 19 | YEAR='20[0-9][0-9]' 20 | NEW_YEAR="${1:-$(date '+%Y')}" 21 | SUFFIX=',* \(.* and \)*Jeroen T\. Vermeulen' 22 | grep -rIl "$PREFIX-$YEAR$SUFFIX" | 23 | xargs -r sed -i -e "s/\\($PREFIX\\)-$YEAR\\($SUFFIX\\)/\\1-$NEW_YEAR\\2/" 24 | 25 | # This one is so different that I'd rather keep it a special case. 26 | sed \ 27 | -i \ 28 | -e "s/\\(2000\\)-$YEAR\\(,* Jeroen T\\. Vermeulen\\)/\1-$NEW_YEAR\\2/" \ 29 | doc/conf.py 30 | -------------------------------------------------------------------------------- /localhost.sql: -------------------------------------------------------------------------------- 1 | -- Adminer 4.8.1 PostgreSQL 16.2 dump 2 | 3 | DROP TABLE IF EXISTS "chat"; 4 | DROP SEQUENCE IF EXISTS chat_id_seq; 5 | CREATE SEQUENCE chat_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1; 6 | 7 | CREATE TABLE "public"."chat" ( 8 | "id" integer DEFAULT nextval('chat_id_seq') NOT NULL, 9 | "content" text NOT NULL, 10 | "sender" character varying(50) NOT NULL, 11 | "receiver" character varying(50) NOT NULL, 12 | "time" timestamp NOT NULL, 13 | "sender_isread" smallint NOT NULL, 14 | "receiver_isread" smallint NOT NULL, 15 | CONSTRAINT "chat_pkey" PRIMARY KEY ("id") 16 | ) WITH (oids = false); 17 | 18 | INSERT INTO "chat" ("id", "content", "sender", "receiver", "time", "sender_isread", "receiver_isread") VALUES 19 | (1, 'Welcome to flypen! We are glad to see you here!', 'FlypenTeam', 'bwb', '2024-03-29 11:27:41.712719', 0, 1), 20 | (2, '1', 'bwb', 'lj', '2024-03-29 13:33:36.10067', 1, 1), 21 | (8, '1', 'lj', 'bwb', '2024-03-29 16:09:07.696584', 1, 0); 22 | 23 | DROP TABLE IF EXISTS "file"; 24 | CREATE TABLE "public"."file" ( 25 | "filename" text NOT NULL, 26 | CONSTRAINT "file_pkey" PRIMARY KEY ("filename") 27 | ) WITH (oids = false); 28 | 29 | 30 | DROP TABLE IF EXISTS "users"; 31 | CREATE TABLE "public"."users" ( 32 | "username" character varying(50) NOT NULL, 33 | "password" text NOT NULL, 34 | "avatar" integer NOT NULL, 35 | "friends" text NOT NULL, 36 | "createtime" timestamp NOT NULL, 37 | "req" text NOT NULL, 38 | CONSTRAINT "users_pkey" PRIMARY KEY ("username") 39 | ) WITH (oids = false); 40 | 41 | INSERT INTO "users" ("username", "password", "avatar", "friends", "createtime", "req") VALUES 42 | ('FlypenTeam', 'FlypenTeam', 0, '', '2024-03-29 10:29:43.397413', ''), 43 | ('bwb', '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b', 9, 'FlypenTeam,lj', '2024-03-29 11:27:41.680964', ''), 44 | ('lj', '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b', 2, 'FlypenTeam,bwb', '2024-03-29 11:11:01.3027', ''); 45 | 46 | -- 2024-03-29 16:14:55.438097+08 47 | -------------------------------------------------------------------------------- /msg_controller.h: -------------------------------------------------------------------------------- 1 | #ifndef _MSG_CONTROLLER_H_ 2 | #define _MSG_CONTROLLER_H_ 3 | #include 4 | using namespace drogon; 5 | void chat(const HttpRequestPtr &req, std::function &&callback); 6 | void info(const HttpRequestPtr &req, std::function &&callback); 7 | void check(const HttpRequestPtr &req, std::function &&callback); 8 | void request_processing(const HttpRequestPtr &req, std::function &&callback); 9 | void friend_operation(const HttpRequestPtr &req, std::function &&callback); 10 | void getPublicKey(const HttpRequestPtr& req, std::function &&callback); 11 | #endif -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flypen", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": {} 6 | } -------------------------------------------------------------------------------- /pgsql.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void sql_unlocked(const std::string &DeleteName) ; 7 | int sql_findexist(const std::string &receiver) ; 8 | int lockcheck(const std::string &filename) ; 9 | void process(pqxx::work &txn, std::vector s) ; 10 | void sql_delete_operation(const std::string &sender, const std::string &receiver) ; 11 | void sql_process_request(const std::string &sender, const std::string &receiver, const std::string &attitude) ; 12 | void sql_addrequest(const std::string &sender, const std::string &receiver) ; 13 | void sql_addhistory(const std::string &sender, const std::string &receiver, const std::string &message, const std::string& nonce, const std::string &isread) ; 14 | void sql_add(const std::string &username, const std::string &passwd, int avatar, const std::string &public_key) ; 15 | Json::Value get_my_info(const std::string &me) ; 16 | bool sql_check(const std::string &usesr, const std::string &passwd = "@DEFAULT@") ; 17 | Json::Value sql_find_my_msg(const std::string &me, const std::string &connect_type) ; 18 | void set_avatar(const std::string &person, int avatar) ; 19 | std::string sql_query_public_key(const std::string& userName); -------------------------------------------------------------------------------- /root/12121: -------------------------------------------------------------------------------- 1 | 121112 2 | -------------------------------------------------------------------------------- /root/123: -------------------------------------------------------------------------------- 1 | bwb 2 | -------------------------------------------------------------------------------- /root/bwb: -------------------------------------------------------------------------------- 1 | bwb 2 | -------------------------------------------------------------------------------- /root/lglglgly/lgylgy: -------------------------------------------------------------------------------- 1 | ### this is llggyy file~ 2 | 3 | ```c++ 4 | #include 5 | int main() 6 | { 7 | std::cout<<"Hello, world!"< 5 | int main() 6 | { 7 | std::cout<<"Hello, world!"</dev/null 82 | echo -ne "\r\033[K" 83 | echo -e "\e[1;31m-- WRONG\e[0m" 84 | cd .. 85 | -------------------------------------------------------------------------------- /user_controller.h: -------------------------------------------------------------------------------- 1 | #ifndef _USER_CONTROLLER_H_ 2 | #define _USER_CONTROLLER_H_ 3 | 4 | #include 5 | using namespace drogon; 6 | 7 | typedef void (*HandlerFunc)(const Json::Value &, std::string *str, int *); 8 | 9 | void Handle(const HttpRequestPtr &req, std::function &&callback, HandlerFunc handler); 10 | void registerUser(const Json::Value &req_json, std::string *msg, int *code); 11 | void loginUser(const Json::Value &req_json, std::string *msg, int *code); 12 | void avatar(const HttpRequestPtr &req, std::function &&callback); 13 | void userInit(const std::string&, const std::string&); 14 | #endif --------------------------------------------------------------------------------