diff --git a/include/cif++/cql/transaction.hpp b/include/cif++/cql/transaction.hpp new file mode 100644 index 0000000..a20d74e --- /dev/null +++ b/include/cif++/cql/transaction.hpp @@ -0,0 +1,105 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 NKI/AVL, Netherlands Cancer Institute + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "cif++/datablock.hpp" +#include "cif++/item.hpp" +#include "cif++/row.hpp" + +// -------------------------------------------------------------------- + +namespace cif::cql +{ + +class result; +class row; +class transaction; + +// -------------------------------------------------------------------- + +class field +{ + public: + + /** Return the contents of this item as type @tparam T */ + template + auto as() const -> T + { + return m_item.as(); + } + + /** Return the contents of this item as type @tparam T or, if not + * set, use @a dv as the default value. + */ + template + auto value_or(const T &dv) const + { + return m_item.value_or(dv); + } + + private: + cif::item_handle m_item; +}; + +// -------------------------------------------------------------------- + +class row +{ + public: + + + +}; + +// -------------------------------------------------------------------- + +class result +{ + public: + + row &one_row(); + + + private: + friend class transaction; + + result(); + +}; + + +// -------------------------------------------------------------------- + +class transaction +{ + public: + transaction(const datablock &db); + + result exec(std::string_view query); +}; + +} \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7b98613..3a8cb42 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -51,6 +51,7 @@ list( spinner reconstruction validate-pdbx + cql ) add_library(test-main OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/test-main.cpp") diff --git a/test/cql-test.cpp b/test/cql-test.cpp new file mode 100644 index 0000000..c0696c7 --- /dev/null +++ b/test/cql-test.cpp @@ -0,0 +1,94 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 NKI/AVL, Netherlands Cancer Institute + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test-main.hpp" + +#include +#include + +#include + +#include + +// -------------------------------------------------------------------- + +cif::file operator""_cf(const char *text, std::size_t length) +{ + struct membuf : public std::streambuf + { + membuf(char *text, std::size_t length) + { + this->setg(text, text, text + length); + } + } buffer(const_cast(text), length); + + std::istream is(&buffer); + return cif::file(is); +} + +// -------------------------------------------------------------------- + +TEST_CASE("cql-1") +{ + cif::file f(gTestDir / ".." / "examples" / "1cbs.cif.gz"); + auto &db = f.front(); + + cif::cql::transaction tx(db); + + CHECK(tx.exec("SELECT COUNT(*) FROM entry").one_field() == 1); + CHECK(tx.exec("SELECT COUNT(*) FROM entry WHERE id = '1CBS'").one_field() == 1); + CHECK(tx.exec("SELECT COUNT(*) FROM entry WHERE id = 'XXXX'").one_field() == 0); + + CHECK(tx.exec("SELECT COUNT(*) FROM citation").one_field() == 4); + CHECK(tx.exec("SELECT COUNT(page_last) FROM citation").one_field() == 1); + + const char *kPrimaryAuthors[] = { + "Kleywegt, G.J.", + "Bergfors, T.", + "Senn, H.", + "Le Motte, P.", + "Gsell, B.", + "Shudo, K.", + "Jones, T.A." + }; + + auto r = tx.exec("SELECT name FROM citation_author WHERE citation_id = 'primary'"); + CHECK(r.size() == 7); + for (size_t ix = 0; auto row : r) + { + REQUIRE(ix < (sizeof(kPrimaryAuthors) / sizeof(char*))); + CHECK(row["name"].as() == kPrimaryAuthors[ix++]); + CHECK(row["ordinal"].as() == ix); + } + + // for (size_t ix = 0; const auto &[name, ordinal] : tx.stream("SELECT name FROM citation_author WHERE citation_id = 'primary'")) + // { + // REQUIRE(ix < (sizeof(kPrimaryAuthors) / sizeof(char*))); + // CHECK(name == kPrimaryAuthors[ix++]); + // CHECK(ordinal == ix); + // } + +} \ No newline at end of file