├── .github └── workflows │ └── main.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CQL_Guide ├── ch01.md ├── ch02.md ├── ch03.md ├── ch04.md ├── ch05.md ├── ch06.md ├── ch07.md ├── ch08.md ├── ch09.md ├── ch10.md ├── ch11.md ├── ch12.md ├── ch13.md ├── ch14.md ├── ch15.md ├── generated │ ├── guide.html │ ├── guide.md │ ├── internal.html │ ├── internal.md │ ├── make_guide.sh │ └── make_internal.sh ├── int01.md ├── int02.md ├── int03.md ├── int04.md ├── int05.md ├── int06.md ├── int07.md ├── int08.md ├── x1.md ├── x10.md ├── x11.md ├── x2.md ├── x3.md ├── x4.md ├── x5.md ├── x6.md ├── x7.md ├── x8.md └── x9.md ├── LICENSE ├── README.md ├── diagrams ├── format_diagrams.sh ├── json_output_railroad_diagram.html ├── railroad_diagram.html └── rr-replacements.txt ├── docs ├── code-coverage.md ├── dev_notes.md ├── getting-started.md ├── introduction.md ├── playground.md └── testing.md ├── sources ├── .gitignore ├── Makefile ├── ast.c ├── ast.h ├── bytebuf.c ├── bytebuf.h ├── cg_c.c ├── cg_c.h ├── cg_common.c ├── cg_common.h ├── cg_json_schema.c ├── cg_json_schema.h ├── cg_lua.c ├── cg_lua.h ├── cg_objc.c ├── cg_objc.h ├── cg_query_plan.c ├── cg_query_plan.h ├── cg_schema.c ├── cg_schema.h ├── cg_stats.c ├── cg_stats.h ├── cg_test_helpers.c ├── cg_test_helpers.h ├── cg_udf.c ├── cg_udf.h ├── charbuf.c ├── charbuf.h ├── common │ ├── Makefile_common │ ├── amalgam_common.sh │ ├── cov_common.sh │ ├── json_check.py │ ├── ok_common.sh │ ├── test_bison.sh │ ├── test_common.sh │ ├── test_flex.sh │ ├── test_helpers.sh │ └── update_docs.sh ├── compat.c ├── compat.h ├── cov.sh ├── cql.h ├── cql.l ├── cql.y ├── cqljson │ └── cqljson.py ├── cqlrt.c ├── cqlrt.h ├── cqlrt.lua ├── cqlrt_cf │ ├── .gitignore │ ├── clean.sh │ ├── cqlholder.m │ ├── cqlrt_cf.c │ ├── cqlrt_cf.h │ ├── demo_main.m │ ├── demo_todo.sql │ └── make.sh ├── cqlrt_common.c ├── cqlrt_common.h ├── crc64xz.c ├── crc64xz.h ├── demo │ ├── demo.sh │ ├── demo.sql │ └── demo_client.c ├── diags.h ├── dotpng.sh ├── encoders.c ├── encoders.h ├── eval.c ├── eval.h ├── flow.c ├── flow.h ├── gen_sql.c ├── gen_sql.h ├── grammar_docs │ ├── cql_grammar.md │ ├── cql_grammar.txt │ ├── diagram_tweaks.txt │ ├── grammar.js │ ├── json_grammar.md │ ├── json_grammar.txt │ ├── json_replacements.l │ ├── make_grammar.sh │ ├── make_json_grammar.sh │ ├── replacements.l │ ├── tree_sitter.py │ └── ys.c ├── java_demo │ ├── CGSQLMain.java │ ├── README.md │ ├── Sample.sql │ ├── TestResult.c │ ├── TestResult.java │ ├── clean.sh │ ├── com │ │ └── facebook │ │ │ └── cgsql │ │ │ ├── CQLResultSet.java │ │ │ ├── CQLViewModel.java │ │ │ └── EncodedString.java │ ├── com_facebook_cgsql_CQLResultSet.c │ ├── cqljava.py │ └── make.sh ├── json_test │ ├── json_test.l │ └── json_test.y ├── linetester │ ├── linetest.c │ ├── linetest.h │ ├── linetest.sql │ ├── linetest_main.c │ └── regen.sh ├── list.c ├── list.h ├── lua_demo │ ├── README │ ├── demo.sh │ ├── demo.sql │ ├── lua_upgrade0.ref │ ├── lua_upgrade1.ref │ ├── lua_upgrade2.ref │ ├── lua_upgrade3.ref │ ├── lua_upgrade4.ref │ ├── prepare_run_test.sh │ ├── run_test.sh │ ├── t1.sql │ ├── t2.sql │ ├── t3.sql │ ├── t4.sql │ ├── t5.sql │ ├── t6.sql │ ├── test_helpers.lua │ └── upgrade_harness.cql ├── make_amalgam.sh ├── minipool.c ├── minipool.h ├── ok.sh ├── printf.c ├── printf.h ├── query_plan.sh ├── query_plan_test.c ├── repl │ ├── README.md │ ├── clean.sh │ ├── clean_query_plan.sh │ ├── go.sh │ ├── go.sql │ ├── go_query_plan.sh │ └── main.c ├── result_set_extension.c ├── rewrite.c ├── rewrite.h ├── rt.c ├── rt.h ├── rt_common.c ├── run_test_client.c ├── sem.c ├── sem.h ├── sha256.c ├── sha256.h ├── symtab.c ├── symtab.h ├── test.sh ├── test │ ├── LICENSE │ ├── alt_cqlrt.err.ref │ ├── amalgam_test.c │ ├── asm_query_ns_needed.err.ref │ ├── badpath.err.ref │ ├── bigquote.err.ref │ ├── bigquote.sql │ ├── c_include_namespace_missing.err.ref │ ├── c_include_needed.err.ref │ ├── cg_1_2.err.ref │ ├── cg_requires_file.err.ref │ ├── cg_test.sql │ ├── cg_test_assembly_query.sql │ ├── cg_test_assembly_query_c.c.ref │ ├── cg_test_assembly_query_c.h.ref │ ├── cg_test_assembly_query_json.out.ref │ ├── cg_test_assembly_query_objc.out.ref │ ├── cg_test_base_fragment.sql │ ├── cg_test_base_fragment_c.c.ref │ ├── cg_test_base_fragment_c.h.ref │ ├── cg_test_base_fragment_json.out.ref │ ├── cg_test_base_fragment_objc.out.ref │ ├── cg_test_c.c.ref │ ├── cg_test_c.err.ref │ ├── cg_test_c.h.ref │ ├── cg_test_c_globals.c.ref │ ├── cg_test_c_globals.h.ref │ ├── cg_test_c_globals.sql │ ├── cg_test_c_type_getters.sql │ ├── cg_test_c_with_header.c.ref │ ├── cg_test_c_with_header.h.ref │ ├── cg_test_c_with_namespace.c.ref │ ├── cg_test_c_with_namespace.h.ref │ ├── cg_test_c_with_type_getters.c.ref │ ├── cg_test_c_with_type_getters.h.ref │ ├── cg_test_exports.out.ref │ ├── cg_test_extension_fragment.sql │ ├── cg_test_extension_fragment_c.c.ref │ ├── cg_test_extension_fragment_c.h.ref │ ├── cg_test_extension_fragment_json.out.ref │ ├── cg_test_extension_fragment_objc.out.ref │ ├── cg_test_generated_from.sql │ ├── cg_test_json_schema.out.ref │ ├── cg_test_json_schema.sql │ ├── cg_test_lua.err.ref │ ├── cg_test_lua.lua.ref │ ├── cg_test_lua.sql │ ├── cg_test_no_result_set.sql │ ├── cg_test_objc.err.ref │ ├── cg_test_objc.out.ref │ ├── cg_test_out_object.sql │ ├── cg_test_prev_invalid.sql │ ├── cg_test_query_plan.out.ref │ ├── cg_test_query_plan.sql │ ├── cg_test_query_plan_js.out.ref │ ├── cg_test_schema_min_version_upgrade.err.ref │ ├── cg_test_schema_min_version_upgrade.out.ref │ ├── cg_test_schema_partial_upgrade.err.ref │ ├── cg_test_schema_partial_upgrade.out.ref │ ├── cg_test_schema_prev.err.ref │ ├── cg_test_schema_prev.out.ref │ ├── cg_test_schema_sqlite.err.ref │ ├── cg_test_schema_sqlite.out.ref │ ├── cg_test_schema_upgrade.err.ref │ ├── cg_test_schema_upgrade.out.ref │ ├── cg_test_schema_upgrade.sql │ ├── cg_test_test_helpers.out.ref │ ├── cg_test_test_helpers.sql │ ├── cql_amalgam_test.err.ref │ ├── cql_amalgam_test.out.ref │ ├── cql_amalgam_test_semantic_error.sql │ ├── cql_amalgam_test_success.sql │ ├── cql_amalgam_test_syntax_error.sql │ ├── cqlrt_arg_missing.err.ref │ ├── cqltest.c │ ├── cqltest.h │ ├── dottest.out.ref │ ├── dottest.sql │ ├── error.sql │ ├── excl_invalid_regions.err.ref │ ├── gen_exports_args.err.ref │ ├── generate_file_file.err.ref │ ├── generate_file_type.err.ref │ ├── global_proc_missing.err.ref │ ├── global_proc_needed.err.ref │ ├── in_arg_missing.err.ref │ ├── inc_invalid_regions.err.ref │ ├── invalid_arg.err.ref │ ├── linetest.expected │ ├── linetest.sql │ ├── noresult.sql │ ├── objc_include_missing.err.ref │ ├── objc_no_results.err.ref │ ├── parse_test_cql_inferred_notnull.err.ref │ ├── parse_test_cql_inferred_notnull.sql │ ├── parse_test_fetch_from_call_columns.err.ref │ ├── parse_test_fetch_from_call_columns.sql │ ├── prev_and_codegen_incompat.err.ref │ ├── rt_arg_bogus.err.ref │ ├── rt_arg_missing.err.ref │ ├── run_test.sql │ ├── schema_version_error.sql │ ├── schema_version_ok.sql │ ├── sem_abort.err.ref │ ├── sem_test.err.ref │ ├── sem_test.out.ref │ ├── sem_test.sql │ ├── sem_test_dev.err.ref │ ├── sem_test_dev.out.ref │ ├── sem_test_dev.sql │ ├── sem_test_migrate.err.ref │ ├── sem_test_migrate.out.ref │ ├── sem_test_migrate.sql │ ├── sem_test_prev.err.ref │ ├── sem_test_prev.out.ref │ ├── sem_test_prev.sql │ ├── semantic_error.sql │ ├── simple_error.err.ref │ ├── stats.csv.ref │ ├── stats_test.sql │ ├── test.out.ref │ ├── test.sql │ ├── udf.c.ref │ ├── udf.h.ref │ ├── unwriteable.err.ref │ ├── upgrade_schema_v0.out.ref │ ├── upgrade_schema_v1.out.ref │ ├── upgrade_schema_v2.out.ref │ ├── upgrade_schema_v3.out.ref │ ├── upgrade_schema_v4.out.ref │ ├── usage.out.ref │ ├── write_fail.err.ref │ └── writefails.sql ├── test_helpers_test.c ├── tester │ ├── dbhelp.c │ ├── dbhelp.h │ ├── dbhelp.sql │ ├── main.c │ └── regen.sh ├── unit_tests.c ├── unit_tests.h ├── update_docs.sh └── upgrade │ ├── SchemaPersistentV0.sql │ ├── SchemaPersistentV1.sql │ ├── SchemaPersistentV2.sql │ ├── SchemaPersistentV3.sql │ ├── SchemaPersistentV4.sql │ ├── downgrade_test.c │ ├── errortrace.inc │ ├── upgrade_test.c │ ├── upgrade_test.sh │ └── upgrade_validate.sql └── website ├── .eslintrc.js ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .stylelintrc.js ├── README.md ├── babel.config.js ├── blog ├── 2020-10-12-welcome.md ├── 2020-11-12-update.md ├── 2020-11-15-boxed-cursors.md ├── 2020-11-16-error-tracing.md ├── 2020-11-18-error-tracing-macro.md ├── 2020-11-20-like-forms-tutorial.md ├── 2020-12-03-declare-enum-intro.md ├── 2020-12-08-arg-bundle-intro.md ├── 2020-12-16-virtual-table-intro.md ├── 2021-01-14-named-types-intro.md ├── 2021-01-20-type-kinds-intro.md ├── 2021-02-10-free-empty-results.md ├── 2021-02-14-select-if-nothing.md ├── 2021-02-21-result-variable.md ├── 2021-12-14-shared-fragments.md ├── 2021-12-30-flow-analysis.md ├── 2022-02-03-columns-sugar.md ├── 2022-02-19-expression-frags.md ├── 2022-02-21-from-general.md ├── 2022-03-17-blob-storage.md ├── 2022-10-05-backed-tables.md ├── 2022-10-06-parent-child.md └── 2022-11-07-schema-notes-2022.md ├── docusaurus.config.js ├── package.json ├── plugins └── my-loaders │ └── index.js ├── sidebars.js ├── sidebarsGuide.js ├── src ├── components │ └── DiagramContent.js ├── css │ └── custom.css └── pages │ ├── index.js │ ├── json-diagram.js │ ├── program-diagram.js │ └── styles.module.css ├── static ├── .nojekyll ├── CNAME └── img │ ├── CGSQL-Icon.png │ ├── CGSQL-Icon.svg │ ├── CGSQL-Logo.png │ ├── CGSQL-Logo.svg │ ├── favicon.ico │ └── oss_logo.png └── yarn.lock /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | on: [push] 2 | 3 | jobs: 4 | build_docs_job: 5 | runs-on: ubuntu-latest 6 | strategy: 7 | matrix: 8 | python-version: [3.6] 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v2 12 | id: build 13 | - name: Build the Website 14 | run: | 15 | cd website 16 | yarn 17 | yarn build 18 | 19 | - name: Get output time 20 | run: echo "The time was ${{ steps.build.outputs.time }}" 21 | - name: Deploy 22 | uses: JamesIves/github-pages-deploy-action@releases/v3 23 | with: 24 | ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | BRANCH: gh-pages # The branch the action should deploy to. 26 | FOLDER: website/build # The folder the action should deploy. 27 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to CG-SQL 2 | We want to make contributing to this project as easy and transparent as 3 | possible. 4 | 5 | ## Pull Requests 6 | We actively welcome your pull requests. 7 | 8 | 1. Fork the repo and create your branch from `master`. 9 | 2. If you've added code that should be tested, add tests. 10 | 3. If you've changed APIs, update the documentation. 11 | 4. Ensure the test suite passes. 12 | 5. Make sure your code lints. 13 | 6. If you haven't already, complete the Contributor License Agreement ("CLA"). 14 | 15 | ## Contributor License Agreement ("CLA") 16 | In order to accept your pull request, we need you to submit a CLA. You only need 17 | to do this once to work on any of Meta Platforms's open source projects. 18 | 19 | Complete your CLA here: 20 | 21 | ## Issues 22 | We use GitHub issues to track public bugs. Please ensure your description is 23 | clear and has sufficient instructions to be able to reproduce the issue. 24 | 25 | Meta Platforms has a [bounty program](https://www.facebook.com/whitehat/) for the safe 26 | disclosure of security bugs. In those cases, please go through the process 27 | outlined on that page and do not file a public issue. 28 | 29 | ## License 30 | By contributing to CG-SQL, you agree that your contributions will be licensed 31 | under the LICENSE file in the root directory of this source tree. 32 | -------------------------------------------------------------------------------- /CQL_Guide/generated/make_guide.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | rm -f guide.md 8 | (echo -n "") >guide.tmp 9 | for f in ../ch*.md 10 | do 11 | ( cat "$f"; echo ""; echo "" ) >>guide.tmp 12 | done 13 | 14 | # one digit appendices first 15 | for f in ../x?.md 16 | do 17 | (cat "$f"; \ 18 | echo ""; \ 19 | echo ""; \ 20 | echo "" ) >>guide.tmp 21 | done 22 | 23 | # two digit appendices second 24 | for f in ../x??.md 25 | do 26 | (cat "$f"; \ 27 | echo ""; \ 28 | echo ""; \ 29 | echo "" ) >>guide.tmp 30 | done 31 | 32 | # remove the docusaurus coding and replace it with simple markdown for the composite guide. 33 | sed -e '/^id:/d' -e '/^sidebar_label:/d' -e 's/^title: "\(.*\)"/## \1/' -e '/^---$/d' guide.md 34 | rm guide.tmp 35 | 36 | pandoc --toc -s -f markdown -t html --metadata title="The CQL Programming Language" guide.md -o guide.html 37 | -------------------------------------------------------------------------------- /CQL_Guide/generated/make_internal.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | (echo -n "") >internal.tmp 8 | for f in ../int*.md 9 | do 10 | ( cat "$f"; echo ""; echo "" ) >>internal.tmp 11 | done 12 | 13 | # remove the docusaurus coding and replace it with simple markdown for the composite guide. 14 | sed -e '/^id:/d' -e '/^sidebar_label:/d' -e 's/^title: "\(.*\)"/## \1/' -e '/^---$/d' internal.md 15 | rm internal.tmp 16 | 17 | pandoc --toc -s -f markdown -t html --metadata title="CQL Internals" internal.md -o internal.html 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Meta Platforms, Inc. and affiliates. 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 |

7 | CG/SQL 8 |

9 | 10 | CG/SQL is a code generation system for the popular SQLite library that allows developers to write stored procedures in a variant of Transact-SQL (T-SQL) and compile them into C code that uses SQLite’s C API to do the coded operations. CG/SQL enables engineers to create highly complex stored procedures with very large queries, without the manual code checking that existing methods require. 11 | 12 | The full system also includes features for managing and upgrading schema, creating test code for stored procedures, getting query plans for procedures, as well as interfacing with stored procedures from other languages, such as Java and Objective-C. The JSON output allows for the creation of even more analysis or interfacing code. The package includes extensive documentation on the language and system. 13 | 14 | Find out more at our [website](https://cgsql.dev/). 15 | 16 | ## Getting Started 17 | 18 | Please refer to our documentation to start using CG/SQL: 19 | - [CG/SQL Language Summary](https://cgsql.dev/docs/introduction) 20 | - [Getting Started with CG/SQL](https://cgsql.dev/docs/getting-started) 21 | - [Writing a Hello World Program](https://cgsql.dev/cql-guide/ch01#getting-started) 22 | - [Playground](https://cgsql.dev/docs/playground) 23 | 24 | For Contributors: 25 | - [Typical Dev Cycle](https://cgsql.dev/docs/dev-notes) 26 | - [Testing CG/SQL](https://cgsql.dev/docs/testing) 27 | - [Code Coverage](https://cgsql.dev/docs/code-coverage) 28 | 29 | ## Licensing 30 | 31 | CG/SQL is [MIT-licensed](./LICENSE). 32 | -------------------------------------------------------------------------------- /diagrams/format_diagrams.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | function move_font { 8 | file_name=$1 9 | sed -e '/font: normal 12px Verdana, sans-serif;/d' -e 's/a.palette/p,li { font: normal 12px Verdana, sans-serif; } a.palette/g' < "$file_name".html > "$file_name".thtml 10 | mv "$file_name".thtml "$file_name".html 11 | } 12 | 13 | 14 | move_font 'railroad_diagram' 15 | move_font 'json_output_railroad_diagram' 16 | -------------------------------------------------------------------------------- /diagrams/rr-replacements.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # This converts the railroads output to standard looking html 7 | # Some of the xhtml output just doesn't parse in most versions of Chrome 8 | # when it's embedded on the page like we do. So we strip out the header 9 | # and replace it with something more normal looking as well as some 10 | # internal node names. This was done by comparing what Chrome has in 11 | # its dom after a successful load with the raw output of the railroads tool. 12 | 13 | 1,2d 14 | s_ xmlns:xhtml="http://www.w3.org/1999/xhtml"__g 15 | s_ xmlns:svg="http://www.w3.org/2000/svg"__g 16 | s_ xmlns="http://www.w3.org/2000/svg"__g 17 | s_ xmlns:xlink="http://www.w3.org/1999/xlink"__g 18 | s_ xmlns="http://www.w3.org/1999/xhtml"__g 19 | s_/,/<\/style>/d 24 | s_.*__ 25 | -------------------------------------------------------------------------------- /docs/code-coverage.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: code-coverage 3 | title: Code Coverage CG/SQL 4 | sidebar_label: Code Coverage CG/SQL 5 | --- 6 | :::note 7 | Due to issues that we don't currently understand, `gcovr` on macOS with the latest XCode tools is not working. 8 | Consequently, the following script fails on macOS. See https://github.com/facebookincubator/CG-SQL/issues/92 for 9 | a more complete discussion. The problem doesn't seem to have anything to do with CG/SQL per se, but there it is... 10 | ::: 11 | 12 | Run this command in the [/sources](https://github.com/facebookincubator/CG-SQL/tree/main/sources) directory: 13 | ``` 14 | ./cov.sh 15 | ``` 16 | 17 | This will run the test scripts with the coverage flag, which causes the coverage build. 18 | If the tests pass a coverage report is created. 19 | 20 | The same build options are available as `cov.sh` uses `test.sh` to do the heavy lifting. 21 | -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: getting-started 3 | title: Getting Started with CG/SQL 4 | sidebar_label: Getting Started 5 | --- 6 | 7 | ## Building 8 | :::caution 9 | Please make sure you meet the [requirements](#requirements). 10 | ::: 11 | 12 | Set your current directory to the CG/SQL [`sources`](https://github.com/facebookincubator/CG-SQL/tree/main/sources) directory, wherever that may be, then: 13 | 14 | ``` 15 | make clean 16 | make 17 | ``` 18 | 19 | This compiles CQL and puts the result at `out/cql`. Now you can run it to show available command options (also [documented here](https://cgsql.dev/cql-guide/x1)): 20 | ```bash 21 | $ out/cql 22 | ``` 23 | 24 | You might want to alias the location of `out/cql`. For example, by using the `alias` command in Linux or MacOS. 25 | 26 | ## Next Steps 27 | 28 | - Go to the [first chapter of the CQL Guide](/cql-guide/ch01#getting-started) to write your first CQL program! 29 | The [second chapter](/cql-guide/ch02#a-sample-program) has a less trivial program that walks through how to query a SQLite database with CQL. 30 | - [CGL Language Cheatsheet](/cql-guide/x6) 31 | - [CQL Playground](/docs/playground) 32 | 33 | ## Requirements 34 | 35 | ### MacOS Users 36 | The default bison and flex on Mac are quite old. You'll need to replace them. The Build 37 | produces an error if this is happening. You can get a more recent versions like this: 38 | 39 | ``` 40 | brew install bison 41 | brew link bison --force 42 | brew install flex 43 | brew link flex --force 44 | ``` 45 | 46 | ### Linux Users 47 | The default SQLite on Ubuntu systems is also fairly old. Some of the tests (particularly 48 | the query plan tests) use features not available in this version. You'll want to link 49 | against a newer sqlite to pass all the tests. 50 | 51 | From a bare Ubuntu installation, you might need to add these components: 52 | 53 | sudo apt install 54 | 55 | * make 56 | * gcc 57 | * flex 58 | * bison 59 | * sqlite3 60 | * libsqlite3-dev 61 | 62 | After which I was able to do the normal installations. 63 | 64 | For the coverage build you need 65 | * gcovr 66 | 67 | And if you want to do the AST visualizations in PNG form you need 68 | * graphviz 69 | 70 | ## Options 71 | 72 | * If you add `CGSQL_GCC` to your environment the `Makefile` will add `CFLAGS += -std=c99` 73 | to try to be more interoperable with gcc. 74 | 75 | * If you add `SQLITE_PATH` to your environment the `Makefile` will try to compile `sqlite3-all.c` from that path 76 | and it will link that in instead of using `-lsqlite3`. 77 | 78 | ## Amalgam Build 79 | 80 | The amalgam is created by `./make_amalgam.sh` and the result is in `out/cql_amalgam.c` 81 | 82 | You can create and test the amalgam in one step (preferred) using 83 | 84 | ``` 85 | ./test.sh --use_amalgam 86 | ``` 87 | 88 | This will cause the amalgam to be created and compiled. Then the test suite will run against that binary. 89 | -------------------------------------------------------------------------------- /docs/playground.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: playground 3 | title: CG/SQL Playground 4 | sidebar_label: Playground 5 | --- 6 | 7 | ## CQL Playground 8 | While we do not offer an interactive REPL environment, we have bootstrapped an environment to run simple CQL programs in the [`repl` folder of our repository](https://github.com/facebookincubator/CG-SQL/tree/main/sources/repl). You can run it by doing this from the CQL repository: 9 | 10 | ```bash 11 | $ cd repl 12 | $ ./go.sh 13 | ``` 14 | 15 | By default, you'll get this output: 16 | ``` 17 | ../out/cql ready 18 | CQL Mini App Thingy 19 | Hello from CQL. 20 | Edit as you please 21 | ``` 22 | 23 | [`go.sh`](https://github.com/facebookincubator/CG-SQL/tree/main/sources/repl/go.sh) runs the `go()` stored procedure defined in [`go.sql`](https://github.com/facebookincubator/CG-SQL/tree/main/sources/repl/go.sql). You can experiment with the CQL language by editing the `go.sql` file, as you please. 24 | 25 | The contents of `go.sh` also offers a basic demonstration of how CQL should be typically used to transpile files into a C executable. 26 | 27 | ## Query Plan Playground 28 | Within the same `repl` directory, we have a script that demonstrates [CQL's query plan generation feature](/cql-guide/ch15) with [go.sql](https://github.com/facebookincubator/CG-SQL/tree/main/sources/repl/go.sql). 29 | 30 | Run this script in the `/repl` directory of the CQL repository: 31 | ```bash 32 | $ cd repl 33 | $ ./go_query_plan.sh 34 | ``` 35 | 36 | The script will generate the output of `EXPLAIN QUERY PLAN` of the SQL statements used in `go.sql`. 37 | 38 | ```json 39 | ["Query", "Stat", "Graph"], 40 | [ 41 | "INSERT INTO my_table(str) VALUES(\"Hello from CQL.\"), (\"Edit as you please.\")", 42 | [ 43 | [], 44 | [{"value": "SCAN", "style": {"fontSize": 14, "color": "red", "fontWeight": "bold"}}, {"value": 1, "style": {"fontSize": 14, "color": "red", "fontWeight": "bold"}}], 45 | [] 46 | ], 47 | "\n?\n|...SCAN 2 CONSTANT ROWS" 48 | ], 49 | [ 50 | "SELECT *\n FROM my_table", 51 | [ 52 | [], 53 | [{"value": "SCAN", "style": {"fontSize": 14, "color": "red", "fontWeight": "bold"}}, {"value": 1, "style": {"fontSize": 14, "color": "red", "fontWeight": "bold"}}], 54 | [] 55 | ], 56 | "\n?\n|...SCAN TABLE my_table" 57 | ], 58 | ``` 59 | 60 | :::info 61 | You might notice the above output has a lot of extraneous stuff, like what seems to be CSS styling in JSON format. This is something that will be addressed in the future. In the meantime, you can use [something like `jq`](https://stedolan.github.io/jq/) to filter stuff out. For example: 62 | ```bash 63 | $ ./go_query_plan.sh | jq '.[0][0][1:-1][] | {"query": .[0], "explain": .[2]}' 64 | ``` 65 | ::: 66 | -------------------------------------------------------------------------------- /docs/testing.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: testing 3 | title: Testing CG/SQL 4 | sidebar_label: Testing CG/SQL 5 | --- 6 | 7 | Run this command in the [/sources](https://github.com/facebookincubator/CG-SQL/tree/main/sources) directory: 8 | ``` 9 | ./test.sh 10 | ``` 11 | 12 | This will build and run the test suite 13 | 14 | ``` 15 | ./test.sh --use_amalgam 16 | ``` 17 | 18 | Does the same thing but it tests the built amalgam rather than the normal build 19 | 20 | > See details in our [CQL Internals documentation](/cql-guide/int04#testing). 21 | -------------------------------------------------------------------------------- /sources/.gitignore: -------------------------------------------------------------------------------- 1 | # Performance Notice: 2 | # 3 | # Gitignore is parsed lazily. Prefer putting rules in subdirectories. 4 | # For example, to ignore "foo/bar/baz", do: 5 | # 6 | # # In foo/bar/.gitignore: 7 | # /baz 8 | # 9 | # Instead of: 10 | # 11 | # # COUNTER EXAMPLE 12 | # # In .gitignore 13 | # /foo/bar/baz 14 | 15 | # Lines that start with '#' are comments. 16 | 17 | /out 18 | *.gcda 19 | *.gcno 20 | .pbcopy.swp 21 | 22 | /repl/go_query_plan 23 | /repl/go 24 | 25 | /repl/go-qp.sql 26 | /repl/go.sql.pre 27 | /repl/*.c 28 | /repl/*.h 29 | /repl/*.h.gch 30 | /repl/*.o 31 | -------------------------------------------------------------------------------- /sources/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # the common make file requires no overrides for the OSS build 7 | 8 | include common/Makefile_common 9 | -------------------------------------------------------------------------------- /sources/bytebuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "bytebuf.h" 9 | 10 | // The open operations simply zeros the buffer contents 11 | cql_noexport void bytebuf_open(bytebuf *_Nonnull buf) { 12 | buf->max = 0; 13 | buf->ptr = 0; 14 | buf->used = 0; 15 | } 16 | 17 | // The close operation releases any allocated memory 18 | // Note that bytebuf itself is most often on the stack so it's not freed 19 | // if the bytebuf was allocated it's owned by whoever allocated it. 20 | cql_noexport void bytebuf_close(bytebuf *_Nonnull buf) { 21 | free(buf->ptr); 22 | buf->max = 0; 23 | buf->ptr = NULL; 24 | } 25 | 26 | // This creates the needed space in the bytebuf, the buffer grows if it has to. 27 | // The newly allocated memory begins with garbage data.. 28 | cql_noexport void *_Nonnull bytebuf_alloc(bytebuf *_Nonnull buf, uint32_t needed) { 29 | uint32_t avail = buf->max - buf->used; 30 | 31 | if (needed > avail) { 32 | buf->max += needed + BYTEBUF_GROWTH_SIZE; 33 | char *newptr = _new_array(char, buf->max); 34 | 35 | if (buf->used) memcpy(newptr, buf->ptr, buf->used); 36 | 37 | free(buf->ptr); 38 | buf->ptr = newptr; 39 | } 40 | 41 | void *result = buf->ptr + buf->used; 42 | buf->used += needed; 43 | return result; 44 | } 45 | 46 | // The most common operation is to append into an existing bytebuf, this is the alloc operation 47 | // followed by a copy. Callers often do other things like retain embedded pointers or whatnot 48 | // but the bytebuf is below anything like that. 49 | cql_noexport void bytebuf_append(bytebuf *_Nonnull buf, const void *_Nonnull bytes, uint32_t count) { 50 | void *mem = bytebuf_alloc(buf, count); 51 | memcpy(mem, bytes, count); 52 | } 53 | -------------------------------------------------------------------------------- /sources/bytebuf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // This is a simple growable memory buffer, it may have arbitrary 9 | // binary in it. It's the peer to charbuf for bytes. 10 | 11 | #pragma once 12 | 13 | #include "cql.h" 14 | 15 | #define BYTEBUF_GROWTH_SIZE 1024 16 | 17 | typedef struct bytebuf { 18 | char *_Nullable ptr; // pointer to stored data, if any 19 | uint32_t used; // bytes used in current buffer 20 | uint32_t max; // max bytes in current buffer 21 | } bytebuf; 22 | 23 | cql_noexport void bytebuf_open(bytebuf *_Nonnull buf); 24 | cql_noexport void bytebuf_close(bytebuf *_Nonnull buf); 25 | cql_noexport void *_Nonnull bytebuf_alloc(bytebuf *_Nonnull buf, uint32_t needed); 26 | cql_noexport void bytebuf_append(bytebuf *_Nonnull buf, const void *_Nonnull bytes, uint32_t count); 27 | 28 | // helper macro for new from a bufferß 29 | #define bytebuf_new(buf, T) ((T*)bytebuf_alloc(buf, sizeof(T))) 30 | 31 | // helper macro to append a normal variable 32 | #define bytebuf_append_var(buf, var) bytebuf_append(buf, &var, sizeof(var)) 33 | 34 | // cleanup a non-null buffer 35 | #define BYTEBUF_CLEANUP(b) if (b) {bytebuf_close(b); b = NULL; } 36 | -------------------------------------------------------------------------------- /sources/cg_c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "cql.h" 11 | 12 | cql_noexport void cg_c_main(struct ast_node *root); 13 | cql_noexport void cg_c_cleanup(void); 14 | -------------------------------------------------------------------------------- /sources/cg_json_schema.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "cql.h" 11 | 12 | cql_noexport void cg_json_schema_main(struct ast_node *root); 13 | -------------------------------------------------------------------------------- /sources/cg_objc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "cql.h" 11 | 12 | cql_noexport void cg_objc_main(struct ast_node *root); 13 | -------------------------------------------------------------------------------- /sources/cg_query_plan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "cql.h" 11 | 12 | // Entry point for cql query plan result type. 13 | // The result type takes as an input a cql with one or many sql or cql statements 14 | // It codegen a CQL stored proc that print out the query plan report of all 15 | // elegible sql statement in the input. All sql statement are not eligible to 16 | // run in an explain statement, this is the reason why we used in the previous 17 | // sentence the word eligible. 18 | // The query plan report contains: 19 | // - the target sql statement 20 | // - the list of algorithm used in the target sql statement 21 | // - the sequence of execution of the plan for the target sql statement 22 | 23 | cql_noexport void cg_query_plan_main(struct ast_node *root); 24 | -------------------------------------------------------------------------------- /sources/cg_schema.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "ast.h" 11 | 12 | cql_noexport void cg_schema_main(struct ast_node *root); 13 | cql_noexport void cg_schema_upgrade_main(struct ast_node *root); 14 | cql_noexport void cg_schema_sqlite_main(struct ast_node *root); 15 | -------------------------------------------------------------------------------- /sources/cg_stats.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "cql.h" 11 | 12 | 13 | // Entry point for cg_stats result time 14 | 15 | // This type takes as input the AST and emits aggregated 16 | // statistics about its AST shape on a per-proc basis in CSV form. 17 | // This output help you to understand the nature of your procs 18 | 19 | cql_noexport void cg_stats_main(struct ast_node *root); 20 | -------------------------------------------------------------------------------- /sources/cg_test_helpers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "cql.h" 11 | 12 | cql_noexport void cg_test_helpers_main(struct ast_node *root); 13 | -------------------------------------------------------------------------------- /sources/cg_udf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #if defined(CQL_AMALGAM_LEAN) && !defined(CQL_AMALGAM_UDF) 9 | 10 | // stubs to avoid link errors 11 | cql_noexport void cg_udf_main(struct ast_node *root) {} 12 | 13 | #else 14 | 15 | #include 16 | #include "ast.h" 17 | #include "cg_udf.h" 18 | #include "charbuf.h" 19 | #include "cg_common.h" 20 | #include "cql.h" 21 | 22 | cql_noexport void cg_udf_main(struct ast_node *root) { 23 | Contract(options.file_names_count == 2); 24 | cql_exit_on_semantic_errors(root); 25 | exit_on_validating_schema(); 26 | 27 | CHARBUF_OPEN(header_file); 28 | CHARBUF_OPEN(body_file); 29 | 30 | bprintf(&body_file, "%s", rt->source_prefix); 31 | 32 | bprintf(&body_file, "#include \"%s\"\n\n", options.file_names[0]); 33 | bprintf(&body_file, "static void _udf_callback(sqlite3_context* context, int argc, sqlite3_value** argv) {\n"); 34 | bprintf(&body_file, "}\n"); 35 | 36 | bprintf(&body_file, "\nvoid create_udf(sqlite3 *_Nonnull _db_) {\n"); 37 | 38 | for (list_item *item = all_functions_list; item; item = item->next) { 39 | EXTRACT_ANY_NOTNULL(any_func, item->ast); 40 | bool_t is_select_func = 41 | is_ast_declare_select_func_stmt(any_func) || 42 | is_ast_declare_select_func_no_check_stmt(any_func); 43 | Contract(is_select_func || is_ast_declare_func_stmt(any_func)); 44 | 45 | if (is_select_func) { 46 | EXTRACT_STRING(name, any_func->left); 47 | 48 | bprintf(&body_file, " sqlite3_create_function_v2(\n"); 49 | bprintf(&body_file, " _db_,\n"); 50 | bprintf(&body_file, " \"%s\",\n", name); 51 | bprintf(&body_file, " -1,\n"); // stub function takes any number of args 52 | bprintf(&body_file, " SQLITE_UTF8 | SQLITE_DETERMINISTIC,\n"); 53 | bprintf(&body_file, " NULL,\n"); 54 | bprintf(&body_file, " &_udf_callback,\n"); 55 | bprintf(&body_file, " NULL,\n"); 56 | bprintf(&body_file, " NULL,\n"); 57 | bprintf(&body_file, " NULL\n"); 58 | bprintf(&body_file, " );\n"); 59 | } 60 | } 61 | 62 | bprintf(&body_file, "}\n"); 63 | 64 | bprintf(&header_file, "%s", rt->header_prefix); 65 | bprintf(&header_file, rt->cqlrt_template, rt->cqlrt); 66 | bprintf(&header_file, "void create_udf(sqlite3 *_Nonnull _db_); \n\n"); 67 | 68 | if (options.test) { 69 | while (root->right) { 70 | root = root->right; 71 | } 72 | bprintf(&header_file, "// The statement ending at line %d\n\n", root->left->lineno); 73 | bprintf(&body_file, "// The statement ending at line %d\n\n", root->left->lineno); 74 | } 75 | 76 | cql_write_file(options.file_names[0], header_file.ptr); 77 | cql_write_file(options.file_names[1], body_file.ptr); 78 | 79 | CHARBUF_CLOSE(body_file); 80 | CHARBUF_CLOSE(header_file); 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /sources/cg_udf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "cql.h" 11 | 12 | // Entry point for user defined function result type. 13 | // The result type takes as an input a cql file and out put c code to registered 14 | // into sqlite database all user defined functions used in the cql file. The 15 | // actual user defined function implement is a bogus implementation that we 16 | // might have to revisit in the future. For now it's enough to allow query 17 | // plan result type to support udf. 18 | 19 | // Note: this probably needs to also learn about table valued functions 20 | 21 | cql_noexport void cg_udf_main(struct ast_node *root); 22 | -------------------------------------------------------------------------------- /sources/charbuf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #define CHARBUF_INTERNAL_SIZE 1024 11 | #define CHARBUF_GROWTH_SIZE 1024 12 | 13 | typedef struct charbuf 14 | { 15 | char *ptr; // pointer to stored data, if any 16 | uint32_t used; // bytes used in current buffer 17 | uint32_t max; // max bytes in current buffer 18 | 19 | // builtin buffer storage 20 | char internal[CHARBUF_INTERNAL_SIZE]; 21 | } charbuf; 22 | 23 | cql_data_decl( int32_t charbuf_open_count ); 24 | 25 | cql_noexport void bopen(charbuf* b); 26 | cql_noexport void bclose(charbuf *b); 27 | cql_noexport void bclear(charbuf *b); 28 | cql_noexport void vbprintf(charbuf *b, const char *format, va_list args); 29 | cql_noexport void bprintf(charbuf *b, const char *format, ...); 30 | cql_noexport CSTR dup_printf(const char *format, ...); 31 | cql_noexport void bputc(charbuf *b, char c); 32 | cql_noexport void bindent(charbuf *output, charbuf *input, int32_t indent); 33 | cql_noexport bool_t breadline(charbuf *output, CSTR *data); 34 | 35 | #define CHARBUF_OPEN(x) \ 36 | int32_t __saved_charbuf_count##x = charbuf_open_count; \ 37 | charbuf x; \ 38 | bopen(&x) 39 | 40 | #define CHARBUF_CLOSE(x) \ 41 | bclose(&x); \ 42 | Invariant(__saved_charbuf_count##x == charbuf_open_count) 43 | 44 | // These helpers push a buffer and use it for the output temporarily. 45 | // When the buffer is finished (at END_INDENT) bindent is used to 46 | // indent it by the indicated amount. They assume the output buffer is called 47 | // "output". 48 | #define BEGIN_INDENT(name, level) \ 49 | charbuf *name##_saved = output; \ 50 | int32_t name##_level = level; \ 51 | CHARBUF_OPEN(name); \ 52 | output = &name; 53 | 54 | #define END_INDENT(name) \ 55 | output = name##_saved; \ 56 | bindent(output, &name, name##_level); \ 57 | CHARBUF_CLOSE(name); 58 | 59 | -------------------------------------------------------------------------------- /sources/common/cov_common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | COV_ARGS="${COV_COVERAGE_ARGS}" 8 | 9 | OUT_DIR="out" 10 | 11 | coverage() { 12 | rm -f *.gcov 13 | 14 | if ! ./test.sh --coverage 15 | then 16 | echo "you can't run coverage until the tests all pass" 17 | return 1 18 | fi 19 | 20 | # super spammy, we only care about the errors 21 | if ! gcov out/*.gcda >/dev/null 22 | then 23 | echo "error running gcov" 24 | return 1 25 | fi 26 | 27 | echo generating ${OUT_DIR}/report.html 28 | if ! "$@" \ 29 | -g -k \ 30 | --html \ 31 | --html-details \ 32 | -o ${OUT_DIR}/report.html \ 33 | ${COV_EXTRA_ARGS} \ 34 | -e test \ 35 | -e tester \ 36 | -e linetester \ 37 | -e json_test \ 38 | -e out \ 39 | -e cql.c \ 40 | -e cql.y.c \ 41 | -e cqltest.c \ 42 | -e result_set_extension.c \ 43 | -e run_test_client.c \ 44 | -e query_plan_test.c \ 45 | -e run_test.c \ 46 | -e generated_upgrade \ 47 | -e upgrade 48 | then 49 | echo "error generating html" 50 | return 1 51 | fi 52 | 53 | echo generating ${OUT_DIR}/report.txt 54 | if ! "$@" \ 55 | -g -k \ 56 | -o ${OUT_DIR}/report.txt \ 57 | ${COV_EXTRA_ARGS} \ 58 | -e test \ 59 | -e tester \ 60 | -e linetester \ 61 | -e json_test \ 62 | -e out \ 63 | -e cql.c \ 64 | -e cql.y.c \ 65 | -e cqltest.c \ 66 | -e result_set_extension.c \ 67 | -e run_test_client.c \ 68 | -e query_plan_test.c \ 69 | -e run_test.c \ 70 | -e generated_upgrade \ 71 | -e upgrade 72 | then 73 | echo "error generating plain text" 74 | return 1 75 | fi 76 | 77 | rm -f *.gcov 78 | 79 | return 0 80 | } 81 | -------------------------------------------------------------------------------- /sources/common/json_check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | import json 8 | import sys 9 | 10 | data = json.load(sys.stdin) 11 | json_data = json.dumps(data, indent=2) 12 | print(json_data) 13 | -------------------------------------------------------------------------------- /sources/common/test_bison.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # Checking for the super common case of the XCode version of Bison 8 | # This could be generalized obviously... but this one deserves special treatment 9 | 10 | echo "Testing bison version of " "$1" 11 | $1 -V 12 | if [ -n "$($1 -V | grep ' 2[.]3')" ] ; then 13 | echo Bison 2.3 detected, this is too old. Use brew install bison to update. See README.md 14 | exit 91 15 | fi 16 | 17 | exit 0 18 | -------------------------------------------------------------------------------- /sources/common/test_flex.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # Checking for the super common case of the XCode version of Flex 8 | # This could be generalized obviously... but this one deserves special treatment 9 | 10 | echo "Testing flex version of " "$1" 11 | $1 -V 12 | if [ -n "$($1 -V | grep ' 2[.]5')" ] ; then 13 | echo "Flex 2.5 detected, this is too old. Use brew install flex to update. See README.md" 14 | exit 90 15 | fi 16 | 17 | exit 0 18 | -------------------------------------------------------------------------------- /sources/common/test_helpers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | failed() { 8 | echo '--------------------------------- FAILED' 9 | make_clean_msg 10 | exit 1 11 | } 12 | 13 | make_clean_msg() { 14 | echo "To clean artifacts: make clean" 15 | } 16 | 17 | colordiff() { 18 | diff --color "$@" 19 | return $? 20 | } 21 | 22 | # Note that we need the line numbers in the main output so that we can use the test 23 | # tools to see which output came from what input. However this causes silly diffs 24 | # so the reference output has the line numbers stripped. When comparing against 25 | # the reference output we replace the line numbers with XXXX 26 | normalize_lines() { 27 | sed -e "s/The statement ending at line .*/The statement ending at line XXXX/" \ 28 | -e "/(c) Meta Platforms, Inc. and affiliates/d" \ 29 | -e "/g.nerated S.gnedSource<<.*>>/d" \ 30 | -e "s/MBQ/CGB/g" \ 31 | -e "s/MCQ/CGC/g" \ 32 | -e "s/MBI/CGO/g" \ 33 | -e "s/com.facebook.msys.mci/com.facebook.cgsql/g" \ 34 | -e "/autogenerated by CQL/d" \ 35 | -e "s/\/.*\/xplat\//XXX\//" \ 36 | -e "s/.sql.* error:/.sql:XXXX:1: error:/" <"$1" >"$1.tmp" 37 | cp "$1.tmp" "$1" 38 | rm "$1.tmp" 39 | } 40 | 41 | 42 | __on_diff_exit() { 43 | normalize_lines "$1" 44 | normalize_lines "$2" 45 | if ! colordiff "$1" "$2" 46 | then 47 | # --non-interactive forces interactive mode off. If the environment is not actually interactive 48 | # (connected to a terminal for both output and input), interactive mode is also disabled. 49 | if [ "$NON_INTERACTIVE" == 1 ] || [ ! -t 0 ] || [ ! -t 1 ]; 50 | then 51 | echo "When running: diff $*" 52 | echo "The above differences were detected. If these are expected then run ok.sh to proceed." 53 | echo "Don't just run ok.sh to make the error go away; you have to really understand the diff first!" 54 | echo " " 55 | failed 56 | else 57 | read -rp "When running: diff $* 58 | The above differences were detected. Is this expected? 59 | Don't just accept to make the error go away; you have to really understand the diff first! (y/N) " ANS 60 | case $ANS in 61 | [Yy]* ) cp "$2" "$1" 2>/dev/null;; 62 | * ) echo " "; failed 63 | esac 64 | fi 65 | fi 66 | } 67 | 68 | on_diff_exit() { 69 | __on_diff_exit "${TEST_DIR}/$1.ref" "${OUT_DIR}/$1" 70 | } 71 | -------------------------------------------------------------------------------- /sources/compat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "cql.h" 9 | #include "compat.h" 10 | #include "minipool.h" 11 | 12 | cql_noexport char *_Nonnull Strdup(const char *_Nonnull s) { 13 | uint32_t length = (uint32_t)(strlen(s) + 1); 14 | void *result = minipool_alloc(str_pool, length); 15 | Invariant(result); 16 | return (char *)memcpy(result, s, length); 17 | } 18 | 19 | cql_noexport int32_t Strcasecmp(const char *_Nonnull s1, const char *_Nonnull s2) { 20 | const char *p1 = s1; 21 | const char *p2 = s2; 22 | int32_t result; 23 | if (p1 == p2) 24 | return 0; 25 | while ((result = Tolower(*p1) - Tolower(*p2++)) == 0) 26 | if (*p1++ == '\0') 27 | break; 28 | return result; 29 | } 30 | 31 | cql_noexport int32_t Strncasecmp(const char *_Nonnull s1, const char *_Nonnull s2, size_t n) { 32 | const char *p1 = s1; 33 | const char *p2 = s2; 34 | int32_t result = 0; 35 | 36 | for (; n != 0; --n) { 37 | if ((result = Tolower(*p1) - Tolower(*p2++)) != 0) { 38 | return result; 39 | } 40 | if (*p1++ == '\0') 41 | return 0; 42 | } 43 | return result; 44 | } 45 | 46 | cql_noexport int32_t Strendswith(const char *_Nonnull haystack, const char *_Nonnull needle) { 47 | size_t haystack_len = strlen(haystack); 48 | size_t needle_len = strlen(needle); 49 | 50 | return (haystack_len >= needle_len) && 51 | (!Strncasecmp(haystack + haystack_len - needle_len, needle, needle_len)); 52 | } 53 | 54 | cql_noexport bool_t Islower(char c) { 55 | return c >= 'a' && c <= 'z'; 56 | } 57 | 58 | cql_noexport bool_t Isupper(char c) { 59 | return c >= 'A' && c <= 'Z'; 60 | } 61 | 62 | cql_noexport bool_t Isalpha(char c) { 63 | return Islower(c) || Isupper(c); 64 | } 65 | 66 | cql_noexport bool_t Isdigit(char c) { 67 | return c >= '0' && c <= '9'; 68 | } 69 | 70 | cql_noexport bool_t Isxdigit(char c) { 71 | return Isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); 72 | } 73 | 74 | cql_noexport char Tolower(char c) { 75 | return Isupper(c) ? c + ('a' - 'A') : c; 76 | } 77 | 78 | cql_noexport char Toupper(char c) { 79 | return Islower(c) ? c - ('a' - 'A') : c; 80 | } 81 | -------------------------------------------------------------------------------- /sources/compat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | cql_noexport char *_Nonnull Strdup(const char *_Nonnull s); 11 | cql_noexport int32_t Strcasecmp(const char *_Nonnull s1, const char *_Nonnull s2); 12 | cql_noexport int32_t Strncasecmp(const char *_Nonnull s1, const char *_Nonnull s2, size_t n); 13 | cql_noexport int32_t Strendswith(const char *_Nonnull haystack, const char *_Nonnull needle); 14 | 15 | // On Windows, the normal versions of some of these function assert on non-ASCII 16 | // characters when using a debug CRT library. These alternative versions allow 17 | // us to avoid "ctype.h" entirely. 18 | cql_noexport bool_t Isalpha(char c); 19 | cql_noexport bool_t Isdigit(char c); 20 | cql_noexport bool_t Islower(char c); 21 | cql_noexport bool_t Isupper(char c); 22 | cql_noexport bool_t Isxdigit(char c); 23 | cql_noexport char Tolower(char c); 24 | cql_noexport char Toupper(char c); 25 | -------------------------------------------------------------------------------- /sources/cov.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | COV_EXTRA_ARGS="" 8 | 9 | # shellcheck disable=SC1091 10 | source common/cov_common.sh || exit 1 11 | 12 | OUT_DIR="out" 13 | 14 | if ! coverage gcovr 15 | then 16 | echo "A coverage step failed, aborting" 17 | exit 1 18 | fi 19 | 20 | cat "${OUT_DIR}/report.txt" 21 | exit 0 22 | -------------------------------------------------------------------------------- /sources/cqlrt_cf/.gitignore: -------------------------------------------------------------------------------- 1 | demo_objc.h 2 | demo_todo.c 3 | demo_todo.h 4 | demo 5 | demo.dSYM/ 6 | -------------------------------------------------------------------------------- /sources/cqlrt_cf/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | rm -f demo_todo.h 8 | rm -f demo_todo.c 9 | rm -f demo_objc.h 10 | rm -f cqlrt_cf.h.gch 11 | rm -f demo 12 | rm -rf demo.dSYM 13 | -------------------------------------------------------------------------------- /sources/cqlrt_cf/demo_main.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #import "demo_objc.h" 12 | 13 | int main(int argc, char **argv) 14 | { 15 | 16 | @autoreleasepool { 17 | 18 | // Note: not exactly world class error handling but that isn't the point 19 | 20 | // create a db 21 | sqlite3 *db; 22 | int rc = sqlite3_open(":memory:", &db); 23 | if (rc != SQLITE_OK) { 24 | exit(1); 25 | } 26 | 27 | // make schema if needed (it always will be here because memory databases begin empty 28 | rc = todo_create_tables(db); 29 | if (rc != SQLITE_OK) { 30 | exit(2); 31 | } 32 | 33 | // add some tasks 34 | const char *const default_tasks[] = { 35 | "Buy milk", 36 | "Walk dog", 37 | "Write code" 38 | }; 39 | 40 | for (int i = 0; i < 3; i++) { 41 | // note we make a string reference from a c string here 42 | cql_string_ref dtask = cql_string_ref_new(default_tasks[i]); 43 | rc = todo_add(db, dtask); 44 | cql_string_release(dtask); // and then dispose of the reference 45 | if (rc != SQLITE_OK) { 46 | exit(3); 47 | } 48 | } 49 | 50 | // mark a task as done 51 | rc = todo_setdone_(db, 1, true); 52 | if (rc != SQLITE_OK) { 53 | exit(4); 54 | } 55 | 56 | // delete a row in the middle, rowid = 2 57 | rc = todo_delete(db, 2); 58 | if (rc != SQLITE_OK) { 59 | exit(5); 60 | } 61 | 62 | // select out some results 63 | todo_tasks_result_set_ref result_set_ref; 64 | rc = todo_tasks_fetch_results(db, &result_set_ref); 65 | if (rc != SQLITE_OK) { 66 | printf("error: %d\n", rc); 67 | exit(2); 68 | } 69 | 70 | CGS_todo_tasks *rs = CGS_todo_tasks_from_todo_tasks(result_set_ref); 71 | cql_release(result_set_ref); // objective C is now in control of the refs 72 | 73 | // get result count 74 | cql_int32 result_count = CGS_todo_tasks_result_count(rs); 75 | 76 | // loop to print 77 | for (cql_int32 row = 0; row < result_count; row++) { 78 | // note the usual "get" semantics, no retain here 79 | NSString *text = CGS_todo_tasks_get_description(rs, row); 80 | cql_bool done = CGS_todo_tasks_get_done(rs, row); 81 | cql_int64 rowid = CGS_todo_tasks_get_rowid(rs, row); 82 | 83 | NSLog(@"%d: rowid:%lld %@ (%s)\n", row, rowid, text, done ? "done" : "not done"); 84 | } 85 | 86 | // and close the database 87 | sqlite3_close(db); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /sources/cqlrt_cf/demo_todo.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- This is a simple schema for keep track of tasks and whether they are done 9 | 10 | -- this serves to both declare the table and create the schema 11 | create proc todo_create_tables() 12 | begin 13 | 14 | create table if not exists tasks( 15 | description text not null, 16 | done bool default false not null 17 | ); 18 | 19 | end; 20 | 21 | -- adds a new not-done task 22 | create proc todo_add(task TEXT NOT null) 23 | begin 24 | insert into tasks values(task, false); 25 | end; 26 | 27 | -- gets the tasks in inserted order 28 | create proc todo_tasks() 29 | begin 30 | select rowid, description, done from tasks order by rowid; 31 | end; 32 | 33 | -- updates a given task by rowid 34 | create proc todo_setdone_(rowid_ integer not null, done_ bool not null) 35 | begin 36 | update tasks set done = done_ where rowid == rowid_; 37 | end; 38 | 39 | -- deletes a given task by rowid 40 | create proc todo_delete(rowid_ integer not null) 41 | begin 42 | delete from tasks where rowid == rowid_; 43 | end; 44 | -------------------------------------------------------------------------------- /sources/cqlrt_cf/make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # exit when any command fails 8 | set -e 9 | 10 | echo "building cql" 11 | (cd .. ; make) 12 | 13 | echo "building C code" 14 | ../out/cql --in demo_todo.sql --cg demo_todo.h demo_todo.c --cqlrt cqlrt_cf.h 15 | 16 | # note --rt objc_mit used so that even the non-OSS build will do the OSS version of the output 17 | # for normal users here is no difference between objc and objc_mit this is an internal thing 18 | # objc_mit normalizes the output. 19 | 20 | echo "building OBJC code" 21 | ../out/cql --in demo_todo.sql --cg demo_objc.h --rt objc_mit --objc_c_include_path demo_todo.h --cqlrt cqlrt_cf.h 22 | 23 | echo "building executable" 24 | cc -o demo -g -I.. -I. demo_todo.c demo_main.m cqlrt_cf.c cqlholder.m -lsqlite3 -framework Foundation -fobjc-arc 25 | 26 | echo "running demo" 27 | ./demo 28 | 29 | echo "" 30 | echo "Done" 31 | echo "" 32 | echo "to clean the directory run ./clean.sh" 33 | -------------------------------------------------------------------------------- /sources/demo/demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | set -euo pipefail 8 | 9 | set -e 10 | 11 | O="../out" 12 | 13 | (cd ..; make demo-binary) 14 | ${O}/demo 15 | echo "SUCCESS" 16 | -------------------------------------------------------------------------------- /sources/demo/demo.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- demo stored procs 9 | 10 | DECLARE PROC printf NO CHECK; 11 | 12 | CREATE PROC make_mixed () 13 | BEGIN 14 | CREATE TABLE mixed( 15 | id INTEGER NOT NULL, 16 | name TEXT, 17 | code LONG_INT, 18 | flag BOOL, 19 | rate REAL 20 | ); 21 | END; 22 | 23 | CREATE PROC load_mixed () 24 | BEGIN 25 | DELETE FROM mixed; 26 | INSERT INTO mixed VALUES(1, 'a name', 12, 1, 5.0); 27 | INSERT INTO mixed VALUES(2, 'some name', 14, 3, 7.0); 28 | INSERT INTO mixed VALUES(3, 'yet another name', 15, 3, 17.4); 29 | INSERT INTO mixed VALUES(4, 'some name', 19, 4, 9.1); 30 | INSERT INTO mixed VALUES(5, 'what name', 21, 8, 12.3); 31 | END; 32 | 33 | CREATE PROC update_mixed (id_ INTEGER NOT NULL, rate_ REAL NOT NULL) 34 | BEGIN 35 | UPDATE mixed 36 | SET rate = rate_ 37 | WHERE id = id_; 38 | END; 39 | 40 | @ATTRIBUTE(cql:identity=(id, code)) 41 | @ATTRIBUTE(cql:generate_copy) 42 | CREATE PROC get_mixed (lim INTEGER NOT NULL) 43 | BEGIN 44 | SELECT * 45 | FROM mixed 46 | ORDER BY id 47 | LIMIT lim; 48 | END; 49 | 50 | CREATE PROC mandelbrot () 51 | BEGIN 52 | DECLARE C CURSOR FOR WITH RECURSIVE 53 | xaxis (x) AS ( SELECT -2.0 UNION ALL SELECT x + 0.05 FROM xaxis WHERE x < 1.2), 54 | yaxis (y) AS ( SELECT -1.0 UNION ALL SELECT y + 0.1 FROM yaxis WHERE y < 1.0), 55 | m (iter, cx, cy, x, y) AS ( 56 | SELECT 0 AS iter, x AS cx, y AS cy, 0.0 AS x, 0.0 AS y 57 | FROM xaxis, yaxis 58 | UNION ALL 59 | SELECT iter + 1 AS iter, cx, cy, x * x - y * y + cx AS x, 2.0 * x * y + cy AS y 60 | FROM m 61 | WHERE m.x * m.x + m.y * m.y < 4.0 AND m.iter < 28), 62 | m2 (iter, cx, cy) AS ( 63 | SELECT max(iter), cx, cy 64 | FROM m 65 | GROUP BY cx, cy), 66 | a (t) AS ( 67 | SELECT group_concat(substr(' .+*#', 1 + min(iter / 7, 4), 1), '') 68 | FROM m2 69 | GROUP BY cy) 70 | SELECT group_concat(rtrim(t), "\n") AS line 71 | FROM a; 72 | 73 | LOOP FETCH C 74 | BEGIN 75 | CALL printf("%s\n", C.line); 76 | END; 77 | END; 78 | -------------------------------------------------------------------------------- /sources/demo/demo_client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "cqlrt.h" 9 | #include "demo.h" 10 | 11 | // super cheesy error handling 12 | #define _E(c, x) if (!(c)) { \ 13 | printf("!" #x "%s:%d\n", __FILE__, __LINE__); \ 14 | goto error; \ 15 | } 16 | #define E(x) _E(x, x) 17 | #define SQL_E(x) _E(SQLITE_OK == (x), x) 18 | 19 | static void print_result_set(const char *label, get_mixed_result_set_ref result_set) { 20 | cql_int32 id; 21 | cql_bool b_is_null; 22 | cql_bool b_value; 23 | cql_bool code_is_null; 24 | cql_int64 code_value; 25 | cql_string_ref name; 26 | 27 | for (cql_int32 i = 0; i < get_mixed_result_count(result_set); i++) { 28 | id = get_mixed_get_id(result_set, i); 29 | b_is_null = get_mixed_get_flag_is_null(result_set, i); 30 | b_value = get_mixed_get_flag_value(result_set, i); 31 | code_is_null = get_mixed_get_code_is_null(result_set, i); 32 | code_value = get_mixed_get_code_value(result_set, i); 33 | name = get_mixed_get_name(result_set, i); 34 | 35 | printf("%s: row %d) %d %d %d %d %lld %s\n", label, i, id, b_is_null, b_value, code_is_null, code_value, name->ptr); 36 | } 37 | } 38 | 39 | int main(int argc, char **argv) { 40 | printf("CQL data access demo: creating and reading from a table\n"); 41 | 42 | sqlite3 *db = NULL; 43 | SQL_E(sqlite3_open(":memory:", &db)); 44 | 45 | get_mixed_result_set_ref result_set; 46 | get_mixed_result_set_ref result_set_copy; 47 | get_mixed_result_set_ref result_set_updated; 48 | cql_int32 count = 5; 49 | cql_int32 copy_index = 1; 50 | cql_int32 copy_count = 3; 51 | 52 | SQL_E(make_mixed(db)); 53 | SQL_E(load_mixed(db)); 54 | SQL_E(get_mixed_fetch_results(db, &result_set, count)); 55 | get_mixed_copy(result_set, &result_set_copy, copy_index, copy_count); 56 | SQL_E(update_mixed(db, get_mixed_get_id(result_set, 0), 1234.5)); 57 | SQL_E(get_mixed_fetch_results(db, &result_set_updated, count)); 58 | 59 | cql_int32 result_set_count = get_mixed_result_count(result_set); 60 | E(result_set_count == count); 61 | 62 | cql_int32 result_set_copy_count = get_mixed_result_count(result_set_copy); 63 | E(result_set_copy_count == copy_count); 64 | 65 | print_result_set("result_set", result_set); 66 | print_result_set("result_set_copy", result_set_copy); 67 | print_result_set("result_set_updated", result_set_updated); 68 | 69 | for (cql_int32 i = 0; i < copy_count; ++i) { 70 | E(get_mixed_row_equal(result_set, copy_index + i, result_set_copy, i)); 71 | } 72 | 73 | E(get_mixed_row_same(result_set, 0, result_set_updated, 0)); 74 | E(get_mixed_row_same(result_set, 1, result_set_updated, 1)); 75 | E(!get_mixed_row_same(result_set, 0, result_set_updated, 1)); 76 | 77 | cql_result_set_release(result_set); 78 | cql_result_set_release(result_set_copy); 79 | 80 | SQL_E(mandelbrot(db)); 81 | return 0; 82 | 83 | error: 84 | return 1; 85 | } 86 | -------------------------------------------------------------------------------- /sources/diags.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // enable lots of extra warnings for cql 9 | 10 | #pragma clang diagnostic error "-Wall" 11 | 12 | // in case your compiler doesn't have some of the below 13 | #pragma clang diagnostic ignored "-Wunknown-warning-option" 14 | 15 | #pragma clang diagnostic error "-Wduplicate-method-match" 16 | #pragma clang diagnostic error "-Wparentheses" 17 | #pragma clang diagnostic error "-Wreturn-type" 18 | #pragma clang diagnostic error "-Wshadow" 19 | #pragma clang diagnostic error "-Wunguarded-availability" 20 | #pragma clang diagnostic error "-Wuninitialized" 21 | #pragma clang diagnostic error "-Wunknown-pragmas" 22 | #pragma clang diagnostic error "-Wimplicit-int-conversion" 23 | #pragma clang diagnostic error "-Wshorten-64-to-32" 24 | #pragma clang diagnostic error "-Wsign-conversion" 25 | #pragma clang diagnostic error "-Wconversion" 26 | 27 | #ifdef NDEBUG 28 | // Many symbols are "unused" becuase they only appear in asserts, so we have to suppress 29 | // those warnings in a non-debug build. 30 | #pragma clang diagnostic ignored "-Wunused-variable" 31 | #pragma clang diagnostic ignored "-Wunused-function" 32 | #else 33 | // The debug build should be clean 34 | #pragma clang diagnostic error "-Wunused-variable" 35 | #pragma clang diagnostic error "-Wunused-function" 36 | #endif 37 | 38 | #ifndef __clang__ 39 | #ifndef _Nonnull 40 | /* Hide Clang-only nullability specifiers if not Clang */ 41 | #define _Nonnull 42 | #define _Nullable 43 | #endif 44 | #endif 45 | 46 | #if defined(CQL_AMALGAM_LEAN) 47 | // in this version there are going to be unused stubs a-plenty 48 | #pragma clang diagnostic ignored "-Wunused-function" 49 | #pragma clang diagnostic ignored "-Wunused-variable" 50 | #endif 51 | -------------------------------------------------------------------------------- /sources/dotpng.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | ./out/cql --dot < "$1" > "out/$1.dot" || exit 1 8 | dot "out/$1.dot" -Tpng -o "out/$1.png" || exit 1 9 | echo "Created out/$1.dot and made out/$1.png with it." 10 | open "out/$1.png" 11 | -------------------------------------------------------------------------------- /sources/encoders.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | // string literal swizzlers 11 | 12 | #define PRETTY_QUOTE_SINGLE_LINE 0 13 | #define PRETTY_QUOTE_MULTI_LINE 1 14 | #define PRETTY_QUOTE_C 0 15 | #define PRETTY_QUOTE_JSON 2 16 | 17 | cql_noexport void cg_decode_string_literal(CSTR _Nonnull str, charbuf *_Nonnull output); 18 | cql_noexport void cg_encode_string_literal(CSTR _Nonnull str, charbuf *_Nonnull output); 19 | cql_noexport void cg_encode_char_as_c_string_literal(char c, charbuf *_Nonnull output); 20 | cql_noexport void cg_encode_char_as_json_string_literal(char c, charbuf *_Nonnull output); 21 | 22 | cql_noexport void cg_encode_json_string_literal(CSTR _Nonnull str, charbuf *_Nonnull output); 23 | cql_noexport void cg_encode_c_string_literal(CSTR _Nonnull str, charbuf *_Nonnull output); 24 | cql_noexport void cg_decode_c_string_literal(CSTR _Nonnull str, charbuf *_Nonnull output); 25 | cql_noexport void cg_pretty_quote_plaintext(CSTR _Nonnull str, charbuf *_Nonnull output, uint32_t flags); 26 | cql_noexport void cg_remove_slash_star_and_star_slash(charbuf *_Nonnull b); 27 | cql_noexport void cg_pretty_quote_compressed_text(CSTR _Nonnull str, charbuf *_Nonnull output); 28 | -------------------------------------------------------------------------------- /sources/eval.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #if defined(CQL_AMALGAM_LEAN) && !defined(CQL_AMALGAM_SEM) 11 | 12 | // minimal stuff goes here (none at this point) 13 | 14 | #else 15 | 16 | #include "ast.h" 17 | #include "bytebuf.h" 18 | #include "symtab.h" 19 | #include "charbuf.h" 20 | #include "list.h" 21 | #include "sem.h" 22 | 23 | #define EVAL_NIL {0, 0, 0, 0, false} 24 | 25 | #define EVAL_FORMAT_NORMAL 1 26 | #define EVAL_FORMAT_FOR_C 2 27 | #define EVAL_FORMAT_FOR_LUA 3 28 | 29 | typedef struct eval_node { 30 | sem_t sem_type; 31 | int64_t int64_value; 32 | int32_t int32_value; 33 | double real_value; 34 | bool_t bool_value; 35 | } eval_node; 36 | 37 | cql_noexport void eval_init(); 38 | cql_noexport void eval_cleanup(); 39 | cql_noexport void eval(ast_node *_Nonnull expr, eval_node *_Nonnull result); 40 | cql_noexport ast_node *_Nonnull eval_set(ast_node *_Nonnull expr, eval_node *_Nonnull result); 41 | cql_noexport void eval_cast_to(eval_node *_Nonnull result, sem_t sem_type); 42 | cql_noexport void eval_add_one(eval_node *_Nonnull result); 43 | cql_noexport void eval_format_number(eval_node *_Nonnull result, int32_t format_mode, charbuf *_Nonnull output); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /sources/grammar_docs/diagram_tweaks.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # First we get rid of all of the versions of the operators that do not have NOT 7 | 8 | s/math_expr "BETWEEN" math_expr "AND" math_expr \|// 9 | s/math_expr "IS" math_expr \|// 10 | s/math_expr "LIKE" math_expr \|// 11 | s/math_expr "MATCH" math_expr \|// 12 | s/math_expr "GLOB" math_expr \|// 13 | s/math_expr "REGEXP" math_expr \|// 14 | s/math_expr "IN" '(' expr_list ')' \|// 15 | s/math_expr "IN" '(' select_stmt ')' \|// 16 | s/math_expr "IS TRUE" \|// 17 | s/math_expr "IS FALSE" \|// 18 | 19 | # then we make all the NOT versions have optional NOT 20 | 21 | s/math_expr "IS NOT" /math_expr "IS" "NOT" ? /g 22 | s/math_expr "IS NOT TRUE"/math_expr "IS" "NOT" ? "TRUE"/g 23 | s/math_expr "IS NOT FALSE"/math_expr "IS" "NOT" ? "FALSE"/g 24 | s/math_expr "NOT BETWEEN"/math_expr "NOT" ? "BETWEEN"/ 25 | s/math_expr "NOT LIKE"/math_expr "NOT" ? "LIKE"/ 26 | s/math_expr "NOT MATCH"/math_expr "NOT" ? "MATCH"/ 27 | s/math_expr "NOT GLOB"/math_expr "NOT" ? "GLOB"/ 28 | s/math_expr "NOT REGEXP"/math_expr "NOT" ? "REGEXP"/ 29 | s/math_expr "NOT IN" '(' /math_expr "NOT" ? "IN" '(' /g 30 | -------------------------------------------------------------------------------- /sources/grammar_docs/make_json_grammar.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # exit when any command fails 8 | set -e 9 | 10 | # move to the location of the script for a fixed reference 11 | DIR="$( dirname -- "$0"; )" 12 | cd "${DIR}" || exit 13 | 14 | echo compiling yacc stripper 15 | (cd ..; make out/ys) 16 | 17 | echo compiling replacements 18 | (cd ..; make out/json_replacements) 19 | 20 | echo stripping JSON grammar 21 | ../out/ys <../json_test/json_test.y | sed -e "/^ *$/d" | ../out/json_replacements | sed -e 's/ *$//' >json.txt 22 | 23 | echo formatting for railroad tool 24 | 25 | awk json_grammar.txt 28 | 29 | echo "railroad diagram format in json_grammar.txt (paste into https://www.bottlecaps.de/rr/ui)" 30 | 31 | cat <json_grammar.md 32 | --- 33 | id: x5 34 | title: "Appendix 5: JSON Schema Grammar" 35 | sidebar_label: "Appendix 5: JSON Schema Grammar" 36 | --- 37 | 43 | 44 | What follows is taken from the JSON validation grammar with the tree building rules removed. 45 | 46 | EOF 47 | 48 | echo "Snapshot as of $(date)" >>json_grammar.md 49 | 50 | cat <>json_grammar.md 51 | 52 | ### Rules 53 | 54 | EOF 55 | 56 | echo '```' >>json_grammar.md 57 | cat json.txt >>json_grammar.md 58 | echo '```' >>json_grammar.md 59 | 60 | echo wiki format in json_grammar.md 61 | 62 | echo cleanup 63 | rm json.txt 64 | -------------------------------------------------------------------------------- /sources/java_demo/CGSQLMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import com.facebook.cgsql.CQLResultSet; 9 | import java.nio.charset.StandardCharsets; 10 | import sample.*; 11 | 12 | public class CGSQLMain { 13 | public static void main(String[] args) { 14 | TestResult.open(); 15 | 16 | // get result set handle 17 | long handle = TestResult.getTestResult(); 18 | 19 | // make the sample result set 20 | Sample.SampleViewModel data = new Sample.SampleViewModel(new CQLResultSet(handle)); 21 | 22 | // use the results 23 | dumpResults(data); 24 | 25 | // release the connection 26 | TestResult.close(); 27 | } 28 | 29 | public static void dumpResults(Sample.SampleViewModel data) { 30 | System.out.println("Dumping Results"); 31 | int count = data.getCount(); 32 | System.out.println(String.format("count = %d", count)); 33 | 34 | for (int i = 0; i < count; i++) { 35 | byte[] bytes = data.get_bytes(i); 36 | String s = new String(bytes, StandardCharsets.UTF_8); 37 | System.out.println( 38 | String.format( 39 | "Row %d: name:%s blob:%s age:%d(encoded = %s) thing:%f key1:%s key2:%s(encoded = %s)", 40 | i, 41 | data.get_name(i), 42 | s, 43 | data.get_age(i), 44 | Boolean.toString(data.get_age_IsEncoded()), 45 | data.get_thing(i), 46 | data.get_key1(i), 47 | data.get_key2(i), 48 | Boolean.toString(data.get_key2_IsEncoded()))); 49 | 50 | Sample.ChildViewModel child = new Sample.ChildViewModel(data.get_my_child_result(i)); 51 | for (int j = 0; j < child.getCount(); j++) { 52 | System.out.println( 53 | String.format("--> Child Row %d: x:%d y:%s", j, child.get_x(j), child.get_y(j))); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /sources/java_demo/README.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | # Java/JNI Example 9 | 10 | These files serve to illustrate how you can interoperate with CQL generated 11 | code in Java. 12 | 13 | * `./CGSQLMain.java` 14 | 15 | This is just a simple main program that creates the result set and then prints it out. 16 | It's not especially reusable but we need a main so here it is. 17 | 18 | 19 | * `./TestResult.c` 20 | * `./TestResult.h` 21 | * `./TestResult.java` 22 | 23 | This is the JNI class that runs the particular stored procedure we need in this 24 | sample. See Sample.sql below. The native code has to 25 | * open a database 26 | * call the stored procedure with any args (there are none other than the database in this example) 27 | * for any real code this would need to be generalized 28 | * close the database 29 | 30 | The general purpose classes and the compiler output concern themselves with 31 | allowing result sets to be accessed from Java. There is no general way to 32 | invoke stored procedures with arbitrary signatures at this time. Though you could 33 | imagine using the JSON output to codegen JNI wrappers as well as result set 34 | readers. This area is ripe for future development to make Java access easier. 35 | 36 | * `./com_facebook_cgsql_CQLResultSet.c` 37 | * `./com_facebook_cgsql_CQLResultSet.h` 38 | * `./com/facebook/cgsql/CQLResultSet.java` 39 | * `./com/facebook/cgsql/CQLViewModel.java` 40 | 41 | These are the re-usable parts. `CQLResultSet` uses standard JNI methods to 42 | read the primitive types out of any result set. The compiler produce a subclass 43 | of `CQLViewModel` that uses `CQLResultSet` to do its job. The JNI C file 44 | `com_facebook_cgsql_CQLResultSet.c` has the necessary calls to the runtime to 45 | do that reading. Each of the functions is just a few lines of code. The `.h` file 46 | is auto-generated by `java -h` from the .java and hence doesn't actually need 47 | to be checked in but it's included because it's useful to browse without 48 | building and any diffs might be interesting in further porting efforts. 49 | 50 | * `./Sample.sql` 51 | 52 | This is is a stored procedure that creates a table, puts stuff in it, and then returns 53 | its contents. This is in some sense the core of the demo. Everything else is 54 | scaffolding. 55 | 56 | * `./make.sh` 57 | * `./clean.sh` 58 | 59 | Use `make.sh` to build and execute the JNI demo. Use `clean.sh` to clean up 60 | the build artifacts afterwards. 61 | 62 | Build notes: 63 | 64 | * set `CGSQL_GCC=1` if you're using GCC rather than clang 65 | * set `JAVA_HOME` to the location of your JDK, for `jni.h` and friends. 66 | * set `SQLITE_PATH` to the location of your SQLite installation if you want to use an amalgam build of SQLITE rather than just use `-lsqlite3` 67 | 68 | `make.sh` is itself pretty straightforward 69 | -------------------------------------------------------------------------------- /sources/java_demo/Sample.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- Any kind of child result set will do the job for this test 9 | -- note that with the json based code generation you can have 10 | -- as many procs per file as you like. 11 | create proc Child(i integer not null) 12 | begin 13 | declare C cursor like (x integer not null, y text not null); 14 | let j := 0; 15 | while j < i 16 | begin 17 | set j := j + 1; 18 | fetch C using 19 | j x, 20 | printf("<< %d >>", j) y; 21 | out union C; 22 | end; 23 | end; 24 | 25 | /* this is a demo procedure, it's rather silly... */ 26 | @attribute(cql:vault_sensitive) 27 | @attribute(cql:custom_type_for_encoded_column) 28 | create proc Sample() 29 | begin 30 | /* add the table we will be using */ 31 | create table my_data( 32 | name text, 33 | age integer @sensitive, 34 | thing real, 35 | bytes blob, 36 | key1 text, 37 | key2 text @sensitive); 38 | 39 | /* insert some data */ 40 | declare i integer not null; 41 | set i := 0; 42 | while (i < 5) 43 | begin 44 | /* avoiding @dummy_seed even though it's perfect here just so that 45 | * we don't take a dependency on the printf sqlite function. If 46 | * your sqlite is very old you won't have that and we don't want the 47 | * JNI test to fail just because of a printf 48 | */ 49 | insert into my_data using 50 | "name_"||i AS name, 51 | i AS age, 52 | i AS thing, 53 | cast("blob_"||i as blob) AS bytes, 54 | "code_1"||i AS key1, 55 | "code_2"||i AS key2; 56 | set i := i + 1; 57 | end; 58 | 59 | set i := 0; 60 | /* the result will have a variety of data types to exercise the JNI helpers */ 61 | declare C cursor for select * from my_data; 62 | loop fetch C 63 | begin 64 | declare result cursor like (like C, my_child_result object); 65 | fetch result from values(from C, Child(i)); 66 | out union result; 67 | set i := i + 1; 68 | end; 69 | end; 70 | -------------------------------------------------------------------------------- /sources/java_demo/TestResult.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "TestResult.h" 9 | #include "cqlrt.h" 10 | #include "Sample.h" 11 | 12 | static sqlite3 * _db; 13 | 14 | /* 15 | * Class: TestResult 16 | * Method: open 17 | * Signature: ()I 18 | */ 19 | JNIEXPORT jint JNICALL Java_TestResult_open(JNIEnv *env, jclass thiz) { 20 | return sqlite3_open(":memory:", &_db); 21 | } 22 | 23 | /* 24 | * Class: TestResult 25 | * Method: getTestResult 26 | * Signature: ()J 27 | */ 28 | JNIEXPORT jlong JNICALL Java_TestResult_getTestResult(JNIEnv *env, jclass thiz) { 29 | Sample_result_set_ref result_set; 30 | cql_code rc = Sample_fetch_results(_db, &result_set); 31 | if (rc) return 0; 32 | return (jlong)result_set; 33 | } 34 | 35 | /* 36 | * Class: TestResult 37 | * Method: close 38 | * Signature: ()V 39 | */ 40 | JNIEXPORT void JNICALL Java_TestResult_close(JNIEnv *env, jclass thiz) { 41 | sqlite3_close(_db); 42 | _db = NULL; 43 | } 44 | -------------------------------------------------------------------------------- /sources/java_demo/TestResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | public final class TestResult { 9 | static { 10 | System.loadLibrary("TestResult"); 11 | } 12 | 13 | public static native int open(); 14 | 15 | public static native long getTestResult(); 16 | 17 | public static native void close(); 18 | } 19 | -------------------------------------------------------------------------------- /sources/java_demo/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | rm -f CGSQLMain.class 8 | rm -f CQLResultSet.java 9 | rm -f TestResult.h 10 | rm -f TestResult.class 11 | rm -f TestResult.o 12 | rm -f com/facebook/cgsql/CQLResultSet.class 13 | rm -f com/facebook/cgsql/CQLViewModel.class 14 | rm -f com/facebook/cgsql/EncodedString.class 15 | rm -f com_facebook_cgsql_CQLResultSet.h 16 | rm -f com_facebook_cgsql_CQLResultSet.o 17 | rm -f Sample.c 18 | rm -f Sample.h 19 | rm -f Sample.o 20 | rm -f Sample.pre 21 | rm -rf sample 22 | rm -rf child 23 | rm -f sqlite3-all.o 24 | rm -rf libCQLResultSet* 25 | rm -rf libTestResult* 26 | -------------------------------------------------------------------------------- /sources/java_demo/com/facebook/cgsql/CQLViewModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package com.facebook.cgsql; 9 | 10 | /** 11 | * Super class extended by all CQL based view models. 12 | * 13 | *

YOU CANNOT USE THIS CLASS DIRECTLY 14 | * 15 | *

This class is only meant to be used directly by generated code, so any other code that depends 16 | * on this class directly is considered invalid and could break anytime without further notice. 17 | */ 18 | public abstract class CQLViewModel { 19 | protected CQLResultSet mResultSet; 20 | 21 | public CQLViewModel(CQLResultSet resultSet) { 22 | mResultSet = resultSet; 23 | } 24 | 25 | public long rowHashCode(int row) { 26 | return mResultSet.rowHashCode(row); 27 | } 28 | 29 | public boolean rowsEqual(int row1, CQLViewModel rs2, int row2) { 30 | return mResultSet.rowsEqual(row1, rs2.mResultSet, row2); 31 | } 32 | 33 | public boolean rowsSame(int row1, CQLViewModel rs2, int row2) { 34 | if (!hasIdentityColumns()) { 35 | return false; 36 | } 37 | return mResultSet.rowsSame(row1, rs2.mResultSet, row2); 38 | } 39 | 40 | protected abstract boolean hasIdentityColumns(); 41 | } 42 | -------------------------------------------------------------------------------- /sources/java_demo/com/facebook/cgsql/EncodedString.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package com.facebook.cgsql; 9 | 10 | /** 11 | * EncodedString is a simple class that encapsulates the encoded string from a ResultSet to restrict 12 | * and control its access 13 | * 14 | *

It has no getter so it hides the encoded string. 15 | * 16 | *

Use case: You could add a method to this class that takes as parameter a TextView and write a 17 | * decoded value of the encoded string directly to the TextView. Like that only the TextView get to 18 | * have the decode value of the encoded string. 19 | */ 20 | public class EncodedString { 21 | public String mValue; 22 | 23 | public EncodedString(String value) { 24 | mValue = value; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sources/linetester/linetest.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "cqlrt.h" 11 | 12 | 13 | // Generated from linetest.sql:39 14 | extern CQL_WARN_UNUSED cql_code linetest_setup(sqlite3 *_Nonnull _db_); 15 | 16 | // Generated from linetest.sql:46 17 | extern CQL_WARN_UNUSED cql_code linetest_add(sqlite3 *_Nonnull _db_, cql_string_ref _Nonnull source_, cql_string_ref _Nonnull procname_, cql_int32 line_, cql_string_ref _Nonnull data_, cql_int32 physical_line_); 18 | 19 | // Generated from linetest.sql:55 20 | extern CQL_WARN_UNUSED cql_code linetest_dump(sqlite3 *_Nonnull _db_); 21 | 22 | // Generated from linetest.sql:64 23 | extern CQL_WARN_UNUSED cql_code dump_proc_records(sqlite3 *_Nonnull _db_, cql_string_ref _Nonnull source_, cql_string_ref _Nonnull procname_); 24 | 25 | // Generated from linetest.sql:73 26 | extern CQL_WARN_UNUSED cql_code dump(sqlite3 *_Nonnull _db_, cql_string_ref _Nonnull procname); 27 | 28 | // Generated from linetest.sql:134 29 | extern CQL_WARN_UNUSED cql_code compare_lines(sqlite3 *_Nonnull _db_, cql_int32 *_Nonnull procs, cql_int32 *_Nonnull compares, cql_int32 *_Nonnull errors); 30 | -------------------------------------------------------------------------------- /sources/linetester/regen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # @licenselint-loose-mode 8 | 9 | set -euo pipefail 10 | 11 | pushd .. 12 | make clean && make 13 | popd 14 | 15 | ../out/cql --nolines --in linetest.sql --cg linetest.h linetest.c 16 | 17 | # We do all this so that we can normalize the generated helper. We 18 | # want the same header shape with the OSS version of CQL and the 19 | # internal and they have different copyright messages. The 20 | # test helper is part of the OSS. 21 | 22 | sed -e "/autogenerated/d" \ 23 | -e "/generated SignedSource/d" \ 24 | -e "/(c).*Meta Platforms/d" linetest.c2 25 | 26 | sed -e "/autogenerated/d" \ 27 | -e "/generated SignedSource/d" \ 28 | -e "/(c).*Meta Platforms/d" linetest.h2 29 | 30 | (cat <linetest.c 31 | /* 32 | * Copyright (c) Meta Platforms, Inc. and affiliates. 33 | * 34 | * This source code is licensed under the MIT license found in the 35 | * LICENSE file in the root directory of this source tree. 36 | */ 37 | EOF 38 | 39 | (cat <linetest.h 40 | /* 41 | * Copyright (c) Meta Platforms, Inc. and affiliates. 42 | * 43 | * This source code is licensed under the MIT license found in the 44 | * LICENSE file in the root directory of this source tree. 45 | */ 46 | EOF 47 | 48 | rm linetest.h2 linetest.c2 49 | -------------------------------------------------------------------------------- /sources/list.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // super simple linked list handlers 9 | 10 | #include "cql.h" 11 | #include "ast.h" 12 | #include "list.h" 13 | 14 | cql_noexport void add_item_to_list(list_item **head, struct ast_node *ast) { 15 | list_item *item = _ast_pool_new(list_item); 16 | item->next = *head; 17 | item->ast = ast; 18 | *head = item; 19 | } 20 | 21 | cql_noexport void reverse_list(list_item **head) { 22 | list_item *cur = *head; 23 | list_item *prev = NULL; 24 | list_item *next = NULL; 25 | 26 | while (cur) { 27 | next = cur->next; 28 | cur->next = prev; 29 | prev = cur; 30 | cur = next; 31 | } 32 | *head = prev; 33 | } 34 | -------------------------------------------------------------------------------- /sources/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // super simple linked list handlers 9 | 10 | #pragma once 11 | 12 | // no need to free this list anymore minipool will do it for 13 | // you automatically at the end of a CQL run. 14 | // @see minipool 15 | typedef struct list_item { 16 | struct ast_node *ast; 17 | struct list_item *next; 18 | } list_item; 19 | 20 | cql_noexport void add_item_to_list(list_item **head, struct ast_node *ast); 21 | cql_noexport void reverse_list(list_item **head); 22 | -------------------------------------------------------------------------------- /sources/lua_demo/README: -------------------------------------------------------------------------------- 1 | demo.sh can be run from this directory 2 | 3 | run_test.sh should be run from the main sources directory 4 | 5 | the main test script does not execute lua code because that would require assumptions about 6 | lua install that we are not yet willing to make 7 | -------------------------------------------------------------------------------- /sources/lua_demo/demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | set -euo pipefail 8 | 9 | DIR="$( dirname -- "$0"; )" 10 | cd "${DIR}" || exit 11 | 12 | set -e 13 | 14 | O="../out" 15 | cp ../cqlrt.lua $O 16 | 17 | echo test1 18 | $O/cql --in t1.sql --cg $O/x.l --rt lua 19 | (cd $O ; lua $O/x.l) 20 | echo test2 21 | $O/cql --in t2.sql --cg $O/x.l --rt lua 22 | (cd $O ; lua $O/x.l) 23 | echo test3 24 | $O/cql --in t3.sql --cg $O/x.l --rt lua 25 | (cd $O ; lua $O/x.l) 26 | echo test4 27 | $O/cql --in t4.sql --cg $O/x.l --rt lua 28 | (cd $O ; lua $O/x.l) 29 | echo test5 30 | $O/cql --in t5.sql --cg $O/x.l --rt lua 31 | (cd $O ; lua $O/x.l) 32 | echo test6 33 | $O/cql --in t6.sql --cg $O/x.l --rt lua 34 | (cd $O ; lua $O/x.l) 35 | echo demo 36 | $O/cql --in demo.sql --cg $O/x.l --rt lua 37 | (cd $O ; lua $O/x.l) 38 | 39 | echo "" 40 | echo "run test (NOTE: some exception spam is normal, the tests throwing exceptions on purpose)" 41 | echo "" 42 | 43 | ./run_test.sh 44 | -------------------------------------------------------------------------------- /sources/lua_demo/demo.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- demo stored procs 9 | 10 | DECLARE PROC printf NO CHECK; 11 | 12 | CREATE PROC make_mixed () 13 | BEGIN 14 | CREATE TABLE mixed( 15 | id INTEGER NOT NULL, 16 | name TEXT, 17 | code LONG_INT, 18 | flag BOOL, 19 | rate REAL 20 | ); 21 | END; 22 | 23 | CREATE PROC load_mixed () 24 | BEGIN 25 | DELETE FROM mixed; 26 | INSERT INTO mixed VALUES(1, 'a name', 12, 1, 5.0); 27 | INSERT INTO mixed VALUES(2, 'some name', 14, 3, 7.0); 28 | INSERT INTO mixed VALUES(3, 'yet another name', 15, 3, 17.4); 29 | INSERT INTO mixed VALUES(4, 'some name', 19, 4, 9.1); 30 | INSERT INTO mixed VALUES(5, 'what name', 21, 8, 12.3); 31 | END; 32 | 33 | CREATE PROC update_mixed (id_ INTEGER NOT NULL, rate_ REAL NOT NULL) 34 | BEGIN 35 | UPDATE mixed 36 | SET rate = rate_ 37 | WHERE id = id_; 38 | END; 39 | 40 | CREATE PROC get_mixed (lim INTEGER NOT NULL) 41 | BEGIN 42 | SELECT * FROM mixed ORDER BY id 43 | LIMIT lim; 44 | END; 45 | 46 | CREATE PROC mandelbrot () 47 | BEGIN 48 | DECLARE C CURSOR FOR WITH RECURSIVE 49 | xaxis (x) AS ( SELECT -2.0 UNION ALL SELECT x + 0.05 FROM xaxis WHERE x < 1.2), 50 | yaxis (y) AS ( SELECT -1.0 UNION ALL SELECT y + 0.1 FROM yaxis WHERE y < 1.0), 51 | m (iter, cx, cy, x, y) AS ( 52 | SELECT 0 AS iter, x AS cx, y AS cy, 0.0 AS x, 0.0 AS y 53 | FROM xaxis, yaxis 54 | UNION ALL 55 | SELECT iter + 1 AS iter, cx, cy, x * x - y * y + cx AS x, 2.0 * x * y + cy AS y 56 | FROM m 57 | WHERE m.x * m.x + m.y * m.y < 4.0 AND m.iter < 28), 58 | m2 (iter, cx, cy) AS ( 59 | SELECT max(iter), cx, cy 60 | FROM m 61 | GROUP BY cx, cy), 62 | a (t) AS ( 63 | SELECT group_concat(substr(' .+*#', 1 + min(iter / 7, 4), 1), '') 64 | FROM m2 65 | GROUP BY cy) 66 | SELECT group_concat(rtrim(t), "\n") AS line 67 | FROM a; 68 | 69 | LOOP FETCH C 70 | BEGIN 71 | CALL printf("%s\n", C.line); 72 | END; 73 | END; 74 | 75 | create proc print_mixed() 76 | begin 77 | declare C cursor for call get_mixed(50); 78 | loop fetch C 79 | begin 80 | call printf("%d %s %lld %lld %f\n", C.id, C.name, C.code, C.flag, C.rate); 81 | end; 82 | end; 83 | 84 | create proc go() 85 | begin 86 | call make_mixed(); 87 | call load_mixed(); 88 | call print_mixed(); 89 | call printf("\nupdating mixed values 3 and 4\n"); 90 | call update_mixed(3, 999.99); 91 | call update_mixed(4, 199.99); 92 | call print_mixed(); 93 | call mandelbrot(); 94 | end; 95 | 96 | @echo lua, "function printf(...) io.write(cql_printf(...)) end\n"; 97 | @echo lua, "go(sqlite3.open_memory())\n"; 98 | -------------------------------------------------------------------------------- /sources/lua_demo/lua_upgrade1.ref: -------------------------------------------------------------------------------- 1 | reference results for version 1 2 | 3 | ----- extra_index ----- 4 | 5 | type: index 6 | tbl_name: g1 7 | CREATE INDEX extra_index ON g1 ( 8 | id) 9 | 10 | ----- extra_trigger ----- 11 | 12 | type: trigger 13 | tbl_name: g1 14 | CREATE TRIGGER extra_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END 15 | 16 | ----- extra_view ----- 17 | 18 | type: view 19 | tbl_name: extra_view 20 | CREATE VIEW extra_view AS SELECT id, 21 | name FROM g1 22 | 23 | ----- g1 ----- 24 | 25 | type: table 26 | tbl_name: g1 27 | CREATE TABLE g1( 28 | id INTEGER PRIMARY KEY, 29 | name TEXT) 30 | 31 | ----- lua_upgrade_cql_schema_facets ----- 32 | 33 | type: table 34 | tbl_name: lua_upgrade_cql_schema_facets 35 | CREATE TABLE lua_upgrade_cql_schema_facets( 36 | facet TEXT NOT NULL PRIMARY KEY, 37 | version LONG_INT NOT NULL) 38 | 39 | ----- sqlite_autoindex_lua_upgrade_cql_schema_facets_1 ----- 40 | 41 | type: index 42 | tbl_name: lua_upgrade_cql_schema_facets 43 | 44 | ----- staying_index ----- 45 | 46 | type: index 47 | tbl_name: g1 48 | CREATE INDEX staying_index ON g1 ( 49 | id) 50 | 51 | ----- staying_trigger ----- 52 | 53 | type: trigger 54 | tbl_name: g1 55 | CREATE TRIGGER staying_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END 56 | 57 | ----- staying_view ----- 58 | 59 | type: view 60 | tbl_name: staying_view 61 | CREATE VIEW staying_view AS SELECT id, 62 | name FROM g1 63 | 64 | ----- test_create_table_A ----- 65 | 66 | type: table 67 | tbl_name: test_create_table_A 68 | CREATE TABLE test_create_table_A( 69 | colA INTEGER, 70 | colB LONG_INT, 71 | colC TEXT, 72 | colD TEXT) 73 | 74 | ----- test_create_table_B ----- 75 | 76 | type: table 77 | tbl_name: test_create_table_B 78 | CREATE TABLE test_create_table_B( 79 | colA TEXT, 80 | colB LONG_INT, 81 | colC INTEGER) 82 | 83 | ----- test_recreate_table_A ----- 84 | 85 | type: table 86 | tbl_name: test_recreate_table_A 87 | CREATE TABLE test_recreate_table_A( 88 | colA INTEGER, 89 | colC TEXT, 90 | colD TEXT) 91 | 92 | ----- test_recreate_table_B ----- 93 | 94 | type: table 95 | tbl_name: test_recreate_table_B 96 | CREATE TABLE test_recreate_table_B( 97 | colA INTEGER, 98 | colB LONG_INT, 99 | colC INTEGER) 100 | 101 | ----- test_this_table_will_become_create ----- 102 | 103 | type: table 104 | tbl_name: test_this_table_will_become_create 105 | CREATE TABLE test_this_table_will_become_create( 106 | id INTEGER PRIMARY KEY) 107 | 108 | ----- use_g1 ----- 109 | 110 | type: table 111 | tbl_name: use_g1 112 | CREATE TABLE use_g1( 113 | id INTEGER PRIMARY KEY REFERENCES g1 ( 114 | id), 115 | name2 TEXT) 116 | 117 | -------------------------------------------------------------------------------- /sources/lua_demo/lua_upgrade3.ref: -------------------------------------------------------------------------------- 1 | reference results for version 3 2 | 3 | ----- extra_index ----- 4 | 5 | type: index 6 | tbl_name: g1 7 | CREATE INDEX extra_index ON g1 ( 8 | id) 9 | 10 | ----- extra_trigger ----- 11 | 12 | type: trigger 13 | tbl_name: g1 14 | CREATE TRIGGER extra_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END 15 | 16 | ----- extra_view ----- 17 | 18 | type: view 19 | tbl_name: extra_view 20 | CREATE VIEW extra_view AS SELECT id, 21 | name FROM g1 22 | 23 | ----- g1 ----- 24 | 25 | type: table 26 | tbl_name: g1 27 | CREATE TABLE g1( 28 | id INTEGER PRIMARY KEY, 29 | name TEXT) 30 | 31 | ----- gChild ----- 32 | 33 | type: table 34 | tbl_name: gChild 35 | CREATE TABLE gChild( 36 | id INTEGER PRIMARY KEY REFERENCES gParent ( 37 | id)) 38 | 39 | ----- gParent ----- 40 | 41 | type: table 42 | tbl_name: gParent 43 | CREATE TABLE gParent( 44 | id INTEGER PRIMARY KEY) 45 | 46 | ----- lua_upgrade_cql_schema_facets ----- 47 | 48 | type: table 49 | tbl_name: lua_upgrade_cql_schema_facets 50 | CREATE TABLE lua_upgrade_cql_schema_facets( 51 | facet TEXT NOT NULL PRIMARY KEY, 52 | version LONG_INT NOT NULL) 53 | 54 | ----- sqlite_autoindex_lua_upgrade_cql_schema_facets_1 ----- 55 | 56 | type: index 57 | tbl_name: lua_upgrade_cql_schema_facets 58 | 59 | ----- staying_index ----- 60 | 61 | type: index 62 | tbl_name: g1 63 | CREATE INDEX staying_index ON g1 ( 64 | id) 65 | 66 | ----- staying_trigger ----- 67 | 68 | type: trigger 69 | tbl_name: g1 70 | CREATE TRIGGER staying_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END 71 | 72 | ----- staying_view ----- 73 | 74 | type: view 75 | tbl_name: staying_view 76 | CREATE VIEW staying_view AS SELECT id, 77 | name FROM g1 78 | 79 | ----- test_create_table_C ----- 80 | 81 | type: table 82 | tbl_name: test_create_table_C 83 | CREATE TABLE test_create_table_C( 84 | colA TEXT, 85 | colB LONG_INT, 86 | colC LONG_INT) 87 | 88 | ----- test_recreate_table_B ----- 89 | 90 | type: table 91 | tbl_name: test_recreate_table_B 92 | CREATE TABLE test_recreate_table_B( 93 | colA INTEGER, 94 | colB LONG_INT, 95 | colC INTEGER) 96 | 97 | ----- test_view ----- 98 | 99 | type: view 100 | tbl_name: test_view 101 | CREATE VIEW test_view AS SELECT colA, 102 | colB FROM test_create_table_C 103 | 104 | ----- use_g1 ----- 105 | 106 | type: table 107 | tbl_name: use_g1 108 | CREATE TABLE use_g1( 109 | id INTEGER PRIMARY KEY REFERENCES g1 ( 110 | id), 111 | name2 TEXT) 112 | 113 | -------------------------------------------------------------------------------- /sources/lua_demo/prepare_run_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | set -euo pipefail 8 | 9 | make 10 | rm -f out/x.l out/run_test.lua 11 | cc -DLUA_RUN_TEST -E -x c test/run_test.sql >out/lua_run_test.sql 2>out/lua_preprocess.errs 12 | out/cql --in out/lua_run_test.sql --cg out/run_test_core.lua --rt lua --global_proc go 13 | 14 | cat lua_demo/test_helpers.lua out/run_test_core.lua >out/run_test.lua 15 | echo "go(sqlite3.open_memory())" >>out/run_test.lua 16 | 17 | 18 | prep_upgrader() { 19 | V="$1" 20 | 21 | if [ "$V" -eq 4 ]; then 22 | ex="--schema_exclusive" 23 | else 24 | ex="" 25 | fi 26 | 27 | cc -DLUA_RUN_TEST -E -x c "upgrade/SchemaPersistentV$V.sql" >"out/lua_upgrade$V.sql" 2>out/lua_preprocess.errs 28 | # shellcheck disable=SC2086 29 | out/cql --in "out/lua_upgrade$V.sql" --cg "out/lua_schema_upgrade$V.sql" --rt schema_upgrade --global_proc lua_upgrade ${ex} 30 | cat >"out/lua_schema_upgrade$V.sql" 31 | out/cql --in "out/lua_schema_upgrade$V.sql" --cg "out/lua_schema_upgrade$V.lua" --rt lua 32 | } 33 | 34 | for i in {0..4} 35 | do 36 | prep_upgrader "$i" 37 | done 38 | -------------------------------------------------------------------------------- /sources/lua_demo/run_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | set -euo pipefail 8 | 9 | DIR="$( dirname -- "$0"; )" 10 | cd "${DIR}/.." 11 | 12 | lua_demo/prepare_run_test.sh 13 | lua out/run_test.lua 14 | 15 | echo "schema upgrade test" 16 | 17 | schema_upgrade() { 18 | V=$1 19 | O=$2 20 | lua "out/lua_schema_upgrade$V.lua" >out/lua_upgrade.txt "$O" 21 | } 22 | 23 | schema_diff() { 24 | V=$1 25 | if ! diff "lua_demo/lua_upgrade$V.ref" out/lua_upgrade.txt 26 | then 27 | echo diff "lua_demo/lua_upgrade$V.ref" out/lua_upgrade.txt 28 | echo failed 29 | exit 1 30 | fi 31 | } 32 | 33 | echo no diffs means success 34 | 35 | rm -f out/*.db 36 | 37 | for i in {0..4} 38 | do 39 | schema_upgrade "$i" "out/lua_db$i.db" 40 | schema_diff "$i" 41 | done 42 | 43 | rm -f out/*.db 44 | 45 | for i in {0..4} 46 | do 47 | echo "upgrade incrementally to $i" 48 | schema_upgrade "$i" out/lua_db.db 49 | schema_diff "$i" 50 | done 51 | 52 | 53 | for i in {0..4} 54 | do 55 | for j in {0..4} 56 | do 57 | if [ "$j" -le "$i" ]; then 58 | 59 | echo "Upgrade from nothing to v$j, then to v$i -- must match direct update to v$i" 60 | rm -f out/*.db 61 | schema_upgrade "$j" out/lua_db.db 62 | schema_upgrade "$i" out/lua_db.db 63 | schema_diff "$i" 64 | fi 65 | 66 | done 67 | done 68 | -------------------------------------------------------------------------------- /sources/lua_demo/t1.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | create table foo(x integer); 9 | declare proc printf no check; 10 | 11 | create proc foo() 12 | begin 13 | let z := case when 5 then 3 else 7 end; 14 | switch z 15 | when 1, 3 then set z := 5; 16 | when 2, 4 then set z := 6; 17 | else set z := 7; 18 | end; 19 | 20 | while 1 21 | begin 22 | while 2 23 | begin 24 | continue; 25 | end; 26 | continue; 27 | end; 28 | end; 29 | 30 | create proc curs(out x integer) 31 | begin 32 | declare C cursor for select 1 x, 2 y; 33 | fetch C; 34 | out C; 35 | end; 36 | 37 | create proc bar(u integer not null) 38 | begin 39 | declare C cursor for select u+1 x, u+2 y; 40 | let z := 0L; 41 | loop fetch C 42 | begin 43 | set z := z + C.x + C.y; 44 | end; 45 | end; 46 | 47 | create proc fib(n integer not null, out result integer not null) 48 | begin 49 | if n <= 2 then 50 | set result := 1; 51 | else 52 | set result := fib(n-1) + fib(n-2); 53 | end if; 54 | end; 55 | 56 | create proc out_stmt_dml_proc() 57 | begin 58 | declare C cursor for select 157 x; 59 | fetch C; 60 | out C; 61 | end; 62 | 63 | create proc out_stmt_proc_helper() 64 | begin 65 | declare C cursor like (x integer); 66 | fetch C from values (287); 67 | out C; 68 | end; 69 | 70 | create proc out_stmt_proc() 71 | begin 72 | declare C cursor fetch from call out_stmt_proc_helper(); 73 | out C; 74 | end; 75 | 76 | create proc f1() 77 | begin 78 | select * from foo where x > 100; 79 | end; 80 | 81 | create proc use_f(x integer) 82 | begin 83 | call f1(); 84 | end; 85 | 86 | declare proc read_stuff() using transaction; 87 | 88 | @echo lua, "function read_stuff(db)\n"; 89 | @echo lua, " local rc\n"; 90 | @echo lua, " local result\n"; 91 | @echo lua, " rc, result = use_f_fetch_results(db, 5)\n"; 92 | @echo lua, " print(rc, #result, result[1].x)\n"; 93 | @echo lua, " rc, result = out_stmt_dml_proc_fetch_results(db)\n"; 94 | @echo lua, " print(rc, #result, result[1].x)\n"; 95 | @echo lua, " result = out_stmt_proc_fetch_results()\n"; 96 | @echo lua, " print(#result, result[1].x)\n"; 97 | @echo lua, " return rc\n"; 98 | @echo lua, "end\n\n"; 99 | 100 | create proc go() 101 | begin 102 | create table foo(x integer); 103 | insert into foo values(105); 104 | insert into foo values(6); 105 | call read_stuff(); 106 | 107 | let i := 1; 108 | while i <= 8 109 | begin 110 | call printf("i:%2d fib_i:%2d\n", i, fib(i)); 111 | set i := i + 1; 112 | end; 113 | end; 114 | 115 | @echo lua, "function printf(...) io.write(cql_printf(...)) end\n"; 116 | @echo lua, "go(sqlite3.open_memory())\n"; 117 | -------------------------------------------------------------------------------- /sources/lua_demo/t2.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare proc print no check; 9 | 10 | create proc foo(out x integer ) 11 | begin 12 | set x := (select 5); 13 | end; 14 | 15 | create proc bar(out x integer ) 16 | begin 17 | set x := 5; 18 | end; 19 | 20 | create proc out_union() 21 | begin 22 | declare C cursor like (id integer, name text); 23 | let i := 1; 24 | while i <= 5 25 | begin 26 | fetch C from values(i, printf("str --%d", i)); 27 | out union C; 28 | set i := i + 1; 29 | end; 30 | end; 31 | 32 | create proc out_union_dml() 33 | begin 34 | declare C cursor for select 1 id, "xxx" name; 35 | fetch C; 36 | out union C; 37 | out union C; 38 | end; 39 | 40 | declare proc print no check; 41 | 42 | create proc call_out_union() 43 | begin 44 | declare C cursor for call out_union(); 45 | loop fetch C 46 | begin 47 | call print(C.id, C.name); 48 | end; 49 | end; 50 | 51 | create proc call_out_union_fetch2() 52 | begin 53 | declare C cursor for call out_union(); 54 | fetch C; 55 | fetch C; 56 | end; 57 | 58 | create proc out_cursor() 59 | begin 60 | declare C cursor for select 1 id, "xxx" name; 61 | fetch C; 62 | out C; 63 | end; 64 | 65 | create proc call_out() 66 | begin 67 | declare C cursor fetch from call out_cursor(); 68 | end; 69 | 70 | create proc go() 71 | begin 72 | call print(foo()); 73 | call call_out_union(); 74 | end; 75 | 76 | @echo lua, "function printf(...) io.write(cql_printf(...)) end\n"; 77 | @echo lua, "go(sqlite3.open_memory())\n"; 78 | -------------------------------------------------------------------------------- /sources/lua_demo/t3.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare function make_str(x integer) text; 9 | declare procedure printf no check; 10 | 11 | create proc make_values() 12 | begin 13 | let i := 0; 14 | while i < 25 15 | begin 16 | declare C cursor like (x integer, y text); 17 | fetch C from values (i, printf("%d", i)); 18 | out union C; 19 | set i := i + 1; 20 | end; 21 | end; 22 | 23 | 24 | create proc print_values() 25 | begin 26 | declare C cursor for call make_values(); 27 | loop fetch C 28 | begin 29 | call printf("%d %d\n", C.x, C.y); 30 | end; 31 | end; 32 | 33 | @echo lua, "function printf(...) io.write(cql_printf(...)) end\n"; 34 | @echo lua, "print_values()\n"; 35 | -------------------------------------------------------------------------------- /sources/lua_demo/t4.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | @attribute(cql:shared_fragment) 9 | create proc foo(x integer) 10 | begin 11 | if x is 7 then 12 | select 9 x, 8 y; 13 | else if x is not null then 14 | select x x, 1 y 15 | union all 16 | select x+1 x, 2 y; 17 | else 18 | select 999 x, 998 y; 19 | end if; 20 | end; 21 | 22 | create proc bar(config integer) 23 | begin 24 | with 25 | x(*) as (call foo(config)), 26 | y(*) as (call foo(config+100)) 27 | select x.*, y.x as a, y.y as b from x join y; 28 | end; 29 | 30 | declare proc print no check; 31 | 32 | create proc dump(config integer) 33 | begin 34 | call print("dumping results for config value:", config); 35 | declare C cursor for call bar(config); 36 | loop fetch C 37 | begin 38 | call print(C.x, C.y, C.a, C.b); 39 | end; 40 | end; 41 | 42 | create proc go() 43 | begin 44 | call dump(7); 45 | call dump(null); 46 | call dump(20); 47 | end; 48 | 49 | @echo lua, "go(sqlite3.open_memory())\n"; 50 | -------------------------------------------------------------------------------- /sources/lua_demo/t5.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare proc print no check; 9 | 10 | create proc make_schema() 11 | begin 12 | create table p_table ( 13 | id integer primary key, 14 | name text 15 | ); 16 | 17 | create table c_table ( 18 | id integer references p_table(id), 19 | info text 20 | ); 21 | 22 | insert into p_table values (1, "foo"), (2, "bar"); 23 | insert into c_table values (1, "1_info1"), (1, "1_info2"); 24 | insert into c_table values (2, "2_info3"), (2, "2_info4"); 25 | insert into c_table values (3, "3_info5"), (3, "3_info6"); 26 | end; 27 | 28 | create proc parent() 29 | begin 30 | select * from p_table; 31 | end; 32 | 33 | create proc child() 34 | begin 35 | select * from c_table; 36 | end; 37 | 38 | create proc parent_child() 39 | begin 40 | out union call parent() join call child() using(id); 41 | end; 42 | 43 | create proc child2(id_ integer not null) 44 | begin 45 | select * from c_table where id = id_; 46 | end; 47 | 48 | 49 | create proc parent_manual_child() 50 | begin 51 | let i := 1; 52 | while i < 3 53 | begin 54 | declare C cursor like (id integer, child1 object); 55 | fetch C from values (i, child2(i)); 56 | out union C; 57 | set i := i + 1; 58 | end; 59 | end; 60 | 61 | create proc go() 62 | begin 63 | call make_schema(); 64 | 65 | call print("testing parentchild result sets created with sugar syntax"); 66 | 67 | declare C cursor for call parent_child(); 68 | loop fetch C 69 | begin 70 | call print("cursor C", C.id, C.name); 71 | declare D cursor for C.child1; 72 | loop fetch D 73 | begin 74 | call print("", D.id, D.info); 75 | end; 76 | end; 77 | 78 | call print("testing manually created child result sets"); 79 | 80 | declare C2 cursor for call parent_manual_child(); 81 | loop fetch C2 82 | begin 83 | call print("cursor C2", C2.id); 84 | declare D2 cursor for C2.child1; 85 | loop fetch D2 86 | begin 87 | call print("", D2.id, D2.info); 88 | end; 89 | end; 90 | end; 91 | 92 | @echo lua, "go(sqlite3.open_memory())\n"; 93 | 94 | -------------------------------------------------------------------------------- /sources/lua_demo/t6.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- this is not going to be defined so calling it will crash lua to exit with a fail stack 9 | declare proc error no check; 10 | declare proc print no check; 11 | 12 | create proc expect(true_expr bool not null) 13 | begin 14 | if not true_expr then 15 | call error("expecatation failed"); 16 | end if; 17 | end; 18 | 19 | create proc go() 20 | begin 21 | call print("testing code gen for min long and max long"); 22 | 23 | let min_l0 := -9223372036854775808; -- min long 24 | let min_l1 := 0x8000000000000000; -- this also min_long 25 | let min_l2 := (1L<<63); -- min long with arithmetic 26 | let min_l3 := const(1L<<63); -- min long with constant folding 27 | 28 | let max_l0 := 9223372036854775807; -- max long 29 | let max_l1 := 0x7fffffffffffffff; -- this is also max_long 30 | let max_l2 := ~(1L<<63); -- max long with arithmetic 31 | let max_l3 := const(~(1L<<63)); -- max long with constant folding 32 | 33 | -- several ways of generating min long 34 | call expect(min_l0 == min_l1); 35 | call expect(min_l0 == min_l2); 36 | call expect(min_l0 == min_l3); 37 | -- several ways of generating max long 38 | call expect(max_l0 == max_l1); 39 | call expect(max_l0 == max_l2); 40 | call expect(max_l0 == max_l3); 41 | -- no rounding or float wierdness going on, exact integer check 42 | 43 | call expect(min_l0 + max_l0 == -1); 44 | call expect(min_l1 + max_l0 == -1); 45 | call expect(min_l2 + max_l0 == -1); 46 | call expect(min_l3 + max_l0 == -1); 47 | call expect(-9223372036854775808 + 9223372036854775807 == -1); 48 | call expect(9223372036854775807 + -9223372036854775808 == -1); 49 | call expect(0x7fffffffffffffff + 0x8000000000000000 == -1); 50 | call expect(0x8000000000000000 + 0x7fffffffffffffff == -1); 51 | 52 | 53 | declare z real not null; 54 | set z := 9223372036854775807; 55 | 56 | -- this is verifying that the constant above has been stored as a double 57 | call expect(z - 1 == z + 0.0 - 1); 58 | 59 | -- if you don't do the constants just write you get errors 60 | -- here we expect the error to illustrate the problem 61 | -- we can never generate the literal -9223372036854775808 62 | -- if we do it gets converted to a float 63 | 64 | @echo lua, "\n-- this code gen would be wrong, note the expect says ~=\n"; 65 | @echo lua, "-- we should expect == here but min_long will be rounded\n"; 66 | @echo lua, "-- we must generate (-9223372036854775807-1) as above\n"; 67 | @echo lua, "expect(-1 ~= -9223372036854775808 + 9223372036854775807)\n"; 68 | 69 | end; 70 | 71 | @echo lua, "go(sqlite3.open_memory())\n"; 72 | -------------------------------------------------------------------------------- /sources/make_amalgam.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | process_license() { 8 | 9 | cat < "out/make.out" 20 | then 21 | echo "CQL build failed" 22 | cat "out/make.out" 23 | failed 24 | fi 25 | 26 | CQL="out/cql" 27 | 28 | # echo semantic analysis 29 | if ! ${CQL} --sem --ast --dev --in "out/qp_in" >"out/__temp" 2>"out/cg_test_query_plan.err" 30 | then 31 | echo "CQL semantic analysis returned error" 32 | cat "out/cg_test_query_plan.err" 33 | failed 34 | fi 35 | 36 | # echo codegen query plan 37 | if ! ${CQL} --test --dev --cg "out/cg_test_query_plan.out" --in "out/qp_in" --rt query_plan 2>"out/cg_test_query_plan.err" 38 | then 39 | echo "CQL codegen query plan error" 40 | cat "out/cg_test_query_plan.err" 41 | failed 42 | fi 43 | 44 | # echo semantic analysis of generated code (pre check) 45 | if ! ${CQL} --sem --ast --dev --test --in "out/cg_test_query_plan.out" >"out/__temp" 2>"out/cg_test_query_plan.err" 46 | then 47 | echo "CQL query plan semantic analysis returned error" 48 | cat "out/cg_test_query_plan.err" 49 | failed 50 | fi 51 | 52 | # build any udfs needed 53 | if ! ${CQL} --test --dev --cg "out/udf.h" "out/udf.c" --in "out/cg_test_query_plan.out" --rt udf 2>"out/udf.err" 54 | then 55 | echo "CQL codegen udf return error" 56 | cat "out/udf.err" 57 | failed 58 | fi 59 | 60 | # build query plan c code 61 | if ! ${CQL} --test --dev --cg "out/query_plan.h" "out/query_plan.c" --in "out/cg_test_query_plan.out" 2>"out/query_plan_print.err" 62 | then 63 | echo "CQL codegen query plan return error" 64 | cat "out/query_plan_print.err" 65 | failed 66 | fi 67 | 68 | # compile query plan code with Makefile 69 | if ! make query_plan_test >"out/make.out" 2>"out/make.err" 70 | then 71 | echo "CQL query plan build failed" 72 | echo "stdout" 73 | cat "out/make.out" 74 | echo "stderr" 75 | cat "out/make.err" 76 | failed 77 | fi 78 | 79 | # Run query plan in c. It will output the query plan. 80 | # Nothing else should be output in this script otherwise it'll break the formatted text 81 | "./out/query_plan_test" 82 | -------------------------------------------------------------------------------- /sources/query_plan_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include 9 | #include "cqlrt.h" 10 | 11 | extern cql_code query_plan(sqlite3 *_Nonnull _db_); 12 | extern void create_udf(sqlite3 *_Nonnull _db_); 13 | 14 | int main(int argc, char **argv) { 15 | // Setup database 16 | sqlite3 *db = NULL; 17 | cql_code rc; 18 | 19 | rc = sqlite3_open(":memory:", &db); 20 | 21 | create_udf(db); 22 | 23 | if (rc == SQLITE_OK) { 24 | rc = query_plan(db); 25 | } 26 | 27 | if (rc) { 28 | fprintf(stderr, "sqlite error: code = %d, msg = %s\n", rc, sqlite3_errmsg(db)); 29 | } 30 | 31 | sqlite3_close(db); 32 | return rc; 33 | } 34 | -------------------------------------------------------------------------------- /sources/repl/README.md: -------------------------------------------------------------------------------- 1 | # CQL Playground 2 | 3 | ## CQL REPL 4 | Experiment with CQL with [`go.sql`](go.sql)! 5 | 6 | Run [`./go.sh`](go.sh) to compile `go.sql`. It will run the `go()` procedure in `go.sql`. 7 | 8 | ## Query Planner 9 | You can get query plans for the SQL statements you write in `go.sql` by running [`./go_query_plan.sh`](go_query_plan.sh). 10 | -------------------------------------------------------------------------------- /sources/repl/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | rm -f go go.c go.h go.sql.pre 8 | rm -rf go.dSYM 9 | -------------------------------------------------------------------------------- /sources/repl/clean_query_plan.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | rm -f go_query_plan go-qp.sql go-qp.* go-qp-udf.* query_plan_test.* 8 | -------------------------------------------------------------------------------- /sources/repl/go.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | set -euo pipefail 8 | 9 | set -e 10 | 11 | CQL=../out/cql 12 | if [ ! -f "${CQL}" ]; then 13 | echo "${CQL} not found" 14 | echo "cd .." 15 | echo "make clean" 16 | echo "make" 17 | exit 1 18 | fi 19 | 20 | echo "${CQL} ready" 21 | 22 | ./clean.sh 23 | cc -E -x c go.sql >go.sql.pre 24 | $CQL --in go.sql.pre --cg go.h go.c 25 | cc -g -I.. -I. -o go go.c ../cqlrt.c main.c -lsqlite3 26 | ./go 27 | -------------------------------------------------------------------------------- /sources/repl/go.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | DECLARE PROC printf NO CHECK; 9 | 10 | CREATE PROC make_schema () 11 | BEGIN 12 | CREATE TABLE my_table( 13 | str text 14 | ); 15 | END; 16 | 17 | CREATE PROC go () 18 | BEGIN 19 | call make_schema(); 20 | 21 | insert into my_table 22 | values 23 | ("Hello from CQL."), 24 | ("Edit as you please."); 25 | 26 | declare C cursor for select * from my_table; 27 | loop fetch C 28 | begin 29 | call printf("%s\n", C.str); 30 | end; 31 | END; 32 | -------------------------------------------------------------------------------- /sources/repl/go_query_plan.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | set -euo pipefail 8 | 9 | CQL_FILE=go.sql 10 | CQL_ROOT_DIR=.. 11 | CQL=$CQL_ROOT_DIR/out/cql 12 | 13 | if [ ! -f "${CQL}" ]; then 14 | echo "${CQL} not found" 15 | echo "cd .." 16 | echo "make clean" 17 | echo "make" 18 | exit 1 19 | fi 20 | 21 | ./clean.sh 22 | ./clean_query_plan.sh 23 | 24 | # Generate Query Plan Script 25 | cc -E -x c $CQL_FILE >go.sql.pre 26 | $CQL --in go.sql.pre --rt query_plan --cg go-qp.sql 27 | 28 | # Generate UDF stubs 29 | $CQL --in $CQL_FILE --rt udf --cg go-qp-udf.h go-qp-udf.c 30 | 31 | # Compile and link CQL artifacts, with a main C file query_plan_test.c 32 | $CQL --in go-qp.sql --cg go-qp.h go-qp.c --dev 33 | cc -I$CQL_ROOT_DIR -I. -c $CQL_ROOT_DIR/query_plan_test.c go-qp.c go-qp-udf.c 34 | cc -I$CQL_ROOT_DIR -I. -O -o go_query_plan go-qp.o go-qp-udf.o query_plan_test.o $CQL_ROOT_DIR/cqlrt.c -lsqlite3 35 | 36 | # Run and generate query plans 37 | ./go_query_plan 38 | -------------------------------------------------------------------------------- /sources/repl/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "cqlrt.h" 9 | #include "go.h" 10 | 11 | // super cheesy error handling 12 | #define _E(c, x) if (!(c)) { \ 13 | printf("!" #x "%s:%d\n", __FILE__, __LINE__); \ 14 | goto error; \ 15 | } 16 | 17 | #define E(x) _E(x, x) 18 | #define SQL_E(x) _E(SQLITE_OK == (x), x) 19 | 20 | // patternlint-disable-next-line prefer-sized-ints-in-msys 21 | int main(int argc, char **argv) { 22 | printf("CQL Mini App Thingy\n"); 23 | 24 | sqlite3 *db = NULL; 25 | SQL_E(sqlite3_open(":memory:", &db)); 26 | 27 | SQL_E(go(db)); 28 | return 0; 29 | 30 | error: 31 | return 1; 32 | } 33 | -------------------------------------------------------------------------------- /sources/rt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #define RT_IP_NOTICE(x) // none will be emitted 9 | 10 | // note the @ is split from the generated so that tools don't think this is a generated file 11 | #define RT_AUTOGEN(x) x " @" "generated S" "ignedSource<>\n" 12 | #define RT_SIGNSRC(x) x " @" "generated S" "ignedSource<>\n" 13 | 14 | #define RT_SYM_PREFIX "CGS_" 15 | #define RT_STRING_ENCODE "cql_string_ref_encode" 16 | #define RT_IMPL_SYMBOL_PREFIX "" 17 | #define RT_OBJC_CASE cg_symbol_case_snake 18 | 19 | #define RT_SHOULD_GENERATE_COPY NULL 20 | #define RT_REGISTER_PROC_NAME NULL 21 | 22 | #define RT_EXTRAS 23 | #define RT_EXTRA_CLEANUP 24 | 25 | #include "rt_common.c" 26 | -------------------------------------------------------------------------------- /sources/rt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "cql.h" 9 | 10 | cql_noexport rtdata *find_rtdata(CSTR name); 11 | cql_noexport void rt_cleanup(void); 12 | -------------------------------------------------------------------------------- /sources/sha256.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // MIT license applies only to the extent that this file has been modified 9 | // from the public domain version, which, as it happens, is barely at all. 10 | // 11 | // The original header with claritications from its github readme is 12 | // included here including the public domain nature of the original code, 13 | // and attribution to the original author. 14 | 15 | /********************************************************************* 16 | * Filename: sha256.h 17 | * Author: Brad Conte (brad AT bradconte.com) 18 | * Release: This code is released into the public domain free of any 19 | * restrictions. The author requests acknowledgement if the 20 | * code is used, but does not require it. 21 | * This code is provided free of any liability and without 22 | * any quality claims by the author. 23 | * Disclaimer: This code is presented "as is" without any guarantees. 24 | * Details: Defines the API for the corresponding SHA1 implementation. 25 | *********************************************************************/ 26 | 27 | #ifndef SHA256_H 28 | #define SHA256_H 29 | 30 | /*************************** HEADER FILES ***************************/ 31 | #include 32 | #include 33 | 34 | /****************************** MACROS ******************************/ 35 | #define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest 36 | 37 | /**************************** DATA TYPES ****************************/ 38 | typedef uint8_t SHA256_BYTE; // 8-bit byte 39 | typedef uint32_t SHA256_WORD; // 32-bit word (portable type) 40 | 41 | typedef struct { 42 | SHA256_BYTE data[64]; 43 | SHA256_WORD datalen; 44 | uint64_t bitlen; 45 | SHA256_WORD state[8]; 46 | } SHA256_CTX; 47 | 48 | /*********************** FUNCTION DECLARATIONS **********************/ 49 | void sha256_init(SHA256_CTX *ctx); 50 | void sha256_update(SHA256_CTX *ctx, const SHA256_BYTE data[], size_t len); 51 | void sha256_final(SHA256_CTX *ctx, SHA256_BYTE hash[]); 52 | 53 | #endif // SHA256_H 54 | -------------------------------------------------------------------------------- /sources/symtab.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "bytebuf.h" 11 | #include "charbuf.h" 12 | 13 | typedef struct symtab_entry { 14 | const char *_Nullable sym; 15 | void *_Nullable val; 16 | } symtab_entry; 17 | 18 | typedef struct symtab { 19 | uint32_t count; 20 | uint32_t capacity; 21 | symtab_entry *_Nullable payload; 22 | uint32_t (*_Nonnull hash)(const char *_Nonnull str); 23 | int32_t (*_Nonnull cmp)(const char *_Nonnull c1, const char *_Nonnull c2); 24 | void (*_Nullable teardown)(void *_Nonnull val); 25 | } symtab; 26 | 27 | #define SYMTAB_INIT_SIZE 4 28 | #define SYMTAB_LOAD_FACTOR .75 29 | 30 | cql_noexport symtab *_Nonnull symtab_new_case_sens(void); 31 | cql_noexport symtab *_Nonnull symtab_new(void); 32 | cql_noexport void symtab_delete(symtab *_Nonnull syms); 33 | cql_noexport bool_t symtab_add(symtab *_Nonnull syms, const char *_Nonnull sym_new, void *_Nullable val_new); 34 | cql_noexport symtab_entry *_Nullable symtab_find(symtab *_Nullable syms, const char *_Nonnull sym_needed); 35 | 36 | // Special case support for symbol table of byte buffers, char buffers, nested symbol tables 37 | // these are commmon. 38 | cql_noexport bytebuf *_Nonnull symtab_ensure_bytebuf(symtab *_Nonnull syms, const char *_Nonnull sym_new); 39 | cql_noexport void symtab_append_bytes(symtab *_Nonnull syms, const char *_Nonnull sym_new, const void *_Nullable bytes, size_t count); 40 | cql_noexport symtab *_Nonnull symtab_ensure_symtab(symtab *_Nonnull syms, const char *_Nonnull name); 41 | cql_noexport bool_t symtab_add_symtab(symtab *_Nonnull syms, CSTR _Nonnull name, symtab *_Nonnull data); 42 | cql_noexport charbuf *_Nonnull symtab_ensure_charbuf(symtab *_Nonnull syms, const char *_Nonnull sym_new); 43 | 44 | // patternlint-disable-next-line prefer-sized-ints-in-msys 45 | cql_noexport int default_symtab_comparator(symtab_entry *_Nonnull entry1, symtab_entry *_Nonnull entry2); 46 | 47 | // patternlint-disable-next-line prefer-sized-ints-in-msys 48 | cql_noexport symtab_entry *_Nonnull symtab_copy_sorted_payload(symtab *_Nonnull syms, int (*_Nonnull comparator)(symtab_entry *_Nonnull entry1, symtab_entry *_Nonnull entry2)); 49 | 50 | #define SYMTAB_CLEANUP(x) if (x) { symtab_delete(x); x = NULL; } 51 | -------------------------------------------------------------------------------- /sources/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | OUT_DIR="out" 8 | TEST_DIR="test" 9 | CQL="./${OUT_DIR}/cql" 10 | 11 | # shellcheck disable=SC2034 12 | ERROR_DOC="../CQL_Guide/x4.md" 13 | 14 | # shellcheck disable=SC1091 15 | source common/test_helpers.sh || exit 1 16 | 17 | while [ "$1" != "" ] 18 | do 19 | if [ "$1" == "--coverage" ] 20 | then 21 | MAKE_COVERAGE_ARGS="COVERAGE=1" 22 | TEST_COVERAGE_ARGS="--coverage" 23 | shift 1 24 | elif [ "$1" == "--use_amalgam" ] 25 | then 26 | CQL=${OUT_DIR}/cql_amalgam 27 | shift 1 28 | elif [ "$1" == "--non_interactive" ] 29 | then 30 | # shellcheck disable=SC2034 31 | NON_INTERACTIVE=1 32 | shift 1 33 | else 34 | echo "Usage: test.sh [--coverage] [--use_amalgam] [--non_interactive]" 35 | exit 1 36 | fi 37 | done 38 | 39 | # no extra tests 40 | extra_tests() { 41 | echo "no extra tests at this time" 42 | } 43 | 44 | # shellcheck disable=SC1091 45 | source common/test_common.sh || exit 1 46 | -------------------------------------------------------------------------------- /sources/test/LICENSE: -------------------------------------------------------------------------------- 1 | The contents of this test directory (test related sources) are included in the license 2 | found in the root directory. 3 | 4 | Many of the files cannot be reasonably marked individually or are otherwise generated 5 | and so marking them would be onerous. This file serves to indicate that the unmarked 6 | files in this directory are covered by the license. 7 | -------------------------------------------------------------------------------- /sources/test/alt_cqlrt.err.ref: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/sources/test/alt_cqlrt.err.ref -------------------------------------------------------------------------------- /sources/test/amalgam_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include 9 | 10 | #pragma clang diagnostic ignored "-Wnullability-completeness" 11 | 12 | #define CQL_IS_NOT_MAIN 13 | #include "out/cql_amalgam.c" 14 | 15 | // Runs cql parsing multiple times in the same run session. 16 | // This is to verify that cql emits expected output for each 17 | // parsing even with no exits between. This requires lots of 18 | // bison and CQL state to be reset properly. 19 | int32_t main(int32_t argc, char **argv) { 20 | if (argc != 4) { 21 | fprintf( 22 | stderr, 23 | "Usage: amalgam_test file1 file2 file3\n\n" 24 | "file1: a cql file with no errors\n" 25 | "file2: a cql file with a semantic error\n" 26 | "file3: a cql file with a syntax error\n"); 27 | return 1; 28 | } 29 | 30 | const char *cql_success_file = (char *) argv[1]; 31 | const char *cql_semantic_error_file = (char *) argv[2]; 32 | const char *cql_syntax_error_file = (char *) argv[3]; 33 | 34 | fprintf(stdout, "-- RUN %s:\n", cql_success_file); 35 | fprintf(stderr, "-- RUN %s:\n", cql_success_file); 36 | const char *args_1[5] = {"cql", "--in", cql_success_file, "--sem", "--echo"}; 37 | if (cql_main(5, (char **)args_1) != 0) { 38 | fprintf(stderr, "%s reported an error: this is unexpected\n", cql_success_file); 39 | exit(1); 40 | } 41 | 42 | fprintf(stdout, "\n-- RUN %s:\n", cql_semantic_error_file); 43 | fprintf(stderr, "\n-- RUN %s:\n", cql_semantic_error_file); 44 | const char *args_2[5] = {"cql", "--in", cql_semantic_error_file, "--sem", "--echo"}; 45 | if (cql_main(5, (char **)args_2) == 0) { 46 | fprintf(stderr, "%s did not reported an error: this is unexpected\n", cql_semantic_error_file); 47 | exit(1); 48 | } 49 | 50 | fprintf(stdout, "\n-- RUN %s:\n", cql_syntax_error_file); 51 | fprintf(stderr, "\n-- RUN %s:\n", cql_syntax_error_file); 52 | const char *args_3[5] = {"cql", "--in", cql_syntax_error_file, "--sem", "--echo"}; 53 | if (cql_main(5, (char **)args_3) == 0) { 54 | fprintf(stderr, "%s did not reported an error: this is unexpected\n", cql_syntax_error_file); 55 | exit(1); 56 | } 57 | 58 | fprintf(stdout, "\n-- RUN %s:\n", cql_success_file); 59 | fprintf(stderr, "\n-- RUN %s:\n", cql_success_file); 60 | if (cql_main(5, (char **)args_1) != 0) { 61 | fprintf(stderr, "%s reported an error: this is unexpected\n", cql_success_file); 62 | exit(1); 63 | } 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /sources/test/asm_query_ns_needed.err.ref: -------------------------------------------------------------------------------- 1 | assembly query namespace not provided for extension fragment; no code gen. 2 | -------------------------------------------------------------------------------- /sources/test/badpath.err.ref: -------------------------------------------------------------------------------- 1 | unable to open '/xx/yy/zz' for read 2 | -------------------------------------------------------------------------------- /sources/test/bigquote.err.ref: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/sources/test/bigquote.err.ref -------------------------------------------------------------------------------- /sources/test/bigquote.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare x text; 9 | 10 | set x := 'sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd sdfasdfasdfafafdsadfakjdflajfd lajkfd ajkfd asjfsadjf aljf lajf asjkf saljf sajf adsjf lsajf jfdlajfl adsjfl dasjf alsjf dsajf lsajf lasdjkfs alfjas lfjas ldfjadslfjsdafsfd' ; 11 | -------------------------------------------------------------------------------- /sources/test/c_include_namespace_missing.err.ref: -------------------------------------------------------------------------------- 1 | --c_include_namespace requires an additional param for the C include namespace. 2 | -------------------------------------------------------------------------------- /sources/test/c_include_needed.err.ref: -------------------------------------------------------------------------------- 1 | The C header path must be provided as argument (use --objc_c_include_path) 2 | -------------------------------------------------------------------------------- /sources/test/cg_1_2.err.ref: -------------------------------------------------------------------------------- 1 | --rt objc requires 1 files for --cg, but received 2 2 | -------------------------------------------------------------------------------- /sources/test/cg_requires_file.err.ref: -------------------------------------------------------------------------------- 1 | --cg requires additional arguments. 2 | -------------------------------------------------------------------------------- /sources/test/cg_test_assembly_query.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- test base table with combination of fields 9 | create table bar( 10 | id INTEGER NOT NULL, 11 | @attribute(collossal_cave='xyzzy') 12 | name TEXT, 13 | rate LONG INT, 14 | type INTEGER, 15 | size REAL @create(2) 16 | ); 17 | 18 | -- test table for extension query fragment join 19 | create table plugin_table( 20 | id integer primary key, 21 | name text, 22 | flag BOOL 23 | ); 24 | 25 | -- TEST: base fragment attribute 26 | -- - cql_cleanup 27 | @attribute(cql:base_fragment=assembly_core) 28 | create proc base_fragment(id_ integer not null, name_ text not null) 29 | begin 30 | with 31 | assembly_core(x, y, z) as (select id, name, rate from bar where id = id_) 32 | select * from assembly_core; 33 | end; 34 | 35 | -- TEST: extension fragment one 36 | -- - cql_code%extension_fragment_one 37 | @attribute(cql:extension_fragment=assembly_core) 38 | create proc extension_fragment_one(id_ INTEGER NOT NULL, name_ text not null) 39 | begin 40 | with 41 | assembly_core (x, y, z) AS (SELECT 1, nullable("a"), nullable(3L)), -- this is stub for the core 42 | plugin_one(*) as ( 43 | select * from assembly_core 44 | union all 45 | select 1 x, "y" y, 7 z) 46 | select * from plugin_one; 47 | end; 48 | 49 | -- TEST: extension fragment one 50 | -- - cql_code%extension_fragment_two 51 | @attribute(cql:extension_fragment=assembly_core) 52 | create proc extension_fragment_two(id_ integer not null, name_ text not null) 53 | begin 54 | with 55 | assembly_core (x, y, z) AS (SELECT 1, nullable("a"), nullable(3L)), -- this is stub for the core 56 | plugin_two(x, y, z, flag) as ( 57 | select assembly_core.*, plugin_table.flag from assembly_core 58 | left outer join plugin_table on plugin_table.name = assembly_core.y AND plugin_table.id = id_) 59 | select * from plugin_two; 60 | end; 61 | 62 | -- TEST: assembly fragment attribute 63 | -- + assembly_core 64 | -- + FROM plugin_one 65 | -- + FROM plugin_two 66 | @attribute(cql:assembly_fragment=assembly_core) 67 | CREATE PROC assembly_core(id_ INTEGER NOT NULL, name_ text not null) 68 | begin 69 | with 70 | assembly_core (x, y, z) AS (SELECT 1, nullable("a"), nullable(3L)) -- this is stub for the core 71 | select * from assembly_core; 72 | end; 73 | -------------------------------------------------------------------------------- /sources/test/cg_test_assembly_query_objc.out.ref: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #import 4 | 5 | 6 | #import 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | @class CGBAssemblyCore; 11 | 12 | #ifdef CQL_EMIT_OBJC_INTERFACES 13 | @interface CGBAssemblyCore 14 | @end 15 | #endif 16 | 17 | static inline CGBAssemblyCore *CGBAssemblyCoreFromCGCAssemblyCore(CGCAssemblyCoreResultSetRef resultSet) 18 | { 19 | return (__bridge CGBAssemblyCore *)resultSet; 20 | } 21 | 22 | static inline CGCAssemblyCoreResultSetRef CGCAssemblyCoreFromCGBAssemblyCore(CGBAssemblyCore *resultSet) 23 | { 24 | return (__bridge CGCAssemblyCoreResultSetRef)resultSet; 25 | } 26 | 27 | static inline int32_t CGBAssemblyCoreGetX(CGBAssemblyCore *resultSet, int32_t row) 28 | { 29 | CGCAssemblyCoreResultSetRef cResultSet = CGCAssemblyCoreFromCGBAssemblyCore(resultSet); 30 | return CGCAssemblyCoreGetX(cResultSet, row); 31 | } 32 | 33 | static inline NSString *_Nullable CGBAssemblyCoreGetY(CGBAssemblyCore *resultSet, int32_t row) 34 | { 35 | CGCAssemblyCoreResultSetRef cResultSet = CGCAssemblyCoreFromCGBAssemblyCore(resultSet); 36 | return (__bridge NSString *)CGCAssemblyCoreGetY(cResultSet, row); 37 | } 38 | 39 | static inline NSNumber *_Nullable CGBAssemblyCoreGetZ(CGBAssemblyCore *resultSet, int32_t row) 40 | { 41 | CGCAssemblyCoreResultSetRef cResultSet = CGCAssemblyCoreFromCGBAssemblyCore(resultSet); 42 | return CGCAssemblyCoreGetZIsNull(cResultSet, row) ? nil : @(CGCAssemblyCoreGetZValue(cResultSet, row)); 43 | } 44 | 45 | static inline NSNumber *_Nullable CGBAssemblyCoreGetFlag(CGBAssemblyCore *resultSet, int32_t row) 46 | { 47 | CGCAssemblyCoreResultSetRef cResultSet = CGCAssemblyCoreFromCGBAssemblyCore(resultSet); 48 | return CGCAssemblyCoreGetFlagIsNull(cResultSet, row) ? nil : @(CGCAssemblyCoreGetFlagValue(cResultSet, row)); 49 | } 50 | 51 | static inline int32_t CGBAssemblyCoreResultCount(CGBAssemblyCore *resultSet) 52 | { 53 | return CGCAssemblyCoreResultCount(CGCAssemblyCoreFromCGBAssemblyCore(resultSet)); 54 | } 55 | 56 | static inline NSUInteger CGBAssemblyCoreRowHash(CGBAssemblyCore *resultSet, int32_t row) 57 | { 58 | return CGCAssemblyCoreRowHash(CGCAssemblyCoreFromCGBAssemblyCore(resultSet), row); 59 | } 60 | 61 | static inline BOOL CGBAssemblyCoreRowEqual(CGBAssemblyCore *resultSet1, int32_t row1, CGBAssemblyCore *resultSet2, int32_t row2) 62 | { 63 | return CGCAssemblyCoreRowEqual(CGCAssemblyCoreFromCGBAssemblyCore(resultSet1), row1, CGCAssemblyCoreFromCGBAssemblyCore(resultSet2), row2); 64 | } 65 | 66 | NS_ASSUME_NONNULL_END 67 | -------------------------------------------------------------------------------- /sources/test/cg_test_base_fragment.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- test base table with combination of fields 9 | create table bar( 10 | id INTEGER NOT NULL, 11 | @attribute(collossal_cave='xyzzy') 12 | name TEXT, 13 | rate LONG INT, 14 | type INTEGER, 15 | size REAL @create(2) 16 | ); 17 | 18 | -- second test base table 19 | create table foo( 20 | id TEXT PRIMARY KEY NOT NULL, 21 | name TEXT, 22 | col INTEGER 23 | ); 24 | 25 | -- test table for extension query fragment join 26 | create table plugin_table( 27 | id INTEGER primary key, 28 | name TEXT, 29 | flag BOOL, 30 | timestamp_ms LONG INT NOT NULL DEFAULT 0 31 | ); 32 | 33 | -- TEST: base fragment attribute 34 | -- - cql_cleanup 35 | @attribute(cql:base_fragment=assembly_core) 36 | create proc base_fragment(id_ integer not null, name_ text not null) 37 | begin 38 | with 39 | assembly_core(x, y, z) as (select id, name, rate from bar where id = id_) 40 | select * from assembly_core; 41 | end; 42 | 43 | -- TEST: second base fragment attribute 44 | -- - cql_cleanup 45 | @attribute(cql:base_fragment=assembly_non_core) 46 | create proc second_base_fragment(name_ TEXT not null) 47 | begin 48 | with 49 | assembly_non_core(a, b, c) as (select id, name, col from foo where name = name_) 50 | select * from assembly_non_core; 51 | end; 52 | -------------------------------------------------------------------------------- /sources/test/cg_test_base_fragment_c.c.ref: -------------------------------------------------------------------------------- 1 | 2 | #include "out/cg_test_base_fragment_c.h" 3 | 4 | #pragma clang diagnostic push 5 | #pragma clang diagnostic ignored "-Wunknown-warning-option" 6 | #pragma clang diagnostic ignored "-Wbitwise-op-parentheses" 7 | #pragma clang diagnostic ignored "-Wshift-op-parentheses" 8 | #pragma clang diagnostic ignored "-Wlogical-not-parentheses" 9 | #pragma clang diagnostic ignored "-Wlogical-op-parentheses" 10 | #pragma clang diagnostic ignored "-Wliteral-conversion" 11 | #pragma clang diagnostic ignored "-Wunused-but-set-variable" 12 | #pragma clang diagnostic ignored "-Wunused-function" 13 | extern cql_object_ref _Nonnull cql_partition_create(void); 14 | extern cql_bool cql_partition_cursor(cql_object_ref _Nonnull p, cql_dynamic_cursor *_Nonnull key, cql_dynamic_cursor *_Nonnull value); 15 | extern cql_object_ref _Nonnull cql_extract_partition(cql_object_ref _Nonnull p, cql_dynamic_cursor *_Nonnull key); 16 | extern cql_object_ref _Nonnull cql_string_dictionary_create(void); 17 | extern cql_bool cql_string_dictionary_add(cql_object_ref _Nonnull dict, cql_string_ref _Nonnull key, cql_string_ref _Nonnull value); 18 | extern cql_string_ref _Nullable cql_string_dictionary_find(cql_object_ref _Nonnull dict, cql_string_ref _Nullable key); 19 | extern cql_string_ref _Nonnull cql_cursor_format(cql_dynamic_cursor *_Nonnull C); 20 | 21 | // The statement ending at line XXXX 22 | 23 | /* 24 | @ATTRIBUTE(cql:base_fragment=assembly_core) 25 | CREATE PROC base_fragment (id_ INTEGER NOT NULL, name_ TEXT NOT NULL) 26 | BEGIN 27 | WITH 28 | assembly_core (x, y, z) AS (SELECT id, name, rate 29 | FROM bar 30 | WHERE id = id_) 31 | SELECT * 32 | FROM assembly_core; 33 | END; 34 | */ 35 | 36 | // The statement ending at line XXXX 37 | 38 | /* 39 | @ATTRIBUTE(cql:base_fragment=assembly_non_core) 40 | CREATE PROC second_base_fragment (name_ TEXT NOT NULL) 41 | BEGIN 42 | WITH 43 | assembly_non_core (a, b, c) AS (SELECT id, name, col 44 | FROM foo 45 | WHERE name = name_) 46 | SELECT * 47 | FROM assembly_non_core; 48 | END; 49 | */ 50 | #pragma clang diagnostic pop 51 | -------------------------------------------------------------------------------- /sources/test/cg_test_base_fragment_objc.out.ref: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #import 4 | 5 | 6 | #import 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | NS_ASSUME_NONNULL_END 11 | -------------------------------------------------------------------------------- /sources/test/cg_test_c.err.ref: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/sources/test/cg_test_c.err.ref -------------------------------------------------------------------------------- /sources/test/cg_test_c_globals.h.ref: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cqlrt.h" 4 | 5 | 6 | // The statement ending at line XXXX 7 | 8 | // The statement ending at line XXXX 9 | 10 | // The statement ending at line XXXX 11 | 12 | // The statement ending at line XXXX 13 | 14 | // The statement ending at line XXXX 15 | 16 | // The statement ending at line XXXX 17 | 18 | // The statement ending at line XXXX 19 | 20 | // The statement ending at line XXXX 21 | #ifndef _foo_var_group_decl_ 22 | #define _foo_var_group_decl_ 1 23 | 24 | typedef struct c_row { 25 | cql_bool _has_row_; 26 | cql_uint16 _refs_count_; 27 | cql_uint16 _refs_offset_; 28 | cql_int32 x; 29 | } c_row; 30 | extern c_row c; 31 | extern cql_nullable_int32 x; 32 | 33 | typedef struct serialized_cursor_row { 34 | cql_bool _has_row_; 35 | cql_uint16 _refs_count_; 36 | cql_uint16 _refs_offset_; 37 | cql_int32 id; 38 | cql_string_ref _Nullable t; 39 | } serialized_cursor_row; 40 | extern serialized_cursor_row serialized_cursor; 41 | extern cql_dynamic_cursor serialized_cursor_dyn; 42 | #endif 43 | 44 | // The statement ending at line XXXX 45 | extern CQL_WARN_UNUSED cql_code p(sqlite3 *_Nonnull _db_, cql_blob_ref _Nullable x); 46 | 47 | // The statement ending at line XXXX 48 | -------------------------------------------------------------------------------- /sources/test/cg_test_c_globals.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- TEST 9 | -- this generates nothing in the header 10 | -- - blobshape 11 | @attribute(cql:blob_storage) 12 | create table blobshape( 13 | id integer not null, 14 | t text 15 | ); 16 | 17 | -- + #ifndef _foo_var_group_decl_ 18 | -- + #define _foo_var_group_decl_ 1 19 | -- + typedef struct c_row { 20 | -- + cql_bool _has_row_; 21 | -- + cql_uint16 _refs_count_; 22 | -- + cql_uint16 _refs_offset_; 23 | -- + cql_int32 x; 24 | -- + } c_row; 25 | -- + extern c_row c; 26 | -- + extern cql_nullable_int32 x; 27 | -- + #endif 28 | -- + typedef struct serialized_cursor_row { 29 | -- + cql_bool _has_row_; 30 | -- + cql_uint16 _refs_count_; 31 | -- + cql_uint16 _refs_offset_; 32 | -- + cql_int32 id; 33 | -- + cql_string_ref _Nullable t; 34 | -- + } serialized_cursor_row; 35 | -- + extern serialized_cursor_row serialized_cursor; 36 | -- + extern cql_dynamic_cursor serialized_cursor_dyn; 37 | declare group foo 38 | begin 39 | declare c cursor like select 1 x; 40 | declare x integer; 41 | declare serialized_cursor cursor like blobshape; 42 | end; 43 | 44 | create proc p(x blob) 45 | begin 46 | fetch serialized_cursor from blob x; 47 | end; 48 | 49 | -- TEST: When we emit the group, nothing goes in the header 50 | -- - extern 51 | -- - c_row 52 | -- - nullable_int32 53 | @emit_group foo; 54 | -------------------------------------------------------------------------------- /sources/test/cg_test_extension_fragment_objc.out.ref: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #import 4 | 5 | 6 | #import 7 | 8 | NS_ASSUME_NONNULL_BEGIN 9 | 10 | NS_ASSUME_NONNULL_END 11 | -------------------------------------------------------------------------------- /sources/test/cg_test_generated_from.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- A sample table. 9 | create table bar( 10 | id INTEGER NOT NULL PRIMARY KEY, 11 | @attribute(collossal_cave='xyzzy') 12 | name TEXT, 13 | rate LONG INT, 14 | type INTEGER, 15 | size REAL @create(2) 16 | ); 17 | 18 | -- A sample procedure. 19 | create procedure sample_proc() 20 | begin 21 | end; 22 | 23 | -- Testing @echo both with and without a newline ending 24 | @echo c, "/* A"; 25 | @echo c, " comment */\n"; 26 | -------------------------------------------------------------------------------- /sources/test/cg_test_lua.err.ref: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/sources/test/cg_test_lua.err.ref -------------------------------------------------------------------------------- /sources/test/cg_test_no_result_set.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | create table bar( 9 | id INTEGER NOT NULL, 10 | name TEXT, 11 | rate LONG INT, 12 | type INTEGER, 13 | size REAL 14 | ); 15 | 16 | create procedure outparm_test(out foo integer not null) 17 | begin 18 | set foo := 1; 19 | delete from bar where id = foo; 20 | end; 21 | -------------------------------------------------------------------------------- /sources/test/cg_test_objc.err.ref: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/sources/test/cg_test_objc.err.ref -------------------------------------------------------------------------------- /sources/test/cg_test_out_object.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | 9 | create proc cursor_with_object(object_ Object) 10 | begin 11 | declare C cursor like cursor_with_object arguments; 12 | fetch C from arguments; 13 | out C; 14 | end; 15 | -------------------------------------------------------------------------------- /sources/test/cg_test_prev_invalid.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /* you can't codegen C if previous schema mode was enabled */ 9 | 10 | create proc whatever() 11 | begin 12 | select 1 x; 13 | end; 14 | 15 | @previous_schema; 16 | -------------------------------------------------------------------------------- /sources/test/cg_test_schema_min_version_upgrade.err.ref: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/sources/test/cg_test_schema_min_version_upgrade.err.ref -------------------------------------------------------------------------------- /sources/test/cg_test_schema_partial_upgrade.err.ref: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/sources/test/cg_test_schema_partial_upgrade.err.ref -------------------------------------------------------------------------------- /sources/test/cg_test_schema_prev.err.ref: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/sources/test/cg_test_schema_prev.err.ref -------------------------------------------------------------------------------- /sources/test/cg_test_schema_sqlite.err.ref: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/sources/test/cg_test_schema_sqlite.err.ref -------------------------------------------------------------------------------- /sources/test/cg_test_schema_upgrade.err.ref: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/sources/test/cg_test_schema_upgrade.err.ref -------------------------------------------------------------------------------- /sources/test/cql_amalgam_test.err.ref: -------------------------------------------------------------------------------- 1 | -- RUN test/cql_amalgam_test_success.sql: 2 | 3 | -- RUN test/cql_amalgam_test_semantic_error.sql: 4 | test/cql_amalgam_test_semantic_error.sql:XXXX:1: error: in str : CQL0069: name not found 'bogus' 5 | semantic errors present; no code gen. 6 | 7 | -- RUN test/cql_amalgam_test_syntax_error.sql: 8 | test/cql_amalgam_test_syntax_error.sql:XXXX:1: error: syntax error, unexpected SELECT 9 | Parse errors found, no further passes will run. 10 | 11 | -- RUN test/cql_amalgam_test_success.sql: 12 | -------------------------------------------------------------------------------- /sources/test/cql_amalgam_test.out.ref: -------------------------------------------------------------------------------- 1 | -- RUN test/cql_amalgam_test_success.sql: 2 | CREATE TABLE t( 3 | a TEXT, 4 | b INTEGER 5 | ); 6 | 7 | SELECT a, b 8 | FROM t; 9 | 10 | -- RUN test/cql_amalgam_test_semantic_error.sql: 11 | CREATE TABLE t( 12 | a TEXT, 13 | b INTEGER 14 | ); 15 | 16 | SELECT bogus 17 | FROM t; 18 | 19 | -- RUN test/cql_amalgam_test_syntax_error.sql: 20 | 21 | -- RUN test/cql_amalgam_test_success.sql: 22 | CREATE TABLE t( 23 | a TEXT, 24 | b INTEGER 25 | ); 26 | 27 | SELECT a, b 28 | FROM t; 29 | -------------------------------------------------------------------------------- /sources/test/cql_amalgam_test_semantic_error.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | create table t ( 9 | a text, 10 | b integer 11 | ); 12 | 13 | select bogus from t; 14 | -------------------------------------------------------------------------------- /sources/test/cql_amalgam_test_success.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | create table t ( 9 | a text, 10 | b integer 11 | ); 12 | 13 | select a, b from t; 14 | -------------------------------------------------------------------------------- /sources/test/cql_amalgam_test_syntax_error.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | select select 9 | -------------------------------------------------------------------------------- /sources/test/cqlrt_arg_missing.err.ref: -------------------------------------------------------------------------------- 1 | --cqlrt requires an additional param for the name of the runtime header. 2 | -------------------------------------------------------------------------------- /sources/test/cqltest.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "cqlrt.h" 9 | 10 | extern cql_code cql_startup(sqlite3 *db); 11 | extern cql_code run_client(sqlite3 *db); 12 | 13 | int main(int argc, char **argv) { 14 | // Setup database 15 | sqlite3 *db = NULL; 16 | cql_code rc; 17 | 18 | // first access the database using the C interface 19 | rc = sqlite3_open(":memory:", &db); 20 | if (rc == SQLITE_OK) { 21 | rc = run_client(db); 22 | } 23 | sqlite3_close(db); 24 | if (rc) exit(rc); 25 | 26 | // now try again using the stored procs 27 | rc = sqlite3_open(":memory:", &db); 28 | 29 | if (rc == SQLITE_OK) { 30 | rc = cql_startup(db); 31 | } 32 | sqlite3_close(db); 33 | 34 | exit(rc); 35 | } 36 | -------------------------------------------------------------------------------- /sources/test/cqltest.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare tests integer not null; 9 | declare tests_passed integer not null; 10 | declare fails integer not null; 11 | declare expectations integer not null; 12 | declare function get_outstanding_refs() integer not null; 13 | declare start_refs integer not null; 14 | declare end_refs integer not null; 15 | declare proc printf no check; 16 | declare proc exit no check; 17 | 18 | #define EXPECT(pred) call errcheck(pred, #pred, __LINE__) 19 | 20 | #define BEGIN_SUITE() 21 | 22 | #define END_SUITE() call end_suite(); 23 | 24 | #define BEGIN_TEST(x) \ 25 | create procedure test_##x() \ 26 | begin \ 27 | begin try \ 28 | set tests := tests + 1; \ 29 | declare starting_fails integer not null; \ 30 | set starting_fails := fails; 31 | 32 | #define END_TEST(x) \ 33 | end try; \ 34 | begin catch \ 35 | call printf("%s had an unexpected CQL exception (usually a db error)\n", #x); \ 36 | set fails := fails + 1; \ 37 | throw; \ 38 | end catch; \ 39 | if starting_fails != fails then \ 40 | call printf("%s failed.\n", #x); \ 41 | else \ 42 | set tests_passed := tests_passed + 1; \ 43 | end if; \ 44 | end; \ 45 | set start_refs := get_outstanding_refs(); \ 46 | call test_##x(); \ 47 | set end_refs := get_outstanding_refs(); \ 48 | if start_refs != end_refs then \ 49 | call printf("Test %s unbalanced refs. Starting refs %d, ending refs %d.\n", #x, start_refs, end_refs); \ 50 | set fails := fails + 1; \ 51 | end if; 52 | 53 | create procedure errcheck(passed bool @sensitive, message text, line integer not null) 54 | begin 55 | set expectations := expectations + 1; 56 | if not coalesce(passed, 0) then 57 | call printf("test: %s: FAIL on line %d\n", message, line); 58 | set fails := fails + 1; 59 | end if; 60 | end; 61 | 62 | create procedure end_suite() 63 | begin 64 | call printf("%d tests executed. %d passed, %d failed. %d expectations failed of %d.\n", 65 | tests, tests_passed, tests - tests_passed, fails, expectations); 66 | call exit(fails); 67 | end; 68 | -------------------------------------------------------------------------------- /sources/test/dottest.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- general dot print example for nodes of non primitive types 9 | select x,y,5.2 from A 10 | order by a,b,c,d ASC limit 5; 11 | 12 | -- print select binary expression with all numerical data types 13 | select 1.2 + 2147483648 * 3; 14 | 15 | -- print string type ast node 16 | select 'a' || 'b'; 17 | -------------------------------------------------------------------------------- /sources/test/error.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | foo 9 | -------------------------------------------------------------------------------- /sources/test/excl_invalid_regions.err.ref: -------------------------------------------------------------------------------- 1 | invalid region specified 'bogus' 2 | -------------------------------------------------------------------------------- /sources/test/gen_exports_args.err.ref: -------------------------------------------------------------------------------- 1 | --cg had the wrong number of arguments, argument 3 was needed 2 | -------------------------------------------------------------------------------- /sources/test/generate_file_file.err.ref: -------------------------------------------------------------------------------- 1 | unknown arg '--generate_file_type' 2 | -------------------------------------------------------------------------------- /sources/test/generate_file_type.err.ref: -------------------------------------------------------------------------------- 1 | unknown arg '--generate_file_type' 2 | -------------------------------------------------------------------------------- /sources/test/global_proc_missing.err.ref: -------------------------------------------------------------------------------- 1 | --global_proc requires an additional param for the global proc name. 2 | -------------------------------------------------------------------------------- /sources/test/global_proc_needed.err.ref: -------------------------------------------------------------------------------- 1 | There are global statements but no global proc name was specified (use --global_proc) 2 | -------------------------------------------------------------------------------- /sources/test/in_arg_missing.err.ref: -------------------------------------------------------------------------------- 1 | --in requires an additional param for the file name. 2 | -------------------------------------------------------------------------------- /sources/test/inc_invalid_regions.err.ref: -------------------------------------------------------------------------------- 1 | invalid region specified 'bogus' 2 | -------------------------------------------------------------------------------- /sources/test/invalid_arg.err.ref: -------------------------------------------------------------------------------- 1 | unknown arg '--garbonzo!!' 2 | -------------------------------------------------------------------------------- /sources/test/linetest.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare proc printf no check; 9 | 10 | -- testing line numbers for simple statement boundaries, any statement will do 11 | -- something with no "interior" works best. 12 | create proc based_statements() 13 | begin 14 | declare x integer not null; 15 | set x := 1; 16 | set x := 2; 17 | set x := 3; 18 | @echo c, "/* hello "; -- no line info for these! 19 | @echo c, "world \n"; -- no line info for these! 20 | set x := 4; 21 | set x := 5; 22 | end; 23 | 24 | -- testing simple if statements in various forms 25 | create proc if_test() 26 | begin 27 | declare x integer not null; 28 | if x = 1 then 29 | set x := 10; 30 | end if; 31 | 32 | if x = 2 then 33 | set x := 21; 34 | else 35 | set x := 22; 36 | end if; 37 | 38 | if x = 3 then 39 | set x := 31; 40 | else if x = 3 then 41 | set x := 32; 42 | else 43 | set x := 32; 44 | end if; 45 | end; 46 | 47 | -- testing if and case together with a coalesce thrown in 48 | create proc case_if() 49 | begin 50 | if 1 then 51 | call printf("one"); 52 | else 53 | call printf("two"); 54 | end if; 55 | 56 | declare x integer; 57 | 58 | set x := coalesce( case 59 | when 1 60 | then 200 61 | when 2 62 | then 300 63 | end, 64 | 3000); 65 | end; 66 | 67 | -- testing the in predicate by itself 68 | create proc in_pred_lines(i integer not null, out b bool not null ) 69 | begin 70 | set b := i in ( 71 | 1, 72 | 3, 73 | 7); 74 | end; 75 | 76 | -- testing in predicate mixed with case 77 | create proc in_pred_and_case(i integer not null, out b bool not null ) 78 | begin 79 | set b := case when 80 | i > 8 81 | then 82 | i in ( 83 | 10, 84 | 12, 85 | 14) 86 | else 87 | i in ( 88 | 1, 89 | 3, 90 | 7) 91 | end; 92 | end; 93 | -------------------------------------------------------------------------------- /sources/test/noresult.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | create proc AnyProcWithNoResultSet() 9 | begin 10 | declare x integer; 11 | end; 12 | -------------------------------------------------------------------------------- /sources/test/objc_include_missing.err.ref: -------------------------------------------------------------------------------- 1 | --objc_c_include_path requires an additional param for the include path of a C header. 2 | -------------------------------------------------------------------------------- /sources/test/objc_no_results.err.ref: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/sources/test/objc_no_results.err.ref -------------------------------------------------------------------------------- /sources/test/parse_test_cql_inferred_notnull.err.ref: -------------------------------------------------------------------------------- 1 | test/parse_test_cql_inferred_notnull.sql:XXXX:1: error: Call to internal function is not allowed 'cql_inferred_notnull' 2 | Parse errors found, no further passes will run. 3 | -------------------------------------------------------------------------------- /sources/test/parse_test_cql_inferred_notnull.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | call cql_inferred_notnull(x); 9 | -------------------------------------------------------------------------------- /sources/test/parse_test_fetch_from_call_columns.err.ref: -------------------------------------------------------------------------------- 1 | test/parse_test_fetch_from_call_columns.sql:XXXX:1: error: Cursor columns not allowed in this form. 2 | Parse errors found, no further passes will run. 3 | -------------------------------------------------------------------------------- /sources/test/parse_test_fetch_from_call_columns.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | fetch c () from call p(); 9 | -------------------------------------------------------------------------------- /sources/test/prev_and_codegen_incompat.err.ref: -------------------------------------------------------------------------------- 1 | This code generation mode is not compatible with @previous_schema validation mode. 2 | -------------------------------------------------------------------------------- /sources/test/rt_arg_bogus.err.ref: -------------------------------------------------------------------------------- 1 | unknown cg runtime 'foo' 2 | -------------------------------------------------------------------------------- /sources/test/rt_arg_missing.err.ref: -------------------------------------------------------------------------------- 1 | --rt requires an additional param (e.g., c, objc, json_schema). 2 | -------------------------------------------------------------------------------- /sources/test/schema_version_error.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- TEST : set up for schema upgrade 9 | -- + @SCHEMA_UPGRADE (2); 10 | -- + {schema_upgrade_version_stmt}: ok 11 | -- + {int 2} 12 | -- - Error 13 | @schema_upgrade_version(2); 14 | 15 | -- TEST : double declaration 16 | -- + {schema_upgrade_version_stmt}: err 17 | -- + error: % schema upgrade version declaration may only appear once 18 | -- +1 error: 19 | @schema_upgrade_version(2); 20 | 21 | create view X as select 1 a, 2 b; 22 | 23 | -- TEST: try to use a view in a proc in a migration scenario 24 | -- + {create_proc_stmt}: err 25 | -- + error: % table/view not defined (view hidden in migration script) 'X' 26 | -- +1 error: 27 | create proc p() 28 | begin 29 | select * from X; 30 | end; 31 | -------------------------------------------------------------------------------- /sources/test/schema_version_ok.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | @schema_upgrade_version(2); 9 | -------------------------------------------------------------------------------- /sources/test/sem_abort.err.ref: -------------------------------------------------------------------------------- 1 | test/semantic_error.sql:XXXX:1: error: in assign : CQL0173: variable not found 'x' 2 | semantic errors present; no code gen. 3 | -------------------------------------------------------------------------------- /sources/test/sem_test_dev.err.ref: -------------------------------------------------------------------------------- 1 | test/sem_test_dev.sql:XXXX:1: error: in explain_stmt : CQL0292: explain statement is only available in dev mode because its result set may vary between SQLite versions 2 | test/sem_test_dev.sql:XXXX:1: error: in explain_stmt : CQL0292: explain statement is only available in dev mode because its result set may vary between SQLite versions 3 | semantic errors present; no code gen. 4 | -------------------------------------------------------------------------------- /sources/test/sem_test_dev.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- TEST: explain not supported 9 | -- + {explain_stmt}: err 10 | -- + {int 1} 11 | -- + error: % Explain statement is only available in dev mode because its result set may vary between sqlite versions 12 | -- +1 error: 13 | explain select 1; 14 | 15 | -- TEST: explain query plan with select 16 | -- + {explain_stmt}: err 17 | -- + {int 2} 18 | -- + error: % Explain statement is only available in dev mode because its result set may vary between sqlite versions 19 | -- +1 error: 20 | explain query plan select * from foo inner join bar where foo.id = 1; 21 | -------------------------------------------------------------------------------- /sources/test/sem_test_migrate.err.ref: -------------------------------------------------------------------------------- 1 | test/sem_test_migrate.sql:XXXX:1: error: in str : CQL0069: name not found 'rate_2' 2 | test/sem_test_migrate.sql:XXXX:1: error: in str : CQL0188: procedure is supposed to do schema migration but it doesn't have any DML 'deletor' 3 | test/sem_test_migrate.sql:XXXX:1: error: in params : CQL0233: procedure previously declared as schema upgrade proc, it can have no args 'name_creator' 4 | test/sem_test_migrate.sql:XXXX:1: error: in str : CQL0151: table in delete statement does not exist (not visible in schema version 5) 't1' 5 | test/sem_test_migrate.sql:XXXX:1: error: in str : CQL0151: table in delete statement does not exist (not visible in schema version 5) 't3' 6 | test/sem_test_migrate.sql:XXXX:1: error: in previous_schema_stmt : CQL0254: switching to previous schema validation mode not allowed if @schema_upgrade_version was used 7 | semantic errors present; no code gen. 8 | -------------------------------------------------------------------------------- /sources/test/semantic_error.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- there is no x, this causes the fail path to be taken and no code is generated 9 | -- that's the entire test... any eror will do 10 | set x := 1; 11 | -------------------------------------------------------------------------------- /sources/test/simple_error.err.ref: -------------------------------------------------------------------------------- 1 | test/error.sql:XXXX:1: error: syntax error, unexpected ID 2 | Parse errors found, no further passes will run. 3 | -------------------------------------------------------------------------------- /sources/test/stats.csv.ref: -------------------------------------------------------------------------------- 1 | "foo","add",1 2 | "foo","create_proc_stmt",1 3 | "foo","let_stmt",1 4 | "foo","num",2 5 | "foo","stmt_list",1 6 | "foo","str",2 7 | -------------------------------------------------------------------------------- /sources/test/stats_test.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | create proc foo() 9 | begin 10 | let z := 1 + 2; 11 | end; 12 | -------------------------------------------------------------------------------- /sources/test/udf.c.ref: -------------------------------------------------------------------------------- 1 | 2 | #include "out/udf.h" 3 | 4 | static void _udf_callback(sqlite3_context* context, int argc, sqlite3_value** argv) { 5 | } 6 | 7 | void create_udf(sqlite3 *_Nonnull _db_) { 8 | sqlite3_create_function_v2( 9 | _db_, 10 | "is_declare_func_enabled", 11 | -1, 12 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 13 | NULL, 14 | &_udf_callback, 15 | NULL, 16 | NULL, 17 | NULL 18 | ); 19 | sqlite3_create_function_v2( 20 | _db_, 21 | "is_declare_func_wall", 22 | -1, 23 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 24 | NULL, 25 | &_udf_callback, 26 | NULL, 27 | NULL, 28 | NULL 29 | ); 30 | sqlite3_create_function_v2( 31 | _db_, 32 | "array_num_at", 33 | -1, 34 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 35 | NULL, 36 | &_udf_callback, 37 | NULL, 38 | NULL, 39 | NULL 40 | ); 41 | sqlite3_create_function_v2( 42 | _db_, 43 | "select_virtual_table", 44 | -1, 45 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 46 | NULL, 47 | &_udf_callback, 48 | NULL, 49 | NULL, 50 | NULL 51 | ); 52 | sqlite3_create_function_v2( 53 | _db_, 54 | "bgetkey_type", 55 | -1, 56 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 57 | NULL, 58 | &_udf_callback, 59 | NULL, 60 | NULL, 61 | NULL 62 | ); 63 | sqlite3_create_function_v2( 64 | _db_, 65 | "bgetval_type", 66 | -1, 67 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 68 | NULL, 69 | &_udf_callback, 70 | NULL, 71 | NULL, 72 | NULL 73 | ); 74 | sqlite3_create_function_v2( 75 | _db_, 76 | "bgetkey", 77 | -1, 78 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 79 | NULL, 80 | &_udf_callback, 81 | NULL, 82 | NULL, 83 | NULL 84 | ); 85 | sqlite3_create_function_v2( 86 | _db_, 87 | "bgetval", 88 | -1, 89 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 90 | NULL, 91 | &_udf_callback, 92 | NULL, 93 | NULL, 94 | NULL 95 | ); 96 | sqlite3_create_function_v2( 97 | _db_, 98 | "bcreatekey", 99 | -1, 100 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 101 | NULL, 102 | &_udf_callback, 103 | NULL, 104 | NULL, 105 | NULL 106 | ); 107 | sqlite3_create_function_v2( 108 | _db_, 109 | "bcreateval", 110 | -1, 111 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 112 | NULL, 113 | &_udf_callback, 114 | NULL, 115 | NULL, 116 | NULL 117 | ); 118 | sqlite3_create_function_v2( 119 | _db_, 120 | "bupdatekey", 121 | -1, 122 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 123 | NULL, 124 | &_udf_callback, 125 | NULL, 126 | NULL, 127 | NULL 128 | ); 129 | sqlite3_create_function_v2( 130 | _db_, 131 | "bupdateval", 132 | -1, 133 | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 134 | NULL, 135 | &_udf_callback, 136 | NULL, 137 | NULL, 138 | NULL 139 | ); 140 | } 141 | // The statement ending at line XXXX 142 | 143 | -------------------------------------------------------------------------------- /sources/test/udf.h.ref: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cqlrt.h" 4 | 5 | void create_udf(sqlite3 *_Nonnull _db_); 6 | 7 | // The statement ending at line XXXX 8 | 9 | -------------------------------------------------------------------------------- /sources/test/unwriteable.err.ref: -------------------------------------------------------------------------------- 1 | unable to open /xx/yy/zz for write 2 | -------------------------------------------------------------------------------- /sources/test/upgrade_schema_v1.out.ref: -------------------------------------------------------------------------------- 1 | reference results for version 1 2 | 3 | ----- extra_index ----- 4 | 5 | type: index 6 | tbl_name: g1 7 | CREATE INDEX extra_index ON g1 ( 8 | id) 9 | 10 | ----- extra_trigger ----- 11 | 12 | type: trigger 13 | tbl_name: g1 14 | CREATE TRIGGER extra_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END 15 | 16 | ----- extra_view ----- 17 | 18 | type: view 19 | tbl_name: extra_view 20 | CREATE VIEW extra_view AS SELECT id, 21 | name FROM g1 22 | 23 | ----- g1 ----- 24 | 25 | type: table 26 | tbl_name: g1 27 | CREATE TABLE g1( 28 | id INTEGER PRIMARY KEY, 29 | name TEXT) 30 | 31 | ----- sqlite_autoindex_test_cql_schema_facets_1 ----- 32 | 33 | type: index 34 | tbl_name: test_cql_schema_facets 35 | 36 | ----- staying_index ----- 37 | 38 | type: index 39 | tbl_name: g1 40 | CREATE INDEX staying_index ON g1 ( 41 | id) 42 | 43 | ----- staying_trigger ----- 44 | 45 | type: trigger 46 | tbl_name: g1 47 | CREATE TRIGGER staying_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END 48 | 49 | ----- staying_view ----- 50 | 51 | type: view 52 | tbl_name: staying_view 53 | CREATE VIEW staying_view AS SELECT id, 54 | name FROM g1 55 | 56 | ----- test_cql_schema_facets ----- 57 | 58 | type: table 59 | tbl_name: test_cql_schema_facets 60 | CREATE TABLE test_cql_schema_facets( 61 | facet TEXT NOT NULL PRIMARY KEY, 62 | version LONG_INT NOT NULL) 63 | 64 | ----- test_create_table_A ----- 65 | 66 | type: table 67 | tbl_name: test_create_table_A 68 | CREATE TABLE test_create_table_A( 69 | colA INTEGER, 70 | colB LONG_INT, 71 | colC TEXT, 72 | colD TEXT) 73 | 74 | ----- test_create_table_B ----- 75 | 76 | type: table 77 | tbl_name: test_create_table_B 78 | CREATE TABLE test_create_table_B( 79 | colA TEXT, 80 | colB LONG_INT, 81 | colC INTEGER) 82 | 83 | ----- test_recreate_table_A ----- 84 | 85 | type: table 86 | tbl_name: test_recreate_table_A 87 | CREATE TABLE test_recreate_table_A( 88 | colA INTEGER, 89 | colC TEXT, 90 | colD TEXT) 91 | 92 | ----- test_recreate_table_B ----- 93 | 94 | type: table 95 | tbl_name: test_recreate_table_B 96 | CREATE TABLE test_recreate_table_B( 97 | colA INTEGER, 98 | colB LONG_INT, 99 | colC INTEGER) 100 | 101 | ----- test_this_table_will_become_create ----- 102 | 103 | type: table 104 | tbl_name: test_this_table_will_become_create 105 | CREATE TABLE test_this_table_will_become_create( 106 | id INTEGER PRIMARY KEY) 107 | 108 | ----- use_g1 ----- 109 | 110 | type: table 111 | tbl_name: use_g1 112 | CREATE TABLE use_g1( 113 | id INTEGER PRIMARY KEY REFERENCES g1 ( 114 | id), 115 | name2 TEXT) 116 | 117 | -------------------------------------------------------------------------------- /sources/test/upgrade_schema_v3.out.ref: -------------------------------------------------------------------------------- 1 | reference results for version 3 2 | 3 | ----- extra_index ----- 4 | 5 | type: index 6 | tbl_name: g1 7 | CREATE INDEX extra_index ON g1 ( 8 | id) 9 | 10 | ----- extra_trigger ----- 11 | 12 | type: trigger 13 | tbl_name: g1 14 | CREATE TRIGGER extra_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END 15 | 16 | ----- extra_view ----- 17 | 18 | type: view 19 | tbl_name: extra_view 20 | CREATE VIEW extra_view AS SELECT id, 21 | name FROM g1 22 | 23 | ----- g1 ----- 24 | 25 | type: table 26 | tbl_name: g1 27 | CREATE TABLE g1( 28 | id INTEGER PRIMARY KEY, 29 | name TEXT) 30 | 31 | ----- gChild ----- 32 | 33 | type: table 34 | tbl_name: gChild 35 | CREATE TABLE gChild( 36 | id INTEGER PRIMARY KEY REFERENCES gParent ( 37 | id)) 38 | 39 | ----- gParent ----- 40 | 41 | type: table 42 | tbl_name: gParent 43 | CREATE TABLE gParent( 44 | id INTEGER PRIMARY KEY) 45 | 46 | ----- sqlite_autoindex_test_cql_schema_facets_1 ----- 47 | 48 | type: index 49 | tbl_name: test_cql_schema_facets 50 | 51 | ----- staying_index ----- 52 | 53 | type: index 54 | tbl_name: g1 55 | CREATE INDEX staying_index ON g1 ( 56 | id) 57 | 58 | ----- staying_trigger ----- 59 | 60 | type: trigger 61 | tbl_name: g1 62 | CREATE TRIGGER staying_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END 63 | 64 | ----- staying_view ----- 65 | 66 | type: view 67 | tbl_name: staying_view 68 | CREATE VIEW staying_view AS SELECT id, 69 | name FROM g1 70 | 71 | ----- test_cql_schema_facets ----- 72 | 73 | type: table 74 | tbl_name: test_cql_schema_facets 75 | CREATE TABLE test_cql_schema_facets( 76 | facet TEXT NOT NULL PRIMARY KEY, 77 | version LONG_INT NOT NULL) 78 | 79 | ----- test_create_table_C ----- 80 | 81 | type: table 82 | tbl_name: test_create_table_C 83 | CREATE TABLE test_create_table_C( 84 | colA TEXT, 85 | colB LONG_INT, 86 | colC LONG_INT) 87 | 88 | ----- test_recreate_table_B ----- 89 | 90 | type: table 91 | tbl_name: test_recreate_table_B 92 | CREATE TABLE test_recreate_table_B( 93 | colA INTEGER, 94 | colB LONG_INT, 95 | colC INTEGER) 96 | 97 | ----- test_view ----- 98 | 99 | type: view 100 | tbl_name: test_view 101 | CREATE VIEW test_view AS SELECT colA, 102 | colB FROM test_create_table_C 103 | 104 | ----- use_g1 ----- 105 | 106 | type: table 107 | tbl_name: use_g1 108 | CREATE TABLE use_g1( 109 | id INTEGER PRIMARY KEY REFERENCES g1 ( 110 | id), 111 | name2 TEXT) 112 | 113 | -------------------------------------------------------------------------------- /sources/test/write_fail.err.ref: -------------------------------------------------------------------------------- 1 | unable to open out/unwritable.h.out for write 2 | -------------------------------------------------------------------------------- /sources/test/writefails.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | create proc ThisFileCannotBeWritten() 9 | begin 10 | select 1 as A; 11 | end; 12 | -------------------------------------------------------------------------------- /sources/tester/dbhelp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "cqlrt.h" 11 | 12 | 13 | // Generated from dbhelp.sql:40 14 | extern CQL_WARN_UNUSED cql_code dbhelp_setup(sqlite3 *_Nonnull _db_); 15 | 16 | // Generated from dbhelp.sql:50 17 | extern CQL_WARN_UNUSED cql_code dbhelp_prev_line(sqlite3 *_Nonnull _db_, cql_int32 line_, cql_int32 *_Nonnull prev); 18 | 19 | // Generated from dbhelp.sql:56 20 | extern CQL_WARN_UNUSED cql_code dbhelp_add(sqlite3 *_Nonnull _db_, cql_int32 line, cql_string_ref _Nonnull data); 21 | 22 | // Generated from dbhelp.sql:61 23 | extern CQL_WARN_UNUSED cql_code dbhelp_add_source(sqlite3 *_Nonnull _db_, cql_int32 line, cql_string_ref _Nonnull data); 24 | 25 | // Generated from dbhelp.sql:70 26 | extern CQL_WARN_UNUSED cql_code dbhelp_dump_line(sqlite3 *_Nonnull _db_, cql_int32 line_); 27 | 28 | // Generated from dbhelp.sql:78 29 | extern CQL_WARN_UNUSED cql_code dbhelp_find(sqlite3 *_Nonnull _db_, cql_int32 line_, cql_string_ref _Nonnull pattern, cql_int32 *_Nonnull search_line, cql_int32 *_Nonnull found); 30 | 31 | // Generated from dbhelp.sql:87 32 | extern CQL_WARN_UNUSED cql_code dbhelp_dump_source(sqlite3 *_Nonnull _db_, cql_int32 line1, cql_int32 line2); 33 | 34 | // Generated from dbhelp.sql:92 35 | #define CRC_dbhelp_source -2582919431962037637L 36 | 37 | extern cql_string_ref _Nonnull dbhelp_source_stored_procedure_name; 38 | 39 | #define dbhelp_source_data_types_count 2 40 | 41 | #ifndef result_set_type_decl_dbhelp_source_result_set 42 | #define result_set_type_decl_dbhelp_source_result_set 1 43 | cql_result_set_type_decl(dbhelp_source_result_set, dbhelp_source_result_set_ref); 44 | #endif 45 | extern cql_int32 dbhelp_source_get_line(dbhelp_source_result_set_ref _Nonnull result_set, cql_int32 row); 46 | extern cql_string_ref _Nonnull dbhelp_source_get_data(dbhelp_source_result_set_ref _Nonnull result_set, cql_int32 row); 47 | extern cql_int32 dbhelp_source_result_count(dbhelp_source_result_set_ref _Nonnull result_set); 48 | extern CQL_WARN_UNUSED cql_code dbhelp_source_fetch_results(sqlite3 *_Nonnull _db_, dbhelp_source_result_set_ref _Nullable *_Nonnull result_set); 49 | #define dbhelp_source_row_hash(result_set, row) cql_result_set_get_meta((cql_result_set_ref)(result_set))->rowHash((cql_result_set_ref)(result_set), row) 50 | #define dbhelp_source_row_equal(rs1, row1, rs2, row2) \ 51 | cql_result_set_get_meta((cql_result_set_ref)(rs1))->rowsEqual( \ 52 | (cql_result_set_ref)(rs1), \ 53 | row1, \ 54 | (cql_result_set_ref)(rs2), \ 55 | row2) 56 | -------------------------------------------------------------------------------- /sources/tester/dbhelp.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | -- This file generates dbhelp.c, dbhelp.c is licensed per the below. 9 | 10 | -- ------ cql-verify db helpers 11 | 12 | @echo c, "\n"; 13 | @echo c, "\n"; 14 | @echo c, "//\n"; 15 | @echo c, "// This file is auto-generated by dbhelp.sql, it is checked in just\n"; 16 | @echo c, "// in case CQL is broken by a change. The Last Known Good Verifier\n"; 17 | @echo c, "// can be used to verify the tests pass again, or report failures\n"; 18 | @echo c, "// while things are still otherwise broken. Rebuild with 'regen.sh'\n"; 19 | @echo c, "//\n"; 20 | @echo c, "\n"; 21 | 22 | declare proc printf no check; 23 | 24 | -- setup the table and the index 25 | create procedure dbhelp_setup() 26 | begin 27 | create table test_output( 28 | line integer not null, 29 | data text not null 30 | ); 31 | 32 | create index __idx__test_lines on test_output (line); 33 | 34 | create table source_input( 35 | line integer not null, 36 | data text not null 37 | ); 38 | 39 | create index __idx__source_lines on source_input (line); 40 | end; 41 | 42 | create procedure dbhelp_prev_line(line_ integer not null, out prev integer not null) 43 | begin 44 | begin try 45 | set prev := (select ifnull(max(line),-1) from test_output where line < line_); 46 | end try; 47 | begin catch 48 | set prev := 0; 49 | end catch; 50 | end; 51 | 52 | -- add a row to the results table 53 | create procedure dbhelp_add(line integer not null, data text not null) 54 | begin 55 | insert into test_output values (line, data); 56 | end; 57 | 58 | create procedure dbhelp_add_source(line integer not null, data text not null) 59 | begin 60 | insert into source_input values (line, data); 61 | end; 62 | 63 | create procedure dbhelp_dump_line(line_ integer not null) 64 | begin 65 | declare C cursor for select * from test_output where line = line_; 66 | loop fetch C 67 | begin 68 | call printf('%s', C.data); 69 | end; 70 | end; 71 | 72 | -- find the statement that came after line_ 73 | -- search the results of that statement for the indicated pattern 74 | create proc dbhelp_find(line_ integer not null, pattern text not null, out search_line integer not null, out found integer not null) 75 | begin 76 | set search_line := (select line from test_output where line >= line_ limit 1); 77 | set found := (select count(*) from test_output where line = search_line and data like pattern); 78 | end; 79 | 80 | create procedure dbhelp_dump_source(line1 integer not null, line2 integer not null) 81 | begin 82 | declare C cursor for select * from source_input where line > line1 and line <= line2; 83 | loop fetch C 84 | begin 85 | call printf('%s', C.data); 86 | end; 87 | end; 88 | 89 | create procedure dbhelp_source() 90 | begin 91 | select * from source_input; 92 | end; 93 | -------------------------------------------------------------------------------- /sources/tester/regen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # @licenselint-loose-mode 8 | 9 | set -euo pipefail 10 | 11 | pushd .. 12 | make clean && make 13 | popd 14 | 15 | ../out/cql --nolines --in dbhelp.sql --cg dbhelp.h dbhelp.c 16 | 17 | # We do all this so that we can normalize the generated helper. We 18 | # want the same header shape with the OSS version of CQL and the 19 | # internal and they have different copyright messages. The 20 | # test helper is part of the OSS. 21 | 22 | sed -e "/autogenerated/d" \ 23 | -e "/generated SignedSource/d" \ 24 | -e "/(c).*Meta Platforms/d" dbhelp.c2 25 | 26 | sed -e "/autogenerated/d" \ 27 | -e "/generated SignedSource/d" \ 28 | -e "/(c).*Meta Platforms/d" dbhelp.h2 29 | 30 | (cat <dbhelp.c 31 | /* 32 | * Copyright (c) Meta Platforms, Inc. and affiliates. 33 | * 34 | * This source code is licensed under the MIT license found in the 35 | * LICENSE file in the root directory of this source tree. 36 | */ 37 | EOF 38 | 39 | (cat <dbhelp.h 40 | /* 41 | * Copyright (c) Meta Platforms, Inc. and affiliates. 42 | * 43 | * This source code is licensed under the MIT license found in the 44 | * LICENSE file in the root directory of this source tree. 45 | */ 46 | EOF 47 | 48 | rm dbhelp.h2 dbhelp.c2 49 | -------------------------------------------------------------------------------- /sources/unit_tests.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /** 9 | * Run all known CQL unit test. Crashes and prints an error message if any 10 | * of the tests fails. 11 | */ 12 | cql_noexport void run_unit_tests(void); 13 | -------------------------------------------------------------------------------- /sources/update_docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | set -euo pipefail 8 | 9 | CQL_SOURCES=$(git rev-parse --show-toplevel)/sources 10 | GRAMMAR_DOCS=${CQL_SOURCES}/grammar_docs 11 | CQL_GUIDE=${CQL_SOURCES}/../CQL_Guide 12 | DIAGRAMS=${CQL_SOURCES}/../diagrams 13 | 14 | # shellcheck disable=SC1091 15 | source common/update_docs.sh || exit 1 16 | -------------------------------------------------------------------------------- /sources/upgrade/SchemaPersistentV0.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /* @create/@delete tables */ 9 | CREATE TABLE test_create_table_A( 10 | colA INT, 11 | colB LONG INT, 12 | colC TEXT 13 | ); 14 | 15 | /* @recreate tables */ 16 | CREATE TABLE test_recreate_table_A( 17 | colA INT, 18 | colB LONG INT, 19 | colC TEXT 20 | ) @recreate; 21 | 22 | -- make a recreate-group with an FK dependency (legal) 23 | CREATE TABLE g1( 24 | id INTEGER PRIMARY KEY, 25 | name TEXT 26 | ) @recreate(gr1); 27 | 28 | CREATE TABLE use_g1( 29 | id INTEGER PRIMARY KEY REFERENCES g1(id), 30 | name2 TEXT 31 | ) @recreate(gr1); 32 | 33 | -- we will migrate this table to create in version 1 34 | CREATE TABLE test_this_table_will_become_create( 35 | xyzzy integer -- we'll change the table in a significant way 36 | ) @recreate; 37 | 38 | -- we will be unsubscribing and resubscribing this table in later versions 39 | CREATE TABLE test_for_unsub( 40 | unsub_id integer, 41 | x text 42 | ); 43 | 44 | -- making an index for the table, this will appear and disappear 45 | CREATE INDEX test_for_unsub_index ON test_for_unsub(x); 46 | 47 | -- making a trigger for the table, this will appear and disappear 48 | CREATE TRIGGER test_for_unsub_trigger 49 | BEFORE DELETE ON test_for_unsub 50 | WHEN old.unsub_id = 3 51 | BEGIN 52 | DELETE FROM test_for_unsub WHERE unsub_id = 3; 53 | END; 54 | 55 | -- we will be unsubscribing and resubscribing this table in later versions 56 | CREATE TABLE recreate_test_for_unsub( 57 | unsub_id integer, 58 | x text 59 | ) @recreate(a_recreate_group); 60 | 61 | -- making an index for the table, this will appear and disappear 62 | CREATE INDEX recreate_test_for_unsub_index ON recreate_test_for_unsub(x); 63 | 64 | -- making a trigger for the table, this will appear and disappear 65 | CREATE TRIGGER recreate_test_for_unsub_trigger 66 | BEFORE DELETE ON recreate_test_for_unsub 67 | WHEN old.unsub_id = 3 68 | BEGIN 69 | DELETE FROM recreate_test_for_unsub WHERE unsub_id = 3; 70 | END; 71 | 72 | -- extra items that will disappear when we switch to exclusive mode 73 | CREATE VIEW extra_view AS SELECT * FROM g1; 74 | 75 | CREATE INDEX extra_index ON g1(id); 76 | 77 | CREATE TRIGGER extra_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END; 78 | 79 | -- additional items that will not disappear even in exclusive mode 80 | CREATE VIEW staying_view AS SELECT * FROM g1; 81 | 82 | CREATE INDEX staying_index ON g1(id); 83 | 84 | CREATE TRIGGER staying_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END; 85 | -------------------------------------------------------------------------------- /sources/upgrade/SchemaPersistentV1.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /* @create/@delete tables */ 9 | CREATE TABLE test_create_table_A( 10 | colA INT, 11 | colB LONG INT, 12 | colC TEXT, 13 | colD TEXT @create(1) 14 | ); 15 | 16 | CREATE TABLE test_create_table_B( 17 | colA TEXT, 18 | colB LONG INT, 19 | colC INT 20 | ) @create(1); 21 | 22 | /* @recreate tables */ 23 | CREATE TABLE test_recreate_table_A( 24 | colA INT, 25 | colC TEXT, 26 | colD TEXT 27 | ) @recreate; 28 | 29 | CREATE TABLE test_recreate_table_B( 30 | colA INT, 31 | colB LONG INT, 32 | colC INT 33 | ) @recreate; 34 | 35 | -- make a recreate-group with an FK dependency (legal) 36 | 37 | CREATE TABLE g1( 38 | id INTEGER PRIMARY KEY, 39 | name TEXT 40 | ) @recreate(gr1); 41 | 42 | CREATE TABLE use_g1( 43 | id INTEGER PRIMARY KEY REFERENCES g1(id), 44 | name2 TEXT 45 | ) @recreate(gr1); 46 | 47 | -- this table changes to the create plan (note table contents changed) 48 | CREATE TABLE test_this_table_will_become_create( 49 | id integer primary key 50 | ) @create(1, cql:from_recreate); 51 | 52 | -- we will be unsubscribing and resubscribing this table in later versions 53 | CREATE TABLE test_for_unsub( 54 | unsub_id integer, 55 | x text 56 | ); 57 | 58 | -- making an index for the table, this will appear and disappear 59 | CREATE INDEX test_for_unsub_index ON test_for_unsub(x); 60 | 61 | -- making a trigger for the table, this will appear and disappear 62 | CREATE TRIGGER test_for_unsub_trigger 63 | BEFORE DELETE ON test_for_unsub 64 | WHEN old.unsub_id = 3 65 | BEGIN 66 | DELETE FROM test_for_unsub WHERE unsub_id = 3; 67 | END; 68 | 69 | -- we will be unsubscribing and resubscribing this table in later versions 70 | CREATE TABLE recreate_test_for_unsub( 71 | unsub_id integer, 72 | x text 73 | ) @recreate(a_recreate_group); 74 | 75 | -- making an index for the table, this will appear and disappear 76 | CREATE INDEX recreate_test_for_unsub_index ON recreate_test_for_unsub(x); 77 | 78 | -- making a trigger for the table, this will appear and disappear 79 | CREATE TRIGGER recreate_test_for_unsub_trigger 80 | BEFORE DELETE ON recreate_test_for_unsub 81 | WHEN old.unsub_id = 3 82 | BEGIN 83 | DELETE FROM recreate_test_for_unsub WHERE unsub_id = 3; 84 | END; 85 | 86 | @unsub(test_for_unsub); 87 | @unsub(recreate_test_for_unsub); 88 | 89 | -- extra items that will disappear when we switch to exclusive mode 90 | CREATE VIEW extra_view AS SELECT * FROM g1; 91 | 92 | CREATE INDEX extra_index ON g1(id); 93 | 94 | CREATE TRIGGER extra_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END; 95 | 96 | -- additional items that will not disappear even in exclusive mode 97 | CREATE VIEW staying_view AS SELECT * FROM g1; 98 | 99 | CREATE INDEX staying_index ON g1(id); 100 | 101 | CREATE TRIGGER staying_trigger BEFORE DELETE ON g1 BEGIN SELECT 1; END; 102 | -------------------------------------------------------------------------------- /sources/upgrade/downgrade_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | // All versions have the same signatures, include them all! 12 | // If we screwed this up the compiler will complain! 13 | // 14 | // Note that the downgrade test of course uses the upgrader but with a bad setup 15 | // there is no such thing as a generated downgrader... 16 | #include "generated_upgrade0.h" 17 | #include "generated_upgrade1.h" 18 | #include "generated_upgrade2.h" 19 | #include "generated_upgrade3.h" 20 | 21 | int downgrade(sqlite3* db, test_result_set_ref* result_set) { 22 | return test_fetch_results(db, result_set); 23 | } 24 | 25 | int validate(sqlite3* db, test_result_set_ref result_set) { 26 | cql_int32 count = test_result_count(result_set); 27 | if (count != 1) { 28 | printf("Expected 1 facet for database downgrade, got %d\n", count); 29 | return SQLITE_ERROR; 30 | } 31 | cql_string_ref expected_facet = cql_string_ref_new("downgrade detected"); 32 | cql_string_ref actual_facet = test_get_facet(result_set, 0); 33 | if (!cql_string_equal(expected_facet, actual_facet)) { 34 | cql_alloc_cstr(actual_facet_c, actual_facet); 35 | printf("Expected 'downgrade detected' facet, got '%s'\n", actual_facet_c); 36 | cql_free_cstr(actual_facet_c, actual_facet); 37 | cql_string_release(expected_facet); 38 | return SQLITE_ERROR; 39 | } 40 | const char* sql = "DROP VIEW test_view"; 41 | if (sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK) { 42 | printf("Expected 'test_view' to remain in the DB\n"); 43 | return SQLITE_ERROR; 44 | } 45 | return SQLITE_OK; 46 | } 47 | 48 | int main(int argc, char* argv[]) { 49 | if (argc != 2) { 50 | printf("Expected usage: ./downgrade_test /path/to/db/\n"); 51 | return SQLITE_ERROR; 52 | } 53 | 54 | sqlite3* db; 55 | if (sqlite3_open_v2( 56 | argv[1], &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) { 57 | printf("Unable to open DB.\n"); 58 | return SQLITE_ERROR; 59 | } 60 | 61 | test_result_set_ref result_set; 62 | if (downgrade(db, &result_set)) { 63 | printf("Unable to downgrade DB.\n"); 64 | return SQLITE_ERROR; 65 | } 66 | 67 | if (validate(db, result_set)) { 68 | printf("Unable to validate that the downgrade was detected.\n"); 69 | cql_result_set_release(result_set); 70 | return SQLITE_ERROR; 71 | } 72 | 73 | if (sqlite3_close_v2(db)) { 74 | printf("Unable to close DB.\n"); 75 | cql_result_set_release(result_set); 76 | return SQLITE_ERROR; 77 | } 78 | 79 | cql_result_set_release(result_set); 80 | return SQLITE_OK; 81 | } 82 | 83 | cql_code mockable_sqlite3_step(sqlite3_stmt *stmt) { 84 | return sqlite3_step(stmt); 85 | } 86 | -------------------------------------------------------------------------------- /sources/upgrade/errortrace.inc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /* 9 | * Include this file to enable error tracing in interesting places. 10 | * It isn't used anywhere by default but you can jam it into a failing upgrader 11 | * to help you debug. 12 | */ 13 | 14 | @echo c, "#undef cql_error_trace\n"; 15 | @echo c, "#define cql_error_trace() fprintf(stderr, \"SQL Failure %d %s: %s %d\\n\", _rc_, sqlite3_errmsg(_db_), __FILE__, __LINE__)\n"; 16 | -------------------------------------------------------------------------------- /website/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | const OFF = 0; 11 | const WARNING = 1; 12 | const ERROR = 2; 13 | 14 | module.exports = { 15 | root: true, 16 | env: { 17 | browser: true, 18 | commonjs: true, 19 | jest: true, 20 | node: true, 21 | }, 22 | parser: 'babel-eslint', 23 | parserOptions: { 24 | allowImportExportEverywhere: true, 25 | }, 26 | extends: ['airbnb', 'prettier', 'prettier/react'], 27 | plugins: ['react-hooks', 'header'], 28 | rules: { 29 | // Ignore certain webpack alias because it can't be resolved 30 | 'import/no-unresolved': [ 31 | ERROR, 32 | {ignore: ['^@theme', '^@docusaurus', '^@generated']}, 33 | ], 34 | 'import/extensions': OFF, 35 | 'header/header': [ 36 | ERROR, 37 | 'block', 38 | 39 | [ 40 | '*', 41 | ' * Copyright (c) Meta Platforms, Inc. and affiliates.', 42 | ' *', 43 | ' * This source code is licensed under the MIT license found in the', 44 | ' * LICENSE file in the root directory of this source tree.', 45 | ' *', 46 | // Unfortunately eslint-plugin-header doesn't support optional lines. 47 | // If you want to enforce your website JS files to have @flow or @format, 48 | // modify these lines accordingly. 49 | { 50 | pattern: '.* @format', 51 | }, 52 | ' ', 53 | ], 54 | ], 55 | 'react/jsx-closing-bracket-location': OFF, // Conflicts with Prettier. 56 | 'react/jsx-filename-extension': OFF, 57 | 'react-hooks/rules-of-hooks': ERROR, 58 | 'react/prop-types': OFF, // PropTypes aren't used much these days. 59 | }, 60 | }; 61 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | # ESLint 23 | .eslintcache 24 | -------------------------------------------------------------------------------- /website/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .docusaurus 4 | -------------------------------------------------------------------------------- /website/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": false, 4 | "jsxBracketSameLine": true, 5 | "printWidth": 80, 6 | "proseWrap": "never", 7 | "singleQuote": true, 8 | "trailingComma": "all" 9 | } 10 | -------------------------------------------------------------------------------- /website/.stylelintrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | module.exports = { 9 | plugins: ['stylelint-copyright'], 10 | rules: { 11 | 'docusaurus/copyright-header': true, 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. 4 | 5 | ## Contributing 6 | 7 | Docusaurus uses Markdown and MDX for its content, so there are almost no limits to what can be done on the site. 8 | 9 | ### Blogging 10 | 11 | If you would like to contribute to the blog, add a new entry to the /blog directory. Please follow a metadata format described in the initial post. 12 | 13 | ### Docs 14 | 15 | Primary documentation is located in the [/docs folder](https://github.com/facebookincubator/CG-SQL/tree/master/docs). To add a new entry, do the following: 16 | 17 | 1) Create a new `.md` file, let's say `example.md` 18 | 2) In the `example.md`, add a heading with the next metadata: 19 | * `id` - ID for the file to be referenced in the Docusaurus's navigation and URL structure 20 | * `title` - Title of the file as it will be shown on the site 21 | * `sidebar_label` - Label of the file for a navigation sidebar 22 | 23 | Example for `example.md`: 24 | 25 | ``` 26 | id: example 27 | title: Example for CG/SQL 28 | sidebar_label: Example for CG/SQL 29 | ``` 30 | 3) In [/website/sidebars.js](https://github.com/facebookincubator/CG-SQL/blob/master/website/sidebars.js), add `id` of your newly created site. You will need to either create a new subheading for the sidebar or add your new file under an existing sidebar. 31 | 32 | Example for `example.md`: 33 | `Resources: ['dev-notes', 'example'],` 34 | 35 | ### CQL Guide 36 | 37 | Similarly to the [Docs' contributions](#docs), CQL Guide uses Markdown for its files and follow the same pattern for headers' metadata. 38 | 39 | The only difference is that instead of using [/website/sidebars.js](https://github.com/facebookincubator/CG-SQL/blob/master/website/sidebars.js), a contributor needs to work with [/website/sidebarsGuide.js](https://github.com/facebookincubator/CG-SQL/blob/master/website/sidebars.js) 40 | -------------------------------------------------------------------------------- /website/babel.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | module.exports = { 11 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 12 | }; 13 | -------------------------------------------------------------------------------- /website/blog/2020-10-12-welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: welcome 3 | title: Welcome 4 | author: CG/SQL Team 5 | author_title: Maintainer of CG/SQL 6 | author_url: https://github.com/facebookincubator 7 | author_image_url: https://avatars2.githubusercontent.com/u/69631?s=200&v=4 8 | tags: [facebook, cg-sql, welcome] 9 | --- 10 | 11 | Hello everyone! 12 | 13 | Thank you for visiting the CG/SQL's blog page. If you would like to read the very first blog announcing the project, please go over to the [Facebook's Engineering post](https://engineering.fb.com/open-source/cg-sql/) published in early Octover 2020. 14 | 15 | Looking forward to working with all of you! 16 | 17 | Sincerely, 18 | CG/SQL Team 19 | -------------------------------------------------------------------------------- /website/blog/2021-01-14-named-types-intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: named-types-into 3 | title: Introducing Named Types 4 | author: CG/SQL Team 5 | author_title: Maintainer of CG/SQL 6 | author_url: https://github.com/facebookincubator 7 | author_image_url: https://avatars2.githubusercontent.com/u/69631?s=200&v=4 8 | tags: [facebook, cg-sql] 9 | --- 10 | 11 | A common source of errors in stored procedures is incorrect typing in arguments. For instance, a particular key 12 | for an entity might need to be `LONG` or even always `LONG NOT NULL` or `LONG NOT NULL @SENSITIVE` and the only 13 | way to do this in the past was maybe with some `#define` thing. Otherwise you have to diligently get the type right 14 | in all the places, and should it ever change, again you have to visit all the places. To help with this situation, 15 | and to make code a little more self-describing we add named types to the language. This is a lot like `typedef` in 16 | the C language. They do not create different incompatible types but do let you name things well. 17 | 18 | You can now write these sorts of forms: 19 | 20 | ``` 21 | declare foo_id type long not null; 22 | 23 | create table foo( 24 | id foo_id primary key autoincrement, 25 | name text 26 | ); 27 | 28 | create proc inserter(name_ text, out id foo_id) 29 | begin 30 | insert into foo(id, name) values(NULL, name_); 31 | set id := last_insert_rowid(); 32 | end; 33 | ``` 34 | 35 | Refer to the [railroad diagram](https://cgsql.dev/program-diagram#declare_stmt) for the grammar details. 36 | 37 | Additionally any enumerated type can be used as a type name. e.g. 38 | 39 | ``` 40 | declare enum thing integer ( 41 | thing1, 42 | thing2 43 | ); 44 | 45 | declare x thing; 46 | ``` 47 | 48 | Enumerations always get "not null" in addition to their base type. 49 | 50 | This isn't a very complex feature but we hope that it will help create clearer code that is less likely to have type-related bugs. 51 | -------------------------------------------------------------------------------- /website/blog/2021-02-10-free-empty-results.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: free-empty-results 3 | title: Change in No-Result Semantics 4 | author: CG/SQL Team 5 | author_title: Maintainer of CG/SQL 6 | author_url: https://github.com/facebookincubator 7 | author_image_url: https://avatars2.githubusercontent.com/u/69631?s=200&v=4 8 | tags: [facebook, cg-sql] 9 | --- 10 | 11 | Important change in CQL semantics. 12 | 13 | Previously if you did an early return, or fall through the end, from a procedure that is supposed to return a result set 14 | but did not in fact provide one, you would get a fake SQLITE_ERROR. Now you get an empty result set for "free". 15 | 16 | This interpretation seems much more natural and avoids a lot of really annoying stub selects to comply with the contract. 17 | 18 | This also works for the `out` statement in the same fashion. 19 | 20 | If you want to return an error, use `throw`. This is a lot more natural... 21 | 22 | examples: 23 | 24 | ```sql 25 | -- this gives you an empty result set if x <= 0 26 | create proc maybe_return(x integer) 27 | begin 28 | if x > 0 then 29 | select * from foo where foo.y > x; 30 | end if; 31 | end; 32 | 33 | -- so does this 34 | create proc maybe_return(x integer) 35 | begin 36 | if x <= 0 then 37 | return; 38 | end if; 39 | select * from foo where foo.y > x; 40 | end; 41 | 42 | -- so does this 43 | create proc maybe_out(x integer) 44 | begin 45 | if x <= 0 then 46 | declare C cursor for select etc. 47 | out C; 48 | end if; 49 | end; 50 | ``` 51 | -------------------------------------------------------------------------------- /website/blog/2021-02-14-select-if-nothing.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: select-if-nothing 3 | title: Introducing Select .. If Nothing 4 | author: CG/SQL Team 5 | author_title: Maintainer of CG/SQL 6 | author_url: https://github.com/facebookincubator 7 | author_image_url: https://avatars2.githubusercontent.com/u/69631?s=200&v=4 8 | tags: [facebook, cg-sql] 9 | --- 10 | 11 | The nested select statement is frequently misused, in particular if you get no rows back from the expression that's an error. So for instance: 12 | 13 | ```sql 14 | set x_ := (select x from foo.x where id = y); 15 | ``` 16 | 17 | This will throw (with a peculiar error, `SQLITE_DONE`) if there is no such row. 18 | 19 | Sometimes people try to fix this problem with a nullcheck: 20 | 21 | ```sql 22 | set x_ := IFNULL((select x from foo.x where id = y), -1); 23 | ``` 24 | 25 | That doesn't help at all. It's not a null value situation, there's no row at all. 26 | 27 | ```sql 28 | set x_ := (select IFNULL(x,-1) from foo.x where id = y), -1); 29 | ``` 30 | 31 | Is likewise unhelpful. To help with this situation we add two forms: 32 | 33 | 34 | ```sql 35 | -- useful if foo.x is already known to be not null 36 | set x_ := (select x from foo.x where id = y IF NOTHING -1); 37 | 38 | -- useful if foo.x might be null 39 | set x_ := (select x from foo.x where id = y IF NOTHING OR NULL -1); 40 | ``` 41 | 42 | Both of these deal with the case where there is no row. The second lets you have a simple default for both 43 | no row or null value. That form is equivalent to: 44 | 45 | ```sql 46 | set x_ := (select IFNULL(x,-1) from foo.x where id = y IF NOTHING -1); 47 | ``` 48 | 49 | i.e. both problem cases are handled. 50 | 51 | Of course the -1 here could be any valid expression, even a second `(select...)` 52 | -------------------------------------------------------------------------------- /website/blog/2021-02-21-result-variable.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: result-variable 3 | title: Introducing @RC builtin variable 4 | author: CG/SQL Team 5 | author_title: Maintainer of CG/SQL 6 | author_url: https://github.com/facebookincubator 7 | author_image_url: https://avatars2.githubusercontent.com/u/69631?s=200&v=4 8 | tags: [facebook, cg-sql] 9 | --- 10 | 11 | We've long needed a way to see the most recent SQLite result code SQLite in the context 12 | of say a `catch` block (most other times you can assume SQLITE_OK was the last 13 | result code otherwise control flow would transfer elsewhere. Sometimes SQLITE_ROW 14 | or SQLITE_DONE might be the current result code. 15 | 16 | Soon we'll provide a sample header that declares the most common error codes in an enum but 17 | for now you could do something like this: 18 | 19 | ```sql 20 | -- pasted from the sqlite.c 21 | #define SQLITE_BUSY 5 /* The database file is locked */ 22 | 23 | -- this is a contrived example 24 | create proc get_first_foo(out can_retry bool not null) 25 | begin 26 | 27 | -- can_retry is set to 0 automatically, language semantics guarantee this 28 | 29 | begin try 30 | select foo from bar limit 1; 31 | end try; 32 | begin catch 33 | set can_retry := (@rc == SQLITE_BUSY); 34 | throw; -- rethrow the original error 35 | end catch; 36 | end; 37 | ``` 38 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "clean": "docusaurus clear", 10 | "swizzle": "docusaurus swizzle", 11 | "deploy": "docusaurus deploy", 12 | "serve": "docusaurus serve", 13 | "ci": "yarn lint && yarn prettier:diff", 14 | "lint": "eslint --cache \"**/*.js\" && stylelint \"**/*.css\"", 15 | "prettier": "prettier --config .prettierrc --write \"**/*.{js,md}\"", 16 | "prettier:diff": "prettier --config .prettierrc --list-different \"**/*.{js,md}\"" 17 | }, 18 | "dependencies": { 19 | "@docusaurus/core": "^2.3.0", 20 | "@docusaurus/preset-classic": "^2.3.0", 21 | "@mdx-js/react": "^1.5.8", 22 | "clsx": "^1.1.1", 23 | "docusaurus-plugin-internaldocs-fb": "^1.10.1", 24 | "html-loader": "^1.3.2", 25 | "my-loaders": "file:plugins/my-loaders", 26 | "react": "^17.0.1", 27 | "react-dom": "^17.0.1" 28 | }, 29 | "devDependencies": { 30 | "babel-eslint": "^10.0.3", 31 | "eslint": "^6.7.1", 32 | "eslint-config-airbnb": "^18.0.1", 33 | "eslint-config-prettier": "^6.7.0", 34 | "eslint-plugin-header": "^3.0.0", 35 | "eslint-plugin-import": "^2.21.2", 36 | "eslint-plugin-jsx-a11y": "^6.2.3", 37 | "eslint-plugin-react": "^7.20.0", 38 | "eslint-plugin-react-hooks": "^4.0.4", 39 | "prettier": "^2.0.2", 40 | "stylelint": "^13.2.1" 41 | }, 42 | "browserslist": { 43 | "production": [ 44 | ">0.2%", 45 | "not dead", 46 | "not op_mini all" 47 | ], 48 | "development": [ 49 | "last 1 chrome version", 50 | "last 1 firefox version", 51 | "last 1 safari version" 52 | ] 53 | }, 54 | "resolutions": { 55 | "trim": "0.0.3", 56 | "minimatch": "3.1.2" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /website/plugins/my-loaders/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | module.exports = function(context, options) { 11 | return { 12 | name: 'loaders', 13 | configureWebpack(config, isServer) { 14 | return { 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.(html)$/, 19 | use: { 20 | loader: 'html-loader', 21 | }, 22 | }, 23 | ], 24 | }, 25 | }; 26 | }, 27 | }; 28 | }; 29 | -------------------------------------------------------------------------------- /website/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | module.exports = { 11 | someSidebar: { 12 | 'Quick Start': ['introduction', 'getting-started', 'playground'], 13 | 'Contributors': ['dev-notes', 'code-coverage', 'testing'], 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /website/sidebarsGuide.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | module.exports = { 11 | someSidebar: { 12 | 'CQL Guide': [ 13 | 'ch01', 'ch02', 'ch03', 'ch04', 'ch05', 14 | 'ch06', 'ch07', 'ch08', 'ch09', 'ch10', 15 | 'ch11', 'ch12', 'ch13', 'ch14', 'ch15' 16 | ], 17 | Appendix: [ 18 | 'x1', 'x2', 'x3', 'x4', 'x5', 19 | 'x6', 'x7', 'x8', 'x9', 'x10', 20 | 'x11' 21 | ], 22 | 'CQL Internals': [ 23 | 'int01', 'int02', 'int03', 'int04', 'int05', 24 | 'int06', 'int07', 'int08' 25 | ], 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /website/src/components/DiagramContent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | class DiagramContent extends React.Component { 12 | render() { 13 | return ( 14 |

15 |
16 |
17 |
18 |
19 |
20 |
21 | ); 22 | } 23 | } 24 | 25 | export default DiagramContent; 26 | -------------------------------------------------------------------------------- /website/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | /** 11 | * Any CSS included here will be global. The classic template 12 | * bundles Infima by default. Infima is a CSS framework designed to 13 | * work well for content-centric websites. 14 | */ 15 | 16 | /* You can override the default Infima variables here. */ 17 | 18 | :root { 19 | --ifm-color-primary: #357dc2; 20 | --ifm-color-primary-dark: #3071af; 21 | --ifm-color-primary-darker: #2d6aa5; 22 | --ifm-color-primary-darkest: #255888; 23 | --ifm-color-primary-light: #4489cc; 24 | --ifm-color-primary-lighter: #4e8fcf; 25 | --ifm-color-primary-lightest: #6ba2d6; 26 | --ifm-code-font-size: 95%; 27 | } 28 | 29 | .docusaurus-highlight-code-line { 30 | background-color: rgb(72, 77, 91); 31 | display: block; 32 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 33 | padding: 0 var(--ifm-pre-padding); 34 | } 35 | 36 | 37 | /* Announcement banner */ 38 | 39 | :root { 40 | --docusaurus-announcement-bar-height: auto !important; 41 | } 42 | 43 | div[class^="announcementBarContent"] { 44 | line-height: 40px; 45 | font-size: 20px; 46 | font-weight: bold; 47 | padding: 8px 30px; 48 | } 49 | 50 | div[class^="announcementBarContent"] a { 51 | text-decoration: underline; 52 | display: inline-block; 53 | color: var(--ifm-color-primary-lightest) !important; 54 | } 55 | 56 | div[class^="announcementBarContent"] a:hover { 57 | color: var(--brand) !important; 58 | } 59 | 60 | @media only screen and (max-width: 768px) { 61 | .announcement { 62 | font-size: 18px; 63 | } 64 | } 65 | 66 | @media only screen and (max-width: 500px) { 67 | .announcement { 68 | font-size: 15px; 69 | line-height: 22px; 70 | padding: 6px 30px; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /website/src/pages/json-diagram.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 13 | import DiagramContent from '../components/DiagramContent'; 14 | 15 | var resultsTemplate = require('../../../diagrams/json_output_railroad_diagram.html'); 16 | 17 | function Diagrams() { 18 | const context = useDocusaurusContext(); 19 | const {siteConfig = {}} = context; 20 | return ( 21 | 24 | 25 | 26 | ); 27 | } 28 | 29 | export default Diagrams; 30 | -------------------------------------------------------------------------------- /website/src/pages/program-diagram.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 13 | import DiagramContent from '../components/DiagramContent'; 14 | 15 | var resultsTemplate = require('../../../diagrams/railroad_diagram.html'); 16 | 17 | function Diagrams() { 18 | const context = useDocusaurusContext(); 19 | const {siteConfig = {}} = context; 20 | return ( 21 | 24 | 25 | 26 | ); 27 | } 28 | 29 | export default Diagrams; 30 | -------------------------------------------------------------------------------- /website/src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | /** 11 | * CSS files with the .module.css suffix will be treated as CSS modules 12 | * and scoped locally. 13 | */ 14 | 15 | .heroBanner { 16 | padding: 4rem 0; 17 | text-align: center; 18 | position: relative; 19 | overflow: hidden; 20 | } 21 | 22 | @media screen and (max-width: 966px) { 23 | .heroBanner { 24 | padding: 2rem; 25 | } 26 | } 27 | 28 | .buttons { 29 | display: flex; 30 | align-items: center; 31 | justify-content: center; 32 | } 33 | 34 | .features { 35 | display: flex; 36 | align-items: center; 37 | padding: 2rem 0; 38 | width: 100%; 39 | } 40 | 41 | .featureImage { 42 | height: 200px; 43 | width: 200px; 44 | } 45 | 46 | .features { 47 | display: flex; 48 | align-items: center; 49 | padding: 4rem 0; 50 | width: 100%; 51 | } 52 | 53 | .featureImage { 54 | margin: 0 auto; 55 | } 56 | 57 | .videoSection { 58 | background-color: #f7f7f7; 59 | } 60 | 61 | html[data-theme='dark'] .videoSection { 62 | background-color: #33363b; 63 | } 64 | -------------------------------------------------------------------------------- /website/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/website/static/.nojekyll -------------------------------------------------------------------------------- /website/static/CNAME: -------------------------------------------------------------------------------- 1 | cgsql.dev 2 | -------------------------------------------------------------------------------- /website/static/img/CGSQL-Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/website/static/img/CGSQL-Icon.png -------------------------------------------------------------------------------- /website/static/img/CGSQL-Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/website/static/img/CGSQL-Logo.png -------------------------------------------------------------------------------- /website/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/website/static/img/favicon.ico -------------------------------------------------------------------------------- /website/static/img/oss_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookincubator/CG-SQL/c32ca40310a322e82ec4d6d863d77eed1633ef02/website/static/img/oss_logo.png --------------------------------------------------------------------------------