[
  {
    "path": ".docker/Dockerfile",
    "content": "FROM golang:1.21-bullseye as build-env\n\nARG APP_VERSION\n\nWORKDIR /usr/src/app\nADD ./ /usr/src/app\n\nRUN go build -ldflags \"-X github.com/nixys/nxs-data-anonymizer/ctx.version=$APP_VERSION\" -o /nxs-data-anonymizer\n\nFROM alpine\n\nRUN apk update --no-cache && apk add --no-cache tar postgresql-client mysql-client libc6-compat s3cmd\n\nCOPY --from=build-env /nxs-data-anonymizer /\n\n"
  },
  {
    "path": ".github/release.yml",
    "content": "# .github/release.yml\n\nchangelog:\n  exclude:\n    labels:\n    - ignore-for-release\n  categories:\n  - title: Breaking Changes 🛠\n    labels:\n    - Semver-Major\n    - breaking-change\n  - title: Exciting New Features 🎉\n    labels:\n    - Semver-Minor\n    - enhancement\n  - title: Fixes 🪲\n    labels:\n    - Semver-Patch\n    - bug\n  - title: Other Changes\n    labels:\n    - \"*\""
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Release\n\non:\n  push:\n    tags:\n    - 'v*'\n\njobs:\n\n  build-and-publish-release:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        include:\n        - os: ubuntu-latest\n          TARGET: arm64\n        - os: ubuntu-latest\n          TARGET: amd64\n\n    steps:\n    - name: Building ${{ matrix.TARGET }}\n      run: echo \"${{ matrix.TARGET }}\"\n\n    - uses: actions/checkout@v4\n\n    - uses: actions/setup-go@v3\n      name: Set up Go\n      with:\n        go-version: 1.21\n\n    - name: Get version\n      id: get_version\n      uses: battila7/get-version-action@v2\n\n    - name: Build\n      run: GOOS=linux GOARCH=${{ matrix.TARGET }} CGO_ENABLED=0 go build -ldflags=\"-s -w -X github.com/nixys/nxs-data-anonymizer/ctx.version=${{ steps.get_version.outputs.version-without-v }}\" -v -o nxs-data-anonymizer\n\n    - name: Compress\n      uses: a7ul/tar-action@v1.1.2\n      id: compress\n      with:\n        command: c\n        files: |\n          ./nxs-data-anonymizer\n          ./README.md\n          ./LICENSE\n        outPath: nxs-data-anonymizer-${{ matrix.TARGET }}.tar.gz\n\n    - uses: actions/upload-artifact@v4\n      with:\n        name: nxs-data-anonymizer-${{ matrix.TARGET }}.tar.gz\n        path: nxs-data-anonymizer-${{ matrix.TARGET }}.tar.gz\n\n    - uses: softprops/action-gh-release@v1\n      name: Upload binaries to release\n      if: github.ref_type == 'tag'\n      with:\n        files: nxs-data-anonymizer-${{ matrix.TARGET }}.tar.gz\n        prerelease: ${{ contains(github.ref_name, 'rc') }}\n        generate_release_notes: true\n        append_body: true\n\n  build-and-push-docker:\n    runs-on: ubuntu-latest\n    environment: secure\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v4\n\n    - name: Get version\n      id: get_version\n      uses: battila7/get-version-action@v2\n\n    - name: Login to Registry Hub\n      uses: docker/login-action@v2\n      with:\n        username: ${{ secrets.REGISTRY_USERNAME }}\n        password: ${{ secrets.REGISTRY_TOKEN }}\n\n    - name: Set up Docker Buildx\n      uses: docker/setup-buildx-action@v2\n\n    - name: Docker meta for app\n      id: meta-app\n      uses: docker/metadata-action@v4\n      with:\n        images: |\n          nixyslab/nxs-data-anonymizer\n\n    - name: Build and push app\n      uses: docker/build-push-action@v4\n      with:\n        context: .\n        file: .docker/Dockerfile\n        push: true\n        tags: ${{ steps.meta-app.outputs.tags }}\n        build-args: APP_VERSION=${{ steps.get_version.outputs.version-without-v }}\"\n\n"
  },
  {
    "path": ".gitignore",
    "content": "/.project\n/.vscode\n/.tmp\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n    Copyright 2023 Nixys <hello@nixys.io>\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "![photo_2023-07-28_15-28-52](https://github.com/nixys/nxs-data-anonymizer/assets/27485608/165a90a0-929f-460b-8dbd-2903c0d91f36)\n\n# nxs-data-anonymizer\n\n[![Telegram News][tg-news-badge]][tg-news-url]\n[![Telegram Chat][tg-chat-badge]][tg-chat-url]\n\n## Introduction\n\nnxs-data-anonymizer is a tool for anonymizing **PostgreSQL** and **MySQL/MariaDB/Percona** databases' dump.\n\n### Features\n\n- Supported databases and versions:\n  - PostgreSQL (9/10/11/12/13/14/15/all versions)\n  - MySQL/MariaDB/Percona (5.7/8.0/8.1/all versions)\n- Flexible data faking based on:\n  - Go templates and [Sprig template’s library](https://masterminds.github.io/sprig/) like [Helm](https://helm.sh/docs/chart_template_guide/functions_and_pipelines/). You may also use values of other columns for same row to build more flexible rules\n  - External commands you may execute to create table field values\n  - Security enforcement rules\n  - Link cells across the database to generate the same values\n- Stream data processing. It means that you can a use the tool through a pipe in command line and redirect dump from source DB directly to the destination DB with required transformations\n- Easy to integrate into your CI/CD\n\n### Who can use the tool\n\nDevelopment and project teams which are dealing with production and test/dev/stage or dynamic namespaces with databases and need to ensure security and prevent data leaks.\n\n## Quickstart\n\nInspect your database structure and [set up](#settings) the nxs-data-anonymizer config in accordance with the sensitive data you need to anonymize. \n\nYou are able to use this tool in any way you want. Three most common ways are described below.\n\n#### Console\n\nIn order to operate with your database anonymization via console you need to go through the following steps:\n- Download and untar the nxs-data-anonymizer [binary](https://github.com/nixys/nxs-data-anonymizer/releases)\n- Run the nxs-data-anonymizer through the command line with [arguments](#command-line-arguments) you want to use\n\nFor example, use the following command if you need to anonymize your PostgreSQL database from production to dev on fly (PostgreSQL Client need to be installed):\n```console\nexport PGPASSWORD=password; pg_dump -U postgres prod | /path/to/nxs-data-anonymizer -t pgsql -c /path/to/nxs-data-anonymizer.conf | psql -U postgres dev\n```\n\n#### GitLab CI\n\nThis section describes how to integrate nxs-data-anonymizer into your GitLab CI. You may add jobs presented below into your `.gitlab-ci.yml` and adjust it for yourself.\n\n##### Job: anonymize prod\n\nJob described in this section is able to perform the following tasks:\n- Run when special tag for `main` branch is set\n- Create a `production` database dump, anonymize and upload it into s3 bucket\n\nJob sample:\n```yaml\nanonymize:\n  stage: anonymize\n  image: nixyslab/nxs-data-anonymizer:latest\n  variables:\n    GIT_STRATEGY: none\n    PG_HOST: ${PG_HOST_PROD}\n    PG_USER: ${PG_USER_PROD}\n    PGPASSWORD: ${PG_PASS_PROD}\n  before_script: \n  - echo \"${S3CMD_CFG}\" > ~/.s3cmd\n  - echo \"${NXS_DA_CFG}\" > /nxs-data-anonymizer.conf\n  script:\n  - pg_dump -h ${PG_HOST} -U ${PG_USER} --schema=${PG_SCHEMA} ${PG_DATABASE} | /nxs-data-anonymizer -t pgsql -c /nxs-data-anonymizer.conf | gzip | s3cmd put - s3://bucket/anondump.sql.gz\n  only:\n  - /^v.*$/\n  except:\n  - branches\n  - merge_requests\n```\n\n##### Job: update stage\n\nJob described in this section deals with the following:\n- Manual job for `stage` branch\n- Download the anonymized dump from s3 bucket and load into `stage` database\n\nJob sample:\n```yaml\nrestore-stage:\n  stage: restore\n  image: nixyslab/nxs-data-anonymizer:latest\n  variables:\n    GIT_STRATEGY: none\n    PG_HOST: ${PG_HOST_STAGE}\n    PG_USER: ${PG_USER_STAGE}\n    PGPASSWORD: ${PG_PASS_STAGE}\n  before_script: \n  - echo \"${S3CMD_CFG}\" > ~/.s3cmd\n  script:\n  - s3cmd --no-progress --quiet get s3://bucket/anondump.sql.gz - | gunzip | psql -h ${PG_HOST} -U ${PG_USER} --schema=${PG_SCHEMA} ${PG_DATABASE}\n  only:\n  - stage\n  when: manual\n```\n\n##### CI/CD variables\n\nThis section contains a description of CI/CD variables used in GitLab CI job samples above.\n\n###### General\n\n| Variable | Description |\n| :---: | :---: |\n|`S3CMD_CFG` | S3 storage config |\n|`PG_SCHEMA`| PgSQL schema |\n|`PG_DATABASE`|PgSQL database name|\n\n###### Production\n\n| Variable | Description |\n| :---: | :---: |\n|`NXS_DA_CFG`|nxs-data-anonymizer config|\n|`PG_HOST_PROD` |PgSQL host|\n|`PG_USER_PROD`|PgSQL user|\n|`PG_PASS_PROD`|PgSQL password|\n\n###### Stage\n\n| Variable | Description |\n| :---: | :---: |\n|`PG_HOST_STAGE`|PgSQL host|\n|`PG_USER_STAGE`|PgSQL user|\n|`PG_PASS_STAGE`|PgSQL password|\n\n#### GitHub Actions\n\nThis section describes how to integrate nxs-data-anonymizer into your GitHub Actions. You may add jobs presented below into your `.github` workflows and adjust it for yourself.\n\n##### Job: anonymize prod\n\nJob described in this section is able to perform the following tasks:\n- Run when special tag is set\n- Create a `production` database dump, anonymize and upload it into s3 bucket\n\n```yaml\non:\n  push:\n    tags:\n    - v*.*\n\njobs:\n  anonymize:\n    runs-on: ubuntu-latest\n    container:\n      image: nixyslab/nxs-data-anonymizer:latest\n      env:\n        PG_HOST: ${{ secrets.PG_HOST_PROD }}\n        PG_USER: ${{ secrets.PG_USER_PROD }}\n        PGPASSWORD: ${{ secrets.PG_PASS_PROD }}\n        PG_SCHEMA: ${{ secrets.PG_SCHEMA }}\n        PG_DATABASE: ${{ secrets.PG_DATABASE }}\n    steps:\n    - name: Create services configs\n      run: |\n        echo \"${{ secrets.S3CMD_CFG }}\" > ~/.s3cmd\n        echo \"${{ secrets.NXS_DA_CFG }}\" > /nxs-data-anonymizer.conf\n    - name: Anonymize\n      run: |\n        pg_dump -h ${PG_HOST} -U ${PG_USER} --schema=${PG_SCHEMA} ${PG_DATABASE} | /nxs-data-anonymizer -t pgsql -c /nxs-data-anonymizer.conf | gzip | s3cmd put - s3://bucket/anondump.sql.gz\n```\n\n##### Job: update stage\n\nJob described in this section deals with the following:\n- Manual job\n- Download the anonymized dump from s3 bucket and load into `stage` database\n\n```yaml\non: workflow_dispatch\n\njobs:\n  restore-stage:\n    runs-on: ubuntu-latest\n    container:\n      image: nixyslab/nxs-data-anonymizer:latest\n      env:\n        PG_HOST: ${{ secrets.PG_HOST_STAGE }}\n        PG_USER: ${{ secrets.PG_USER_STAGE }}\n        PGPASSWORD: ${{ secrets.PG_PASS_STAGE }}\n        PG_SCHEMA: ${{ secrets.PG_SCHEMA }}\n        PG_DATABASE: ${{ secrets.PG_DATABASE }}\n    steps:\n    - name: Create services configs\n      run: |\n        echo \"${{ secrets.S3CMD_CFG }}\" > ~/.s3cmd\n    - name: Restore\n      run: |\n        s3cmd --no-progress --quiet get s3://bucket/anondump.sql.gz - | gunzip | psql -h ${PG_HOST} -U ${PG_USER} --schema=${PG_SCHEMA} ${PG_DATABASE}\n```\n\n##### GitHub Actions secrets\n\nThis section contains a description of secrets used in GitHub Actions job samples above.\n\n###### General\n\n| Variable | Description |\n| :---: | :---: |\n|`S3CMD_CFG` | S3 storage config |\n|`PG_SCHEMA`| PgSQL schema |\n|`PG_DATABASE`|PgSQL database name|\n\n###### Production\n\n| Variable | Description |\n| :---: | :---: |\n|`NXS_DA_CFG`|nxs-data-anonymizer config|\n|`PG_HOST_PROD` |PgSQL host|\n|`PG_USER_PROD`|PgSQL user|\n|`PG_PASS_PROD`|PgSQL password|\n\n###### Stage\n\n| Variable | Description |\n| :---: | :---: |\n|`PG_HOST_STAGE`|PgSQL host|\n|`PG_USER_STAGE`|PgSQL user|\n|`PG_PASS_STAGE`|PgSQL password|\n\n### Settings\n\nDefault configuration file path: `/nxs-data-anonymizer.conf`. The file is represented in yaml.\n\n#### Command line arguments\n\n| Argument         | Short   | Required | Having value | Default value | Description                                                      |\n| :---:            | :---:   | :---:    | :---:     | :---:         |---                                                               |\n| `--help`      | `-h` | No   | No    |  -      | Show program help message |\n| `--version`      | `-v` | No   | No    |  -      | Show program version |\n| `--conf`      | `-c` | No   | Yes    |  `/nxs-data-anonymizer.conf`      | Configuration file path |\n| `--input`      | `-i` | No   | Yes    |  -     | File to read data from. If not specified `stdin` will be used |\n| `--log-format` | `-l` | No   | Yes    |  `json`     | Log file format. You are available to use either `json` or `plain` value |\n| `--output`      | `-o` | No   | Yes    |  -     | File to write data to. If not specified `stdout` will be used |\n| `--type`      | `-t` | Yes   | Yes    |  -     | Database dump file type. Available values: `pgsql`, `mysql` |\n\n#### General settings\n\n| Option         | Type   | Required | Default value | Description                                                      |\n|---             | :---:  | :---:    | :---:         |---                                                               |\n| `logfile`      | String | No       | `stderr`      | Log file path. You may also use `stdout` and `stderr` |\n| `loglevel`     | String | No       | `info`        | Log level. Available values: `debug`, `warn`, `error` and `info` |\n| `progress`     | [Progress](#progress-settings) | No | - | Anonymization progress logging |\n| `variables`     | Map of [Variables](#variables-settings) (key: variable name) | No | - | Global variables to be used in a filters. Variables are set at the init of application and remain unchanged during the runtime  |\n| `link`     | Slice of [Link](#link-settings) | No | - | Rules to link specified columns across the database  |\n| `filters`          | Map of [Filters](#filters-settings) (key: table name) | No      | -             | Filters set for specified tables (key as a table name). Note: for PgSQL you also need to specify a scheme (e.g. `public.tablename`) |\n| `security`     | [Security](#security-settings) | No       | -      | Security enforcement for anonymizer |\n\n\n##### Progress settings\n\n| Option         | Type   | Required | Default value | Description                                                      |\n|---             | :---:  | :---:    | :---:         |---                                                               |\n| `rhythm`      | String | No       | `0s`    | Frequency write into the log a read bytes count. Progress will be written to the log only when this option is specified and has none-zero value. You may use a human-readable values (e.g. `30s`, `5m`, etc) |\n| `humanize`      | Bool | No       | `false`    | Set this option to `true` if you need to write into the log a read bytes count in a human-readable format. On `false` raw bytes count will be written to the log |\n\n##### Variables settings\n\n| Option        | Type   | Required | Default value | Description                                                      |\n|---            | :---:  | :---:    | :---:         |---                                                               |\n| `type`        | String | No       | `template`    | Type of field `value`: `template` and `command` are available  |\n| `value`       | String | Yes      | -             | The value to be used as global variable value within the filters. In accordance with the `type` this value may be either `Go template` or `command`. See below for details|\n\n##### Link settings\n\nLink is used to create the same data with specified rules for different cells across the database.\n\nEach link element has following properties:\n- Able to contain multiple tables and columns for each table\n- All specified cells with the same data before anonymization will have same data after \n- One common rule to generate new values\n\n| Option        | Type   | Required | Default value | Description                                                      |\n|---            | :---:  | :---:    | :---:         |---                                                               |\n| `type`        | String | No       | `template`    | Type of field `value`: `template` and `command` are available  |\n| `value`       | String | Yes      | -             | The value to be used to replace at every cell in specified column. In accordance with the `type` this value may be either `Go template` or `command`. See below for details|\n| `unique`      | Bool   | No       | `false`       | If true checks the generated value for cell is unique whole an all columns specified for `link` element |\n\n##### Filters settings\n\nFilters description for specified table.\n\n| Option         | Type   | Required | Default value | Description                                                      |\n|---             | :---:  | :---:    | :---:         |---                                                               |\n| `columns`      | Map of [Columns](#columns-settings) (key: column name) | No       | -      | Filter rules for specified columns of table (key as a column name) |\n\n###### Columns settings\n\n| Option        | Type   | Required | Default value | Description                                                      |\n|---            | :---:  | :---:    | :---:         |---                                                               |\n| `type`        | String | No       | `template`    | Type of field `value`: `template` and `command` are available  |\n| `value`       | String | Yes      | -             | The value to be used to replace at every cell in specified column. In accordance with the `type` this value may be either `Go template` or `command`. See below for details|\n| `unique`      | Bool   | No       | `false`       | If true checks the generated value for cell is unique whole the column |\n\n**Go template**\n\nTo anonymize a database fields you may use a Go template with the [Sprig template library's](https://masterminds.github.io/sprig/) functions. \n\nAdditional filter functions:\n- `null`: set a field value to `NULL`\n- `isNull`: compare a field value with `NULL`\n- `drop`: drop whole row. If table has filters for several columns and at least one of them returns drop value, whole row will be skipped during the anonymization process\n\nYou may also use the following data in a templates:\n- Current table name. Statement: `{{ .TableName }}`\n- Current column name. Statement: `{{ .CurColumnName }}`\n- Values of other columns in the rules for same row (with values before substitutions). Statement: `{{ .Values.COLUMN_NAME }}` (e.g.: `{{ .Values.username }}`)\n- Global variables. Statement: `{{ .Variables.VARIABLE_NAME }}` (e.g.: `{{ .Variables.password }}`)  \n- Raw column data type. Statement: `{{ .ColumnTypeRaw }}`\n- Regex's capturing groups for the column data type. This variable has array type so you need to use `range` or `index` to access specific element. Statement: `{{ index .ColumnTypeGroups 0 0 }}`. See [Types](#types-settings) for details\n\n**Command**\n\nTo anonymize a database fields you may use a commands (scripts or binaries) with any logic you need. The command's concept has following properties:\n- The command's `stdout` will be used as a new value for the anonymized field\n- Command must return zero exit code, otherwise nxs-data-anonymizer will falls with error (in this case `stderr` will be used as an error text)\n- Environment variables with the row data are available within the command:\n  - `ENVVARTABLE`: contains a name of the current table\n  - `ENVVARCURCOLUMN`: contains the current column name\n  - `ENVVARCOLUMN_{COLUMN_NAME}`: contains values (before substitutions) for all columns for the current row\n  - `ENVVARGLOBAL_{VARIABLE_NAME}`: contains value for specified global variable\n  - `ENVVARCOLUMNTYPERAW`: contains raw column data type\n  - `ENVVARCOLUMNTYPEGROUP_{GROUP_NUM}_{SUBGROUPNUM}`: contains regex's capturing groups for the column data type. See [Types](#types-settings) for details\n\n##### Security settings\n\n| Option         | Type   | Required | Default value | Description                                                      |\n|---             | :---:  | :---:    | :---:         |---                                                               |\n| `policy`      | [Policy](#policy-settings) | No       | -      | Security policy for entities |\n| `exceptions`      | [Exceptions](exceptions-settings) | No       | -      | Exceptions for entities |\n| `defaults`      | [Defaults](defaults-settings) | No       | -      | Default filters for entities |\n\n###### Policy settings\n\n| Option         | Type   | Required | Default value | Description                                                      |\n|---             | :---:  | :---:    | :---:         |---                                                               |\n| `tables`      | String | No       | `pass`      | Security policy for tables. If value `skip` is used all undescribed tables in config will be skipped while anonymization |\n| `columns`      | String | No       | `pass`      | Security policy for columns. If value `randomize` is used all undescribed columns in config will be randomized (with default rules in accordance to types) while anonymization |\n\n_Values to masquerade a columns in accordance with the types see below._\n\n**PgSQL:**\n\n| Type | Value to masquerade |\n|---|:---:|\n| `smallint`    | `0` |\n| `integer`     | `0` |\n| `bigint`      | `0` |\n| `smallserial` | `0` |\n| `serial`      | `0` |\n| `bigserial`   | `0` |\n| `decimal`     | `0.0` |\n| `numeric`     | `0.0` |\n| `real`        | `0.0` |\n| `double`      | `0.0` |\n| `character`   | `randomized character data\"` |\n| `bpchar`      | `randomized bpchar data` |\n| `text`        | `randomized text data` |\n\n**MySQL:**\n\n| Type | Value to masquerade |\n|---|:---:|\n| `bit` |              `0` |\n| `bool` |             `0` |\n| `boolean` |          `0` |\n| `tinyint` |          `0` |\n| `smallint` |         `0` |\n| `mediumint` |        `0` |\n| `int` |              `0` |\n| `integer` |          `0` |\n| `bigint` |           `0` |\n| `float` |            `0.0` |\n| `double` |           `0.0` |\n| `double precision` | `0.0` |\n| `decimal` |          `0.0` |\n| `dec` |              `0.0` |\n| `char` |       `randomized char` (String will be truncated to \"COLUMN_SIZE\" length.)| \n| `varchar` |    `randomized varchar` (String will be truncated to \"COLUMN_SIZE\" length.) | \n| `tinytext` |   `randomized tinytext` | \n| `text` |       `randomized text` | \n| `mediumtext` | `randomized mediumtext` | \n| `longtext` |   `randomized longtext` | \n| `enum` |       Last value from `enum` | \n| `set` |        Last value from `set` | \n| `date` |       `2024-01-01` | \n| `datetime` |   `2024-01-01 00:00:00` | \n| `timestamp` |  `2024-01-01 00:00:00` | \n| `time` |       `00:00:00` | \n| `year` |       `2024` | \n| `json` |       `{\"randomized\": \"json_data\"}` |\n| `binary` |     `cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=` |\n| `varbinary` |  `cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=` |\n| `tinyblob` |   `cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=` |\n| `blob` |       `cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=` |\n| `mediumblob` | `cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=` |\n| `longblob` |   `cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=` |\n\n###### Exceptions settings\n\n| Option         | Type   | Required | Default value | Description                                                      |\n|---             | :---:  | :---:    | :---:         |---                                                               |\n| `tables`      | Slice of strings | No       | -      | Table names without filters which are not be skipped while anonymization if option `security.policy.tables` set to `skip` |\n| `columns`      | Slice of strings | No       | -      | Column names (in any table) without filters which are not be randomized while anonymization if option `security.policy.columns` set to `randomize` |\n\n###### Defaults settings\n\n| Option         | Type   | Required | Default value | Description                                                      |\n|---             | :---:  | :---:    | :---:         |---                                                               |\n| `columns`      | Map of Filters | No       | -      | Default filter for columns (in any table). That filters will be applied for columns with this names without described filters |\n| `types`      | Slice of [Types](#types-settings) | No       | -      | Custom filters for types (in any table). With this filter rules you may override default filters for types |\n\n###### Types settings\n\n| Option         | Type   | Required | Default value | Description                                                      |\n|---             | :---:  | :---:    | :---:         |---                                                               |\n| `regex`      | String | Yes       | -      | Regular expression. Will be checked for match for column data type (in `CREATE TABLE` section). Able to use capturing groups within the regex that available as an additional variable data in the filters (see [Columns](#columns-settings) for details). This ability helps to create more flexible rules to generate the cells value in accordance with  data type  features |\n| `rule`      | [Columns](#columns-settings) | Yes       | -      | Rule will be applied columns with data types matched for specified regular expression |\n\n#### Example\n\nImagine you have a simple database with two tables `users` and `posts` in your production PgSQL like this:\n\n| id | username | password | api_key |\n| :---: | :---: | :---: | :---: |\n| 1 | `admin` | `ZjCX6wUxtXIMtip` | `epezyj0cj5rqrdtxklnzxr3f333uibtz6avek7926141t1c918` |\n| 2 | `alice` | `tuhjLkgwwetiwf8` | `2od4vfsx2irj98hgjaoi6n7wjr02dg79cvqnmet4kyuhol877z` |\n| 3 | `bob`   | `AjRzvRp3DWo6VbA` | `owp7hob5s3o083d5hmursxgcv9wc4foyl20cbxbrr73egj6jkx` |\n\n| id | poster_id | title | content |\n| :---: | :---: | :---: | :---: |\n| 1 | 1 | `example_post_1` | `epezyj0cj5rqrdtxklnzxr3f333uibtz6avek7926141t1c918` |\n| 2 | 2 | `example_post_2` | `2od4vfsx2irj98hgjaoi6n7wjr02dg79cvqnmet4kyuhol877z` |\n| 3 | 3 | `example_post_3` | `owp7hob5s3o083d5hmursxgcv9wc4foyl20cbxbrr73egj6jkx` |\n| 4 | 1 | `example_post_4` | `epezyj0cj5rqrdtxklnzxr3f333uibtz6avek7926141t1c918` |\n| 5 | 2 | `example_post_5` | `2od4vfsx2irj98hgjaoi6n7wjr02dg79cvqnmet4kyuhol877z` |\n| 6 | 3 | `example_post_6` | `owp7hob5s3o083d5hmursxgcv9wc4foyl20cbxbrr73egj6jkx` |\n\nYou need to get a dump with fake values:\n- For `admin`: preset fixed value for a password and API key to avoid the need to change an app settings in your dev/test/stage or local environment after downloading the dump.\n- For others: usernames in format `user_N` (where `N` it is a user ID) and unique random  passwords and API keys.\n- Need to preserve data mapping between `users` and `posts` tables in `id` and `poster_id` columns\n- Need to randomize contents of `content` column.\nIn accordance with these conditions, the nxs-data-anonymizer config may look like this:\n\n```yaml\nvariables:\n#Global variables.\n  adminPassword:\n    type: template\n    value: \"preset_admin_password\"\n  adminAPIKey:\n    value: \"preset_admin_api_key\"\n\n#Block defining rules of behavior with fields and tables for which filters are not specified.\nsecurity:\n# Specifies the required actions for tables and columns that are not specified in the configuration.\n  policy:\n    tables: skip\n    columns: randomize\n# Excludes policy actions for the specified tables and columns.\n  exceptions:\n    tables: \n    - public.posts\n    columns:\n    - title\n# Overrides the default policy actions for the columns specified in this block. The value is generated once and substituted into all instances of the field.\n  defaults:\n    columns:\n      content:\n        value: \"{{- randAlphaNum 20 -}}\"\n\n#Here you define the rules that allow you to preserve the mapping of values ​​between tables.\nlink:\n- rule:\n#Value generation rule.\n    value: \"{{ randInt 1 15\t}}\"\n    unique: true\n  with:\n#Tables and columns to which the rule is applied.\n    public.users:\n    - id\n    public.posts:\n    - poster_id\n\n#Block describing replacement rules for fields.\nfilters:\n  public.users:\n    columns:\n      username:\n        value: \"{{ if eq .Values.username \\\"admin\\\" }}{{ .Values.username }}{{ else }}user_{{ .Values.id }}{{ end }}\"\n      password:\n        type: command\n        value: /path/to/script.sh\n        unique: true\n      api_key:\n        value: \"{{ if eq .Values.username \\\"admin\\\" }}{{ .Variables.adminAPIKey }}{{ else }}{{- randAlphaNum 50 | nospace | lower -}}{{ end }}\"\n        unique: true\n```\n\nThe `/path/to/script.sh` script content is following:\n\n```bash\n#!/bin/bash\n\n# Print preset password if current user is admin\nif [ \"$ENVVARCOLUMN_username\" == \"admin\" ];\nthen\n    echo -n \"$ENVVARGLOBAL_adminPassword\"\n    exit 0\nfi\n\n# Generate password for other users\np=$(pwgen -s 5 1 2>&1) \nif [ ! $? -eq 0 ];\nthen\n\n    # On error print message to stderr and exit with non zero code\n\n    echo -n \"$p\" >&2\n    exit 1\nfi\n\n# Print generated password\necho $p | tr -d '\\n'\n\nexit 0\n```\n\nNow you may execute the following command in order to load anonymized data into your dev DB:\n\n```\npg_dump ... | ./nxs-data-anonymizer -c filters.conf | psql -h localhost -U user example\n```\n\nAs a result:\n| id | username | password | api_key |\n| :---: | :---: | :---: | :---: |\n| 5 | `admin` | `preset_admin_password` | `preset_admin_api_key` |\n| 4 | `user_2` | `Pp4HY` | `dhx4mccxyd8ux5uf1khpbqsws8qqeqs4efex1vhfltzhtjcwcu` |\n| 7 | `user_3`   | `vu5TW` | `lgkkq3csskuyew8fr52vfjjenjzudokmiidg3cohl2bertc93x` |\n\n| id | poster_id | title | content |\n| :---: | :---: | :---: | :---: |\n| 1 | 5 | `example_post_1` | `EDlT6bGXJ2LOS7CE2E4b` |\n| 2 | 4 | `example_post_2` | `EDlT6bGXJ2LOS7CE2E4b` |\n| 3 | 7 | `example_post_3` | `EDlT6bGXJ2LOS7CE2E4b` |\n| 4 | 5 | `example_post_4` | `EDlT6bGXJ2LOS7CE2E4b` |\n| 5 | 4 | `example_post_5` | `EDlT6bGXJ2LOS7CE2E4b` |\n| 6 | 7 | `example_post_6` | `EDlT6bGXJ2LOS7CE2E4b` |\n\nIt's easy. You can find more examples in doc/examples.\n\n## Roadmap\n\nFollowing features are already in backlog for our development team and will be released soon:\n- [x] Global variables with the templated values you may use through the filters for all tables and columns\n- [x] Ability to delete tables and rows from faked dump \n- [ ] Ability to output into log a custom messages. It’s quite useful it order to obtain some generated data like admin passwords, etc\n- [ ] Support of a big variety of databases\n\n## Feedback\n\nFor support and feedback please contact me:\n- telegram: [@borisershov](https://t.me/borisershov)\n- e-mail: b.ershov@nixys.io\n\nFor news and discussions subscribe the channels:\n- Telegram community (news): [@nxs_data_anonymizer](https://t.me/nxs_data_anonymizer)\n- Telegram community (chat): [@nxs_data_anonymizer_chat](https://t.me/nxs_data_anonymizer_chat)\n\n## License\n\nnxs-data-anonymizer is released under the [Apache License 2.0](LICENSE).\n\n[tg-news-badge]: https://img.shields.io/endpoint?url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fnxs_data_anonymizer\n[tg-chat-badge]: https://img.shields.io/endpoint?url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fnxs_data_anonymizer_chat\n[tg-news-url]: https://t.me/nxs_data_anonymizer\n[tg-chat-url]: https://t.me/nxs_data_anonymizer_chat\n[aica-badge]: https://img.shields.io/badge/AI-Code%20Assist-EB9FDA\n[aica-url]: https://app.commanddash.io/agent?github=https://github.com/nixys/nxs-data-anonymizer\n"
  },
  {
    "path": "ctx/args.go",
    "content": "package ctx\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n\t\"github.com/pborman/getopt/v2\"\n)\n\nconst (\n\tconfPathDefault = \"/nxs-data-anonymizer.conf\"\n)\n\nvar version string\n\n// Args contains arguments value read from command line\ntype Args struct {\n\tConfigPath string\n\tLogFormat  LogFormat\n\tInput      *string\n\tOutput     *string\n\tCleanup    bool\n\tDBType     DBType\n}\n\n// ArgsRead reads arguments from command line\nfunc ArgsRead() (Args, error) {\n\n\targs := getopt.New()\n\n\thelpFlag := args.BoolLong(\n\t\t\"help\",\n\t\t'h',\n\t\t\"Show help\")\n\n\tversionFlag := args.BoolLong(\n\t\t\"version\",\n\t\t'v',\n\t\t\"Show program version\")\n\n\tconfPath := args.StringLong(\n\t\t\"conf\",\n\t\t'c',\n\t\tconfPathDefault,\n\t\tfmt.Sprintf(\"Config file path\"))\n\n\tinput := args.StringLong(\n\t\t\"input\",\n\t\t'i',\n\t\t\"\",\n\t\t\"Input file. If not set `stdin` is used\")\n\n\tlogformat := args.EnumLong(\n\t\t\"log-format\",\n\t\t'l',\n\t\t[]string{\n\t\t\tstring(LogFormatJSON),\n\t\t\tstring(LogFormatPlain),\n\t\t},\n\t\tstring(LogFormatJSON),\n\t\tfmt.Sprintf(\"Log file format. Values `%s` or `%s` are available\", LogFormatJSON, LogFormatPlain),\n\t)\n\n\toutput := args.StringLong(\n\t\t\"output\",\n\t\t'o',\n\t\t\"\",\n\t\t\"Output file. If not set `stdout` is used\")\n\n\tdbType := args.EnumLong(\n\t\t\"type\",\n\t\t't',\n\t\t[]string{\n\t\t\tstring(DBTypeMySQL),\n\t\t\tstring(DBTypePgSQL),\n\t\t},\n\t\t\"\",\n\t\tfmt.Sprintf(\"Database type you need to operate. Values `%s` or `%s` are available\", DBTypePgSQL, DBTypeMySQL),\n\t)\n\n\tcleanup := args.BoolLong(\n\t\t\"cleanup\",\n\t\t'C',\n\t\t\"Clean up destination database (experimental). Available only for MySQL\")\n\n\targs.Parse(os.Args)\n\n\t/* Show help */\n\tif *helpFlag == true {\n\t\targsHelp(args)\n\t\treturn Args{}, misc.ErrArgSuccessExit\n\t}\n\n\t/* Show version */\n\tif *versionFlag == true {\n\t\targsVersion()\n\t\treturn Args{}, misc.ErrArgSuccessExit\n\t}\n\n\tif args.IsSet(\"type\") == false {\n\t\tfmt.Println(\"args: 'type' option must be specified\")\n\t\treturn Args{}, misc.ErrConig\n\t}\n\n\treturn Args{\n\t\tConfigPath: *confPath,\n\t\tLogFormat:  LogFormat(*logformat),\n\t\tInput: func() *string {\n\t\t\tif args.IsSet(\"input\") == true {\n\t\t\t\treturn input\n\t\t\t}\n\t\t\treturn nil\n\t\t}(),\n\t\tOutput: func() *string {\n\t\t\tif args.IsSet(\"output\") == true {\n\t\t\t\treturn output\n\t\t\t}\n\t\t\treturn nil\n\t\t}(),\n\t\tCleanup: *cleanup,\n\t\tDBType:  DBType(*dbType),\n\t}, nil\n}\n\nfunc argsHelp(args *getopt.Set) {\n\n\tadditionalDescription := `\n\t\nAdditional description\n\n  Tool for anonymizing PostgreSQL and MySQL databases' dump\n`\n\n\targs.PrintUsage(os.Stdout)\n\tfmt.Println(additionalDescription)\n}\n\nfunc argsVersion() {\n\tfmt.Println(version)\n}\n"
  },
  {
    "path": "ctx/conf.go",
    "content": "package ctx\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n\tconf \"github.com/nixys/nxs-go-conf\"\n)\n\ntype confOpts struct {\n\tLogFile  string `conf:\"logfile\" conf_extraopts:\"default=stderr\"`\n\tLogLevel string `conf:\"loglevel\" conf_extraopts:\"default=info\"`\n\n\tProgress  progressConf                  `conf:\"progress\"`\n\tFilters   map[string]filterConf         `conf:\"filters\"`\n\tLink      []linkConf                    `conf:\"link\"`\n\tSecurity  securityConf                  `conf:\"security\"`\n\tVariables map[string]variableFilterConf `conf:\"variables\"`\n\n\tMySQL *mysqlConf `conf:\"mysql\"`\n}\n\ntype progressConf struct {\n\tRhythm   string `conf:\"rhythm\" conf_extraopts:\"default=0s\"`\n\tHumanize bool   `conf:\"humanize\"`\n}\n\ntype filterConf struct {\n\tColumns map[string]columnFilterConf `conf:\"columns\"`\n}\n\ntype columnFilterConf struct {\n\tType   string `conf:\"type\" conf_extraopts:\"default=template\"`\n\tValue  string `conf:\"value\" conf_extraopts:\"required\"`\n\tUnique bool   `conf:\"unique\"`\n}\n\ntype linkConf struct {\n\tRule columnFilterConf    `conf:\"rule\"`\n\tWith map[string][]string `conf:\"with\" conf_extraopts:\"required\"`\n}\n\ntype variableFilterConf struct {\n\tType  string `conf:\"type\" conf_extraopts:\"default=template\"`\n\tValue string `conf:\"value\" conf_extraopts:\"required\"`\n}\n\ntype securityConf struct {\n\tPolicy     securityPolicyConf     `conf:\"policy\"`\n\tExceptions securityExceptionsConf `conf:\"exceptions\"`\n\tDefaults   securityDefaultsConf   `conf:\"defaults\"`\n}\n\ntype securityPolicyConf struct {\n\tTables  string `conf:\"tables\" conf_extraopts:\"default=pass\"`\n\tColumns string `conf:\"columns\" conf_extraopts:\"default=pass\"`\n}\n\ntype securityExceptionsConf struct {\n\tTables  []string `conf:\"tables\"`\n\tColumns []string `conf:\"columns\"`\n}\n\ntype securityDefaultsConf struct {\n\tColumns map[string]columnFilterConf `conf:\"columns\"`\n\tTypes   []securityDefaultsTypeConf  `conf:\"types\"`\n}\n\ntype securityDefaultsTypeConf struct {\n\tRegex string           `conf:\"regex\" conf_extraopts:\"required\"`\n\tRule  columnFilterConf `conf:\"rule\" conf_extraopts:\"required\"`\n}\n\ntype mysqlConf struct {\n\tHost     string `conf:\"host\" conf_extraopts:\"required\"`\n\tPort     int    `conf:\"port\" conf_extraopts:\"required\"`\n\tDB       string `conf:\"db\" conf_extraopts:\"required\"`\n\tUser     string `conf:\"user\" conf_extraopts:\"required\"`\n\tPassword string `conf:\"password\" conf_extraopts:\"required\"`\n}\n\nfunc confRead(confPath string) (confOpts, error) {\n\n\tvar c confOpts\n\n\terr := conf.Load(&c, conf.Settings{\n\t\tConfPath:    confPath,\n\t\tConfType:    conf.ConfigTypeYAML,\n\t\tUnknownDeny: true,\n\t})\n\tif err != nil {\n\t\treturn c, err\n\t}\n\n\tfor _, f := range c.Filters {\n\t\tfor _, cf := range f.Columns {\n\t\t\tif misc.ValueTypeFromString(cf.Type) == misc.ValueTypeUnknown {\n\t\t\t\treturn c, fmt.Errorf(\"conf read: unknown column filter type\")\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, f := range c.Variables {\n\t\tif misc.ValueTypeFromString(f.Type) == misc.ValueTypeUnknown {\n\t\t\treturn c, fmt.Errorf(\"conf read: unknown variable filter type\")\n\t\t}\n\t}\n\n\tif misc.SecurityPolicyTablesTypeFromString(c.Security.Policy.Tables) == misc.SecurityPolicyTablesUnknown {\n\t\treturn c, fmt.Errorf(\"conf read: unknown security policy tables type\")\n\t}\n\n\tif misc.SecurityPolicyColumnsTypeFromString(c.Security.Policy.Columns) == misc.SecurityPolicyColumnsUnknown {\n\t\treturn c, fmt.Errorf(\"conf read: unknown security policy columns type\")\n\t}\n\n\tfor _, cf := range c.Security.Defaults.Columns {\n\t\tif misc.ValueTypeFromString(cf.Type) == misc.ValueTypeUnknown {\n\t\t\treturn c, fmt.Errorf(\"conf read: unknown default filter type\")\n\t\t}\n\t}\n\n\treturn c, nil\n}\n"
  },
  {
    "path": "ctx/context.go",
    "content": "package ctx\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/interfaces\"\n\tmysql_anonymize \"github.com/nixys/nxs-data-anonymizer/modules/anonymizers/mysql\"\n\tpgsql_anonymize \"github.com/nixys/nxs-data-anonymizer/modules/anonymizers/pgsql\"\n\tprogressreader \"github.com/nixys/nxs-data-anonymizer/modules/progress_reader\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/ds/mysql\"\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n\t\"github.com/nixys/nxs-data-anonymizer/modules/filters/relfilter\"\n\t\"github.com/sirupsen/logrus\"\n\n\tappctx \"github.com/nixys/nxs-go-appctx/v3\"\n)\n\n// Ctx defines application custom context\ntype Ctx struct {\n\tLog        *logrus.Logger\n\tOutput     io.Writer\n\tProgress   progressCtx\n\tDB         DBCtx\n\tAnonymizer interfaces.Anonymizer\n\tPR         *progressreader.ProgressReader\n}\n\ntype DBCtx struct {\n\tCleanup bool\n\tType    DBType\n\tMySQL   *mysql.MySQL\n}\n\ntype DBType string\n\nconst (\n\tDBTypeMySQL DBType = \"mysql\"\n\tDBTypePgSQL DBType = \"pgsql\"\n)\n\ntype LogFormat string\n\nconst (\n\tLogFormatJSON  LogFormat = \"json\"\n\tLogFormatPlain LogFormat = \"plain\"\n)\n\ntype progressCtx struct {\n\tRhythm   time.Duration\n\tHumanize bool\n}\n\ntype SecurityCtx struct {\n\tTablePolicy     misc.SecurityPolicyTablesType\n\tTableExceptions map[string]any\n}\n\n// Init initiates application custom context\nfunc AppCtxInit() (any, error) {\n\n\tvar ir io.Reader\n\n\tc := &Ctx{}\n\n\targs, err := ArgsRead()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tconf, err := confRead(args.ConfigPath)\n\tif err != nil {\n\t\ttmpLogError(\"ctx init\", err)\n\t\treturn nil, err\n\t}\n\n\tc.Log, err = logInit(conf.LogFile, conf.LogLevel, args.LogFormat)\n\tif err != nil {\n\t\ttmpLogError(\"ctx init\", err)\n\t\treturn nil, err\n\t}\n\n\tif args.Input == nil {\n\t\tir = os.Stdin\n\t} else {\n\t\tir, err = os.Open(*args.Input)\n\t\tif err != nil {\n\t\t\tc.Log.WithFields(logrus.Fields{\n\t\t\t\t\"details\": err,\n\t\t\t}).Errorf(\"ctx init: open input file\")\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif args.Output == nil {\n\t\tc.Output = os.Stdout\n\t} else {\n\t\tc.Output, err = os.Create(*args.Output)\n\t\tif err != nil {\n\t\t\tc.Log.WithFields(logrus.Fields{\n\t\t\t\t\"details\": err,\n\t\t\t}).Errorf(\"ctx init: open output file\")\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tc.DB = DBCtx{\n\t\tCleanup: args.Cleanup,\n\t\tType:    args.DBType,\n\t}\n\n\t// DEPRECATED: Connect to MySQL if necessary\n\tif conf.MySQL != nil {\n\t\tm, err := mysql.Connect(mysql.Settings{\n\t\t\tHost:     conf.MySQL.Host,\n\t\t\tPort:     conf.MySQL.Port,\n\t\t\tDatabase: conf.MySQL.DB,\n\t\t\tUser:     conf.MySQL.User,\n\t\t\tPassword: conf.MySQL.Password,\n\t\t})\n\t\tif err != nil {\n\t\t\tc.Log.WithFields(logrus.Fields{\n\t\t\t\t\"details\": err,\n\t\t\t}).Errorf(\"ctx init\")\n\t\t\treturn nil, err\n\t\t}\n\t\tc.DB.MySQL = &m\n\t} else {\n\t\tif args.Cleanup == true {\n\t\t\tc.Log.WithFields(logrus.Fields{\n\t\t\t\t\"details\": \"destination database clean up was requested but connection to database doesn't specified\",\n\t\t\t}).Errorf(\"ctx init\")\n\t\t\treturn nil, misc.ErrConig\n\t\t}\n\t}\n\n\tc.PR = progressreader.Init(ir)\n\n\tvr := func() map[string]relfilter.VariableRuleOpts {\n\t\trules := make(map[string]relfilter.VariableRuleOpts)\n\t\tfor n, f := range conf.Variables {\n\t\t\trules[n] = relfilter.VariableRuleOpts{\n\t\t\t\tType:  misc.ValueType(f.Type),\n\t\t\t\tValue: f.Value,\n\t\t\t}\n\t\t}\n\t\treturn rules\n\t}()\n\n\ttr := func() map[string]map[string]relfilter.ColumnRuleOpts {\n\t\ttables := make(map[string]map[string]relfilter.ColumnRuleOpts)\n\t\tfor t, cs := range conf.Filters {\n\t\t\tcolumns := make(map[string]relfilter.ColumnRuleOpts)\n\t\t\tfor c, f := range cs.Columns {\n\t\t\t\tcolumns[c] = relfilter.ColumnRuleOpts{\n\t\t\t\t\tType:   misc.ValueType(f.Type),\n\t\t\t\t\tValue:  f.Value,\n\t\t\t\t\tUnique: f.Unique,\n\t\t\t\t}\n\t\t\t}\n\t\t\ttables[t] = columns\n\t\t}\n\t\treturn tables\n\t}()\n\n\tdr := func() map[string]relfilter.ColumnRuleOpts {\n\t\tcc := make(map[string]relfilter.ColumnRuleOpts)\n\t\tfor c, cf := range conf.Security.Defaults.Columns {\n\t\t\tcc[c] = relfilter.ColumnRuleOpts{\n\t\t\t\tType:   misc.ValueTypeFromString(cf.Type),\n\t\t\t\tValue:  cf.Value,\n\t\t\t\tUnique: cf.Unique,\n\t\t\t}\n\t\t}\n\t\treturn cc\n\t}()\n\n\ttrc := func() []relfilter.TypeRuleOpts {\n\t\tcc := []relfilter.TypeRuleOpts{}\n\t\tfor _, t := range conf.Security.Defaults.Types {\n\t\t\tcc = append(\n\t\t\t\tcc,\n\t\t\t\trelfilter.TypeRuleOpts{\n\t\t\t\t\tSelector: t.Regex,\n\t\t\t\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\t\t\t\tType:   misc.ValueTypeFromString(t.Rule.Type),\n\t\t\t\t\t\tValue:  t.Rule.Value,\n\t\t\t\t\t\tUnique: t.Rule.Unique,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\treturn cc\n\t}()\n\n\tlnk := []relfilter.LinkOpts{}\n\tfor _, l := range conf.Link {\n\t\tlnk = append(\n\t\t\tlnk,\n\t\t\trelfilter.LinkOpts{\n\t\t\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\t\t\tType:   misc.ValueTypeFromString(l.Rule.Type),\n\t\t\t\t\tValue:  l.Rule.Value,\n\t\t\t\t\tUnique: l.Rule.Unique,\n\t\t\t\t},\n\t\t\t\tWith: l.With,\n\t\t\t},\n\t\t)\n\t}\n\n\tswitch args.DBType {\n\tcase DBTypeMySQL:\n\t\tc.Anonymizer, err = mysql_anonymize.Init(\n\t\t\tc.PR,\n\t\t\tmysql_anonymize.InitOpts{\n\t\t\t\tVariables: vr,\n\t\t\t\tSecurity: mysql_anonymize.SecurityOpts{\n\t\t\t\t\tTablesPolicy:    misc.SecurityPolicyTablesType(conf.Security.Policy.Tables),\n\t\t\t\t\tColumnsPolicy:   misc.SecurityPolicyColumnsTypeFromString(conf.Security.Policy.Columns),\n\t\t\t\t\tTableExceptions: conf.Security.Exceptions.Tables,\n\t\t\t\t},\n\t\t\t\tRules: mysql_anonymize.RulesOpts{\n\t\t\t\t\tTableRules:       tr,\n\t\t\t\t\tDefaultRules:     dr,\n\t\t\t\t\tExceptionColumns: conf.Security.Exceptions.Columns,\n\t\t\t\t\tTypeRuleCustom:   trc,\n\t\t\t\t},\n\t\t\t\tLink: lnk,\n\t\t\t},\n\t\t)\n\t\tif err != nil {\n\t\t\tc.Log.WithFields(logrus.Fields{\n\t\t\t\t\"details\": err,\n\t\t\t}).Errorf(\"ctx init\")\n\t\t\treturn nil, err\n\t\t}\n\tcase DBTypePgSQL:\n\t\tc.Anonymizer, err = pgsql_anonymize.Init(\n\t\t\tc.PR,\n\t\t\tpgsql_anonymize.InitOpts{\n\t\t\t\tVariables: vr,\n\t\t\t\tSecurity: pgsql_anonymize.SecurityOpts{\n\t\t\t\t\tTablesPolicy:    misc.SecurityPolicyTablesType(conf.Security.Policy.Tables),\n\t\t\t\t\tColumnsPolicy:   misc.SecurityPolicyColumnsTypeFromString(conf.Security.Policy.Columns),\n\t\t\t\t\tTableExceptions: conf.Security.Exceptions.Tables,\n\t\t\t\t},\n\t\t\t\tRules: pgsql_anonymize.RulesOpts{\n\t\t\t\t\tTableRules:       tr,\n\t\t\t\t\tDefaultRules:     dr,\n\t\t\t\t\tExceptionColumns: conf.Security.Exceptions.Columns,\n\t\t\t\t\tTypeRuleCustom:   trc,\n\t\t\t\t},\n\t\t\t\tLink: lnk,\n\t\t\t},\n\t\t)\n\t\tif err != nil {\n\t\t\tc.Log.WithFields(logrus.Fields{\n\t\t\t\t\"details\": err,\n\t\t\t}).Errorf(\"ctx init\")\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// Progress settings\n\tc.Progress.Humanize = conf.Progress.Humanize\n\n\tc.Progress.Rhythm, err = time.ParseDuration(conf.Progress.Rhythm)\n\tif err != nil {\n\t\tc.Log.WithFields(logrus.Fields{\n\t\t\t\"details\": err,\n\t\t}).Errorf(\"ctx init\")\n\t\treturn nil, err\n\t}\n\n\treturn c, nil\n}\n\nfunc tmpLogError(msg string, err error) {\n\tl, _ := appctx.DefaultLogInit(os.Stderr, logrus.InfoLevel, &logrus.JSONFormatter{})\n\tl.WithFields(logrus.Fields{\n\t\t\"details\": err,\n\t}).Errorf(msg)\n}\n\nfunc logInit(file, level string, ft LogFormat) (*logrus.Logger, error) {\n\n\tvar (\n\t\tf   *os.File\n\t\terr error\n\t)\n\n\tswitch file {\n\tcase \"stdout\":\n\t\tf = os.Stdout\n\tcase \"stderr\":\n\t\tf = os.Stderr\n\tdefault:\n\t\tf, err = os.OpenFile(file, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"log init: %w\", err)\n\t\t}\n\t}\n\n\t// Validate log level\n\tl, err := logrus.ParseLevel(level)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"log init: %w\", err)\n\t}\n\n\tif ft == LogFormatPlain {\n\t\treturn appctx.DefaultLogInit(f, l, nil)\n\t}\n\n\treturn appctx.DefaultLogInit(f, l, &logrus.JSONFormatter{})\n}\n"
  },
  {
    "path": "doc/examples/drop/MySQL/input.sql",
    "content": "-- MySQL dump 10.13  Distrib 8.4.0, for Linux (x86_64)\n--\n-- Host: localhost    Database: name_db\n-- ------------------------------------------------------\n-- Server version\t8.4.0\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!50503 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `authors`\n--\n\nDROP TABLE IF EXISTS `authors`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `authors` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `first_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `last_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `email` varchar(100) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `birthdate` date NOT NULL,\n  `added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `authors`\n--\n\nLOCK TABLES `authors` WRITE;\n/*!40000 ALTER TABLE `authors` DISABLE KEYS */;\nINSERT INTO `authors` VALUES (1,'Wilford','Wintheiser','brett35@example.com','1981-10-14','1988-09-10 18:37:25'),(2,'Nyasia','Doyle','aracely46@example.com','2007-07-01','1980-10-28 23:57:00'),(3,'Ken','Haag','carroll.harris@example.com','2003-04-16','1997-03-14 18:41:06'),(4,'Leonor','Mann','johns.janick@example.org','1996-05-18','2010-04-12 00:38:42'),(5,'Eloisa','Ratke','lakin.ramiro@example.net','1982-07-22','1996-03-25 09:07:39'),(6,'Nikolas','Dibbert','judson33@example.com','1970-02-22','1979-03-16 10:10:12'),(7,'Kelley','Koch','kaci.koch@example.net','2013-05-01','2020-08-02 02:01:34'),(8,'Glen','Howe','jprosacco@example.net','1971-08-03','1971-01-02 14:19:52'),(9,'Geovanni','Medhurst','kutch.kylie@example.com','2011-04-20','2004-06-10 12:33:11'),(10,'Zella','Davis','hane.terrill@example.org','1991-11-07','2007-09-19 13:48:20');\n/*!40000 ALTER TABLE `authors` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `posts`\n--\n\nDROP TABLE IF EXISTS `posts`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `posts` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `author_id` int NOT NULL,\n  `title` varchar(255) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `description` varchar(500) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `content` text COLLATE utf8mb3_unicode_ci NOT NULL,\n  `date` date NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `posts`\n--\n\nLOCK TABLES `posts` WRITE;\n/*!40000 ALTER TABLE `posts` DISABLE KEYS */;\nINSERT INTO `posts` VALUES (1,1,'Pariatur est in ut provident vero eligendi.','Consequatur quae odio in animi. Quis dolorem aut corporis sed ratione animi et. Iure sunt qui eligendi laudantium harum maxime id id. Quia eos beatae temporibus eos rerum ipsum.','Velit voluptatibus quo est dolorem quos sed et. Illum similique atque et qui. Perspiciatis magnam saepe quis. Consequatur aut dolorem ea.','1975-07-07'),(2,2,'Unde est architecto est.','Consectetur quidem aut eligendi quas. Voluptas aut voluptas ratione reiciendis magnam sint. Ratione et omnis assumenda deserunt voluptatem perspiciatis. Non voluptates quia distinctio nam consectetur vel.','Sed sint at consectetur. Fugiat fugiat omnis debitis dolore. Incidunt vero incidunt enim reiciendis. Odio et illo facilis quo sit quia consequatur voluptatem.','1976-05-25'),(3,3,'Dignissimos perspiciatis nobis quisquam saepe ad aut numquam.','Voluptatibus eum voluptas eveniet veniam ducimus. Modi id vitae est accusamus. Quaerat perferendis voluptas minima dignissimos et. Sapiente explicabo voluptas commodi voluptatem autem totam. Adipisci quos quos quo ea aliquid rerum.','Repellat minus enim occaecati sunt quas. Ab ipsa voluptatibus sunt eos omnis quisquam at voluptatibus. Quo vitae doloremque nesciunt doloremque. Temporibus rerum sunt iste dolores rerum.','1991-12-21'),(4,4,'Voluptas sint modi magnam.','Facere harum pariatur quo eveniet dolor molestias. Quo debitis corporis quasi minima et optio. Ut maiores nihil rerum autem culpa et voluptates. Amet totam rem optio in. Provident ea repudiandae quisquam unde occaecati autem.','Sed quia assumenda quis rerum praesentium harum. Quia minima quo natus. Impedit temporibus perspiciatis et enim doloremque nihil et. Perspiciatis nam occaecati illo dicta asperiores eos nam.','2002-01-23'),(5,5,'Sapiente rem eos enim ullam ipsum ut.','Officia quos voluptas autem consequuntur. Quis consequatur aut vel dolor. Sapiente voluptatem quibusdam dolor nobis earum laboriosam quisquam.','Quibusdam vel tempora explicabo qui. Sunt animi a unde veritatis perferendis similique nostrum vel. Porro ab ad cumque dolorum provident distinctio est ipsum. Esse maxime ea quia.','2017-11-19'),(6,6,'Error quas doloremque est sunt quae.','Corporis quis in sint. Eos vitae aut provident distinctio ullam. Corporis mollitia quam natus qui sapiente officiis.','Ipsam animi aperiam ipsa fuga. Sunt blanditiis possimus aut quod. Doloremque possimus occaecati numquam omnis dolor. Qui nihil qui atque vitae sapiente illo id.','1974-03-23'),(7,7,'Quo impedit quos molestiae dolorum in soluta dolores non.','Harum quasi dolorum et harum iste eveniet et. Cumque ab recusandae architecto est ipsam est. Eligendi et earum ea alias odio sed ut.','Illo earum porro corporis sunt aut. Vel quisquam ut voluptas reiciendis maiores cumque. Qui hic maiores voluptas sapiente reprehenderit. Eos non autem quis maiores perferendis.','2004-12-08'),(8,8,'Nulla quia repellendus et autem vitae provident.','Facere deserunt suscipit quia et et totam vel at. Cumque suscipit est ea quis in quos. Harum dolorum consequuntur illum voluptatem iste enim recusandae.','Excepturi hic tenetur sint nostrum. Nihil itaque repudiandae qui hic minima quis ut. Dolor et aut quaerat exercitationem minima ut. Blanditiis minus et qui dolor ut atque.','1999-02-28'),(9,9,'Similique at quia quia ut recusandae repudiandae delectus.','Et necessitatibus aut accusantium quisquam harum est. Non quam id impedit deleniti. Eaque non architecto facere dolorem nesciunt perferendis. Delectus nihil ut dignissimos. Voluptate rerum reprehenderit aut voluptatem quibusdam quidem.','Tempore iusto minus omnis tempore. Hic aut sequi temporibus consequatur. In vel enim eos nihil sed eos debitis.','2007-08-07'),(10,10,'Est vel aperiam ipsa quod doloremque et est et.','Facere ut et similique voluptates voluptas blanditiis explicabo. Eaque molestiae nihil sed et repellat voluptatem eum autem.','Rem laudantium in aut assumenda. Aspernatur id illo pariatur aut deleniti rem et. Nisi velit neque qui quia.','2009-07-18'),(11,1,'Sint est qui dolorem eum accusantium repudiandae.','Quia tenetur culpa maiores molestias. Id numquam illum earum quos sint ad dolore corrupti. Consequatur quasi itaque est odit qui quod culpa.','Omnis tenetur occaecati accusamus quis corrupti et ipsam. Ullam nobis tempore officia nesciunt iste. Nesciunt vel in eos. Dolor voluptates quod sed quibusdam ut. Fuga quia eum quidem cum.','2010-04-16'),(12,2,'Culpa debitis ut non sapiente voluptatem.','Commodi fugit ullam quaerat quam quo minus. Harum quam ipsam ducimus sit expedita sit. Eos natus quo quibusdam quam repudiandae. Assumenda et sint sit quia qui necessitatibus.','Eum molestiae cupiditate ut minus. Eaque eos eos ipsam voluptatem. Sint aut aliquid modi id dolores consequatur. Aut nemo blanditiis nisi ea nam velit.','1988-12-26'),(13,3,'Ut ut rerum qui quis sed sunt.','Tenetur enim et nisi ex et consequatur omnis nisi. Eos deleniti aut amet illo sed quibusdam. Consequuntur sint quia quia aut magni.','Aut eveniet natus ut. Nostrum aliquid qui nam hic iusto id occaecati qui. Est dolor accusamus qui saepe voluptatem dolorem omnis.','2001-06-01'),(14,4,'Error inventore delectus sapiente non.','Aliquam ut aliquid et laboriosam distinctio ab. Tempore molestiae aut ea nesciunt culpa. Eum maiores molestiae voluptatem animi aliquam. Aspernatur aut soluta totam occaecati in nam ratione asperiores.','Voluptatum id amet qui quia. Nemo nulla atque dignissimos.','1974-12-07'),(15,5,'Ut aut quo aut ea occaecati est voluptas.','Non deleniti molestias velit ut eos veritatis. Et id eaque numquam ipsa iure ut. Molestiae et minus natus.','Necessitatibus asperiores adipisci eaque. Alias sunt illum fugit ab labore laborum est odio. Aspernatur esse qui ut omnis autem. Laudantium quos corporis numquam sapiente enim.','1999-09-12'),(16,6,'Nihil ea qui sequi odit rem.','Omnis ea accusantium qui commodi et ducimus. Magni deserunt sed quo velit. Hic cum tenetur facilis. Non eum quis molestias sunt. Illo saepe architecto doloremque illum sequi.','Nihil iste illum vitae ipsa et et. Reiciendis sint illum quo dignissimos veritatis. Velit eum architecto enim ratione aut.','2003-07-28'),(17,7,'Quia accusantium deserunt suscipit.','Repellat et molestiae magnam quaerat et iure. Enim enim cum quisquam quasi.','Maiores officiis beatae hic hic dolor non officiis. Nulla beatae at aut fugit doloribus et provident. Debitis non dolores iusto impedit. Alias blanditiis velit voluptate et debitis.','2015-05-24'),(18,8,'Inventore et eaque temporibus qui aut exercitationem necessitatibus.','Omnis molestias nemo culpa est dicta dolorem porro. Illum est ut ut molestias similique sit sunt. Consequatur asperiores quaerat voluptate incidunt.','Unde quibusdam asperiores voluptates quaerat et aliquam. Libero at est quibusdam eos aut. Aut voluptatem tempora a nam.','1996-02-06'),(19,9,'Et soluta consequatur porro rem corrupti.','Ullam doloremque explicabo ea ab quam ipsum. Et qui iure vero tempore voluptate aut. Ullam id ab accusamus optio voluptas. Quia quaerat quibusdam aut accusantium impedit et.','Perspiciatis sed dolores aut. Animi sed totam exercitationem fugiat dolores. Ipsa dolorem quia non aliquam. Rerum exercitationem voluptatem dolor beatae veritatis quasi omnis consectetur.','2018-03-31'),(20,10,'Culpa error rerum voluptatem recusandae quae tempora.','Est ullam tempore autem et. Dolorum est eius eaque veniam in quibusdam neque. Ut aspernatur earum sint delectus voluptate deserunt sapiente quia.','Enim quos facere rerum ipsa. Eveniet expedita id eligendi voluptatem magnam quo eos.','2007-01-22'),(21,1,'Harum laudantium fugiat debitis atque sed.','Et asperiores magni qui voluptas a consequatur totam. Inventore enim quaerat consequatur sint quam voluptatibus optio. Est aut repellendus repudiandae reiciendis eveniet veniam. Minima a corrupti non quae.','Voluptate officia ut debitis explicabo corrupti facere reprehenderit. Enim id recusandae vitae est dolores. Aperiam consequuntur ex beatae et alias quia.','1987-06-29'),(22,2,'Non architecto ut voluptas aut voluptas dolor ut.','Dolore delectus optio fuga aut labore necessitatibus. Laborum quis nulla deserunt. Aut corporis repellendus inventore vel.','Facilis soluta ab culpa est. Aut pariatur et dicta sit. Sed qui est numquam est.\\nAtque ex sit eveniet. Iure accusamus optio placeat voluptate non sit ea. Sint dignissimos dolorum debitis ipsam neque.','1993-05-06'),(23,3,'Dolores sed hic vitae ut qui.','Libero illum dolorum est eaque ut. Nesciunt qui vitae recusandae eveniet saepe et ut. Aliquid enim vitae beatae animi quam doloribus accusamus. Eos eos excepturi accusamus ut recusandae.','Distinctio molestiae sint qui. Expedita qui ex dignissimos architecto quo sapiente alias eveniet. Laborum qui aut est doloribus a beatae. Unde adipisci consequuntur et tenetur.','1978-09-08'),(24,4,'Deleniti distinctio eos eveniet.','Ex aperiam animi quis excepturi. Velit qui molestias iste iure voluptatem. Eveniet adipisci quasi amet. Soluta laborum aperiam magni.','Deserunt dolores ut ut ex cum. Quae iusto rerum voluptatum aperiam. Vel voluptatem ut nesciunt delectus blanditiis. Sequi consequuntur temporibus sunt dolores repudiandae.','2003-06-23'),(25,5,'Ea et asperiores odio vel sunt exercitationem.','Quod necessitatibus quis sit aspernatur a. Molestias laudantium voluptatibus quaerat rerum cupiditate. Aut consectetur quia doloribus repellat porro est.','Et alias soluta aliquam qui aut. Explicabo quo consequuntur consequuntur velit distinctio.','1972-09-16'),(26,6,'Accusamus est sed aut minus.','Et libero in in est consequuntur. Illum distinctio doloremque quas.','Neque vel tenetur libero sed aut voluptas. Itaque quod et laudantium magnam tempora qui non. Et sapiente dolores reiciendis sit ab fugiat sed sequi. Reiciendis maxime qui aut laborum dolor.','2017-03-08'),(27,7,'Et sed reprehenderit nobis sed.','Totam amet nisi id quod. Laudantium maxime rem velit consequuntur amet. Et enim eum aspernatur totam. Nulla consequatur similique maxime et qui rerum.','Iure sequi unde consectetur neque in magni. Illo ipsa commodi quae placeat modi numquam numquam. Quae culpa sit distinctio vitae est.','1973-08-04'),(28,8,'Autem ullam aperiam totam assumenda quod esse.','Aut incidunt aspernatur aut sapiente ipsum repellat. Molestiae eaque accusantium maxime. Velit modi ea consectetur natus ea.','Molestias voluptatum cupiditate et minus qui consequuntur. Reprehenderit aut at corrupti. Eius unde ullam aut cum eius molestiae.','2014-04-26'),(29,9,'Ad dolores amet ea nisi aut enim voluptatem.','Eum voluptates sunt occaecati molestiae. Cupiditate labore expedita eius in omnis non. Sit cumque unde cupiditate sequi eius reprehenderit nulla.','Voluptates modi esse quas sit eos praesentium. Quas et rem vero quo veritatis voluptas. Inventore dolorem ut praesentium consequatur rem. Amet ipsam quia officia iste est in.','2006-09-07'),(30,10,'Eos fuga at ex sapiente quasi.','Facere dolores non omnis facilis. Nam cupiditate maiores iure quia adipisci numquam magnam. Esse voluptas voluptatem cum ea voluptas doloremque.','Voluptatem qui qui magnam quis eos. Consequatur ut repudiandae libero dignissimos et quia velit. Eum nisi facere consequatur quod ut. Ad molestiae voluptatem eaque iste et.','2009-07-23');\n/*!40000 ALTER TABLE `posts` ENABLE KEYS */;\nUNLOCK TABLES;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2024-07-19 10:47:53\n"
  },
  {
    "path": "doc/examples/drop/MySQL/nxs-data-anonymizer.conf",
    "content": "filters:\n  authors:\n    columns:\n      first_name:\n        value: \"John\"\n      last_name:\n        value: \"Smith\"\n      email:\n        value: \"JohnSmith@example.com\"\n      birthdate:\n        value: \"{{ if eq .Values.birthdate \\\"1981-10-14\\\" }}{{ drop }}{{ else }}{{ .Values.added }}{{ end }}\"\n      added:\n        value: \"2000-01-01 12:00:00\"\n  posts:\n    columns:\n      author_id:\n        value: \"{{ if eq .Values.author_id \\\"1\\\" }}{{ drop }}{{ else }}{{ .Values.author_id }}{{ end }}\"\n      title:\n        value: \"anon_title\"\n      description:\n        value: \"anon_description\"\n      content:\n        value: \"anon_content\"\n      date:\n        value: \"2001-01-01 12:00:00\""
  },
  {
    "path": "doc/examples/drop/MySQL/output.sql",
    "content": "-- MySQL dump 10.13  Distrib 8.4.0, for Linux (x86_64)\n--\n-- Host: localhost    Database: name_db\n-- ------------------------------------------------------\n-- Server version\t8.4.0\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!50503 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `authors`\n--\n\nDROP TABLE IF EXISTS `authors`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `authors` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `first_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `last_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `email` varchar(100) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `birthdate` date NOT NULL,\n  `added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `authors`\n--\n\nLOCK TABLES `authors` WRITE;\n/*!40000 ALTER TABLE `authors` DISABLE KEYS */;\nINSERT INTO `authors` VALUES (2,'John','Smith','JohnSmith@example.com','1980-10-28 23:57:00','2000-01-01 12:00:00'),(3,'John','Smith','JohnSmith@example.com','1997-03-14 18:41:06','2000-01-01 12:00:00'),(4,'John','Smith','JohnSmith@example.com','2010-04-12 00:38:42','2000-01-01 12:00:00'),(5,'John','Smith','JohnSmith@example.com','1996-03-25 09:07:39','2000-01-01 12:00:00'),(6,'John','Smith','JohnSmith@example.com','1979-03-16 10:10:12','2000-01-01 12:00:00'),(7,'John','Smith','JohnSmith@example.com','2020-08-02 02:01:34','2000-01-01 12:00:00'),(8,'John','Smith','JohnSmith@example.com','1971-01-02 14:19:52','2000-01-01 12:00:00'),(9,'John','Smith','JohnSmith@example.com','2004-06-10 12:33:11','2000-01-01 12:00:00'),(10,'John','Smith','JohnSmith@example.com','2007-09-19 13:48:20','2000-01-01 12:00:00');\n/*!40000 ALTER TABLE `authors` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `posts`\n--\n\nDROP TABLE IF EXISTS `posts`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `posts` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `author_id` int NOT NULL,\n  `title` varchar(255) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `description` varchar(500) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `content` text COLLATE utf8mb3_unicode_ci NOT NULL,\n  `date` date NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `posts`\n--\n\nLOCK TABLES `posts` WRITE;\n/*!40000 ALTER TABLE `posts` DISABLE KEYS */;\nINSERT INTO `posts` VALUES (2,2,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(3,3,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(4,4,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(5,5,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(6,6,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(7,7,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(8,8,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(9,9,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(10,10,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(12,2,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(13,3,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(14,4,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(15,5,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(16,6,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(17,7,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(18,8,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(19,9,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(20,10,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(22,2,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(23,3,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(24,4,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(25,5,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(26,6,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(27,7,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(28,8,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(29,9,'anon_title','anon_description','anon_content','2001-01-01 12:00:00'),(30,10,'anon_title','anon_description','anon_content','2001-01-01 12:00:00');\n/*!40000 ALTER TABLE `posts` ENABLE KEYS */;\nUNLOCK TABLES;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2024-07-19 10:47:53\n"
  },
  {
    "path": "doc/examples/drop/PostgreSQL/input",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: authors; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.authors (\n    id integer NOT NULL,\n    first_name character varying(50) NOT NULL,\n    last_name character varying(50) NOT NULL,\n    email character varying(100) NOT NULL,\n    birthdate date NOT NULL,\n    added timestamp without time zone NOT NULL\n);\n\n\nALTER TABLE public.authors OWNER TO postgres;\n\n--\n-- Name: posts; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.posts (\n    id integer NOT NULL,\n    author_id integer NOT NULL,\n    title character varying(255) NOT NULL,\n    description character varying(500) NOT NULL,\n    content text NOT NULL,\n    date date NOT NULL\n);\n\n\nALTER TABLE public.posts OWNER TO postgres;\n\n--\n-- Data for Name: authors; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.authors (id, first_name, last_name, email, birthdate, added) FROM stdin;\n1\tWilford\tWintheiser\tbrett35@example.com\t1981-10-14\t1988-09-10 18:37:25\n2\tNyasia\tDoyle\taracely46@example.com\t2007-07-01\t1980-10-28 23:57:00\n3\tKen\tHaag\tcarroll.harris@example.com\t2003-04-16\t1997-03-14 18:41:06\n4\tLeonor\tMann\tjohns.janick@example.org\t1996-05-18\t2010-04-12 00:38:42\n5\tEloisa\tRatke\tlakin.ramiro@example.net\t1982-07-22\t1996-03-25 09:07:39\n6\tNikolas\tDibbert\tjudson33@example.com\t1970-02-22\t1979-03-16 10:10:12\n7\tKelley\tKoch\tkaci.koch@example.net\t2013-05-01\t2020-08-02 02:01:34\n8\tGlen\tHowe\tjprosacco@example.net\t1971-08-03\t1971-01-02 14:19:52\n9\tGeovanni\tMedhurst\tkutch.kylie@example.com\t2011-04-20\t2004-06-10 12:33:11\n10\tZella\tDavis\thane.terrill@example.org\t1991-11-07\t2007-09-19 13:48:20\n\\.\n\n\n--\n-- Data for Name: posts; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.posts (id, author_id, title, description, content, date) FROM stdin;\n1\t1\tPariatur est in ut provident vero eligendi.\tConsequatur quae odio in animi. Quis dolorem aut corporis sed ratione animi et. Iure sunt qui eligendi laudantium harum maxime id id. Quia eos beatae temporibus eos rerum ipsum.\tVelit voluptatibus quo est dolorem quos sed et. Illum similique atque et qui. Perspiciatis magnam saepe quis. Consequatur aut dolorem ea.\t1975-07-07\n2\t2\tUnde est architecto est.\tConsectetur quidem aut eligendi quas. Voluptas aut voluptas ratione reiciendis magnam sint. Ratione et omnis assumenda deserunt voluptatem perspiciatis. Non voluptates quia distinctio nam consectetur vel.\tSed sint at consectetur. Fugiat fugiat omnis debitis dolore. Incidunt vero incidunt enim reiciendis. Odio et illo facilis quo sit quia consequatur voluptatem.\t1976-05-25\n3\t3\tDignissimos perspiciatis nobis quisquam saepe ad aut numquam.\tVoluptatibus eum voluptas eveniet veniam ducimus. Modi id vitae est accusamus. Quaerat perferendis voluptas minima dignissimos et. Sapiente explicabo voluptas commodi voluptatem autem totam. Adipisci quos quos quo ea aliquid rerum.\tRepellat minus enim occaecati sunt quas. Ab ipsa voluptatibus sunt eos omnis quisquam at voluptatibus. Quo vitae doloremque nesciunt doloremque. Temporibus rerum sunt iste dolores rerum.\t1991-12-21\n4\t4\tVoluptas sint modi magnam.\tFacere harum pariatur quo eveniet dolor molestias. Quo debitis corporis quasi minima et optio. Ut maiores nihil rerum autem culpa et voluptates. Amet totam rem optio in. Provident ea repudiandae quisquam unde occaecati autem.\tSed quia assumenda quis rerum praesentium harum. Quia minima quo natus. Impedit temporibus perspiciatis et enim doloremque nihil et. Perspiciatis nam occaecati illo dicta asperiores eos nam.\t2002-01-23\n5\t5\tSapiente rem eos enim ullam ipsum ut.\tOfficia quos voluptas autem consequuntur. Quis consequatur aut vel dolor. Sapiente voluptatem quibusdam dolor nobis earum laboriosam quisquam.\tQuibusdam vel tempora explicabo qui. Sunt animi a unde veritatis perferendis similique nostrum vel. Porro ab ad cumque dolorum provident distinctio est ipsum. Esse maxime ea quia.\t2017-11-19\n6\t6\tError quas doloremque est sunt quae.\tCorporis quis in sint. Eos vitae aut provident distinctio ullam. Corporis mollitia quam natus qui sapiente officiis.\tIpsam animi aperiam ipsa fuga. Sunt blanditiis possimus aut quod. Doloremque possimus occaecati numquam omnis dolor. Qui nihil qui atque vitae sapiente illo id.\t1974-03-23\n7\t7\tQuo impedit quos molestiae dolorum in soluta dolores non.\tHarum quasi dolorum et harum iste eveniet et. Cumque ab recusandae architecto est ipsam est. Eligendi et earum ea alias odio sed ut.\tIllo earum porro corporis sunt aut. Vel quisquam ut voluptas reiciendis maiores cumque. Qui hic maiores voluptas sapiente reprehenderit. Eos non autem quis maiores perferendis.\t2004-12-08\n8\t8\tNulla quia repellendus et autem vitae provident.\tFacere deserunt suscipit quia et et totam vel at. Cumque suscipit est ea quis in quos. Harum dolorum consequuntur illum voluptatem iste enim recusandae.\tExcepturi hic tenetur sint nostrum. Nihil itaque repudiandae qui hic minima quis ut. Dolor et aut quaerat exercitationem minima ut. Blanditiis minus et qui dolor ut atque.\t1999-02-28\n9\t9\tSimilique at quia quia ut recusandae repudiandae delectus.\tEt necessitatibus aut accusantium quisquam harum est. Non quam id impedit deleniti. Eaque non architecto facere dolorem nesciunt perferendis. Delectus nihil ut dignissimos. Voluptate rerum reprehenderit aut voluptatem quibusdam quidem.\tTempore iusto minus omnis tempore. Hic aut sequi temporibus consequatur. In vel enim eos nihil sed eos debitis.\t2007-08-07\n10\t10\tEst vel aperiam ipsa quod doloremque et est et.\tFacere ut et similique voluptates voluptas blanditiis explicabo. Eaque molestiae nihil sed et repellat voluptatem eum autem.\tRem laudantium in aut assumenda. Aspernatur id illo pariatur aut deleniti rem et. Nisi velit neque qui quia.\t2009-07-18\n11\t1\tSint est qui dolorem eum accusantium repudiandae.\tQuia tenetur culpa maiores molestias. Id numquam illum earum quos sint ad dolore corrupti. Consequatur quasi itaque est odit qui quod culpa.\tOmnis tenetur occaecati accusamus quis corrupti et ipsam. Ullam nobis tempore officia nesciunt iste. Nesciunt vel in eos. Dolor voluptates quod sed quibusdam ut. Fuga quia eum quidem cum.\t2010-04-16\n12\t2\tCulpa debitis ut non sapiente voluptatem.\tCommodi fugit ullam quaerat quam quo minus. Harum quam ipsam ducimus sit expedita sit. Eos natus quo quibusdam quam repudiandae. Assumenda et sint sit quia qui necessitatibus.\tEum molestiae cupiditate ut minus. Eaque eos eos ipsam voluptatem. Sint aut aliquid modi id dolores consequatur. Aut nemo blanditiis nisi ea nam velit.\t1988-12-26\n13\t3\tUt ut rerum qui quis sed sunt.\tTenetur enim et nisi ex et consequatur omnis nisi. Eos deleniti aut amet illo sed quibusdam. Consequuntur sint quia quia aut magni.\tAut eveniet natus ut. Nostrum aliquid qui nam hic iusto id occaecati qui. Est dolor accusamus qui saepe voluptatem dolorem omnis.\t2001-06-01\n14\t4\tError inventore delectus sapiente non.\tAliquam ut aliquid et laboriosam distinctio ab. Tempore molestiae aut ea nesciunt culpa. Eum maiores molestiae voluptatem animi aliquam. Aspernatur aut soluta totam occaecati in nam ratione asperiores.\tVoluptatum id amet qui quia. Nemo nulla atque dignissimos.\t1974-12-07\n15\t5\tUt aut quo aut ea occaecati est voluptas.\tNon deleniti molestias velit ut eos veritatis. Et id eaque numquam ipsa iure ut. Molestiae et minus natus.\tNecessitatibus asperiores adipisci eaque. Alias sunt illum fugit ab labore laborum est odio. Aspernatur esse qui ut omnis autem. Laudantium quos corporis numquam sapiente enim.\t1999-09-12\n16\t6\tNihil ea qui sequi odit rem.\tOmnis ea accusantium qui commodi et ducimus. Magni deserunt sed quo velit. Hic cum tenetur facilis. Non eum quis molestias sunt. Illo saepe architecto doloremque illum sequi.\tNihil iste illum vitae ipsa et et. Reiciendis sint illum quo dignissimos veritatis. Velit eum architecto enim ratione aut.\t2003-07-28\n17\t7\tQuia accusantium deserunt suscipit.\tRepellat et molestiae magnam quaerat et iure. Enim enim cum quisquam quasi.\tMaiores officiis beatae hic hic dolor non officiis. Nulla beatae at aut fugit doloribus et provident. Debitis non dolores iusto impedit. Alias blanditiis velit voluptate et debitis.\t2015-05-24\n18\t8\tInventore et eaque temporibus qui aut exercitationem necessitatibus.\tOmnis molestias nemo culpa est dicta dolorem porro. Illum est ut ut molestias similique sit sunt. Consequatur asperiores quaerat voluptate incidunt.\tUnde quibusdam asperiores voluptates quaerat et aliquam. Libero at est quibusdam eos aut. Aut voluptatem tempora a nam.\t1996-02-06\n19\t9\tEt soluta consequatur porro rem corrupti.\tUllam doloremque explicabo ea ab quam ipsum. Et qui iure vero tempore voluptate aut. Ullam id ab accusamus optio voluptas. Quia quaerat quibusdam aut accusantium impedit et.\tPerspiciatis sed dolores aut. Animi sed totam exercitationem fugiat dolores. Ipsa dolorem quia non aliquam. Rerum exercitationem voluptatem dolor beatae veritatis quasi omnis consectetur.\t2018-03-31\n20\t10\tCulpa error rerum voluptatem recusandae quae tempora.\tEst ullam tempore autem et. Dolorum est eius eaque veniam in quibusdam neque. Ut aspernatur earum sint delectus voluptate deserunt sapiente quia.\tEnim quos facere rerum ipsa. Eveniet expedita id eligendi voluptatem magnam quo eos.\t2007-01-22\n21\t1\tHarum laudantium fugiat debitis atque sed.\tEt asperiores magni qui voluptas a consequatur totam. Inventore enim quaerat consequatur sint quam voluptatibus optio. Est aut repellendus repudiandae reiciendis eveniet veniam. Minima a corrupti non quae.\tVoluptate officia ut debitis explicabo corrupti facere reprehenderit. Enim id recusandae vitae est dolores. Aperiam consequuntur ex beatae et alias quia.\t1987-06-29\n22\t2\tNon architecto ut voluptas aut voluptas dolor ut.\tDolore delectus optio fuga aut labore necessitatibus. Laborum quis nulla deserunt. Aut corporis repellendus inventore vel.\tFacilis soluta ab culpa est. Aut pariatur et dicta sit. Sed qui est numquam est.\\nAtque ex sit eveniet. Iure accusamus optio placeat voluptate non sit ea. Sint dignissimos dolorum debitis ipsam neque.\t1993-05-06\n23\t3\tDolores sed hic vitae ut qui.\tLibero illum dolorum est eaque ut. Nesciunt qui vitae recusandae eveniet saepe et ut. Aliquid enim vitae beatae animi quam doloribus accusamus. Eos eos excepturi accusamus ut recusandae.\tDistinctio molestiae sint qui. Expedita qui ex dignissimos architecto quo sapiente alias eveniet. Laborum qui aut est doloribus a beatae. Unde adipisci consequuntur et tenetur.\t1978-09-08\n24\t4\tDeleniti distinctio eos eveniet.\tEx aperiam animi quis excepturi. Velit qui molestias iste iure voluptatem. Eveniet adipisci quasi amet. Soluta laborum aperiam magni.\tDeserunt dolores ut ut ex cum. Quae iusto rerum voluptatum aperiam. Vel voluptatem ut nesciunt delectus blanditiis. Sequi consequuntur temporibus sunt dolores repudiandae.\t2003-06-23\n25\t5\tEa et asperiores odio vel sunt exercitationem.\tQuod necessitatibus quis sit aspernatur a. Molestias laudantium voluptatibus quaerat rerum cupiditate. Aut consectetur quia doloribus repellat porro est.\tEt alias soluta aliquam qui aut. Explicabo quo consequuntur consequuntur velit distinctio.\t1972-09-16\n26\t6\tAccusamus est sed aut minus.\tEt libero in in est consequuntur. Illum distinctio doloremque quas.\tNeque vel tenetur libero sed aut voluptas. Itaque quod et laudantium magnam tempora qui non. Et sapiente dolores reiciendis sit ab fugiat sed sequi. Reiciendis maxime qui aut laborum dolor.\t2017-03-08\n27\t7\tEt sed reprehenderit nobis sed.\tTotam amet nisi id quod. Laudantium maxime rem velit consequuntur amet. Et enim eum aspernatur totam. Nulla consequatur similique maxime et qui rerum.\tIure sequi unde consectetur neque in magni. Illo ipsa commodi quae placeat modi numquam numquam. Quae culpa sit distinctio vitae est.\t1973-08-04\n28\t8\tAutem ullam aperiam totam assumenda quod esse.\tAut incidunt aspernatur aut sapiente ipsum repellat. Molestiae eaque accusantium maxime. Velit modi ea consectetur natus ea.\tMolestias voluptatum cupiditate et minus qui consequuntur. Reprehenderit aut at corrupti. Eius unde ullam aut cum eius molestiae.\t2014-04-26\n29\t9\tAd dolores amet ea nisi aut enim voluptatem.\tEum voluptates sunt occaecati molestiae. Cupiditate labore expedita eius in omnis non. Sit cumque unde cupiditate sequi eius reprehenderit nulla.\tVoluptates modi esse quas sit eos praesentium. Quas et rem vero quo veritatis voluptas. Inventore dolorem ut praesentium consequatur rem. Amet ipsam quia officia iste est in.\t2006-09-07\n30\t10\tEos fuga at ex sapiente quasi.\tFacere dolores non omnis facilis. Nam cupiditate maiores iure quia adipisci numquam magnam. Esse voluptas voluptatem cum ea voluptas doloremque.\tVoluptatem qui qui magnam quis eos. Consequatur ut repudiandae libero dignissimos et quia velit. Eum nisi facere consequatur quod ut. Ad molestiae voluptatem eaque iste et.\t2009-07-23\n\\.\n\n\n--\n-- Name: authors authors_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.authors\n    ADD CONSTRAINT authors_pkey PRIMARY KEY (id);\n\n\n--\n-- Name: posts posts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.posts\n    ADD CONSTRAINT posts_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "doc/examples/drop/PostgreSQL/nxs-data-anonymizer.conf",
    "content": "filters:\n  public.authors:\n    columns:\n      first_name:\n        value: \"John\"\n      last_name:\n        value: \"Smith\"\n      email:\n        value: \"JohnSmith@example.com\"\n      birthdate:\n        value: \"{{ if eq .Values.birthdate \\\"1981-10-14\\\" }}{{ drop }}{{ else }}{{ .Values.added }}{{ end }}\" \n      added:\n        value: \"2000-01-01 12:00:00\"\n  public.posts:\n    columns:\n      author_id:\n        value: \"{{ if eq .Values.author_id \\\"1\\\" }}{{ drop }}{{ else }}{{ .Values.author_id }}{{ end }}\"\n      title:\n        value: \"anon_title\"\n      description:\n        value: \"anon_description\"\n      content:\n        value: \"anon_content\"\n      date:\n        value: \"2001-01-01 12:00:00\""
  },
  {
    "path": "doc/examples/drop/PostgreSQL/output",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: authors; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.authors (\n    id integer NOT NULL,\n    first_name character varying(50) NOT NULL,\n    last_name character varying(50) NOT NULL,\n    email character varying(100) NOT NULL,\n    birthdate date NOT NULL,\n    added timestamp without time zone NOT NULL\n);\n\n\nALTER TABLE public.authors OWNER TO postgres;\n\n--\n-- Name: posts; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.posts (\n    id integer NOT NULL,\n    author_id integer NOT NULL,\n    title character varying(255) NOT NULL,\n    description character varying(500) NOT NULL,\n    content text NOT NULL,\n    date date NOT NULL\n);\n\n\nALTER TABLE public.posts OWNER TO postgres;\n\n--\n-- Data for Name: authors; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.authors (id, first_name, last_name, email, birthdate, added) FROM stdin;\n2\tJohn\tSmith\tJohnSmith@example.com\t1980-10-28 23:57:00\t2000-01-01 12:00:00\n3\tJohn\tSmith\tJohnSmith@example.com\t1997-03-14 18:41:06\t2000-01-01 12:00:00\n4\tJohn\tSmith\tJohnSmith@example.com\t2010-04-12 00:38:42\t2000-01-01 12:00:00\n5\tJohn\tSmith\tJohnSmith@example.com\t1996-03-25 09:07:39\t2000-01-01 12:00:00\n6\tJohn\tSmith\tJohnSmith@example.com\t1979-03-16 10:10:12\t2000-01-01 12:00:00\n7\tJohn\tSmith\tJohnSmith@example.com\t2020-08-02 02:01:34\t2000-01-01 12:00:00\n8\tJohn\tSmith\tJohnSmith@example.com\t1971-01-02 14:19:52\t2000-01-01 12:00:00\n9\tJohn\tSmith\tJohnSmith@example.com\t2004-06-10 12:33:11\t2000-01-01 12:00:00\n10\tJohn\tSmith\tJohnSmith@example.com\t2007-09-19 13:48:20\t2000-01-01 12:00:00\n\\.\n\n\n--\n-- Data for Name: posts; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.posts (id, author_id, title, description, content, date) FROM stdin;\n2\t2\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n3\t3\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n4\t4\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n5\t5\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n6\t6\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n7\t7\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n8\t8\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n9\t9\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n10\t10\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n12\t2\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n13\t3\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n14\t4\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n15\t5\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n16\t6\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n17\t7\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n18\t8\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n19\t9\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n20\t10\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n22\t2\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n23\t3\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n24\t4\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n25\t5\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n26\t6\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n27\t7\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n28\t8\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n29\t9\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n30\t10\tanon_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n\\.\n\n\n--\n-- Name: authors authors_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.authors\n    ADD CONSTRAINT authors_pkey PRIMARY KEY (id);\n\n\n--\n-- Name: posts posts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.posts\n    ADD CONSTRAINT posts_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "doc/examples/drop/Readme.md",
    "content": "# Example `variables`\n\nAn example of using nxs-data-anonymizer in a simple configuration with filters and variables blocks.\n\nIn order to use variables in the \"filters\" block, you need to describe the \"variables\" block:\n```yaml\nvariables:\n  some_variable: # Variable name\n    value: \"some_value\" # Variable value\n```\n\nIf you use a function to generate a value, then in this block it will be executed once and the resulting value will be the same for all its occurrences in the dump.\n\nAn example of a configuration:\n```yaml\nvariables:\n  var1:\n    value: \"<fixed_value_or_generation_function_of_value>\"\n  var2:\n    value: \"<fixed_value_or_generation_function_of_value>\"\n  var3:\n    value: \"<fixed_value_or_generation_function_of_value>\"\n\nfilters:\n  table1:\n    columns:\n      table1_col1:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n      table1_col2:\n        value: \"{{ .Variables.var1 }}\"\n      table1_col3:\n        value: \"{{ .Variables.var2 }}\"\n  table2:\n    columns:\n      table2_col1:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n      table2_col2:\n        value: \"{{ .Variables.var1 }}\"\n      table2_col3:\n        value: \"{{ .Variables.var3 }}\"\n```\n\nWorking examples of configurations in the `./MySQL` and `./PostgreSQL` directories."
  },
  {
    "path": "doc/examples/filters/MySQL/input.sql",
    "content": "-- MySQL dump 10.13  Distrib 8.1.0, for Linux (x86_64)\n--\n-- Host: localhost    Database: test_db\n-- ------------------------------------------------------\n-- Server version\t8.1.0\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!50503 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `test_tbl`\n--\n\nDROP TABLE IF EXISTS `test_tbl`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `test_tbl` (\n  `int_count` int NOT NULL,\n  `int_type` int DEFAULT NULL,\n  `dbl_type` double DEFAULT NULL,\n  `vchar_type` varchar(255) DEFAULT NULL,\n  `date_type` date DEFAULT NULL,\n  `time_type` time DEFAULT NULL,\n  PRIMARY KEY (`int_count`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `test_tbl`\n--\n\nLOCK TABLES `test_tbl` WRITE;\n/*!40000 ALTER TABLE `test_tbl` DISABLE KEYS */;\nINSERT INTO `test_tbl` VALUES (1,1,1.1,'aaaaaa',NULL,NULL),(2,2,2.2,'bbbbbb',NULL,NULL),(3,3,3.3,'cccccc',NULL,NULL),(4,4,4.4,'dddddd',NULL,NULL),(5,5,5.5,'eeeeee',NULL,NULL);\n/*!40000 ALTER TABLE `test_tbl` ENABLE KEYS */;\nUNLOCK TABLES;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2023-08-18  6:52:42\n"
  },
  {
    "path": "doc/examples/filters/MySQL/nxs-data-anonymizer.conf",
    "content": "filters:\n  test_tbl:\n    columns:\n      int_type:\n        value: \"1\"\n      dbl_type:\n        value: \"99.999\"\n      vchar_type:\n        value: \"anon-data\"\n      date_type:\n        value: \"2001-01-01\" \n      time_type:\n        value: \"20:20:20\" \n"
  },
  {
    "path": "doc/examples/filters/MySQL/output.sql",
    "content": "-- MySQL dump 10.13  Distrib 8.1.0, for Linux (x86_64)\n--\n-- Host: localhost    Database: test_db\n-- ------------------------------------------------------\n-- Server version\t8.1.0\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!50503 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `test_tbl`\n--\n\nDROP TABLE IF EXISTS `test_tbl`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `test_tbl` (\n  `int_count` int NOT NULL,\n  `int_type` int DEFAULT NULL,\n  `dbl_type` double DEFAULT NULL,\n  `vchar_type` varchar(255) DEFAULT NULL,\n  `date_type` date DEFAULT NULL,\n  `time_type` time DEFAULT NULL,\n  PRIMARY KEY (`int_count`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `test_tbl`\n--\n\nLOCK TABLES `test_tbl` WRITE;\n/*!40000 ALTER TABLE `test_tbl` DISABLE KEYS */;\nINSERT INTO `test_tbl` VALUES (1,1,99.999,'anon-data','2001-01-01','20:20:20'),(2,1,99.999,'anon-data','2001-01-01','20:20:20'),(3,1,99.999,'anon-data','2001-01-01','20:20:20'),(4,1,99.999,'anon-data','2001-01-01','20:20:20'),(5,1,99.999,'anon-data','2001-01-01','20:20:20');\n/*!40000 ALTER TABLE `test_tbl` ENABLE KEYS */;\nUNLOCK TABLES;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2023-08-18  6:52:42\n"
  },
  {
    "path": "doc/examples/filters/PostgreSQL/input",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.1 (Debian 16.1-1.pgdg120+1)\n-- Dumped by pg_dump version 16.1 (Debian 16.1-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: list_types; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.list_types (\n    integer_type integer,\n    numeric_type numeric,\n    double_precision_type double precision,\n    varchar_type character varying,\n    text_type text,\n    date_type date,\n    time_tz_type time with time zone,\n    boolean_type boolean,\n    xml_type xml,\n    jsonb_type jsonb,\n    id bigint NOT NULL\n);\n\n\nALTER TABLE public.list_types OWNER TO postgres;\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres\n--\n\nCREATE SEQUENCE public.list_types_id_seq\n    START WITH 1\n    INCREMENT BY 1\n    NO MINVALUE\n    NO MAXVALUE\n    CACHE 1;\n\n\nALTER SEQUENCE public.list_types_id_seq OWNER TO postgres;\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres\n--\n\nALTER SEQUENCE public.list_types_id_seq OWNED BY public.list_types.id;\n\n\n--\n-- Name: list_types id; Type: DEFAULT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.list_types ALTER COLUMN id SET DEFAULT nextval('public.list_types_id_seq'::regclass);\n\n\n--\n-- Data for Name: list_types; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.list_types (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\n\\N\t42.99465\t\\N\tBiba\t\\N\t\\N\t19:51:50+00\t\\N\t\\N\t\\N\t6\n\\N\t-84.46685\t\\N\tPupa\t\\N\t\\N\t03:34:36+00\t\\N\t\\N\t\\N\t2\n\\N\t72.52040\t\\N\tLupa\t \t\\N\t15:17:37+00\tt\t\\N\t\\N\t4\n\\N\t99.37111\t\\N\tBoba\t \t\\N\t03:34:36+00\t\\N\t\\N\t\\N\t8\n\\N\t-90.90125\t\\N\tCerebla\t\\N\t\\N\t22:00:45+00\t\\N\t\\N\t\\N\t10\n8765542\t\\N\t7.84023409\t \tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel pretium lectus quam id leo in vitae. Dignissim cras tincidunt lobortis feugiat vivamus at augue. Sit amet aliquam id diam maecenas. Ornare lectus sit amet est placerat in egestas erat. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Orci sagittis eu volutpat odio facilisis. Mauris in aliquam sem fringilla ut morbi tincidunt augue interdum. Nisi porta lorem mollis aliquam ut porttitor leo a diam. Amet purus gravida quis blandit turpis cursus in. Risus feugiat in ante metus. Purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Faucibus nisl tincidunt eget nullam. Lectus quam id leo in vitae turpis massa. Nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit. Pretium lectus quam id leo in vitae turpis massa. Blandit aliquam etiam erat velit scelerisque in dictum non. Eu nisl nunc mi ipsum faucibus vitae.\t1996-06-15\t\\N\tt\t<root>\\n  <west>721744494.7994413</west>\\n  <top>-26197703.515699387</top>\\n  <or>event</or>\\n  <art>\\n    <layers>among</layers>\\n    <growth>couple</growth>\\n    <off>official</off>\\n    <made>spring</made>\\n    <poem>1032613367</poem>\\n  </art>\\n  <strong>198858711</strong>\\n</root>\t{\"truck\": 1563128845, \"little\": -1009907448.0705619, \"possible\": \"gave\"}\t1\n4562892\t\\N\t5.8024375\t\\N\tMassa sapien faucibus et molestie ac. Praesent elementum facilisis leo vel. Turpis egestas pretium aenean pharetra magna. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Auctor neque vitae tempus quam pellentesque. Ornare aenean euismod elementum nisi quis eleifend. Purus sit amet luctus venenatis lectus. Tortor consequat id porta nibh venenatis cras sed felis eget. Felis bibendum ut tristique et egestas quis ipsum. Pretium fusce id velit ut tortor pretium viverra. Nam aliquam sem et tortor consequat. Nisl pretium fusce id velit. Sem integer vitae justo eget magna fermentum iaculis. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae auctor eu augue ut lectus arcu. Malesuada fames ac turpis egestas. Ac odio tempor orci dapibus ultrices in. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Et malesuada fames ac turpis egestas integer. Sodales ut eu sem integer vitae justo eget.\t2031-07-14\t\\N\tf\t<root>\\n  <melted>\\n    <officer>-598731677.6283197</officer>\\n    <exist>variety</exist>\\n    <sitting>46234734.5525651</sitting>\\n    <period>rising</period>\\n    <rice>-1556052082.582368</rice>\\n  </melted>\\n  <got>eleven</got>\\n  <onlinetools>1863692621</onlinetools>\\n  <this>-139561185.33627748</this>\\n  <driver>funny</driver>\\n</root>\t[{\"ago\": {\"shut\": \"seven\", \"found\": 469996577.0459976, \"climate\": \"early\"}, \"scene\": \"slightly\", \"medicine\": true}, true, true]\t3\n87689278\t\\N\t-0.31813426\t \tId donec ultrices tincidunt arcu. Id nibh tortor id aliquet lectus. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Cursus vitae congue mauris rhoncus. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sed turpis tincidunt id aliquet. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. Scelerisque eu ultrices vitae auctor eu augue ut. Volutpat ac tincidunt vitae semper quis.\t1976-12-10\t\\N\tt\t<root>\\n  <mission>rise</mission>\\n  <layers>\\n    <wire>consist</wire>\\n    <dinner>someone</dinner>\\n    <electric>white</electric>\\n    <heavy>victory</heavy>\\n    <ice>-761134241.8632131</ice>\\n  </layers>\\n  <help>1111641157</help>\\n  <comfortable>744054503</comfortable>\\n  <highway>1876042205.1417785</highway>\\n</root>\t{\"torn\": [false, -1325125579, false], \"rising\": false, \"volume\": \"grow\"}\t9\n687527896\t\\N\t-1.81914025\t \tFacilisi etiam dignissim diam quis enim. Diam ut venenatis tellus in metus vulputate eu. Mattis rhoncus urna neque viverra justo nec ultrices. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Nec ullamcorper sit amet risus nullam eget felis eget. Fames ac turpis egestas maecenas pharetra convallis posuere. Eget arcu dictum varius duis at consectetur lorem. Porta lorem mollis aliquam ut porttitor leo a diam sollicitudin. Magna fermentum iaculis eu non diam phasellus vestibulum lorem sed. Etiam non quam lacus suspendisse. Parturient montes nascetur ridiculus mus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar.\t2051-05-16\t\\N\tt\t<root>\\n  <piece>\\n    <vertical>398209907.5902777</vertical>\\n    <prove>wind</prove>\\n    <fair>parallel</fair>\\n    <closely>paint</closely>\\n    <see>-1386172501</see>\\n  </piece>\\n  <hide>previous</hide>\\n  <among>skill</among>\\n  <our>conversation</our>\\n  <cell>keep</cell>\\n</root>\t[[-128477882.56726694, 1569798072.8967233, {\"us\": 438307927.6373253, \"think\": -870063635, \"product\": \"stuck\"}], [{\"name\": \"broad\", \"took\": \"brother\", \"alphabet\": -731303259}, [-1065068182.0998564, \"finish\", \"up\"], false], false]\t5\n8767542\t\\N\t5.08081291\t\\N\tFames ac turpis egestas maecenas. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Sit amet commodo nulla facilisi nullam vehicula. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Maecenas ultricies mi eget mauris pharetra. Sed faucibus turpis in eu mi bibendum. Massa ultricies mi quis hendrerit dolor magna. Non diam phasellus vestibulum lorem sed. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus.\t2058-03-29\t\\N\tf\t<root>\\n  <invented>concerned</invented>\\n  <feet>-1671936329.7007055</feet>\\n  <win>slept</win>\\n  <until>how</until>\\n  <lion>-1838021068</lion>\\n</root>\t{\"basis\": \"mine\", \"company\": {\"tired\": false, \"prevent\": false, \"suppose\": 735075799}, \"worried\": {\"iron\": 378563223.91183805, \"nest\": false, \"raise\": {\"date\": false, \"engineer\": true, \"television\": 136840736.65782642}}}\t7\n\\.\n\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres\n--\n\nSELECT pg_catalog.setval('public.list_types_id_seq', 10, true);\n\n\n--\n-- Name: list_types list_types_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.list_types\n    ADD CONSTRAINT list_types_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "doc/examples/filters/PostgreSQL/nxs-data-anonymizer.conf",
    "content": "filters:\n  public.list_types:\n   columns:\n      integer_type:\n        value: \"{{ if (isNull .Values.integer_type) }}{{ 0 }}{{ else }}{{ 123 }}{{ end }}\"\n      numeric_type:\n        value: \"{{ if (isNull .Values.numeric_type) }}{{ 0 }}{{ else }}{{ 1.23 }}{{ end }}\"\n      double_precision_type:\n        value: \"{{ if (isNull .Values.double_precision_type) }}{{ 10 }}{{ else }}{{ 321 }}{{ end }}\"\n      varchar_type:\n        value: \"anon_text\"\n      text_type:\n        value: \"random text\"\n      date_type:\n        value: \"01-01-2000\" \n      time_tz_type:\n        value: \"20:20:20\" \n      boolean_type:\n        value: \"{{ if (isNull .Values.boolean_type) }}{{ false }}{{ else }}{{ true }}{{ end }}\" \n      xml_type:\n        value: \"random_xml\"\n      jsonb_type:\n        value: \"null\" \n      varchar_mass_type:\n        value: \"{esd,lfg,dil}\"\n      integer_mass_type:\n        value:  \"{{`{{4,5,6},{4,5,6}}`}}\"\n      double_mass_type:\n        value: \"{{`{{{0.1,0.2,0.3},{0.1,0.2,0.3}},{{0.1,0.2,0.3},{0.1,0.2,0.3}}}`}}\""
  },
  {
    "path": "doc/examples/filters/PostgreSQL/output",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.1 (Debian 16.1-1.pgdg120+1)\n-- Dumped by pg_dump version 16.1 (Debian 16.1-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: list_types; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.list_types (\n    integer_type integer,\n    numeric_type numeric,\n    double_precision_type double precision,\n    varchar_type character varying,\n    text_type text,\n    date_type date,\n    time_tz_type time with time zone,\n    boolean_type boolean,\n    xml_type xml,\n    jsonb_type jsonb,\n    id bigint NOT NULL\n);\n\n\nALTER TABLE public.list_types OWNER TO postgres;\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres\n--\n\nCREATE SEQUENCE public.list_types_id_seq\n    START WITH 1\n    INCREMENT BY 1\n    NO MINVALUE\n    NO MAXVALUE\n    CACHE 1;\n\n\nALTER SEQUENCE public.list_types_id_seq OWNER TO postgres;\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres\n--\n\nALTER SEQUENCE public.list_types_id_seq OWNED BY public.list_types.id;\n\n\n--\n-- Name: list_types id; Type: DEFAULT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.list_types ALTER COLUMN id SET DEFAULT nextval('public.list_types_id_seq'::regclass);\n\n\n--\n-- Data for Name: list_types; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.list_types (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\n123\t1.23\t321\tanon_text\trandom text\t01-01-2000\t20:20:20\ttrue\trandom_xml\tnull\t6\n123\t1.23\t321\tanon_text\trandom text\t01-01-2000\t20:20:20\ttrue\trandom_xml\tnull\t2\n123\t1.23\t321\tanon_text\trandom text\t01-01-2000\t20:20:20\ttrue\trandom_xml\tnull\t4\n123\t1.23\t321\tanon_text\trandom text\t01-01-2000\t20:20:20\ttrue\trandom_xml\tnull\t8\n123\t1.23\t321\tanon_text\trandom text\t01-01-2000\t20:20:20\ttrue\trandom_xml\tnull\t10\n123\t1.23\t321\tanon_text\trandom text\t01-01-2000\t20:20:20\ttrue\trandom_xml\tnull\t1\n123\t1.23\t321\tanon_text\trandom text\t01-01-2000\t20:20:20\ttrue\trandom_xml\tnull\t3\n123\t1.23\t321\tanon_text\trandom text\t01-01-2000\t20:20:20\ttrue\trandom_xml\tnull\t9\n123\t1.23\t321\tanon_text\trandom text\t01-01-2000\t20:20:20\ttrue\trandom_xml\tnull\t5\n123\t1.23\t321\tanon_text\trandom text\t01-01-2000\t20:20:20\ttrue\trandom_xml\tnull\t7\n\\.\n\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres\n--\n\nSELECT pg_catalog.setval('public.list_types_id_seq', 10, true);\n\n\n--\n-- Name: list_types list_types_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.list_types\n    ADD CONSTRAINT list_types_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "doc/examples/filters/Readme.md",
    "content": "# Example `filters`\n\nAn example of using nxs-data-anonymizer in a simple configuration with one filters block.\n\nAll that needs to be specified in the configuration file is a list of tables to be processed with a list of replacement rules for the columns that need to be changed.\n\nAn example of a configuration:\n```yaml\nfilters:\n  table1: # Table name to process.\n   columns:\n      table1_col1: # Column name to process.\n        value: \"{{ - value_generation_function - }}\" # Value for substitution.\n        unique: true # The unique values ​​flag, default \"false\", is used only with the value generation function.\n      table1_col2:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n      table1_col3:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n  table2:\n    columns:\n      table2_col1:\n        value: \"{{ - value_generation_function - }}\"\n        unique: true\n      table2_col2:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n      table2_col3:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n```\n\nWorking examples of configurations in the `./MySQL` and `./PostgreSQL` directories."
  },
  {
    "path": "doc/examples/links/MySQL/input.sql",
    "content": "-- MySQL dump 10.13  Distrib 8.4.0, for Linux (x86_64)\n--\n-- Host: localhost    Database: name_db\n-- ------------------------------------------------------\n-- Server version\t8.4.0\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!50503 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `authors`\n--\n\nDROP TABLE IF EXISTS `authors`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `authors` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `first_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `last_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `email` varchar(100) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `birthdate` date NOT NULL,\n  `added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `email` (`email`)\n) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `authors`\n--\n\nLOCK TABLES `authors` WRITE;\n/*!40000 ALTER TABLE `authors` DISABLE KEYS */;\nINSERT INTO `authors` VALUES (1,'Wilford','Wintheiser','brett35@example.com','1981-10-14','1988-09-10 18:37:25'),(2,'Nyasia','Doyle','aracely46@example.com','2007-07-01','1980-10-28 23:57:00'),(3,'Ken','Haag','carroll.harris@example.com','2003-04-16','1997-03-14 18:41:06'),(4,'Leonor','Mann','johns.janick@example.org','1996-05-18','2010-04-12 00:38:42'),(5,'Eloisa','Ratke','lakin.ramiro@example.net','1982-07-22','1996-03-25 09:07:39'),(6,'Nikolas','Dibbert','judson33@example.com','1970-02-22','1979-03-16 10:10:12'),(7,'Kelley','Koch','kaci.koch@example.net','2013-05-01','2020-08-02 02:01:34'),(8,'Glen','Howe','jprosacco@example.net','1971-08-03','1971-01-02 14:19:52'),(9,'Geovanni','Medhurst','kutch.kylie@example.com','2011-04-20','2004-06-10 12:33:11'),(10,'Zella','Davis','hane.terrill@example.org','1991-11-07','2007-09-19 13:48:20');\n/*!40000 ALTER TABLE `authors` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `posts`\n--\n\nDROP TABLE IF EXISTS `posts`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `posts` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `author_id` int NOT NULL,\n  `title` varchar(255) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `description` varchar(500) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `content` text COLLATE utf8mb3_unicode_ci NOT NULL,\n  `date` date NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `posts`\n--\n\nLOCK TABLES `posts` WRITE;\n/*!40000 ALTER TABLE `posts` DISABLE KEYS */;\nINSERT INTO `posts` VALUES (1,1,'Pariatur est in ut provident vero eligendi.','Consequatur quae odio in animi. Quis dolorem aut corporis sed ratione animi et. Iure sunt qui eligendi laudantium harum maxime id id. Quia eos beatae temporibus eos rerum ipsum.','Velit voluptatibus quo est dolorem quos sed et. Illum similique atque et qui. Perspiciatis magnam saepe quis. Consequatur aut dolorem ea.','1975-07-07'),(2,2,'Unde est architecto est.','Consectetur quidem aut eligendi quas. Voluptas aut voluptas ratione reiciendis magnam sint. Ratione et omnis assumenda deserunt voluptatem perspiciatis. Non voluptates quia distinctio nam consectetur vel.','Sed sint at consectetur. Fugiat fugiat omnis debitis dolore. Incidunt vero incidunt enim reiciendis. Odio et illo facilis quo sit quia consequatur voluptatem.','1976-05-25'),(3,3,'Dignissimos perspiciatis nobis quisquam saepe ad aut numquam.','Voluptatibus eum voluptas eveniet veniam ducimus. Modi id vitae est accusamus. Quaerat perferendis voluptas minima dignissimos et. Sapiente explicabo voluptas commodi voluptatem autem totam. Adipisci quos quos quo ea aliquid rerum.','Repellat minus enim occaecati sunt quas. Ab ipsa voluptatibus sunt eos omnis quisquam at voluptatibus. Quo vitae doloremque nesciunt doloremque. Temporibus rerum sunt iste dolores rerum.','1991-12-21'),(4,4,'Voluptas sint modi magnam.','Facere harum pariatur quo eveniet dolor molestias. Quo debitis corporis quasi minima et optio. Ut maiores nihil rerum autem culpa et voluptates. Amet totam rem optio in. Provident ea repudiandae quisquam unde occaecati autem.','Sed quia assumenda quis rerum praesentium harum. Quia minima quo natus. Impedit temporibus perspiciatis et enim doloremque nihil et. Perspiciatis nam occaecati illo dicta asperiores eos nam.','2002-01-23'),(5,5,'Sapiente rem eos enim ullam ipsum ut.','Officia quos voluptas autem consequuntur. Quis consequatur aut vel dolor. Sapiente voluptatem quibusdam dolor nobis earum laboriosam quisquam.','Quibusdam vel tempora explicabo qui. Sunt animi a unde veritatis perferendis similique nostrum vel. Porro ab ad cumque dolorum provident distinctio est ipsum. Esse maxime ea quia.','2017-11-19'),(6,6,'Error quas doloremque est sunt quae.','Corporis quis in sint. Eos vitae aut provident distinctio ullam. Corporis mollitia quam natus qui sapiente officiis.','Ipsam animi aperiam ipsa fuga. Sunt blanditiis possimus aut quod. Doloremque possimus occaecati numquam omnis dolor. Qui nihil qui atque vitae sapiente illo id.','1974-03-23'),(7,7,'Quo impedit quos molestiae dolorum in soluta dolores non.','Harum quasi dolorum et harum iste eveniet et. Cumque ab recusandae architecto est ipsam est. Eligendi et earum ea alias odio sed ut.','Illo earum porro corporis sunt aut. Vel quisquam ut voluptas reiciendis maiores cumque. Qui hic maiores voluptas sapiente reprehenderit. Eos non autem quis maiores perferendis.','2004-12-08'),(8,8,'Nulla quia repellendus et autem vitae provident.','Facere deserunt suscipit quia et et totam vel at. Cumque suscipit est ea quis in quos. Harum dolorum consequuntur illum voluptatem iste enim recusandae.','Excepturi hic tenetur sint nostrum. Nihil itaque repudiandae qui hic minima quis ut. Dolor et aut quaerat exercitationem minima ut. Blanditiis minus et qui dolor ut atque.','1999-02-28'),(9,9,'Similique at quia quia ut recusandae repudiandae delectus.','Et necessitatibus aut accusantium quisquam harum est. Non quam id impedit deleniti. Eaque non architecto facere dolorem nesciunt perferendis. Delectus nihil ut dignissimos. Voluptate rerum reprehenderit aut voluptatem quibusdam quidem.','Tempore iusto minus omnis tempore. Hic aut sequi temporibus consequatur. In vel enim eos nihil sed eos debitis.','2007-08-07'),(10,10,'Est vel aperiam ipsa quod doloremque et est et.','Facere ut et similique voluptates voluptas blanditiis explicabo. Eaque molestiae nihil sed et repellat voluptatem eum autem.','Rem laudantium in aut assumenda. Aspernatur id illo pariatur aut deleniti rem et. Nisi velit neque qui quia.','2009-07-18'),(11,1,'Sint est qui dolorem eum accusantium repudiandae.','Quia tenetur culpa maiores molestias. Id numquam illum earum quos sint ad dolore corrupti. Consequatur quasi itaque est odit qui quod culpa.','Omnis tenetur occaecati accusamus quis corrupti et ipsam. Ullam nobis tempore officia nesciunt iste. Nesciunt vel in eos. Dolor voluptates quod sed quibusdam ut. Fuga quia eum quidem cum.','2010-04-16'),(12,2,'Culpa debitis ut non sapiente voluptatem.','Commodi fugit ullam quaerat quam quo minus. Harum quam ipsam ducimus sit expedita sit. Eos natus quo quibusdam quam repudiandae. Assumenda et sint sit quia qui necessitatibus.','Eum molestiae cupiditate ut minus. Eaque eos eos ipsam voluptatem. Sint aut aliquid modi id dolores consequatur. Aut nemo blanditiis nisi ea nam velit.','1988-12-26'),(13,3,'Ut ut rerum qui quis sed sunt.','Tenetur enim et nisi ex et consequatur omnis nisi. Eos deleniti aut amet illo sed quibusdam. Consequuntur sint quia quia aut magni.','Aut eveniet natus ut. Nostrum aliquid qui nam hic iusto id occaecati qui. Est dolor accusamus qui saepe voluptatem dolorem omnis.','2001-06-01'),(14,4,'Error inventore delectus sapiente non.','Aliquam ut aliquid et laboriosam distinctio ab. Tempore molestiae aut ea nesciunt culpa. Eum maiores molestiae voluptatem animi aliquam. Aspernatur aut soluta totam occaecati in nam ratione asperiores.','Voluptatum id amet qui quia. Nemo nulla atque dignissimos.','1974-12-07'),(15,5,'Ut aut quo aut ea occaecati est voluptas.','Non deleniti molestias velit ut eos veritatis. Et id eaque numquam ipsa iure ut. Molestiae et minus natus.','Necessitatibus asperiores adipisci eaque. Alias sunt illum fugit ab labore laborum est odio. Aspernatur esse qui ut omnis autem. Laudantium quos corporis numquam sapiente enim.','1999-09-12'),(16,6,'Nihil ea qui sequi odit rem.','Omnis ea accusantium qui commodi et ducimus. Magni deserunt sed quo velit. Hic cum tenetur facilis. Non eum quis molestias sunt. Illo saepe architecto doloremque illum sequi.','Nihil iste illum vitae ipsa et et. Reiciendis sint illum quo dignissimos veritatis. Velit eum architecto enim ratione aut.','2003-07-28'),(17,7,'Quia accusantium deserunt suscipit.','Repellat et molestiae magnam quaerat et iure. Enim enim cum quisquam quasi.','Maiores officiis beatae hic hic dolor non officiis. Nulla beatae at aut fugit doloribus et provident. Debitis non dolores iusto impedit. Alias blanditiis velit voluptate et debitis.','2015-05-24'),(18,8,'Inventore et eaque temporibus qui aut exercitationem necessitatibus.','Omnis molestias nemo culpa est dicta dolorem porro. Illum est ut ut molestias similique sit sunt. Consequatur asperiores quaerat voluptate incidunt.','Unde quibusdam asperiores voluptates quaerat et aliquam. Libero at est quibusdam eos aut. Aut voluptatem tempora a nam.','1996-02-06'),(19,9,'Et soluta consequatur porro rem corrupti.','Ullam doloremque explicabo ea ab quam ipsum. Et qui iure vero tempore voluptate aut. Ullam id ab accusamus optio voluptas. Quia quaerat quibusdam aut accusantium impedit et.','Perspiciatis sed dolores aut. Animi sed totam exercitationem fugiat dolores. Ipsa dolorem quia non aliquam. Rerum exercitationem voluptatem dolor beatae veritatis quasi omnis consectetur.','2018-03-31'),(20,10,'Culpa error rerum voluptatem recusandae quae tempora.','Est ullam tempore autem et. Dolorum est eius eaque veniam in quibusdam neque. Ut aspernatur earum sint delectus voluptate deserunt sapiente quia.','Enim quos facere rerum ipsa. Eveniet expedita id eligendi voluptatem magnam quo eos.','2007-01-22'),(21,1,'Harum laudantium fugiat debitis atque sed.','Et asperiores magni qui voluptas a consequatur totam. Inventore enim quaerat consequatur sint quam voluptatibus optio. Est aut repellendus repudiandae reiciendis eveniet veniam. Minima a corrupti non quae.','Voluptate officia ut debitis explicabo corrupti facere reprehenderit. Enim id recusandae vitae est dolores. Aperiam consequuntur ex beatae et alias quia.','1987-06-29'),(22,2,'Non architecto ut voluptas aut voluptas dolor ut.','Dolore delectus optio fuga aut labore necessitatibus. Laborum quis nulla deserunt. Aut corporis repellendus inventore vel.','Facilis soluta ab culpa est. Aut pariatur et dicta sit. Sed qui est numquam est.\\nAtque ex sit eveniet. Iure accusamus optio placeat voluptate non sit ea. Sint dignissimos dolorum debitis ipsam neque.','1993-05-06'),(23,3,'Dolores sed hic vitae ut qui.','Libero illum dolorum est eaque ut. Nesciunt qui vitae recusandae eveniet saepe et ut. Aliquid enim vitae beatae animi quam doloribus accusamus. Eos eos excepturi accusamus ut recusandae.','Distinctio molestiae sint qui. Expedita qui ex dignissimos architecto quo sapiente alias eveniet. Laborum qui aut est doloribus a beatae. Unde adipisci consequuntur et tenetur.','1978-09-08'),(24,4,'Deleniti distinctio eos eveniet.','Ex aperiam animi quis excepturi. Velit qui molestias iste iure voluptatem. Eveniet adipisci quasi amet. Soluta laborum aperiam magni.','Deserunt dolores ut ut ex cum. Quae iusto rerum voluptatum aperiam. Vel voluptatem ut nesciunt delectus blanditiis. Sequi consequuntur temporibus sunt dolores repudiandae.','2003-06-23'),(25,5,'Ea et asperiores odio vel sunt exercitationem.','Quod necessitatibus quis sit aspernatur a. Molestias laudantium voluptatibus quaerat rerum cupiditate. Aut consectetur quia doloribus repellat porro est.','Et alias soluta aliquam qui aut. Explicabo quo consequuntur consequuntur velit distinctio.','1972-09-16'),(26,6,'Accusamus est sed aut minus.','Et libero in in est consequuntur. Illum distinctio doloremque quas.','Neque vel tenetur libero sed aut voluptas. Itaque quod et laudantium magnam tempora qui non. Et sapiente dolores reiciendis sit ab fugiat sed sequi. Reiciendis maxime qui aut laborum dolor.','2017-03-08'),(27,7,'Et sed reprehenderit nobis sed.','Totam amet nisi id quod. Laudantium maxime rem velit consequuntur amet. Et enim eum aspernatur totam. Nulla consequatur similique maxime et qui rerum.','Iure sequi unde consectetur neque in magni. Illo ipsa commodi quae placeat modi numquam numquam. Quae culpa sit distinctio vitae est.','1973-08-04'),(28,8,'Autem ullam aperiam totam assumenda quod esse.','Aut incidunt aspernatur aut sapiente ipsum repellat. Molestiae eaque accusantium maxime. Velit modi ea consectetur natus ea.','Molestias voluptatum cupiditate et minus qui consequuntur. Reprehenderit aut at corrupti. Eius unde ullam aut cum eius molestiae.','2014-04-26'),(29,9,'Ad dolores amet ea nisi aut enim voluptatem.','Eum voluptates sunt occaecati molestiae. Cupiditate labore expedita eius in omnis non. Sit cumque unde cupiditate sequi eius reprehenderit nulla.','Voluptates modi esse quas sit eos praesentium. Quas et rem vero quo veritatis voluptas. Inventore dolorem ut praesentium consequatur rem. Amet ipsam quia officia iste est in.','2006-09-07'),(30,10,'Eos fuga at ex sapiente quasi.','Facere dolores non omnis facilis. Nam cupiditate maiores iure quia adipisci numquam magnam. Esse voluptas voluptatem cum ea voluptas doloremque.','Voluptatem qui qui magnam quis eos. Consequatur ut repudiandae libero dignissimos et quia velit. Eum nisi facere consequatur quod ut. Ad molestiae voluptatem eaque iste et.','2009-07-23');\n/*!40000 ALTER TABLE `posts` ENABLE KEYS */;\nUNLOCK TABLES;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2024-07-19 10:47:53\n"
  },
  {
    "path": "doc/examples/links/MySQL/nxs-data-anonymizer.conf",
    "content": "link:\n- rule:\n    value: \"{{ randInt 1 50\t}}\"\n    unique: true\n  with:\n    authors:\n    - id\n    posts:\n    - author_id\n\nfilters:\n  authors:\n    columns:\n      first_name:\n        value: \"{{- randAlphaNum 20 -}}\"\n      last_name:\n        value: \"{{- randAlphaNum 20 -}}\"\n      birthdate:\n        value: \"1999-12-31\" \n      added:\n        value: \"2000-01-01 12:00:00\"\n  posts:\n    columns:\n      id:\n        value: \"{{ randInt 1 100 }}\"\n        unique: true"
  },
  {
    "path": "doc/examples/links/MySQL/output.sql",
    "content": "-- MySQL dump 10.13  Distrib 8.4.0, for Linux (x86_64)\n--\n-- Host: localhost    Database: name_db\n-- ------------------------------------------------------\n-- Server version\t8.4.0\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!50503 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `authors`\n--\n\nDROP TABLE IF EXISTS `authors`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `authors` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `first_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `last_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `email` varchar(100) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `birthdate` date NOT NULL,\n  `added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `email` (`email`)\n) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `authors`\n--\n\nLOCK TABLES `authors` WRITE;\n/*!40000 ALTER TABLE `authors` DISABLE KEYS */;\nINSERT INTO `authors` VALUES (26,'lwjNB8ofmQjcmzIKx23U','pBfm9pHABWxqgVMNk1pY','brett35@example.com','1999-12-31','2000-01-01 12:00:00'),(48,'xtc5AqJUOuAGGBir1Gvn','zdi0Y2ntYLIdTMGBhsRd','aracely46@example.com','1999-12-31','2000-01-01 12:00:00'),(9,'719GkwVKuXEKjAAohgrk','jU68LcKRCwZ3yFAOsQws','carroll.harris@example.com','1999-12-31','2000-01-01 12:00:00'),(15,'Bcync5tDYRvDOad9ulHY','70FuTHdJ2diuXKn5FLUl','johns.janick@example.org','1999-12-31','2000-01-01 12:00:00'),(49,'JsRPcdhoD7eUSG2yqaln','LR33Yhxv4bs2LdcvhTvg','lakin.ramiro@example.net','1999-12-31','2000-01-01 12:00:00'),(10,'jckw1fZr214qyZk2N5qd','Dx1dlwV6M9bownRFj8jv','judson33@example.com','1999-12-31','2000-01-01 12:00:00'),(46,'LynAXGoDTGMsFWxjggUr','mW9QmnaWOWeG0uTR3y4v','kaci.koch@example.net','1999-12-31','2000-01-01 12:00:00'),(8,'ZhCmwfvwrOmSTKN9vXrw','MuUlp8h02AyIQapcTNid','jprosacco@example.net','1999-12-31','2000-01-01 12:00:00'),(18,'04b4LKxXcOioU5JkO6Iy','SBoyCTw1RCtx0rMp6qJ7','kutch.kylie@example.com','1999-12-31','2000-01-01 12:00:00'),(42,'21L1p5ixBhOvI3P3iF5F','xsRxqdLYqLIGpdpNYrNA','hane.terrill@example.org','1999-12-31','2000-01-01 12:00:00');\n/*!40000 ALTER TABLE `authors` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `posts`\n--\n\nDROP TABLE IF EXISTS `posts`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `posts` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `author_id` int NOT NULL,\n  `title` varchar(255) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `description` varchar(500) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `content` text COLLATE utf8mb3_unicode_ci NOT NULL,\n  `date` date NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `posts`\n--\n\nLOCK TABLES `posts` WRITE;\n/*!40000 ALTER TABLE `posts` DISABLE KEYS */;\nINSERT INTO `posts` VALUES (89,26,'Pariatur est in ut provident vero eligendi.','Consequatur quae odio in animi. Quis dolorem aut corporis sed ratione animi et. Iure sunt qui eligendi laudantium harum maxime id id. Quia eos beatae temporibus eos rerum ipsum.','Velit voluptatibus quo est dolorem quos sed et. Illum similique atque et qui. Perspiciatis magnam saepe quis. Consequatur aut dolorem ea.','1975-07-07'),(5,48,'Unde est architecto est.','Consectetur quidem aut eligendi quas. Voluptas aut voluptas ratione reiciendis magnam sint. Ratione et omnis assumenda deserunt voluptatem perspiciatis. Non voluptates quia distinctio nam consectetur vel.','Sed sint at consectetur. Fugiat fugiat omnis debitis dolore. Incidunt vero incidunt enim reiciendis. Odio et illo facilis quo sit quia consequatur voluptatem.','1976-05-25'),(56,9,'Dignissimos perspiciatis nobis quisquam saepe ad aut numquam.','Voluptatibus eum voluptas eveniet veniam ducimus. Modi id vitae est accusamus. Quaerat perferendis voluptas minima dignissimos et. Sapiente explicabo voluptas commodi voluptatem autem totam. Adipisci quos quos quo ea aliquid rerum.','Repellat minus enim occaecati sunt quas. Ab ipsa voluptatibus sunt eos omnis quisquam at voluptatibus. Quo vitae doloremque nesciunt doloremque. Temporibus rerum sunt iste dolores rerum.','1991-12-21'),(46,15,'Voluptas sint modi magnam.','Facere harum pariatur quo eveniet dolor molestias. Quo debitis corporis quasi minima et optio. Ut maiores nihil rerum autem culpa et voluptates. Amet totam rem optio in. Provident ea repudiandae quisquam unde occaecati autem.','Sed quia assumenda quis rerum praesentium harum. Quia minima quo natus. Impedit temporibus perspiciatis et enim doloremque nihil et. Perspiciatis nam occaecati illo dicta asperiores eos nam.','2002-01-23'),(76,49,'Sapiente rem eos enim ullam ipsum ut.','Officia quos voluptas autem consequuntur. Quis consequatur aut vel dolor. Sapiente voluptatem quibusdam dolor nobis earum laboriosam quisquam.','Quibusdam vel tempora explicabo qui. Sunt animi a unde veritatis perferendis similique nostrum vel. Porro ab ad cumque dolorum provident distinctio est ipsum. Esse maxime ea quia.','2017-11-19'),(99,10,'Error quas doloremque est sunt quae.','Corporis quis in sint. Eos vitae aut provident distinctio ullam. Corporis mollitia quam natus qui sapiente officiis.','Ipsam animi aperiam ipsa fuga. Sunt blanditiis possimus aut quod. Doloremque possimus occaecati numquam omnis dolor. Qui nihil qui atque vitae sapiente illo id.','1974-03-23'),(13,46,'Quo impedit quos molestiae dolorum in soluta dolores non.','Harum quasi dolorum et harum iste eveniet et. Cumque ab recusandae architecto est ipsam est. Eligendi et earum ea alias odio sed ut.','Illo earum porro corporis sunt aut. Vel quisquam ut voluptas reiciendis maiores cumque. Qui hic maiores voluptas sapiente reprehenderit. Eos non autem quis maiores perferendis.','2004-12-08'),(42,8,'Nulla quia repellendus et autem vitae provident.','Facere deserunt suscipit quia et et totam vel at. Cumque suscipit est ea quis in quos. Harum dolorum consequuntur illum voluptatem iste enim recusandae.','Excepturi hic tenetur sint nostrum. Nihil itaque repudiandae qui hic minima quis ut. Dolor et aut quaerat exercitationem minima ut. Blanditiis minus et qui dolor ut atque.','1999-02-28'),(61,18,'Similique at quia quia ut recusandae repudiandae delectus.','Et necessitatibus aut accusantium quisquam harum est. Non quam id impedit deleniti. Eaque non architecto facere dolorem nesciunt perferendis. Delectus nihil ut dignissimos. Voluptate rerum reprehenderit aut voluptatem quibusdam quidem.','Tempore iusto minus omnis tempore. Hic aut sequi temporibus consequatur. In vel enim eos nihil sed eos debitis.','2007-08-07'),(11,42,'Est vel aperiam ipsa quod doloremque et est et.','Facere ut et similique voluptates voluptas blanditiis explicabo. Eaque molestiae nihil sed et repellat voluptatem eum autem.','Rem laudantium in aut assumenda. Aspernatur id illo pariatur aut deleniti rem et. Nisi velit neque qui quia.','2009-07-18'),(87,26,'Sint est qui dolorem eum accusantium repudiandae.','Quia tenetur culpa maiores molestias. Id numquam illum earum quos sint ad dolore corrupti. Consequatur quasi itaque est odit qui quod culpa.','Omnis tenetur occaecati accusamus quis corrupti et ipsam. Ullam nobis tempore officia nesciunt iste. Nesciunt vel in eos. Dolor voluptates quod sed quibusdam ut. Fuga quia eum quidem cum.','2010-04-16'),(4,48,'Culpa debitis ut non sapiente voluptatem.','Commodi fugit ullam quaerat quam quo minus. Harum quam ipsam ducimus sit expedita sit. Eos natus quo quibusdam quam repudiandae. Assumenda et sint sit quia qui necessitatibus.','Eum molestiae cupiditate ut minus. Eaque eos eos ipsam voluptatem. Sint aut aliquid modi id dolores consequatur. Aut nemo blanditiis nisi ea nam velit.','1988-12-26'),(95,9,'Ut ut rerum qui quis sed sunt.','Tenetur enim et nisi ex et consequatur omnis nisi. Eos deleniti aut amet illo sed quibusdam. Consequuntur sint quia quia aut magni.','Aut eveniet natus ut. Nostrum aliquid qui nam hic iusto id occaecati qui. Est dolor accusamus qui saepe voluptatem dolorem omnis.','2001-06-01'),(52,15,'Error inventore delectus sapiente non.','Aliquam ut aliquid et laboriosam distinctio ab. Tempore molestiae aut ea nesciunt culpa. Eum maiores molestiae voluptatem animi aliquam. Aspernatur aut soluta totam occaecati in nam ratione asperiores.','Voluptatum id amet qui quia. Nemo nulla atque dignissimos.','1974-12-07'),(49,49,'Ut aut quo aut ea occaecati est voluptas.','Non deleniti molestias velit ut eos veritatis. Et id eaque numquam ipsa iure ut. Molestiae et minus natus.','Necessitatibus asperiores adipisci eaque. Alias sunt illum fugit ab labore laborum est odio. Aspernatur esse qui ut omnis autem. Laudantium quos corporis numquam sapiente enim.','1999-09-12'),(82,10,'Nihil ea qui sequi odit rem.','Omnis ea accusantium qui commodi et ducimus. Magni deserunt sed quo velit. Hic cum tenetur facilis. Non eum quis molestias sunt. Illo saepe architecto doloremque illum sequi.','Nihil iste illum vitae ipsa et et. Reiciendis sint illum quo dignissimos veritatis. Velit eum architecto enim ratione aut.','2003-07-28'),(40,46,'Quia accusantium deserunt suscipit.','Repellat et molestiae magnam quaerat et iure. Enim enim cum quisquam quasi.','Maiores officiis beatae hic hic dolor non officiis. Nulla beatae at aut fugit doloribus et provident. Debitis non dolores iusto impedit. Alias blanditiis velit voluptate et debitis.','2015-05-24'),(28,8,'Inventore et eaque temporibus qui aut exercitationem necessitatibus.','Omnis molestias nemo culpa est dicta dolorem porro. Illum est ut ut molestias similique sit sunt. Consequatur asperiores quaerat voluptate incidunt.','Unde quibusdam asperiores voluptates quaerat et aliquam. Libero at est quibusdam eos aut. Aut voluptatem tempora a nam.','1996-02-06'),(90,18,'Et soluta consequatur porro rem corrupti.','Ullam doloremque explicabo ea ab quam ipsum. Et qui iure vero tempore voluptate aut. Ullam id ab accusamus optio voluptas. Quia quaerat quibusdam aut accusantium impedit et.','Perspiciatis sed dolores aut. Animi sed totam exercitationem fugiat dolores. Ipsa dolorem quia non aliquam. Rerum exercitationem voluptatem dolor beatae veritatis quasi omnis consectetur.','2018-03-31'),(36,42,'Culpa error rerum voluptatem recusandae quae tempora.','Est ullam tempore autem et. Dolorum est eius eaque veniam in quibusdam neque. Ut aspernatur earum sint delectus voluptate deserunt sapiente quia.','Enim quos facere rerum ipsa. Eveniet expedita id eligendi voluptatem magnam quo eos.','2007-01-22'),(9,26,'Harum laudantium fugiat debitis atque sed.','Et asperiores magni qui voluptas a consequatur totam. Inventore enim quaerat consequatur sint quam voluptatibus optio. Est aut repellendus repudiandae reiciendis eveniet veniam. Minima a corrupti non quae.','Voluptate officia ut debitis explicabo corrupti facere reprehenderit. Enim id recusandae vitae est dolores. Aperiam consequuntur ex beatae et alias quia.','1987-06-29'),(77,48,'Non architecto ut voluptas aut voluptas dolor ut.','Dolore delectus optio fuga aut labore necessitatibus. Laborum quis nulla deserunt. Aut corporis repellendus inventore vel.','Facilis soluta ab culpa est. Aut pariatur et dicta sit. Sed qui est numquam est.\\nAtque ex sit eveniet. Iure accusamus optio placeat voluptate non sit ea. Sint dignissimos dolorum debitis ipsam neque.','1993-05-06'),(18,9,'Dolores sed hic vitae ut qui.','Libero illum dolorum est eaque ut. Nesciunt qui vitae recusandae eveniet saepe et ut. Aliquid enim vitae beatae animi quam doloribus accusamus. Eos eos excepturi accusamus ut recusandae.','Distinctio molestiae sint qui. Expedita qui ex dignissimos architecto quo sapiente alias eveniet. Laborum qui aut est doloribus a beatae. Unde adipisci consequuntur et tenetur.','1978-09-08'),(29,15,'Deleniti distinctio eos eveniet.','Ex aperiam animi quis excepturi. Velit qui molestias iste iure voluptatem. Eveniet adipisci quasi amet. Soluta laborum aperiam magni.','Deserunt dolores ut ut ex cum. Quae iusto rerum voluptatum aperiam. Vel voluptatem ut nesciunt delectus blanditiis. Sequi consequuntur temporibus sunt dolores repudiandae.','2003-06-23'),(80,49,'Ea et asperiores odio vel sunt exercitationem.','Quod necessitatibus quis sit aspernatur a. Molestias laudantium voluptatibus quaerat rerum cupiditate. Aut consectetur quia doloribus repellat porro est.','Et alias soluta aliquam qui aut. Explicabo quo consequuntur consequuntur velit distinctio.','1972-09-16'),(69,10,'Accusamus est sed aut minus.','Et libero in in est consequuntur. Illum distinctio doloremque quas.','Neque vel tenetur libero sed aut voluptas. Itaque quod et laudantium magnam tempora qui non. Et sapiente dolores reiciendis sit ab fugiat sed sequi. Reiciendis maxime qui aut laborum dolor.','2017-03-08'),(98,46,'Et sed reprehenderit nobis sed.','Totam amet nisi id quod. Laudantium maxime rem velit consequuntur amet. Et enim eum aspernatur totam. Nulla consequatur similique maxime et qui rerum.','Iure sequi unde consectetur neque in magni. Illo ipsa commodi quae placeat modi numquam numquam. Quae culpa sit distinctio vitae est.','1973-08-04'),(27,8,'Autem ullam aperiam totam assumenda quod esse.','Aut incidunt aspernatur aut sapiente ipsum repellat. Molestiae eaque accusantium maxime. Velit modi ea consectetur natus ea.','Molestias voluptatum cupiditate et minus qui consequuntur. Reprehenderit aut at corrupti. Eius unde ullam aut cum eius molestiae.','2014-04-26'),(64,18,'Ad dolores amet ea nisi aut enim voluptatem.','Eum voluptates sunt occaecati molestiae. Cupiditate labore expedita eius in omnis non. Sit cumque unde cupiditate sequi eius reprehenderit nulla.','Voluptates modi esse quas sit eos praesentium. Quas et rem vero quo veritatis voluptas. Inventore dolorem ut praesentium consequatur rem. Amet ipsam quia officia iste est in.','2006-09-07'),(32,42,'Eos fuga at ex sapiente quasi.','Facere dolores non omnis facilis. Nam cupiditate maiores iure quia adipisci numquam magnam. Esse voluptas voluptatem cum ea voluptas doloremque.','Voluptatem qui qui magnam quis eos. Consequatur ut repudiandae libero dignissimos et quia velit. Eum nisi facere consequatur quod ut. Ad molestiae voluptatem eaque iste et.','2009-07-23');\n/*!40000 ALTER TABLE `posts` ENABLE KEYS */;\nUNLOCK TABLES;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2024-07-19 10:47:53\n"
  },
  {
    "path": "doc/examples/links/PostgreSQL/input",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: authors; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.authors (\n    id integer NOT NULL,\n    first_name character varying(50) NOT NULL,\n    last_name character varying(50) NOT NULL,\n    email character varying(100) NOT NULL,\n    birthdate date NOT NULL,\n    added timestamp without time zone NOT NULL\n);\n\n\nALTER TABLE public.authors OWNER TO postgres;\n\n--\n-- Name: posts; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.posts (\n    id integer NOT NULL,\n    author_id integer NOT NULL,\n    title character varying(255) NOT NULL,\n    description character varying(500) NOT NULL,\n    content text NOT NULL,\n    date date NOT NULL\n);\n\n\nALTER TABLE public.posts OWNER TO postgres;\n\n--\n-- Data for Name: authors; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.authors (id, first_name, last_name, email, birthdate, added) FROM stdin;\n1\tWilford\tWintheiser\tbrett35@example.com\t1981-10-14\t1988-09-10 18:37:25\n2\tNyasia\tDoyle\taracely46@example.com\t2007-07-01\t1980-10-28 23:57:00\n3\tKen\tHaag\tcarroll.harris@example.com\t2003-04-16\t1997-03-14 18:41:06\n4\tLeonor\tMann\tjohns.janick@example.org\t1996-05-18\t2010-04-12 00:38:42\n5\tEloisa\tRatke\tlakin.ramiro@example.net\t1982-07-22\t1996-03-25 09:07:39\n6\tNikolas\tDibbert\tjudson33@example.com\t1970-02-22\t1979-03-16 10:10:12\n7\tKelley\tKoch\tkaci.koch@example.net\t2013-05-01\t2020-08-02 02:01:34\n8\tGlen\tHowe\tjprosacco@example.net\t1971-08-03\t1971-01-02 14:19:52\n9\tGeovanni\tMedhurst\tkutch.kylie@example.com\t2011-04-20\t2004-06-10 12:33:11\n10\tZella\tDavis\thane.terrill@example.org\t1991-11-07\t2007-09-19 13:48:20\n\\.\n\n\n--\n-- Data for Name: posts; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.posts (id, author_id, title, description, content, date) FROM stdin;\n1\t1\tPariatur est in ut provident vero eligendi.\tConsequatur quae odio in animi. Quis dolorem aut corporis sed ratione animi et. Iure sunt qui eligendi laudantium harum maxime id id. Quia eos beatae temporibus eos rerum ipsum.\tVelit voluptatibus quo est dolorem quos sed et. Illum similique atque et qui. Perspiciatis magnam saepe quis. Consequatur aut dolorem ea.\t1975-07-07\n2\t2\tUnde est architecto est.\tConsectetur quidem aut eligendi quas. Voluptas aut voluptas ratione reiciendis magnam sint. Ratione et omnis assumenda deserunt voluptatem perspiciatis. Non voluptates quia distinctio nam consectetur vel.\tSed sint at consectetur. Fugiat fugiat omnis debitis dolore. Incidunt vero incidunt enim reiciendis. Odio et illo facilis quo sit quia consequatur voluptatem.\t1976-05-25\n3\t3\tDignissimos perspiciatis nobis quisquam saepe ad aut numquam.\tVoluptatibus eum voluptas eveniet veniam ducimus. Modi id vitae est accusamus. Quaerat perferendis voluptas minima dignissimos et. Sapiente explicabo voluptas commodi voluptatem autem totam. Adipisci quos quos quo ea aliquid rerum.\tRepellat minus enim occaecati sunt quas. Ab ipsa voluptatibus sunt eos omnis quisquam at voluptatibus. Quo vitae doloremque nesciunt doloremque. Temporibus rerum sunt iste dolores rerum.\t1991-12-21\n4\t4\tVoluptas sint modi magnam.\tFacere harum pariatur quo eveniet dolor molestias. Quo debitis corporis quasi minima et optio. Ut maiores nihil rerum autem culpa et voluptates. Amet totam rem optio in. Provident ea repudiandae quisquam unde occaecati autem.\tSed quia assumenda quis rerum praesentium harum. Quia minima quo natus. Impedit temporibus perspiciatis et enim doloremque nihil et. Perspiciatis nam occaecati illo dicta asperiores eos nam.\t2002-01-23\n5\t5\tSapiente rem eos enim ullam ipsum ut.\tOfficia quos voluptas autem consequuntur. Quis consequatur aut vel dolor. Sapiente voluptatem quibusdam dolor nobis earum laboriosam quisquam.\tQuibusdam vel tempora explicabo qui. Sunt animi a unde veritatis perferendis similique nostrum vel. Porro ab ad cumque dolorum provident distinctio est ipsum. Esse maxime ea quia.\t2017-11-19\n6\t6\tError quas doloremque est sunt quae.\tCorporis quis in sint. Eos vitae aut provident distinctio ullam. Corporis mollitia quam natus qui sapiente officiis.\tIpsam animi aperiam ipsa fuga. Sunt blanditiis possimus aut quod. Doloremque possimus occaecati numquam omnis dolor. Qui nihil qui atque vitae sapiente illo id.\t1974-03-23\n7\t7\tQuo impedit quos molestiae dolorum in soluta dolores non.\tHarum quasi dolorum et harum iste eveniet et. Cumque ab recusandae architecto est ipsam est. Eligendi et earum ea alias odio sed ut.\tIllo earum porro corporis sunt aut. Vel quisquam ut voluptas reiciendis maiores cumque. Qui hic maiores voluptas sapiente reprehenderit. Eos non autem quis maiores perferendis.\t2004-12-08\n8\t8\tNulla quia repellendus et autem vitae provident.\tFacere deserunt suscipit quia et et totam vel at. Cumque suscipit est ea quis in quos. Harum dolorum consequuntur illum voluptatem iste enim recusandae.\tExcepturi hic tenetur sint nostrum. Nihil itaque repudiandae qui hic minima quis ut. Dolor et aut quaerat exercitationem minima ut. Blanditiis minus et qui dolor ut atque.\t1999-02-28\n9\t9\tSimilique at quia quia ut recusandae repudiandae delectus.\tEt necessitatibus aut accusantium quisquam harum est. Non quam id impedit deleniti. Eaque non architecto facere dolorem nesciunt perferendis. Delectus nihil ut dignissimos. Voluptate rerum reprehenderit aut voluptatem quibusdam quidem.\tTempore iusto minus omnis tempore. Hic aut sequi temporibus consequatur. In vel enim eos nihil sed eos debitis.\t2007-08-07\n10\t10\tEst vel aperiam ipsa quod doloremque et est et.\tFacere ut et similique voluptates voluptas blanditiis explicabo. Eaque molestiae nihil sed et repellat voluptatem eum autem.\tRem laudantium in aut assumenda. Aspernatur id illo pariatur aut deleniti rem et. Nisi velit neque qui quia.\t2009-07-18\n11\t1\tSint est qui dolorem eum accusantium repudiandae.\tQuia tenetur culpa maiores molestias. Id numquam illum earum quos sint ad dolore corrupti. Consequatur quasi itaque est odit qui quod culpa.\tOmnis tenetur occaecati accusamus quis corrupti et ipsam. Ullam nobis tempore officia nesciunt iste. Nesciunt vel in eos. Dolor voluptates quod sed quibusdam ut. Fuga quia eum quidem cum.\t2010-04-16\n12\t2\tCulpa debitis ut non sapiente voluptatem.\tCommodi fugit ullam quaerat quam quo minus. Harum quam ipsam ducimus sit expedita sit. Eos natus quo quibusdam quam repudiandae. Assumenda et sint sit quia qui necessitatibus.\tEum molestiae cupiditate ut minus. Eaque eos eos ipsam voluptatem. Sint aut aliquid modi id dolores consequatur. Aut nemo blanditiis nisi ea nam velit.\t1988-12-26\n13\t3\tUt ut rerum qui quis sed sunt.\tTenetur enim et nisi ex et consequatur omnis nisi. Eos deleniti aut amet illo sed quibusdam. Consequuntur sint quia quia aut magni.\tAut eveniet natus ut. Nostrum aliquid qui nam hic iusto id occaecati qui. Est dolor accusamus qui saepe voluptatem dolorem omnis.\t2001-06-01\n14\t4\tError inventore delectus sapiente non.\tAliquam ut aliquid et laboriosam distinctio ab. Tempore molestiae aut ea nesciunt culpa. Eum maiores molestiae voluptatem animi aliquam. Aspernatur aut soluta totam occaecati in nam ratione asperiores.\tVoluptatum id amet qui quia. Nemo nulla atque dignissimos.\t1974-12-07\n15\t5\tUt aut quo aut ea occaecati est voluptas.\tNon deleniti molestias velit ut eos veritatis. Et id eaque numquam ipsa iure ut. Molestiae et minus natus.\tNecessitatibus asperiores adipisci eaque. Alias sunt illum fugit ab labore laborum est odio. Aspernatur esse qui ut omnis autem. Laudantium quos corporis numquam sapiente enim.\t1999-09-12\n16\t6\tNihil ea qui sequi odit rem.\tOmnis ea accusantium qui commodi et ducimus. Magni deserunt sed quo velit. Hic cum tenetur facilis. Non eum quis molestias sunt. Illo saepe architecto doloremque illum sequi.\tNihil iste illum vitae ipsa et et. Reiciendis sint illum quo dignissimos veritatis. Velit eum architecto enim ratione aut.\t2003-07-28\n17\t7\tQuia accusantium deserunt suscipit.\tRepellat et molestiae magnam quaerat et iure. Enim enim cum quisquam quasi.\tMaiores officiis beatae hic hic dolor non officiis. Nulla beatae at aut fugit doloribus et provident. Debitis non dolores iusto impedit. Alias blanditiis velit voluptate et debitis.\t2015-05-24\n18\t8\tInventore et eaque temporibus qui aut exercitationem necessitatibus.\tOmnis molestias nemo culpa est dicta dolorem porro. Illum est ut ut molestias similique sit sunt. Consequatur asperiores quaerat voluptate incidunt.\tUnde quibusdam asperiores voluptates quaerat et aliquam. Libero at est quibusdam eos aut. Aut voluptatem tempora a nam.\t1996-02-06\n19\t9\tEt soluta consequatur porro rem corrupti.\tUllam doloremque explicabo ea ab quam ipsum. Et qui iure vero tempore voluptate aut. Ullam id ab accusamus optio voluptas. Quia quaerat quibusdam aut accusantium impedit et.\tPerspiciatis sed dolores aut. Animi sed totam exercitationem fugiat dolores. Ipsa dolorem quia non aliquam. Rerum exercitationem voluptatem dolor beatae veritatis quasi omnis consectetur.\t2018-03-31\n20\t10\tCulpa error rerum voluptatem recusandae quae tempora.\tEst ullam tempore autem et. Dolorum est eius eaque veniam in quibusdam neque. Ut aspernatur earum sint delectus voluptate deserunt sapiente quia.\tEnim quos facere rerum ipsa. Eveniet expedita id eligendi voluptatem magnam quo eos.\t2007-01-22\n21\t1\tHarum laudantium fugiat debitis atque sed.\tEt asperiores magni qui voluptas a consequatur totam. Inventore enim quaerat consequatur sint quam voluptatibus optio. Est aut repellendus repudiandae reiciendis eveniet veniam. Minima a corrupti non quae.\tVoluptate officia ut debitis explicabo corrupti facere reprehenderit. Enim id recusandae vitae est dolores. Aperiam consequuntur ex beatae et alias quia.\t1987-06-29\n22\t2\tNon architecto ut voluptas aut voluptas dolor ut.\tDolore delectus optio fuga aut labore necessitatibus. Laborum quis nulla deserunt. Aut corporis repellendus inventore vel.\tFacilis soluta ab culpa est. Aut pariatur et dicta sit. Sed qui est numquam est.\\nAtque ex sit eveniet. Iure accusamus optio placeat voluptate non sit ea. Sint dignissimos dolorum debitis ipsam neque.\t1993-05-06\n23\t3\tDolores sed hic vitae ut qui.\tLibero illum dolorum est eaque ut. Nesciunt qui vitae recusandae eveniet saepe et ut. Aliquid enim vitae beatae animi quam doloribus accusamus. Eos eos excepturi accusamus ut recusandae.\tDistinctio molestiae sint qui. Expedita qui ex dignissimos architecto quo sapiente alias eveniet. Laborum qui aut est doloribus a beatae. Unde adipisci consequuntur et tenetur.\t1978-09-08\n24\t4\tDeleniti distinctio eos eveniet.\tEx aperiam animi quis excepturi. Velit qui molestias iste iure voluptatem. Eveniet adipisci quasi amet. Soluta laborum aperiam magni.\tDeserunt dolores ut ut ex cum. Quae iusto rerum voluptatum aperiam. Vel voluptatem ut nesciunt delectus blanditiis. Sequi consequuntur temporibus sunt dolores repudiandae.\t2003-06-23\n25\t5\tEa et asperiores odio vel sunt exercitationem.\tQuod necessitatibus quis sit aspernatur a. Molestias laudantium voluptatibus quaerat rerum cupiditate. Aut consectetur quia doloribus repellat porro est.\tEt alias soluta aliquam qui aut. Explicabo quo consequuntur consequuntur velit distinctio.\t1972-09-16\n26\t6\tAccusamus est sed aut minus.\tEt libero in in est consequuntur. Illum distinctio doloremque quas.\tNeque vel tenetur libero sed aut voluptas. Itaque quod et laudantium magnam tempora qui non. Et sapiente dolores reiciendis sit ab fugiat sed sequi. Reiciendis maxime qui aut laborum dolor.\t2017-03-08\n27\t7\tEt sed reprehenderit nobis sed.\tTotam amet nisi id quod. Laudantium maxime rem velit consequuntur amet. Et enim eum aspernatur totam. Nulla consequatur similique maxime et qui rerum.\tIure sequi unde consectetur neque in magni. Illo ipsa commodi quae placeat modi numquam numquam. Quae culpa sit distinctio vitae est.\t1973-08-04\n28\t8\tAutem ullam aperiam totam assumenda quod esse.\tAut incidunt aspernatur aut sapiente ipsum repellat. Molestiae eaque accusantium maxime. Velit modi ea consectetur natus ea.\tMolestias voluptatum cupiditate et minus qui consequuntur. Reprehenderit aut at corrupti. Eius unde ullam aut cum eius molestiae.\t2014-04-26\n29\t9\tAd dolores amet ea nisi aut enim voluptatem.\tEum voluptates sunt occaecati molestiae. Cupiditate labore expedita eius in omnis non. Sit cumque unde cupiditate sequi eius reprehenderit nulla.\tVoluptates modi esse quas sit eos praesentium. Quas et rem vero quo veritatis voluptas. Inventore dolorem ut praesentium consequatur rem. Amet ipsam quia officia iste est in.\t2006-09-07\n30\t10\tEos fuga at ex sapiente quasi.\tFacere dolores non omnis facilis. Nam cupiditate maiores iure quia adipisci numquam magnam. Esse voluptas voluptatem cum ea voluptas doloremque.\tVoluptatem qui qui magnam quis eos. Consequatur ut repudiandae libero dignissimos et quia velit. Eum nisi facere consequatur quod ut. Ad molestiae voluptatem eaque iste et.\t2009-07-23\n\\.\n\n\n--\n-- Name: authors authors_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.authors\n    ADD CONSTRAINT authors_pkey PRIMARY KEY (id);\n\n\n--\n-- Name: posts posts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.posts\n    ADD CONSTRAINT posts_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "doc/examples/links/PostgreSQL/nxs-data-anonymizer.conf",
    "content": "link:\n- rule:\n    value: \"{{ randInt 1 50\t}}\"\n    unique: true\n  with:\n    public.authors:\n    - id\n    public.posts:\n    - author_id\n\nfilters:\n  public.authors:\n    columns:\n      first_name:\n        value: \"{{- randAlphaNum 20 -}}\"\n      last_name:\n        value: \"{{- randAlphaNum 20 -}}\"\n      birthdate:\n        value: \"1999-12-31\" \n      added:\n        value: \"2000-01-01 12:00:00\"\n  public.posts:\n    columns:\n      id:\n        value: \"{{ randInt 1 100 }}\"\n        unique: true"
  },
  {
    "path": "doc/examples/links/PostgreSQL/output",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: authors; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.authors (\n    id integer NOT NULL,\n    first_name character varying(50) NOT NULL,\n    last_name character varying(50) NOT NULL,\n    email character varying(100) NOT NULL,\n    birthdate date NOT NULL,\n    added timestamp without time zone NOT NULL\n);\n\n\nALTER TABLE public.authors OWNER TO postgres;\n\n--\n-- Name: posts; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.posts (\n    id integer NOT NULL,\n    author_id integer NOT NULL,\n    title character varying(255) NOT NULL,\n    description character varying(500) NOT NULL,\n    content text NOT NULL,\n    date date NOT NULL\n);\n\n\nALTER TABLE public.posts OWNER TO postgres;\n\n--\n-- Data for Name: authors; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.authors (id, first_name, last_name, email, birthdate, added) FROM stdin;\n23\t35sXOxBxUPRVA0NnIIZq\t6eurfFlAsmrwlshZ9lBO\tbrett35@example.com\t1999-12-31\t2000-01-01 12:00:00\n19\t5nBuYvwvvwHmCMPA80ui\tNhCGMK31icSCJjXJjfCj\taracely46@example.com\t1999-12-31\t2000-01-01 12:00:00\n10\tf6R0k3DQr9GWGSqjhQZZ\tep3asHE3WfCICDoeHiuw\tcarroll.harris@example.com\t1999-12-31\t2000-01-01 12:00:00\n36\t6nenSS75QXj0FjujvehB\tiNGLlJWPeEzewRAmVq06\tjohns.janick@example.org\t1999-12-31\t2000-01-01 12:00:00\n17\tGJsk4D80CbJGJREN1Vub\tHLzLFc3lmD3jCWh9h0QV\tlakin.ramiro@example.net\t1999-12-31\t2000-01-01 12:00:00\n42\t1FkGPmdU0PLYg9S33ZsB\tU6kT2W9bYV1An8MWTux6\tjudson33@example.com\t1999-12-31\t2000-01-01 12:00:00\n39\tOEzarFYC58fr4RQGQ7mm\tcsA3jA009Q1wH6AJaq4q\tkaci.koch@example.net\t1999-12-31\t2000-01-01 12:00:00\n37\tUaNlog7FzeYvEufa4LEb\tCPr3R2HG3SvH5FCHUeht\tjprosacco@example.net\t1999-12-31\t2000-01-01 12:00:00\n9\t6VJrbHj1s3O87C6rcjGj\tATUdQe47dfexdIq6YjVs\tkutch.kylie@example.com\t1999-12-31\t2000-01-01 12:00:00\n35\tvdu1dbX34myf6S2wAYhG\t292VinyFnt8MTThIYwk4\thane.terrill@example.org\t1999-12-31\t2000-01-01 12:00:00\n\\.\n\n\n--\n-- Data for Name: posts; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.posts (id, author_id, title, description, content, date) FROM stdin;\n52\t23\tPariatur est in ut provident vero eligendi.\tConsequatur quae odio in animi. Quis dolorem aut corporis sed ratione animi et. Iure sunt qui eligendi laudantium harum maxime id id. Quia eos beatae temporibus eos rerum ipsum.\tVelit voluptatibus quo est dolorem quos sed et. Illum similique atque et qui. Perspiciatis magnam saepe quis. Consequatur aut dolorem ea.\t1975-07-07\n88\t19\tUnde est architecto est.\tConsectetur quidem aut eligendi quas. Voluptas aut voluptas ratione reiciendis magnam sint. Ratione et omnis assumenda deserunt voluptatem perspiciatis. Non voluptates quia distinctio nam consectetur vel.\tSed sint at consectetur. Fugiat fugiat omnis debitis dolore. Incidunt vero incidunt enim reiciendis. Odio et illo facilis quo sit quia consequatur voluptatem.\t1976-05-25\n96\t10\tDignissimos perspiciatis nobis quisquam saepe ad aut numquam.\tVoluptatibus eum voluptas eveniet veniam ducimus. Modi id vitae est accusamus. Quaerat perferendis voluptas minima dignissimos et. Sapiente explicabo voluptas commodi voluptatem autem totam. Adipisci quos quos quo ea aliquid rerum.\tRepellat minus enim occaecati sunt quas. Ab ipsa voluptatibus sunt eos omnis quisquam at voluptatibus. Quo vitae doloremque nesciunt doloremque. Temporibus rerum sunt iste dolores rerum.\t1991-12-21\n71\t36\tVoluptas sint modi magnam.\tFacere harum pariatur quo eveniet dolor molestias. Quo debitis corporis quasi minima et optio. Ut maiores nihil rerum autem culpa et voluptates. Amet totam rem optio in. Provident ea repudiandae quisquam unde occaecati autem.\tSed quia assumenda quis rerum praesentium harum. Quia minima quo natus. Impedit temporibus perspiciatis et enim doloremque nihil et. Perspiciatis nam occaecati illo dicta asperiores eos nam.\t2002-01-23\n25\t17\tSapiente rem eos enim ullam ipsum ut.\tOfficia quos voluptas autem consequuntur. Quis consequatur aut vel dolor. Sapiente voluptatem quibusdam dolor nobis earum laboriosam quisquam.\tQuibusdam vel tempora explicabo qui. Sunt animi a unde veritatis perferendis similique nostrum vel. Porro ab ad cumque dolorum provident distinctio est ipsum. Esse maxime ea quia.\t2017-11-19\n43\t42\tError quas doloremque est sunt quae.\tCorporis quis in sint. Eos vitae aut provident distinctio ullam. Corporis mollitia quam natus qui sapiente officiis.\tIpsam animi aperiam ipsa fuga. Sunt blanditiis possimus aut quod. Doloremque possimus occaecati numquam omnis dolor. Qui nihil qui atque vitae sapiente illo id.\t1974-03-23\n11\t39\tQuo impedit quos molestiae dolorum in soluta dolores non.\tHarum quasi dolorum et harum iste eveniet et. Cumque ab recusandae architecto est ipsam est. Eligendi et earum ea alias odio sed ut.\tIllo earum porro corporis sunt aut. Vel quisquam ut voluptas reiciendis maiores cumque. Qui hic maiores voluptas sapiente reprehenderit. Eos non autem quis maiores perferendis.\t2004-12-08\n4\t37\tNulla quia repellendus et autem vitae provident.\tFacere deserunt suscipit quia et et totam vel at. Cumque suscipit est ea quis in quos. Harum dolorum consequuntur illum voluptatem iste enim recusandae.\tExcepturi hic tenetur sint nostrum. Nihil itaque repudiandae qui hic minima quis ut. Dolor et aut quaerat exercitationem minima ut. Blanditiis minus et qui dolor ut atque.\t1999-02-28\n85\t9\tSimilique at quia quia ut recusandae repudiandae delectus.\tEt necessitatibus aut accusantium quisquam harum est. Non quam id impedit deleniti. Eaque non architecto facere dolorem nesciunt perferendis. Delectus nihil ut dignissimos. Voluptate rerum reprehenderit aut voluptatem quibusdam quidem.\tTempore iusto minus omnis tempore. Hic aut sequi temporibus consequatur. In vel enim eos nihil sed eos debitis.\t2007-08-07\n15\t35\tEst vel aperiam ipsa quod doloremque et est et.\tFacere ut et similique voluptates voluptas blanditiis explicabo. Eaque molestiae nihil sed et repellat voluptatem eum autem.\tRem laudantium in aut assumenda. Aspernatur id illo pariatur aut deleniti rem et. Nisi velit neque qui quia.\t2009-07-18\n22\t23\tSint est qui dolorem eum accusantium repudiandae.\tQuia tenetur culpa maiores molestias. Id numquam illum earum quos sint ad dolore corrupti. Consequatur quasi itaque est odit qui quod culpa.\tOmnis tenetur occaecati accusamus quis corrupti et ipsam. Ullam nobis tempore officia nesciunt iste. Nesciunt vel in eos. Dolor voluptates quod sed quibusdam ut. Fuga quia eum quidem cum.\t2010-04-16\n17\t19\tCulpa debitis ut non sapiente voluptatem.\tCommodi fugit ullam quaerat quam quo minus. Harum quam ipsam ducimus sit expedita sit. Eos natus quo quibusdam quam repudiandae. Assumenda et sint sit quia qui necessitatibus.\tEum molestiae cupiditate ut minus. Eaque eos eos ipsam voluptatem. Sint aut aliquid modi id dolores consequatur. Aut nemo blanditiis nisi ea nam velit.\t1988-12-26\n61\t10\tUt ut rerum qui quis sed sunt.\tTenetur enim et nisi ex et consequatur omnis nisi. Eos deleniti aut amet illo sed quibusdam. Consequuntur sint quia quia aut magni.\tAut eveniet natus ut. Nostrum aliquid qui nam hic iusto id occaecati qui. Est dolor accusamus qui saepe voluptatem dolorem omnis.\t2001-06-01\n5\t36\tError inventore delectus sapiente non.\tAliquam ut aliquid et laboriosam distinctio ab. Tempore molestiae aut ea nesciunt culpa. Eum maiores molestiae voluptatem animi aliquam. Aspernatur aut soluta totam occaecati in nam ratione asperiores.\tVoluptatum id amet qui quia. Nemo nulla atque dignissimos.\t1974-12-07\n24\t17\tUt aut quo aut ea occaecati est voluptas.\tNon deleniti molestias velit ut eos veritatis. Et id eaque numquam ipsa iure ut. Molestiae et minus natus.\tNecessitatibus asperiores adipisci eaque. Alias sunt illum fugit ab labore laborum est odio. Aspernatur esse qui ut omnis autem. Laudantium quos corporis numquam sapiente enim.\t1999-09-12\n68\t42\tNihil ea qui sequi odit rem.\tOmnis ea accusantium qui commodi et ducimus. Magni deserunt sed quo velit. Hic cum tenetur facilis. Non eum quis molestias sunt. Illo saepe architecto doloremque illum sequi.\tNihil iste illum vitae ipsa et et. Reiciendis sint illum quo dignissimos veritatis. Velit eum architecto enim ratione aut.\t2003-07-28\n82\t39\tQuia accusantium deserunt suscipit.\tRepellat et molestiae magnam quaerat et iure. Enim enim cum quisquam quasi.\tMaiores officiis beatae hic hic dolor non officiis. Nulla beatae at aut fugit doloribus et provident. Debitis non dolores iusto impedit. Alias blanditiis velit voluptate et debitis.\t2015-05-24\n65\t37\tInventore et eaque temporibus qui aut exercitationem necessitatibus.\tOmnis molestias nemo culpa est dicta dolorem porro. Illum est ut ut molestias similique sit sunt. Consequatur asperiores quaerat voluptate incidunt.\tUnde quibusdam asperiores voluptates quaerat et aliquam. Libero at est quibusdam eos aut. Aut voluptatem tempora a nam.\t1996-02-06\n70\t9\tEt soluta consequatur porro rem corrupti.\tUllam doloremque explicabo ea ab quam ipsum. Et qui iure vero tempore voluptate aut. Ullam id ab accusamus optio voluptas. Quia quaerat quibusdam aut accusantium impedit et.\tPerspiciatis sed dolores aut. Animi sed totam exercitationem fugiat dolores. Ipsa dolorem quia non aliquam. Rerum exercitationem voluptatem dolor beatae veritatis quasi omnis consectetur.\t2018-03-31\n10\t35\tCulpa error rerum voluptatem recusandae quae tempora.\tEst ullam tempore autem et. Dolorum est eius eaque veniam in quibusdam neque. Ut aspernatur earum sint delectus voluptate deserunt sapiente quia.\tEnim quos facere rerum ipsa. Eveniet expedita id eligendi voluptatem magnam quo eos.\t2007-01-22\n51\t23\tHarum laudantium fugiat debitis atque sed.\tEt asperiores magni qui voluptas a consequatur totam. Inventore enim quaerat consequatur sint quam voluptatibus optio. Est aut repellendus repudiandae reiciendis eveniet veniam. Minima a corrupti non quae.\tVoluptate officia ut debitis explicabo corrupti facere reprehenderit. Enim id recusandae vitae est dolores. Aperiam consequuntur ex beatae et alias quia.\t1987-06-29\n57\t19\tNon architecto ut voluptas aut voluptas dolor ut.\tDolore delectus optio fuga aut labore necessitatibus. Laborum quis nulla deserunt. Aut corporis repellendus inventore vel.\tFacilis soluta ab culpa est. Aut pariatur et dicta sit. Sed qui est numquam est.\\nAtque ex sit eveniet. Iure accusamus optio placeat voluptate non sit ea. Sint dignissimos dolorum debitis ipsam neque.\t1993-05-06\n31\t10\tDolores sed hic vitae ut qui.\tLibero illum dolorum est eaque ut. Nesciunt qui vitae recusandae eveniet saepe et ut. Aliquid enim vitae beatae animi quam doloribus accusamus. Eos eos excepturi accusamus ut recusandae.\tDistinctio molestiae sint qui. Expedita qui ex dignissimos architecto quo sapiente alias eveniet. Laborum qui aut est doloribus a beatae. Unde adipisci consequuntur et tenetur.\t1978-09-08\n72\t36\tDeleniti distinctio eos eveniet.\tEx aperiam animi quis excepturi. Velit qui molestias iste iure voluptatem. Eveniet adipisci quasi amet. Soluta laborum aperiam magni.\tDeserunt dolores ut ut ex cum. Quae iusto rerum voluptatum aperiam. Vel voluptatem ut nesciunt delectus blanditiis. Sequi consequuntur temporibus sunt dolores repudiandae.\t2003-06-23\n54\t17\tEa et asperiores odio vel sunt exercitationem.\tQuod necessitatibus quis sit aspernatur a. Molestias laudantium voluptatibus quaerat rerum cupiditate. Aut consectetur quia doloribus repellat porro est.\tEt alias soluta aliquam qui aut. Explicabo quo consequuntur consequuntur velit distinctio.\t1972-09-16\n75\t42\tAccusamus est sed aut minus.\tEt libero in in est consequuntur. Illum distinctio doloremque quas.\tNeque vel tenetur libero sed aut voluptas. Itaque quod et laudantium magnam tempora qui non. Et sapiente dolores reiciendis sit ab fugiat sed sequi. Reiciendis maxime qui aut laborum dolor.\t2017-03-08\n39\t39\tEt sed reprehenderit nobis sed.\tTotam amet nisi id quod. Laudantium maxime rem velit consequuntur amet. Et enim eum aspernatur totam. Nulla consequatur similique maxime et qui rerum.\tIure sequi unde consectetur neque in magni. Illo ipsa commodi quae placeat modi numquam numquam. Quae culpa sit distinctio vitae est.\t1973-08-04\n47\t37\tAutem ullam aperiam totam assumenda quod esse.\tAut incidunt aspernatur aut sapiente ipsum repellat. Molestiae eaque accusantium maxime. Velit modi ea consectetur natus ea.\tMolestias voluptatum cupiditate et minus qui consequuntur. Reprehenderit aut at corrupti. Eius unde ullam aut cum eius molestiae.\t2014-04-26\n66\t9\tAd dolores amet ea nisi aut enim voluptatem.\tEum voluptates sunt occaecati molestiae. Cupiditate labore expedita eius in omnis non. Sit cumque unde cupiditate sequi eius reprehenderit nulla.\tVoluptates modi esse quas sit eos praesentium. Quas et rem vero quo veritatis voluptas. Inventore dolorem ut praesentium consequatur rem. Amet ipsam quia officia iste est in.\t2006-09-07\n32\t35\tEos fuga at ex sapiente quasi.\tFacere dolores non omnis facilis. Nam cupiditate maiores iure quia adipisci numquam magnam. Esse voluptas voluptatem cum ea voluptas doloremque.\tVoluptatem qui qui magnam quis eos. Consequatur ut repudiandae libero dignissimos et quia velit. Eum nisi facere consequatur quod ut. Ad molestiae voluptatem eaque iste et.\t2009-07-23\n\\.\n\n\n--\n-- Name: authors authors_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.authors\n    ADD CONSTRAINT authors_pkey PRIMARY KEY (id);\n\n\n--\n-- Name: posts posts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.posts\n    ADD CONSTRAINT posts_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "doc/examples/links/Readme.md",
    "content": "# Example `variables`\n\nAn example of using nxs-data-anonymizer in a simple configuration with filters and link blocks.\n\nConfiguration block description:\n```yaml\nlink:\n- rule: # Description of the value generation rule.\n    value: \"some_value_generator\" # Some function for generating values ​​with given parameters.\n    unique: true # Flag of uniqueness of the value.\n  with: # Description of tables with fields for which value coherence must be maintained.\n    some_table1:\n    - id\n    some_table2:\n    - id_from_table1\n```\n\nAn example of a configuration:\n```yaml\nlink:\n- rule:\n    value: \"<generation_function_of_value>\"\n    unique: true\n  with:\n    table1:\n    - col1_linked\n    table2:\n    - col2_linked\n\nfilters:\n  table1:\n    columns:\n      col2:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n      col3:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n  table2:\n    columns:\n      col1:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n      col3:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n```\n\nWorking examples of configurations in the `./MySQL` and `./PostgreSQL` directories."
  },
  {
    "path": "doc/examples/security/MySQL/input.sql",
    "content": "-- MySQL dump 10.13  Distrib 8.4.0, for Linux (x86_64)\n--\n-- Host: localhost    Database: name_db\n-- ------------------------------------------------------\n-- Server version\t8.4.0\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!50503 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `authors`\n--\n\nDROP TABLE IF EXISTS `authors`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `authors` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `first_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `last_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `email` varchar(100) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `birthdate` date NOT NULL,\n  `added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `email` (`email`)\n) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `authors`\n--\n\nLOCK TABLES `authors` WRITE;\n/*!40000 ALTER TABLE `authors` DISABLE KEYS */;\nINSERT INTO `authors` VALUES (1,'Wilford','Wintheiser','brett35@example.com','1981-10-14','1988-09-10 18:37:25'),(2,'Nyasia','Doyle','aracely46@example.com','2007-07-01','1980-10-28 23:57:00'),(3,'Ken','Haag','carroll.harris@example.com','2003-04-16','1997-03-14 18:41:06'),(4,'Leonor','Mann','johns.janick@example.org','1996-05-18','2010-04-12 00:38:42'),(5,'Eloisa','Ratke','lakin.ramiro@example.net','1982-07-22','1996-03-25 09:07:39'),(6,'Nikolas','Dibbert','judson33@example.com','1970-02-22','1979-03-16 10:10:12'),(7,'Kelley','Koch','kaci.koch@example.net','2013-05-01','2020-08-02 02:01:34'),(8,'Glen','Howe','jprosacco@example.net','1971-08-03','1971-01-02 14:19:52'),(9,'Geovanni','Medhurst','kutch.kylie@example.com','2011-04-20','2004-06-10 12:33:11'),(10,'Zella','Davis','hane.terrill@example.org','1991-11-07','2007-09-19 13:48:20');\n/*!40000 ALTER TABLE `authors` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `posts`\n--\n\nDROP TABLE IF EXISTS `posts`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `posts` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `author_id` int NOT NULL,\n  `title` varchar(255) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `description` varchar(500) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `content` text COLLATE utf8mb3_unicode_ci NOT NULL,\n  `date` date NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `posts`\n--\n\nLOCK TABLES `posts` WRITE;\n/*!40000 ALTER TABLE `posts` DISABLE KEYS */;\nINSERT INTO `posts` VALUES (1,1,'Pariatur est in ut provident vero eligendi.','Consequatur quae odio in animi. Quis dolorem aut corporis sed ratione animi et. Iure sunt qui eligendi laudantium harum maxime id id. Quia eos beatae temporibus eos rerum ipsum.','Velit voluptatibus quo est dolorem quos sed et. Illum similique atque et qui. Perspiciatis magnam saepe quis. Consequatur aut dolorem ea.','1975-07-07'),(2,2,'Unde est architecto est.','Consectetur quidem aut eligendi quas. Voluptas aut voluptas ratione reiciendis magnam sint. Ratione et omnis assumenda deserunt voluptatem perspiciatis. Non voluptates quia distinctio nam consectetur vel.','Sed sint at consectetur. Fugiat fugiat omnis debitis dolore. Incidunt vero incidunt enim reiciendis. Odio et illo facilis quo sit quia consequatur voluptatem.','1976-05-25'),(3,3,'Dignissimos perspiciatis nobis quisquam saepe ad aut numquam.','Voluptatibus eum voluptas eveniet veniam ducimus. Modi id vitae est accusamus. Quaerat perferendis voluptas minima dignissimos et. Sapiente explicabo voluptas commodi voluptatem autem totam. Adipisci quos quos quo ea aliquid rerum.','Repellat minus enim occaecati sunt quas. Ab ipsa voluptatibus sunt eos omnis quisquam at voluptatibus. Quo vitae doloremque nesciunt doloremque. Temporibus rerum sunt iste dolores rerum.','1991-12-21'),(4,4,'Voluptas sint modi magnam.','Facere harum pariatur quo eveniet dolor molestias. Quo debitis corporis quasi minima et optio. Ut maiores nihil rerum autem culpa et voluptates. Amet totam rem optio in. Provident ea repudiandae quisquam unde occaecati autem.','Sed quia assumenda quis rerum praesentium harum. Quia minima quo natus. Impedit temporibus perspiciatis et enim doloremque nihil et. Perspiciatis nam occaecati illo dicta asperiores eos nam.','2002-01-23'),(5,5,'Sapiente rem eos enim ullam ipsum ut.','Officia quos voluptas autem consequuntur. Quis consequatur aut vel dolor. Sapiente voluptatem quibusdam dolor nobis earum laboriosam quisquam.','Quibusdam vel tempora explicabo qui. Sunt animi a unde veritatis perferendis similique nostrum vel. Porro ab ad cumque dolorum provident distinctio est ipsum. Esse maxime ea quia.','2017-11-19'),(6,6,'Error quas doloremque est sunt quae.','Corporis quis in sint. Eos vitae aut provident distinctio ullam. Corporis mollitia quam natus qui sapiente officiis.','Ipsam animi aperiam ipsa fuga. Sunt blanditiis possimus aut quod. Doloremque possimus occaecati numquam omnis dolor. Qui nihil qui atque vitae sapiente illo id.','1974-03-23'),(7,7,'Quo impedit quos molestiae dolorum in soluta dolores non.','Harum quasi dolorum et harum iste eveniet et. Cumque ab recusandae architecto est ipsam est. Eligendi et earum ea alias odio sed ut.','Illo earum porro corporis sunt aut. Vel quisquam ut voluptas reiciendis maiores cumque. Qui hic maiores voluptas sapiente reprehenderit. Eos non autem quis maiores perferendis.','2004-12-08'),(8,8,'Nulla quia repellendus et autem vitae provident.','Facere deserunt suscipit quia et et totam vel at. Cumque suscipit est ea quis in quos. Harum dolorum consequuntur illum voluptatem iste enim recusandae.','Excepturi hic tenetur sint nostrum. Nihil itaque repudiandae qui hic minima quis ut. Dolor et aut quaerat exercitationem minima ut. Blanditiis minus et qui dolor ut atque.','1999-02-28'),(9,9,'Similique at quia quia ut recusandae repudiandae delectus.','Et necessitatibus aut accusantium quisquam harum est. Non quam id impedit deleniti. Eaque non architecto facere dolorem nesciunt perferendis. Delectus nihil ut dignissimos. Voluptate rerum reprehenderit aut voluptatem quibusdam quidem.','Tempore iusto minus omnis tempore. Hic aut sequi temporibus consequatur. In vel enim eos nihil sed eos debitis.','2007-08-07'),(10,10,'Est vel aperiam ipsa quod doloremque et est et.','Facere ut et similique voluptates voluptas blanditiis explicabo. Eaque molestiae nihil sed et repellat voluptatem eum autem.','Rem laudantium in aut assumenda. Aspernatur id illo pariatur aut deleniti rem et. Nisi velit neque qui quia.','2009-07-18'),(11,1,'Sint est qui dolorem eum accusantium repudiandae.','Quia tenetur culpa maiores molestias. Id numquam illum earum quos sint ad dolore corrupti. Consequatur quasi itaque est odit qui quod culpa.','Omnis tenetur occaecati accusamus quis corrupti et ipsam. Ullam nobis tempore officia nesciunt iste. Nesciunt vel in eos. Dolor voluptates quod sed quibusdam ut. Fuga quia eum quidem cum.','2010-04-16'),(12,2,'Culpa debitis ut non sapiente voluptatem.','Commodi fugit ullam quaerat quam quo minus. Harum quam ipsam ducimus sit expedita sit. Eos natus quo quibusdam quam repudiandae. Assumenda et sint sit quia qui necessitatibus.','Eum molestiae cupiditate ut minus. Eaque eos eos ipsam voluptatem. Sint aut aliquid modi id dolores consequatur. Aut nemo blanditiis nisi ea nam velit.','1988-12-26'),(13,3,'Ut ut rerum qui quis sed sunt.','Tenetur enim et nisi ex et consequatur omnis nisi. Eos deleniti aut amet illo sed quibusdam. Consequuntur sint quia quia aut magni.','Aut eveniet natus ut. Nostrum aliquid qui nam hic iusto id occaecati qui. Est dolor accusamus qui saepe voluptatem dolorem omnis.','2001-06-01'),(14,4,'Error inventore delectus sapiente non.','Aliquam ut aliquid et laboriosam distinctio ab. Tempore molestiae aut ea nesciunt culpa. Eum maiores molestiae voluptatem animi aliquam. Aspernatur aut soluta totam occaecati in nam ratione asperiores.','Voluptatum id amet qui quia. Nemo nulla atque dignissimos.','1974-12-07'),(15,5,'Ut aut quo aut ea occaecati est voluptas.','Non deleniti molestias velit ut eos veritatis. Et id eaque numquam ipsa iure ut. Molestiae et minus natus.','Necessitatibus asperiores adipisci eaque. Alias sunt illum fugit ab labore laborum est odio. Aspernatur esse qui ut omnis autem. Laudantium quos corporis numquam sapiente enim.','1999-09-12'),(16,6,'Nihil ea qui sequi odit rem.','Omnis ea accusantium qui commodi et ducimus. Magni deserunt sed quo velit. Hic cum tenetur facilis. Non eum quis molestias sunt. Illo saepe architecto doloremque illum sequi.','Nihil iste illum vitae ipsa et et. Reiciendis sint illum quo dignissimos veritatis. Velit eum architecto enim ratione aut.','2003-07-28'),(17,7,'Quia accusantium deserunt suscipit.','Repellat et molestiae magnam quaerat et iure. Enim enim cum quisquam quasi.','Maiores officiis beatae hic hic dolor non officiis. Nulla beatae at aut fugit doloribus et provident. Debitis non dolores iusto impedit. Alias blanditiis velit voluptate et debitis.','2015-05-24'),(18,8,'Inventore et eaque temporibus qui aut exercitationem necessitatibus.','Omnis molestias nemo culpa est dicta dolorem porro. Illum est ut ut molestias similique sit sunt. Consequatur asperiores quaerat voluptate incidunt.','Unde quibusdam asperiores voluptates quaerat et aliquam. Libero at est quibusdam eos aut. Aut voluptatem tempora a nam.','1996-02-06'),(19,9,'Et soluta consequatur porro rem corrupti.','Ullam doloremque explicabo ea ab quam ipsum. Et qui iure vero tempore voluptate aut. Ullam id ab accusamus optio voluptas. Quia quaerat quibusdam aut accusantium impedit et.','Perspiciatis sed dolores aut. Animi sed totam exercitationem fugiat dolores. Ipsa dolorem quia non aliquam. Rerum exercitationem voluptatem dolor beatae veritatis quasi omnis consectetur.','2018-03-31'),(20,10,'Culpa error rerum voluptatem recusandae quae tempora.','Est ullam tempore autem et. Dolorum est eius eaque veniam in quibusdam neque. Ut aspernatur earum sint delectus voluptate deserunt sapiente quia.','Enim quos facere rerum ipsa. Eveniet expedita id eligendi voluptatem magnam quo eos.','2007-01-22'),(21,1,'Harum laudantium fugiat debitis atque sed.','Et asperiores magni qui voluptas a consequatur totam. Inventore enim quaerat consequatur sint quam voluptatibus optio. Est aut repellendus repudiandae reiciendis eveniet veniam. Minima a corrupti non quae.','Voluptate officia ut debitis explicabo corrupti facere reprehenderit. Enim id recusandae vitae est dolores. Aperiam consequuntur ex beatae et alias quia.','1987-06-29'),(22,2,'Non architecto ut voluptas aut voluptas dolor ut.','Dolore delectus optio fuga aut labore necessitatibus. Laborum quis nulla deserunt. Aut corporis repellendus inventore vel.','Facilis soluta ab culpa est. Aut pariatur et dicta sit. Sed qui est numquam est.\\nAtque ex sit eveniet. Iure accusamus optio placeat voluptate non sit ea. Sint dignissimos dolorum debitis ipsam neque.','1993-05-06'),(23,3,'Dolores sed hic vitae ut qui.','Libero illum dolorum est eaque ut. Nesciunt qui vitae recusandae eveniet saepe et ut. Aliquid enim vitae beatae animi quam doloribus accusamus. Eos eos excepturi accusamus ut recusandae.','Distinctio molestiae sint qui. Expedita qui ex dignissimos architecto quo sapiente alias eveniet. Laborum qui aut est doloribus a beatae. Unde adipisci consequuntur et tenetur.','1978-09-08'),(24,4,'Deleniti distinctio eos eveniet.','Ex aperiam animi quis excepturi. Velit qui molestias iste iure voluptatem. Eveniet adipisci quasi amet. Soluta laborum aperiam magni.','Deserunt dolores ut ut ex cum. Quae iusto rerum voluptatum aperiam. Vel voluptatem ut nesciunt delectus blanditiis. Sequi consequuntur temporibus sunt dolores repudiandae.','2003-06-23'),(25,5,'Ea et asperiores odio vel sunt exercitationem.','Quod necessitatibus quis sit aspernatur a. Molestias laudantium voluptatibus quaerat rerum cupiditate. Aut consectetur quia doloribus repellat porro est.','Et alias soluta aliquam qui aut. Explicabo quo consequuntur consequuntur velit distinctio.','1972-09-16'),(26,6,'Accusamus est sed aut minus.','Et libero in in est consequuntur. Illum distinctio doloremque quas.','Neque vel tenetur libero sed aut voluptas. Itaque quod et laudantium magnam tempora qui non. Et sapiente dolores reiciendis sit ab fugiat sed sequi. Reiciendis maxime qui aut laborum dolor.','2017-03-08'),(27,7,'Et sed reprehenderit nobis sed.','Totam amet nisi id quod. Laudantium maxime rem velit consequuntur amet. Et enim eum aspernatur totam. Nulla consequatur similique maxime et qui rerum.','Iure sequi unde consectetur neque in magni. Illo ipsa commodi quae placeat modi numquam numquam. Quae culpa sit distinctio vitae est.','1973-08-04'),(28,8,'Autem ullam aperiam totam assumenda quod esse.','Aut incidunt aspernatur aut sapiente ipsum repellat. Molestiae eaque accusantium maxime. Velit modi ea consectetur natus ea.','Molestias voluptatum cupiditate et minus qui consequuntur. Reprehenderit aut at corrupti. Eius unde ullam aut cum eius molestiae.','2014-04-26'),(29,9,'Ad dolores amet ea nisi aut enim voluptatem.','Eum voluptates sunt occaecati molestiae. Cupiditate labore expedita eius in omnis non. Sit cumque unde cupiditate sequi eius reprehenderit nulla.','Voluptates modi esse quas sit eos praesentium. Quas et rem vero quo veritatis voluptas. Inventore dolorem ut praesentium consequatur rem. Amet ipsam quia officia iste est in.','2006-09-07'),(30,10,'Eos fuga at ex sapiente quasi.','Facere dolores non omnis facilis. Nam cupiditate maiores iure quia adipisci numquam magnam. Esse voluptas voluptatem cum ea voluptas doloremque.','Voluptatem qui qui magnam quis eos. Consequatur ut repudiandae libero dignissimos et quia velit. Eum nisi facere consequatur quod ut. Ad molestiae voluptatem eaque iste et.','2009-07-23');\n/*!40000 ALTER TABLE `posts` ENABLE KEYS */;\nUNLOCK TABLES;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2024-07-19 10:47:53\n"
  },
  {
    "path": "doc/examples/security/MySQL/nxs-data-anonymizer.conf",
    "content": "security:\n  policy:\n    tables: skip\n    columns: randomize\n  exceptions:\n    columns:\n    - email\n    - id\n  defaults:\n    columns:\n      birthdate:\n        value: \"1999-12-31\" \nfilters:\n  authors:\n    columns:\n      first_name:\n        value: \"{{- randAlphaNum 20 -}}\"\n      added:\n        value: \"2000-01-01 12:00:00\""
  },
  {
    "path": "doc/examples/security/MySQL/output.sql",
    "content": "-- MySQL dump 10.13  Distrib 8.4.0, for Linux (x86_64)\n--\n-- Host: localhost    Database: name_db\n-- ------------------------------------------------------\n-- Server version\t8.4.0\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!50503 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `authors`\n--\n\nDROP TABLE IF EXISTS `authors`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `authors` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `first_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `last_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `email` varchar(100) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `birthdate` date NOT NULL,\n  `added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `email` (`email`)\n) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `authors`\n--\n\nLOCK TABLES `authors` WRITE;\n/*!40000 ALTER TABLE `authors` DISABLE KEYS */;\nINSERT INTO `authors` VALUES (1,'1l03v4S3kULe9MT504eo','randomized varchar','brett35@example.com','1999-12-31','2000-01-01 12:00:00'),(2,'qQOaG6T57jIUbjFswSZY','randomized varchar','aracely46@example.com','1999-12-31','2000-01-01 12:00:00'),(3,'r5INLGwas75FRG8HlxIH','randomized varchar','carroll.harris@example.com','1999-12-31','2000-01-01 12:00:00'),(4,'RQ8g1cPBpGlDBXozyOCS','randomized varchar','johns.janick@example.org','1999-12-31','2000-01-01 12:00:00'),(5,'d2sJnwtCGDAeBUszVtnS','randomized varchar','lakin.ramiro@example.net','1999-12-31','2000-01-01 12:00:00'),(6,'rTJerd760gdClROJjVAe','randomized varchar','judson33@example.com','1999-12-31','2000-01-01 12:00:00'),(7,'RMsGEydALqtyaTPBKsp9','randomized varchar','kaci.koch@example.net','1999-12-31','2000-01-01 12:00:00'),(8,'bmz2gTMJRYF4HHPn2wiu','randomized varchar','jprosacco@example.net','1999-12-31','2000-01-01 12:00:00'),(9,'ifxehp3b3jrbafETxeab','randomized varchar','kutch.kylie@example.com','1999-12-31','2000-01-01 12:00:00'),(10,'tAbuLmPP94Z41b1Pp5SZ','randomized varchar','hane.terrill@example.org','1999-12-31','2000-01-01 12:00:00');\n/*!40000 ALTER TABLE `authors` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `posts`\n--\n\nDROP TABLE IF EXISTS `posts`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `posts` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `author_id` int NOT NULL,\n  `title` varchar(255) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `description` varchar(500) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `content` text COLLATE utf8mb3_unicode_ci NOT NULL,\n  `date` date NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `posts`\n--\n\nLOCK TABLES `posts` WRITE;\n/*!40000 ALTER TABLE `posts` DISABLE KEYS */;\n\n/*!40000 ALTER TABLE `posts` ENABLE KEYS */;\nUNLOCK TABLES;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2024-07-19 10:47:53\n"
  },
  {
    "path": "doc/examples/security/PostgreSQL/input",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: authors; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.authors (\n    id integer NOT NULL,\n    first_name character varying(50) NOT NULL,\n    last_name character varying(50) NOT NULL,\n    email character varying(100) NOT NULL,\n    birthdate date NOT NULL,\n    added timestamp without time zone NOT NULL\n);\n\n\nALTER TABLE public.authors OWNER TO postgres;\n\n--\n-- Name: posts; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.posts (\n    id integer NOT NULL,\n    author_id integer NOT NULL,\n    title character varying(255) NOT NULL,\n    description character varying(500) NOT NULL,\n    content text NOT NULL,\n    date date NOT NULL\n);\n\n\nALTER TABLE public.posts OWNER TO postgres;\n\n--\n-- Data for Name: authors; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.authors (id, first_name, last_name, email, birthdate, added) FROM stdin;\n1\tWilford\tWintheiser\tbrett35@example.com\t1981-10-14\t1988-09-10 18:37:25\n2\tNyasia\tDoyle\taracely46@example.com\t2007-07-01\t1980-10-28 23:57:00\n3\tKen\tHaag\tcarroll.harris@example.com\t2003-04-16\t1997-03-14 18:41:06\n4\tLeonor\tMann\tjohns.janick@example.org\t1996-05-18\t2010-04-12 00:38:42\n5\tEloisa\tRatke\tlakin.ramiro@example.net\t1982-07-22\t1996-03-25 09:07:39\n6\tNikolas\tDibbert\tjudson33@example.com\t1970-02-22\t1979-03-16 10:10:12\n7\tKelley\tKoch\tkaci.koch@example.net\t2013-05-01\t2020-08-02 02:01:34\n8\tGlen\tHowe\tjprosacco@example.net\t1971-08-03\t1971-01-02 14:19:52\n9\tGeovanni\tMedhurst\tkutch.kylie@example.com\t2011-04-20\t2004-06-10 12:33:11\n10\tZella\tDavis\thane.terrill@example.org\t1991-11-07\t2007-09-19 13:48:20\n\\.\n\n\n--\n-- Data for Name: posts; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.posts (id, author_id, title, description, content, date) FROM stdin;\n1\t1\tPariatur est in ut provident vero eligendi.\tConsequatur quae odio in animi. Quis dolorem aut corporis sed ratione animi et. Iure sunt qui eligendi laudantium harum maxime id id. Quia eos beatae temporibus eos rerum ipsum.\tVelit voluptatibus quo est dolorem quos sed et. Illum similique atque et qui. Perspiciatis magnam saepe quis. Consequatur aut dolorem ea.\t1975-07-07\n2\t2\tUnde est architecto est.\tConsectetur quidem aut eligendi quas. Voluptas aut voluptas ratione reiciendis magnam sint. Ratione et omnis assumenda deserunt voluptatem perspiciatis. Non voluptates quia distinctio nam consectetur vel.\tSed sint at consectetur. Fugiat fugiat omnis debitis dolore. Incidunt vero incidunt enim reiciendis. Odio et illo facilis quo sit quia consequatur voluptatem.\t1976-05-25\n3\t3\tDignissimos perspiciatis nobis quisquam saepe ad aut numquam.\tVoluptatibus eum voluptas eveniet veniam ducimus. Modi id vitae est accusamus. Quaerat perferendis voluptas minima dignissimos et. Sapiente explicabo voluptas commodi voluptatem autem totam. Adipisci quos quos quo ea aliquid rerum.\tRepellat minus enim occaecati sunt quas. Ab ipsa voluptatibus sunt eos omnis quisquam at voluptatibus. Quo vitae doloremque nesciunt doloremque. Temporibus rerum sunt iste dolores rerum.\t1991-12-21\n4\t4\tVoluptas sint modi magnam.\tFacere harum pariatur quo eveniet dolor molestias. Quo debitis corporis quasi minima et optio. Ut maiores nihil rerum autem culpa et voluptates. Amet totam rem optio in. Provident ea repudiandae quisquam unde occaecati autem.\tSed quia assumenda quis rerum praesentium harum. Quia minima quo natus. Impedit temporibus perspiciatis et enim doloremque nihil et. Perspiciatis nam occaecati illo dicta asperiores eos nam.\t2002-01-23\n5\t5\tSapiente rem eos enim ullam ipsum ut.\tOfficia quos voluptas autem consequuntur. Quis consequatur aut vel dolor. Sapiente voluptatem quibusdam dolor nobis earum laboriosam quisquam.\tQuibusdam vel tempora explicabo qui. Sunt animi a unde veritatis perferendis similique nostrum vel. Porro ab ad cumque dolorum provident distinctio est ipsum. Esse maxime ea quia.\t2017-11-19\n6\t6\tError quas doloremque est sunt quae.\tCorporis quis in sint. Eos vitae aut provident distinctio ullam. Corporis mollitia quam natus qui sapiente officiis.\tIpsam animi aperiam ipsa fuga. Sunt blanditiis possimus aut quod. Doloremque possimus occaecati numquam omnis dolor. Qui nihil qui atque vitae sapiente illo id.\t1974-03-23\n7\t7\tQuo impedit quos molestiae dolorum in soluta dolores non.\tHarum quasi dolorum et harum iste eveniet et. Cumque ab recusandae architecto est ipsam est. Eligendi et earum ea alias odio sed ut.\tIllo earum porro corporis sunt aut. Vel quisquam ut voluptas reiciendis maiores cumque. Qui hic maiores voluptas sapiente reprehenderit. Eos non autem quis maiores perferendis.\t2004-12-08\n8\t8\tNulla quia repellendus et autem vitae provident.\tFacere deserunt suscipit quia et et totam vel at. Cumque suscipit est ea quis in quos. Harum dolorum consequuntur illum voluptatem iste enim recusandae.\tExcepturi hic tenetur sint nostrum. Nihil itaque repudiandae qui hic minima quis ut. Dolor et aut quaerat exercitationem minima ut. Blanditiis minus et qui dolor ut atque.\t1999-02-28\n9\t9\tSimilique at quia quia ut recusandae repudiandae delectus.\tEt necessitatibus aut accusantium quisquam harum est. Non quam id impedit deleniti. Eaque non architecto facere dolorem nesciunt perferendis. Delectus nihil ut dignissimos. Voluptate rerum reprehenderit aut voluptatem quibusdam quidem.\tTempore iusto minus omnis tempore. Hic aut sequi temporibus consequatur. In vel enim eos nihil sed eos debitis.\t2007-08-07\n10\t10\tEst vel aperiam ipsa quod doloremque et est et.\tFacere ut et similique voluptates voluptas blanditiis explicabo. Eaque molestiae nihil sed et repellat voluptatem eum autem.\tRem laudantium in aut assumenda. Aspernatur id illo pariatur aut deleniti rem et. Nisi velit neque qui quia.\t2009-07-18\n11\t1\tSint est qui dolorem eum accusantium repudiandae.\tQuia tenetur culpa maiores molestias. Id numquam illum earum quos sint ad dolore corrupti. Consequatur quasi itaque est odit qui quod culpa.\tOmnis tenetur occaecati accusamus quis corrupti et ipsam. Ullam nobis tempore officia nesciunt iste. Nesciunt vel in eos. Dolor voluptates quod sed quibusdam ut. Fuga quia eum quidem cum.\t2010-04-16\n12\t2\tCulpa debitis ut non sapiente voluptatem.\tCommodi fugit ullam quaerat quam quo minus. Harum quam ipsam ducimus sit expedita sit. Eos natus quo quibusdam quam repudiandae. Assumenda et sint sit quia qui necessitatibus.\tEum molestiae cupiditate ut minus. Eaque eos eos ipsam voluptatem. Sint aut aliquid modi id dolores consequatur. Aut nemo blanditiis nisi ea nam velit.\t1988-12-26\n13\t3\tUt ut rerum qui quis sed sunt.\tTenetur enim et nisi ex et consequatur omnis nisi. Eos deleniti aut amet illo sed quibusdam. Consequuntur sint quia quia aut magni.\tAut eveniet natus ut. Nostrum aliquid qui nam hic iusto id occaecati qui. Est dolor accusamus qui saepe voluptatem dolorem omnis.\t2001-06-01\n14\t4\tError inventore delectus sapiente non.\tAliquam ut aliquid et laboriosam distinctio ab. Tempore molestiae aut ea nesciunt culpa. Eum maiores molestiae voluptatem animi aliquam. Aspernatur aut soluta totam occaecati in nam ratione asperiores.\tVoluptatum id amet qui quia. Nemo nulla atque dignissimos.\t1974-12-07\n15\t5\tUt aut quo aut ea occaecati est voluptas.\tNon deleniti molestias velit ut eos veritatis. Et id eaque numquam ipsa iure ut. Molestiae et minus natus.\tNecessitatibus asperiores adipisci eaque. Alias sunt illum fugit ab labore laborum est odio. Aspernatur esse qui ut omnis autem. Laudantium quos corporis numquam sapiente enim.\t1999-09-12\n16\t6\tNihil ea qui sequi odit rem.\tOmnis ea accusantium qui commodi et ducimus. Magni deserunt sed quo velit. Hic cum tenetur facilis. Non eum quis molestias sunt. Illo saepe architecto doloremque illum sequi.\tNihil iste illum vitae ipsa et et. Reiciendis sint illum quo dignissimos veritatis. Velit eum architecto enim ratione aut.\t2003-07-28\n17\t7\tQuia accusantium deserunt suscipit.\tRepellat et molestiae magnam quaerat et iure. Enim enim cum quisquam quasi.\tMaiores officiis beatae hic hic dolor non officiis. Nulla beatae at aut fugit doloribus et provident. Debitis non dolores iusto impedit. Alias blanditiis velit voluptate et debitis.\t2015-05-24\n18\t8\tInventore et eaque temporibus qui aut exercitationem necessitatibus.\tOmnis molestias nemo culpa est dicta dolorem porro. Illum est ut ut molestias similique sit sunt. Consequatur asperiores quaerat voluptate incidunt.\tUnde quibusdam asperiores voluptates quaerat et aliquam. Libero at est quibusdam eos aut. Aut voluptatem tempora a nam.\t1996-02-06\n19\t9\tEt soluta consequatur porro rem corrupti.\tUllam doloremque explicabo ea ab quam ipsum. Et qui iure vero tempore voluptate aut. Ullam id ab accusamus optio voluptas. Quia quaerat quibusdam aut accusantium impedit et.\tPerspiciatis sed dolores aut. Animi sed totam exercitationem fugiat dolores. Ipsa dolorem quia non aliquam. Rerum exercitationem voluptatem dolor beatae veritatis quasi omnis consectetur.\t2018-03-31\n20\t10\tCulpa error rerum voluptatem recusandae quae tempora.\tEst ullam tempore autem et. Dolorum est eius eaque veniam in quibusdam neque. Ut aspernatur earum sint delectus voluptate deserunt sapiente quia.\tEnim quos facere rerum ipsa. Eveniet expedita id eligendi voluptatem magnam quo eos.\t2007-01-22\n21\t1\tHarum laudantium fugiat debitis atque sed.\tEt asperiores magni qui voluptas a consequatur totam. Inventore enim quaerat consequatur sint quam voluptatibus optio. Est aut repellendus repudiandae reiciendis eveniet veniam. Minima a corrupti non quae.\tVoluptate officia ut debitis explicabo corrupti facere reprehenderit. Enim id recusandae vitae est dolores. Aperiam consequuntur ex beatae et alias quia.\t1987-06-29\n22\t2\tNon architecto ut voluptas aut voluptas dolor ut.\tDolore delectus optio fuga aut labore necessitatibus. Laborum quis nulla deserunt. Aut corporis repellendus inventore vel.\tFacilis soluta ab culpa est. Aut pariatur et dicta sit. Sed qui est numquam est.\\nAtque ex sit eveniet. Iure accusamus optio placeat voluptate non sit ea. Sint dignissimos dolorum debitis ipsam neque.\t1993-05-06\n23\t3\tDolores sed hic vitae ut qui.\tLibero illum dolorum est eaque ut. Nesciunt qui vitae recusandae eveniet saepe et ut. Aliquid enim vitae beatae animi quam doloribus accusamus. Eos eos excepturi accusamus ut recusandae.\tDistinctio molestiae sint qui. Expedita qui ex dignissimos architecto quo sapiente alias eveniet. Laborum qui aut est doloribus a beatae. Unde adipisci consequuntur et tenetur.\t1978-09-08\n24\t4\tDeleniti distinctio eos eveniet.\tEx aperiam animi quis excepturi. Velit qui molestias iste iure voluptatem. Eveniet adipisci quasi amet. Soluta laborum aperiam magni.\tDeserunt dolores ut ut ex cum. Quae iusto rerum voluptatum aperiam. Vel voluptatem ut nesciunt delectus blanditiis. Sequi consequuntur temporibus sunt dolores repudiandae.\t2003-06-23\n25\t5\tEa et asperiores odio vel sunt exercitationem.\tQuod necessitatibus quis sit aspernatur a. Molestias laudantium voluptatibus quaerat rerum cupiditate. Aut consectetur quia doloribus repellat porro est.\tEt alias soluta aliquam qui aut. Explicabo quo consequuntur consequuntur velit distinctio.\t1972-09-16\n26\t6\tAccusamus est sed aut minus.\tEt libero in in est consequuntur. Illum distinctio doloremque quas.\tNeque vel tenetur libero sed aut voluptas. Itaque quod et laudantium magnam tempora qui non. Et sapiente dolores reiciendis sit ab fugiat sed sequi. Reiciendis maxime qui aut laborum dolor.\t2017-03-08\n27\t7\tEt sed reprehenderit nobis sed.\tTotam amet nisi id quod. Laudantium maxime rem velit consequuntur amet. Et enim eum aspernatur totam. Nulla consequatur similique maxime et qui rerum.\tIure sequi unde consectetur neque in magni. Illo ipsa commodi quae placeat modi numquam numquam. Quae culpa sit distinctio vitae est.\t1973-08-04\n28\t8\tAutem ullam aperiam totam assumenda quod esse.\tAut incidunt aspernatur aut sapiente ipsum repellat. Molestiae eaque accusantium maxime. Velit modi ea consectetur natus ea.\tMolestias voluptatum cupiditate et minus qui consequuntur. Reprehenderit aut at corrupti. Eius unde ullam aut cum eius molestiae.\t2014-04-26\n29\t9\tAd dolores amet ea nisi aut enim voluptatem.\tEum voluptates sunt occaecati molestiae. Cupiditate labore expedita eius in omnis non. Sit cumque unde cupiditate sequi eius reprehenderit nulla.\tVoluptates modi esse quas sit eos praesentium. Quas et rem vero quo veritatis voluptas. Inventore dolorem ut praesentium consequatur rem. Amet ipsam quia officia iste est in.\t2006-09-07\n30\t10\tEos fuga at ex sapiente quasi.\tFacere dolores non omnis facilis. Nam cupiditate maiores iure quia adipisci numquam magnam. Esse voluptas voluptatem cum ea voluptas doloremque.\tVoluptatem qui qui magnam quis eos. Consequatur ut repudiandae libero dignissimos et quia velit. Eum nisi facere consequatur quod ut. Ad molestiae voluptatem eaque iste et.\t2009-07-23\n\\.\n\n\n--\n-- Name: authors authors_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.authors\n    ADD CONSTRAINT authors_pkey PRIMARY KEY (id);\n\n\n--\n-- Name: posts posts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.posts\n    ADD CONSTRAINT posts_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "doc/examples/security/PostgreSQL/nxs-data-anonymizer.conf",
    "content": "security:\n  policy:\n    tables: skip\n    columns: randomize\n  exceptions:\n    columns:\n    - email\n    - id\n  defaults:\n    columns:\n      birthdate:\n        value: \"1999-12-31\" \nfilters:\n  public.authors:\n    columns:\n      first_name:\n        value: \"{{- randAlphaNum 20 -}}\"\n      added:\n        value: \"2000-01-01 12:00:00\""
  },
  {
    "path": "doc/examples/security/PostgreSQL/output",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: authors; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.authors (\n    id integer NOT NULL,\n    first_name character varying(50) NOT NULL,\n    last_name character varying(50) NOT NULL,\n    email character varying(100) NOT NULL,\n    birthdate date NOT NULL,\n    added timestamp without time zone NOT NULL\n);\n\n\nALTER TABLE public.authors OWNER TO postgres;\n\n--\n-- Name: posts; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.posts (\n    id integer NOT NULL,\n    author_id integer NOT NULL,\n    title character varying(255) NOT NULL,\n    description character varying(500) NOT NULL,\n    content text NOT NULL,\n    date date NOT NULL\n);\n\n\nALTER TABLE public.posts OWNER TO postgres;\n\n--\n-- Data for Name: authors; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.authors (id, first_name, last_name, email, birthdate, added) FROM stdin;\n1\tuzQxHOrpTjP4LQLsBtuf\trandomized character data\tbrett35@example.com\t1999-12-31\t2000-01-01 12:00:00\n2\tIGX35AiQbhUs8rnbwEu5\trandomized character data\taracely46@example.com\t1999-12-31\t2000-01-01 12:00:00\n3\t50zYnjx22diwRJrkdsHF\trandomized character data\tcarroll.harris@example.com\t1999-12-31\t2000-01-01 12:00:00\n4\trdj068aJyjJWWPGLMCvM\trandomized character data\tjohns.janick@example.org\t1999-12-31\t2000-01-01 12:00:00\n5\tHUG1OQFX1zbnZbjvss2g\trandomized character data\tlakin.ramiro@example.net\t1999-12-31\t2000-01-01 12:00:00\n6\tBVXmaj17oPS6TVbgkxFK\trandomized character data\tjudson33@example.com\t1999-12-31\t2000-01-01 12:00:00\n7\tdT0oZqmVrthd4VP8CHA1\trandomized character data\tkaci.koch@example.net\t1999-12-31\t2000-01-01 12:00:00\n8\tqwhvRdMTcuFZu79qIIKa\trandomized character data\tjprosacco@example.net\t1999-12-31\t2000-01-01 12:00:00\n9\thqfNNYZ1fylWuGKC2Lxy\trandomized character data\tkutch.kylie@example.com\t1999-12-31\t2000-01-01 12:00:00\n10\tTYBlmQpwP9mBz3X0sjj7\trandomized character data\thane.terrill@example.org\t1999-12-31\t2000-01-01 12:00:00\n\\.\n\n\n--\n-- Data for Name: posts; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\n\n\n\n--\n-- Name: authors authors_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.authors\n    ADD CONSTRAINT authors_pkey PRIMARY KEY (id);\n\n\n--\n-- Name: posts posts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.posts\n    ADD CONSTRAINT posts_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "doc/examples/security/Readme.md",
    "content": "# Example `security`\n\nAn example of using nxs-data-anonymizer in a simple configuration with filters and security block.\n\nAn example of a configuration:\n```yaml\nsecurity:\n  policy: # Policy for handling undeclared tables and columns.\n    tables: skip\n    columns: randomize\n  exceptions: # Excludes policy processing for the specified tables and columns.\n    tables: # These tables will not be skipped.\n    - table2\n    columns: # These columns will not be randomized.\n    - excluded_col1\n    - excluded_col2\n  defaults: # Overrides the default randomization value for a column with the specified value. If you use a function to generate a value, that value will be the same for all substitutions.\n    columns:\n      default_col1: # Column name to override the default value.\n        value: \"<fixed_value_or_generation_function_of_value>\"\n\nfilters:\n  table1:\n    columns:\n      table1_col1:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n      table1_col2:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n```\n\nWorking examples of configurations in the `./MySQL` and `./PostgreSQL` directories."
  },
  {
    "path": "doc/examples/variables/MySQL/input.sql",
    "content": "-- MySQL dump 10.13  Distrib 8.4.0, for Linux (x86_64)\n--\n-- Host: localhost    Database: name_db\n-- ------------------------------------------------------\n-- Server version\t8.4.0\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!50503 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `authors`\n--\n\nDROP TABLE IF EXISTS `authors`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `authors` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `first_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `last_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `email` varchar(100) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `birthdate` date NOT NULL,\n  `added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `authors`\n--\n\nLOCK TABLES `authors` WRITE;\n/*!40000 ALTER TABLE `authors` DISABLE KEYS */;\nINSERT INTO `authors` VALUES (1,'Wilford','Wintheiser','brett35@example.com','1981-10-14','1988-09-10 18:37:25'),(2,'Nyasia','Doyle','aracely46@example.com','2007-07-01','1980-10-28 23:57:00'),(3,'Ken','Haag','carroll.harris@example.com','2003-04-16','1997-03-14 18:41:06'),(4,'Leonor','Mann','johns.janick@example.org','1996-05-18','2010-04-12 00:38:42'),(5,'Eloisa','Ratke','lakin.ramiro@example.net','1982-07-22','1996-03-25 09:07:39'),(6,'Nikolas','Dibbert','judson33@example.com','1970-02-22','1979-03-16 10:10:12'),(7,'Kelley','Koch','kaci.koch@example.net','2013-05-01','2020-08-02 02:01:34'),(8,'Glen','Howe','jprosacco@example.net','1971-08-03','1971-01-02 14:19:52'),(9,'Geovanni','Medhurst','kutch.kylie@example.com','2011-04-20','2004-06-10 12:33:11'),(10,'Zella','Davis','hane.terrill@example.org','1991-11-07','2007-09-19 13:48:20');\n/*!40000 ALTER TABLE `authors` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `posts`\n--\n\nDROP TABLE IF EXISTS `posts`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `posts` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `author_id` int NOT NULL,\n  `title` varchar(255) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `description` varchar(500) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `content` text COLLATE utf8mb3_unicode_ci NOT NULL,\n  `date` date NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `posts`\n--\n\nLOCK TABLES `posts` WRITE;\n/*!40000 ALTER TABLE `posts` DISABLE KEYS */;\nINSERT INTO `posts` VALUES (1,1,'Pariatur est in ut provident vero eligendi.','Consequatur quae odio in animi. Quis dolorem aut corporis sed ratione animi et. Iure sunt qui eligendi laudantium harum maxime id id. Quia eos beatae temporibus eos rerum ipsum.','Velit voluptatibus quo est dolorem quos sed et. Illum similique atque et qui. Perspiciatis magnam saepe quis. Consequatur aut dolorem ea.','1975-07-07'),(2,2,'Unde est architecto est.','Consectetur quidem aut eligendi quas. Voluptas aut voluptas ratione reiciendis magnam sint. Ratione et omnis assumenda deserunt voluptatem perspiciatis. Non voluptates quia distinctio nam consectetur vel.','Sed sint at consectetur. Fugiat fugiat omnis debitis dolore. Incidunt vero incidunt enim reiciendis. Odio et illo facilis quo sit quia consequatur voluptatem.','1976-05-25'),(3,3,'Dignissimos perspiciatis nobis quisquam saepe ad aut numquam.','Voluptatibus eum voluptas eveniet veniam ducimus. Modi id vitae est accusamus. Quaerat perferendis voluptas minima dignissimos et. Sapiente explicabo voluptas commodi voluptatem autem totam. Adipisci quos quos quo ea aliquid rerum.','Repellat minus enim occaecati sunt quas. Ab ipsa voluptatibus sunt eos omnis quisquam at voluptatibus. Quo vitae doloremque nesciunt doloremque. Temporibus rerum sunt iste dolores rerum.','1991-12-21'),(4,4,'Voluptas sint modi magnam.','Facere harum pariatur quo eveniet dolor molestias. Quo debitis corporis quasi minima et optio. Ut maiores nihil rerum autem culpa et voluptates. Amet totam rem optio in. Provident ea repudiandae quisquam unde occaecati autem.','Sed quia assumenda quis rerum praesentium harum. Quia minima quo natus. Impedit temporibus perspiciatis et enim doloremque nihil et. Perspiciatis nam occaecati illo dicta asperiores eos nam.','2002-01-23'),(5,5,'Sapiente rem eos enim ullam ipsum ut.','Officia quos voluptas autem consequuntur. Quis consequatur aut vel dolor. Sapiente voluptatem quibusdam dolor nobis earum laboriosam quisquam.','Quibusdam vel tempora explicabo qui. Sunt animi a unde veritatis perferendis similique nostrum vel. Porro ab ad cumque dolorum provident distinctio est ipsum. Esse maxime ea quia.','2017-11-19'),(6,6,'Error quas doloremque est sunt quae.','Corporis quis in sint. Eos vitae aut provident distinctio ullam. Corporis mollitia quam natus qui sapiente officiis.','Ipsam animi aperiam ipsa fuga. Sunt blanditiis possimus aut quod. Doloremque possimus occaecati numquam omnis dolor. Qui nihil qui atque vitae sapiente illo id.','1974-03-23'),(7,7,'Quo impedit quos molestiae dolorum in soluta dolores non.','Harum quasi dolorum et harum iste eveniet et. Cumque ab recusandae architecto est ipsam est. Eligendi et earum ea alias odio sed ut.','Illo earum porro corporis sunt aut. Vel quisquam ut voluptas reiciendis maiores cumque. Qui hic maiores voluptas sapiente reprehenderit. Eos non autem quis maiores perferendis.','2004-12-08'),(8,8,'Nulla quia repellendus et autem vitae provident.','Facere deserunt suscipit quia et et totam vel at. Cumque suscipit est ea quis in quos. Harum dolorum consequuntur illum voluptatem iste enim recusandae.','Excepturi hic tenetur sint nostrum. Nihil itaque repudiandae qui hic minima quis ut. Dolor et aut quaerat exercitationem minima ut. Blanditiis minus et qui dolor ut atque.','1999-02-28'),(9,9,'Similique at quia quia ut recusandae repudiandae delectus.','Et necessitatibus aut accusantium quisquam harum est. Non quam id impedit deleniti. Eaque non architecto facere dolorem nesciunt perferendis. Delectus nihil ut dignissimos. Voluptate rerum reprehenderit aut voluptatem quibusdam quidem.','Tempore iusto minus omnis tempore. Hic aut sequi temporibus consequatur. In vel enim eos nihil sed eos debitis.','2007-08-07'),(10,10,'Est vel aperiam ipsa quod doloremque et est et.','Facere ut et similique voluptates voluptas blanditiis explicabo. Eaque molestiae nihil sed et repellat voluptatem eum autem.','Rem laudantium in aut assumenda. Aspernatur id illo pariatur aut deleniti rem et. Nisi velit neque qui quia.','2009-07-18'),(11,1,'Sint est qui dolorem eum accusantium repudiandae.','Quia tenetur culpa maiores molestias. Id numquam illum earum quos sint ad dolore corrupti. Consequatur quasi itaque est odit qui quod culpa.','Omnis tenetur occaecati accusamus quis corrupti et ipsam. Ullam nobis tempore officia nesciunt iste. Nesciunt vel in eos. Dolor voluptates quod sed quibusdam ut. Fuga quia eum quidem cum.','2010-04-16'),(12,2,'Culpa debitis ut non sapiente voluptatem.','Commodi fugit ullam quaerat quam quo minus. Harum quam ipsam ducimus sit expedita sit. Eos natus quo quibusdam quam repudiandae. Assumenda et sint sit quia qui necessitatibus.','Eum molestiae cupiditate ut minus. Eaque eos eos ipsam voluptatem. Sint aut aliquid modi id dolores consequatur. Aut nemo blanditiis nisi ea nam velit.','1988-12-26'),(13,3,'Ut ut rerum qui quis sed sunt.','Tenetur enim et nisi ex et consequatur omnis nisi. Eos deleniti aut amet illo sed quibusdam. Consequuntur sint quia quia aut magni.','Aut eveniet natus ut. Nostrum aliquid qui nam hic iusto id occaecati qui. Est dolor accusamus qui saepe voluptatem dolorem omnis.','2001-06-01'),(14,4,'Error inventore delectus sapiente non.','Aliquam ut aliquid et laboriosam distinctio ab. Tempore molestiae aut ea nesciunt culpa. Eum maiores molestiae voluptatem animi aliquam. Aspernatur aut soluta totam occaecati in nam ratione asperiores.','Voluptatum id amet qui quia. Nemo nulla atque dignissimos.','1974-12-07'),(15,5,'Ut aut quo aut ea occaecati est voluptas.','Non deleniti molestias velit ut eos veritatis. Et id eaque numquam ipsa iure ut. Molestiae et minus natus.','Necessitatibus asperiores adipisci eaque. Alias sunt illum fugit ab labore laborum est odio. Aspernatur esse qui ut omnis autem. Laudantium quos corporis numquam sapiente enim.','1999-09-12'),(16,6,'Nihil ea qui sequi odit rem.','Omnis ea accusantium qui commodi et ducimus. Magni deserunt sed quo velit. Hic cum tenetur facilis. Non eum quis molestias sunt. Illo saepe architecto doloremque illum sequi.','Nihil iste illum vitae ipsa et et. Reiciendis sint illum quo dignissimos veritatis. Velit eum architecto enim ratione aut.','2003-07-28'),(17,7,'Quia accusantium deserunt suscipit.','Repellat et molestiae magnam quaerat et iure. Enim enim cum quisquam quasi.','Maiores officiis beatae hic hic dolor non officiis. Nulla beatae at aut fugit doloribus et provident. Debitis non dolores iusto impedit. Alias blanditiis velit voluptate et debitis.','2015-05-24'),(18,8,'Inventore et eaque temporibus qui aut exercitationem necessitatibus.','Omnis molestias nemo culpa est dicta dolorem porro. Illum est ut ut molestias similique sit sunt. Consequatur asperiores quaerat voluptate incidunt.','Unde quibusdam asperiores voluptates quaerat et aliquam. Libero at est quibusdam eos aut. Aut voluptatem tempora a nam.','1996-02-06'),(19,9,'Et soluta consequatur porro rem corrupti.','Ullam doloremque explicabo ea ab quam ipsum. Et qui iure vero tempore voluptate aut. Ullam id ab accusamus optio voluptas. Quia quaerat quibusdam aut accusantium impedit et.','Perspiciatis sed dolores aut. Animi sed totam exercitationem fugiat dolores. Ipsa dolorem quia non aliquam. Rerum exercitationem voluptatem dolor beatae veritatis quasi omnis consectetur.','2018-03-31'),(20,10,'Culpa error rerum voluptatem recusandae quae tempora.','Est ullam tempore autem et. Dolorum est eius eaque veniam in quibusdam neque. Ut aspernatur earum sint delectus voluptate deserunt sapiente quia.','Enim quos facere rerum ipsa. Eveniet expedita id eligendi voluptatem magnam quo eos.','2007-01-22'),(21,1,'Harum laudantium fugiat debitis atque sed.','Et asperiores magni qui voluptas a consequatur totam. Inventore enim quaerat consequatur sint quam voluptatibus optio. Est aut repellendus repudiandae reiciendis eveniet veniam. Minima a corrupti non quae.','Voluptate officia ut debitis explicabo corrupti facere reprehenderit. Enim id recusandae vitae est dolores. Aperiam consequuntur ex beatae et alias quia.','1987-06-29'),(22,2,'Non architecto ut voluptas aut voluptas dolor ut.','Dolore delectus optio fuga aut labore necessitatibus. Laborum quis nulla deserunt. Aut corporis repellendus inventore vel.','Facilis soluta ab culpa est. Aut pariatur et dicta sit. Sed qui est numquam est.\\nAtque ex sit eveniet. Iure accusamus optio placeat voluptate non sit ea. Sint dignissimos dolorum debitis ipsam neque.','1993-05-06'),(23,3,'Dolores sed hic vitae ut qui.','Libero illum dolorum est eaque ut. Nesciunt qui vitae recusandae eveniet saepe et ut. Aliquid enim vitae beatae animi quam doloribus accusamus. Eos eos excepturi accusamus ut recusandae.','Distinctio molestiae sint qui. Expedita qui ex dignissimos architecto quo sapiente alias eveniet. Laborum qui aut est doloribus a beatae. Unde adipisci consequuntur et tenetur.','1978-09-08'),(24,4,'Deleniti distinctio eos eveniet.','Ex aperiam animi quis excepturi. Velit qui molestias iste iure voluptatem. Eveniet adipisci quasi amet. Soluta laborum aperiam magni.','Deserunt dolores ut ut ex cum. Quae iusto rerum voluptatum aperiam. Vel voluptatem ut nesciunt delectus blanditiis. Sequi consequuntur temporibus sunt dolores repudiandae.','2003-06-23'),(25,5,'Ea et asperiores odio vel sunt exercitationem.','Quod necessitatibus quis sit aspernatur a. Molestias laudantium voluptatibus quaerat rerum cupiditate. Aut consectetur quia doloribus repellat porro est.','Et alias soluta aliquam qui aut. Explicabo quo consequuntur consequuntur velit distinctio.','1972-09-16'),(26,6,'Accusamus est sed aut minus.','Et libero in in est consequuntur. Illum distinctio doloremque quas.','Neque vel tenetur libero sed aut voluptas. Itaque quod et laudantium magnam tempora qui non. Et sapiente dolores reiciendis sit ab fugiat sed sequi. Reiciendis maxime qui aut laborum dolor.','2017-03-08'),(27,7,'Et sed reprehenderit nobis sed.','Totam amet nisi id quod. Laudantium maxime rem velit consequuntur amet. Et enim eum aspernatur totam. Nulla consequatur similique maxime et qui rerum.','Iure sequi unde consectetur neque in magni. Illo ipsa commodi quae placeat modi numquam numquam. Quae culpa sit distinctio vitae est.','1973-08-04'),(28,8,'Autem ullam aperiam totam assumenda quod esse.','Aut incidunt aspernatur aut sapiente ipsum repellat. Molestiae eaque accusantium maxime. Velit modi ea consectetur natus ea.','Molestias voluptatum cupiditate et minus qui consequuntur. Reprehenderit aut at corrupti. Eius unde ullam aut cum eius molestiae.','2014-04-26'),(29,9,'Ad dolores amet ea nisi aut enim voluptatem.','Eum voluptates sunt occaecati molestiae. Cupiditate labore expedita eius in omnis non. Sit cumque unde cupiditate sequi eius reprehenderit nulla.','Voluptates modi esse quas sit eos praesentium. Quas et rem vero quo veritatis voluptas. Inventore dolorem ut praesentium consequatur rem. Amet ipsam quia officia iste est in.','2006-09-07'),(30,10,'Eos fuga at ex sapiente quasi.','Facere dolores non omnis facilis. Nam cupiditate maiores iure quia adipisci numquam magnam. Esse voluptas voluptatem cum ea voluptas doloremque.','Voluptatem qui qui magnam quis eos. Consequatur ut repudiandae libero dignissimos et quia velit. Eum nisi facere consequatur quod ut. Ad molestiae voluptatem eaque iste et.','2009-07-23');\n/*!40000 ALTER TABLE `posts` ENABLE KEYS */;\nUNLOCK TABLES;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2024-07-19 10:47:53\n"
  },
  {
    "path": "doc/examples/variables/MySQL/nxs-data-anonymizer.conf",
    "content": "variables:\n  first_name:\n    value: \"John\"\n  last_name:\n    value: \"Smith\"\n  email:\n    value: \"JohnSmith@example.com\"\n  birthdate:\n    value: \"1999-12-31\" \n  added:\n    value: \"2000-01-01 12:00:00\"\n  author_id:\n    value: \"1\"\n  title:\n    value: \"anont_title\"\n  description:\n    value: \"anon_description\"\n  content:\n    value: \"anon_content\"\n  date:\n    value: \"2001-01-01 12:00:00\"\n\nfilters:\n  authors:\n    columns:\n      first_name:\n        value: \"{{ .Variables.first_name }}\"\n      last_name:\n        value: \"{{ .Variables.last_name }}\"\n      email:\n        value: \"{{ .Variables.email }}\"\n      birthdate:\n        value: \"{{ .Variables.birthdate }}\"\n      added:\n        value: \"{{ .Variables.added }}\"\n  posts:\n    columns:\n      author_id:\n        value: \"{{ .Variables.author_id }}\"\n      title:\n        value: \"{{ .Variables.title }}\"\n      description:\n        value: \"{{ .Variables.description }}\"\n      content:\n        value: \"{{ .Variables.content }}\"\n      date:\n        value: \"{{ .Variables.date }}\""
  },
  {
    "path": "doc/examples/variables/MySQL/output.sql",
    "content": "-- MySQL dump 10.13  Distrib 8.4.0, for Linux (x86_64)\n--\n-- Host: localhost    Database: name_db\n-- ------------------------------------------------------\n-- Server version\t8.4.0\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!50503 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `authors`\n--\n\nDROP TABLE IF EXISTS `authors`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `authors` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `first_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `last_name` varchar(50) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `email` varchar(100) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `birthdate` date NOT NULL,\n  `added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `authors`\n--\n\nLOCK TABLES `authors` WRITE;\n/*!40000 ALTER TABLE `authors` DISABLE KEYS */;\nINSERT INTO `authors` VALUES (1,'John','Smith','JohnSmith@example.com','1999-12-31','2000-01-01 12:00:00'),(2,'John','Smith','JohnSmith@example.com','1999-12-31','2000-01-01 12:00:00'),(3,'John','Smith','JohnSmith@example.com','1999-12-31','2000-01-01 12:00:00'),(4,'John','Smith','JohnSmith@example.com','1999-12-31','2000-01-01 12:00:00'),(5,'John','Smith','JohnSmith@example.com','1999-12-31','2000-01-01 12:00:00'),(6,'John','Smith','JohnSmith@example.com','1999-12-31','2000-01-01 12:00:00'),(7,'John','Smith','JohnSmith@example.com','1999-12-31','2000-01-01 12:00:00'),(8,'John','Smith','JohnSmith@example.com','1999-12-31','2000-01-01 12:00:00'),(9,'John','Smith','JohnSmith@example.com','1999-12-31','2000-01-01 12:00:00'),(10,'John','Smith','JohnSmith@example.com','1999-12-31','2000-01-01 12:00:00');\n/*!40000 ALTER TABLE `authors` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `posts`\n--\n\nDROP TABLE IF EXISTS `posts`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!50503 SET character_set_client = utf8mb4 */;\nCREATE TABLE `posts` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `author_id` int NOT NULL,\n  `title` varchar(255) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `description` varchar(500) COLLATE utf8mb3_unicode_ci NOT NULL,\n  `content` text COLLATE utf8mb3_unicode_ci NOT NULL,\n  `date` date NOT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `posts`\n--\n\nLOCK TABLES `posts` WRITE;\n/*!40000 ALTER TABLE `posts` DISABLE KEYS */;\nINSERT INTO `posts` VALUES (1,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(2,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(3,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(4,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(5,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(6,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(7,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(8,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(9,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(10,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(11,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(12,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(13,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(14,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(15,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(16,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(17,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(18,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(19,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(20,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(21,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(22,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(23,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(24,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(25,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(26,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(27,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(28,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(29,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00'),(30,1,'anont_title','anon_description','anon_content','2001-01-01 12:00:00');\n/*!40000 ALTER TABLE `posts` ENABLE KEYS */;\nUNLOCK TABLES;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2024-07-19 10:47:53\n"
  },
  {
    "path": "doc/examples/variables/PostgreSQL/input",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: authors; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.authors (\n    id integer NOT NULL,\n    first_name character varying(50) NOT NULL,\n    last_name character varying(50) NOT NULL,\n    email character varying(100) NOT NULL,\n    birthdate date NOT NULL,\n    added timestamp without time zone NOT NULL\n);\n\n\nALTER TABLE public.authors OWNER TO postgres;\n\n--\n-- Name: posts; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.posts (\n    id integer NOT NULL,\n    author_id integer NOT NULL,\n    title character varying(255) NOT NULL,\n    description character varying(500) NOT NULL,\n    content text NOT NULL,\n    date date NOT NULL\n);\n\n\nALTER TABLE public.posts OWNER TO postgres;\n\n--\n-- Data for Name: authors; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.authors (id, first_name, last_name, email, birthdate, added) FROM stdin;\n1\tWilford\tWintheiser\tbrett35@example.com\t1981-10-14\t1988-09-10 18:37:25\n2\tNyasia\tDoyle\taracely46@example.com\t2007-07-01\t1980-10-28 23:57:00\n3\tKen\tHaag\tcarroll.harris@example.com\t2003-04-16\t1997-03-14 18:41:06\n4\tLeonor\tMann\tjohns.janick@example.org\t1996-05-18\t2010-04-12 00:38:42\n5\tEloisa\tRatke\tlakin.ramiro@example.net\t1982-07-22\t1996-03-25 09:07:39\n6\tNikolas\tDibbert\tjudson33@example.com\t1970-02-22\t1979-03-16 10:10:12\n7\tKelley\tKoch\tkaci.koch@example.net\t2013-05-01\t2020-08-02 02:01:34\n8\tGlen\tHowe\tjprosacco@example.net\t1971-08-03\t1971-01-02 14:19:52\n9\tGeovanni\tMedhurst\tkutch.kylie@example.com\t2011-04-20\t2004-06-10 12:33:11\n10\tZella\tDavis\thane.terrill@example.org\t1991-11-07\t2007-09-19 13:48:20\n\\.\n\n\n--\n-- Data for Name: posts; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.posts (id, author_id, title, description, content, date) FROM stdin;\n1\t1\tPariatur est in ut provident vero eligendi.\tConsequatur quae odio in animi. Quis dolorem aut corporis sed ratione animi et. Iure sunt qui eligendi laudantium harum maxime id id. Quia eos beatae temporibus eos rerum ipsum.\tVelit voluptatibus quo est dolorem quos sed et. Illum similique atque et qui. Perspiciatis magnam saepe quis. Consequatur aut dolorem ea.\t1975-07-07\n2\t2\tUnde est architecto est.\tConsectetur quidem aut eligendi quas. Voluptas aut voluptas ratione reiciendis magnam sint. Ratione et omnis assumenda deserunt voluptatem perspiciatis. Non voluptates quia distinctio nam consectetur vel.\tSed sint at consectetur. Fugiat fugiat omnis debitis dolore. Incidunt vero incidunt enim reiciendis. Odio et illo facilis quo sit quia consequatur voluptatem.\t1976-05-25\n3\t3\tDignissimos perspiciatis nobis quisquam saepe ad aut numquam.\tVoluptatibus eum voluptas eveniet veniam ducimus. Modi id vitae est accusamus. Quaerat perferendis voluptas minima dignissimos et. Sapiente explicabo voluptas commodi voluptatem autem totam. Adipisci quos quos quo ea aliquid rerum.\tRepellat minus enim occaecati sunt quas. Ab ipsa voluptatibus sunt eos omnis quisquam at voluptatibus. Quo vitae doloremque nesciunt doloremque. Temporibus rerum sunt iste dolores rerum.\t1991-12-21\n4\t4\tVoluptas sint modi magnam.\tFacere harum pariatur quo eveniet dolor molestias. Quo debitis corporis quasi minima et optio. Ut maiores nihil rerum autem culpa et voluptates. Amet totam rem optio in. Provident ea repudiandae quisquam unde occaecati autem.\tSed quia assumenda quis rerum praesentium harum. Quia minima quo natus. Impedit temporibus perspiciatis et enim doloremque nihil et. Perspiciatis nam occaecati illo dicta asperiores eos nam.\t2002-01-23\n5\t5\tSapiente rem eos enim ullam ipsum ut.\tOfficia quos voluptas autem consequuntur. Quis consequatur aut vel dolor. Sapiente voluptatem quibusdam dolor nobis earum laboriosam quisquam.\tQuibusdam vel tempora explicabo qui. Sunt animi a unde veritatis perferendis similique nostrum vel. Porro ab ad cumque dolorum provident distinctio est ipsum. Esse maxime ea quia.\t2017-11-19\n6\t6\tError quas doloremque est sunt quae.\tCorporis quis in sint. Eos vitae aut provident distinctio ullam. Corporis mollitia quam natus qui sapiente officiis.\tIpsam animi aperiam ipsa fuga. Sunt blanditiis possimus aut quod. Doloremque possimus occaecati numquam omnis dolor. Qui nihil qui atque vitae sapiente illo id.\t1974-03-23\n7\t7\tQuo impedit quos molestiae dolorum in soluta dolores non.\tHarum quasi dolorum et harum iste eveniet et. Cumque ab recusandae architecto est ipsam est. Eligendi et earum ea alias odio sed ut.\tIllo earum porro corporis sunt aut. Vel quisquam ut voluptas reiciendis maiores cumque. Qui hic maiores voluptas sapiente reprehenderit. Eos non autem quis maiores perferendis.\t2004-12-08\n8\t8\tNulla quia repellendus et autem vitae provident.\tFacere deserunt suscipit quia et et totam vel at. Cumque suscipit est ea quis in quos. Harum dolorum consequuntur illum voluptatem iste enim recusandae.\tExcepturi hic tenetur sint nostrum. Nihil itaque repudiandae qui hic minima quis ut. Dolor et aut quaerat exercitationem minima ut. Blanditiis minus et qui dolor ut atque.\t1999-02-28\n9\t9\tSimilique at quia quia ut recusandae repudiandae delectus.\tEt necessitatibus aut accusantium quisquam harum est. Non quam id impedit deleniti. Eaque non architecto facere dolorem nesciunt perferendis. Delectus nihil ut dignissimos. Voluptate rerum reprehenderit aut voluptatem quibusdam quidem.\tTempore iusto minus omnis tempore. Hic aut sequi temporibus consequatur. In vel enim eos nihil sed eos debitis.\t2007-08-07\n10\t10\tEst vel aperiam ipsa quod doloremque et est et.\tFacere ut et similique voluptates voluptas blanditiis explicabo. Eaque molestiae nihil sed et repellat voluptatem eum autem.\tRem laudantium in aut assumenda. Aspernatur id illo pariatur aut deleniti rem et. Nisi velit neque qui quia.\t2009-07-18\n11\t1\tSint est qui dolorem eum accusantium repudiandae.\tQuia tenetur culpa maiores molestias. Id numquam illum earum quos sint ad dolore corrupti. Consequatur quasi itaque est odit qui quod culpa.\tOmnis tenetur occaecati accusamus quis corrupti et ipsam. Ullam nobis tempore officia nesciunt iste. Nesciunt vel in eos. Dolor voluptates quod sed quibusdam ut. Fuga quia eum quidem cum.\t2010-04-16\n12\t2\tCulpa debitis ut non sapiente voluptatem.\tCommodi fugit ullam quaerat quam quo minus. Harum quam ipsam ducimus sit expedita sit. Eos natus quo quibusdam quam repudiandae. Assumenda et sint sit quia qui necessitatibus.\tEum molestiae cupiditate ut minus. Eaque eos eos ipsam voluptatem. Sint aut aliquid modi id dolores consequatur. Aut nemo blanditiis nisi ea nam velit.\t1988-12-26\n13\t3\tUt ut rerum qui quis sed sunt.\tTenetur enim et nisi ex et consequatur omnis nisi. Eos deleniti aut amet illo sed quibusdam. Consequuntur sint quia quia aut magni.\tAut eveniet natus ut. Nostrum aliquid qui nam hic iusto id occaecati qui. Est dolor accusamus qui saepe voluptatem dolorem omnis.\t2001-06-01\n14\t4\tError inventore delectus sapiente non.\tAliquam ut aliquid et laboriosam distinctio ab. Tempore molestiae aut ea nesciunt culpa. Eum maiores molestiae voluptatem animi aliquam. Aspernatur aut soluta totam occaecati in nam ratione asperiores.\tVoluptatum id amet qui quia. Nemo nulla atque dignissimos.\t1974-12-07\n15\t5\tUt aut quo aut ea occaecati est voluptas.\tNon deleniti molestias velit ut eos veritatis. Et id eaque numquam ipsa iure ut. Molestiae et minus natus.\tNecessitatibus asperiores adipisci eaque. Alias sunt illum fugit ab labore laborum est odio. Aspernatur esse qui ut omnis autem. Laudantium quos corporis numquam sapiente enim.\t1999-09-12\n16\t6\tNihil ea qui sequi odit rem.\tOmnis ea accusantium qui commodi et ducimus. Magni deserunt sed quo velit. Hic cum tenetur facilis. Non eum quis molestias sunt. Illo saepe architecto doloremque illum sequi.\tNihil iste illum vitae ipsa et et. Reiciendis sint illum quo dignissimos veritatis. Velit eum architecto enim ratione aut.\t2003-07-28\n17\t7\tQuia accusantium deserunt suscipit.\tRepellat et molestiae magnam quaerat et iure. Enim enim cum quisquam quasi.\tMaiores officiis beatae hic hic dolor non officiis. Nulla beatae at aut fugit doloribus et provident. Debitis non dolores iusto impedit. Alias blanditiis velit voluptate et debitis.\t2015-05-24\n18\t8\tInventore et eaque temporibus qui aut exercitationem necessitatibus.\tOmnis molestias nemo culpa est dicta dolorem porro. Illum est ut ut molestias similique sit sunt. Consequatur asperiores quaerat voluptate incidunt.\tUnde quibusdam asperiores voluptates quaerat et aliquam. Libero at est quibusdam eos aut. Aut voluptatem tempora a nam.\t1996-02-06\n19\t9\tEt soluta consequatur porro rem corrupti.\tUllam doloremque explicabo ea ab quam ipsum. Et qui iure vero tempore voluptate aut. Ullam id ab accusamus optio voluptas. Quia quaerat quibusdam aut accusantium impedit et.\tPerspiciatis sed dolores aut. Animi sed totam exercitationem fugiat dolores. Ipsa dolorem quia non aliquam. Rerum exercitationem voluptatem dolor beatae veritatis quasi omnis consectetur.\t2018-03-31\n20\t10\tCulpa error rerum voluptatem recusandae quae tempora.\tEst ullam tempore autem et. Dolorum est eius eaque veniam in quibusdam neque. Ut aspernatur earum sint delectus voluptate deserunt sapiente quia.\tEnim quos facere rerum ipsa. Eveniet expedita id eligendi voluptatem magnam quo eos.\t2007-01-22\n21\t1\tHarum laudantium fugiat debitis atque sed.\tEt asperiores magni qui voluptas a consequatur totam. Inventore enim quaerat consequatur sint quam voluptatibus optio. Est aut repellendus repudiandae reiciendis eveniet veniam. Minima a corrupti non quae.\tVoluptate officia ut debitis explicabo corrupti facere reprehenderit. Enim id recusandae vitae est dolores. Aperiam consequuntur ex beatae et alias quia.\t1987-06-29\n22\t2\tNon architecto ut voluptas aut voluptas dolor ut.\tDolore delectus optio fuga aut labore necessitatibus. Laborum quis nulla deserunt. Aut corporis repellendus inventore vel.\tFacilis soluta ab culpa est. Aut pariatur et dicta sit. Sed qui est numquam est.\\nAtque ex sit eveniet. Iure accusamus optio placeat voluptate non sit ea. Sint dignissimos dolorum debitis ipsam neque.\t1993-05-06\n23\t3\tDolores sed hic vitae ut qui.\tLibero illum dolorum est eaque ut. Nesciunt qui vitae recusandae eveniet saepe et ut. Aliquid enim vitae beatae animi quam doloribus accusamus. Eos eos excepturi accusamus ut recusandae.\tDistinctio molestiae sint qui. Expedita qui ex dignissimos architecto quo sapiente alias eveniet. Laborum qui aut est doloribus a beatae. Unde adipisci consequuntur et tenetur.\t1978-09-08\n24\t4\tDeleniti distinctio eos eveniet.\tEx aperiam animi quis excepturi. Velit qui molestias iste iure voluptatem. Eveniet adipisci quasi amet. Soluta laborum aperiam magni.\tDeserunt dolores ut ut ex cum. Quae iusto rerum voluptatum aperiam. Vel voluptatem ut nesciunt delectus blanditiis. Sequi consequuntur temporibus sunt dolores repudiandae.\t2003-06-23\n25\t5\tEa et asperiores odio vel sunt exercitationem.\tQuod necessitatibus quis sit aspernatur a. Molestias laudantium voluptatibus quaerat rerum cupiditate. Aut consectetur quia doloribus repellat porro est.\tEt alias soluta aliquam qui aut. Explicabo quo consequuntur consequuntur velit distinctio.\t1972-09-16\n26\t6\tAccusamus est sed aut minus.\tEt libero in in est consequuntur. Illum distinctio doloremque quas.\tNeque vel tenetur libero sed aut voluptas. Itaque quod et laudantium magnam tempora qui non. Et sapiente dolores reiciendis sit ab fugiat sed sequi. Reiciendis maxime qui aut laborum dolor.\t2017-03-08\n27\t7\tEt sed reprehenderit nobis sed.\tTotam amet nisi id quod. Laudantium maxime rem velit consequuntur amet. Et enim eum aspernatur totam. Nulla consequatur similique maxime et qui rerum.\tIure sequi unde consectetur neque in magni. Illo ipsa commodi quae placeat modi numquam numquam. Quae culpa sit distinctio vitae est.\t1973-08-04\n28\t8\tAutem ullam aperiam totam assumenda quod esse.\tAut incidunt aspernatur aut sapiente ipsum repellat. Molestiae eaque accusantium maxime. Velit modi ea consectetur natus ea.\tMolestias voluptatum cupiditate et minus qui consequuntur. Reprehenderit aut at corrupti. Eius unde ullam aut cum eius molestiae.\t2014-04-26\n29\t9\tAd dolores amet ea nisi aut enim voluptatem.\tEum voluptates sunt occaecati molestiae. Cupiditate labore expedita eius in omnis non. Sit cumque unde cupiditate sequi eius reprehenderit nulla.\tVoluptates modi esse quas sit eos praesentium. Quas et rem vero quo veritatis voluptas. Inventore dolorem ut praesentium consequatur rem. Amet ipsam quia officia iste est in.\t2006-09-07\n30\t10\tEos fuga at ex sapiente quasi.\tFacere dolores non omnis facilis. Nam cupiditate maiores iure quia adipisci numquam magnam. Esse voluptas voluptatem cum ea voluptas doloremque.\tVoluptatem qui qui magnam quis eos. Consequatur ut repudiandae libero dignissimos et quia velit. Eum nisi facere consequatur quod ut. Ad molestiae voluptatem eaque iste et.\t2009-07-23\n\\.\n\n\n--\n-- Name: authors authors_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.authors\n    ADD CONSTRAINT authors_pkey PRIMARY KEY (id);\n\n\n--\n-- Name: posts posts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.posts\n    ADD CONSTRAINT posts_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "doc/examples/variables/PostgreSQL/nxs-data-anonymizer.conf",
    "content": "variables:\n  first_name:\n    value: \"John\"\n  last_name:\n    value: \"Smith\"\n  email:\n    value: \"JohnSmith@example.com\"\n  birthdate:\n    value: \"1999-12-31\" \n  added:\n    value: \"2000-01-01 12:00:00\"\n  author_id:\n    value: \"1\"\n  title:\n    value: \"anont_title\"\n  description:\n    value: \"anon_description\"\n  content:\n    value: \"anon_content\"\n  date:\n    value: \"2001-01-01 12:00:00\"\n\nfilters:\n  public.authors:\n    columns:\n      first_name:\n        value: \"{{ .Variables.first_name }}\"\n      last_name:\n        value: \"{{ .Variables.last_name }}\"\n      email:\n        value: \"{{ .Variables.email }}\"\n      birthdate:\n        value: \"{{ .Variables.birthdate }}\"\n      added:\n        value: \"{{ .Variables.added }}\"\n  public.posts:\n    columns:\n      author_id:\n        value: \"{{ .Variables.author_id }}\"\n      title:\n        value: \"{{ .Variables.title }}\"\n      description:\n        value: \"{{ .Variables.description }}\"\n      content:\n        value: \"{{ .Variables.content }}\"\n      date:\n        value: \"{{ .Variables.date }}\""
  },
  {
    "path": "doc/examples/variables/PostgreSQL/output",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: authors; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.authors (\n    id integer NOT NULL,\n    first_name character varying(50) NOT NULL,\n    last_name character varying(50) NOT NULL,\n    email character varying(100) NOT NULL,\n    birthdate date NOT NULL,\n    added timestamp without time zone NOT NULL\n);\n\n\nALTER TABLE public.authors OWNER TO postgres;\n\n--\n-- Name: posts; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.posts (\n    id integer NOT NULL,\n    author_id integer NOT NULL,\n    title character varying(255) NOT NULL,\n    description character varying(500) NOT NULL,\n    content text NOT NULL,\n    date date NOT NULL\n);\n\n\nALTER TABLE public.posts OWNER TO postgres;\n\n--\n-- Data for Name: authors; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.authors (id, first_name, last_name, email, birthdate, added) FROM stdin;\n1\tJohn\tSmith\tJohnSmith@example.com\t1999-12-31\t2000-01-01 12:00:00\n2\tJohn\tSmith\tJohnSmith@example.com\t1999-12-31\t2000-01-01 12:00:00\n3\tJohn\tSmith\tJohnSmith@example.com\t1999-12-31\t2000-01-01 12:00:00\n4\tJohn\tSmith\tJohnSmith@example.com\t1999-12-31\t2000-01-01 12:00:00\n5\tJohn\tSmith\tJohnSmith@example.com\t1999-12-31\t2000-01-01 12:00:00\n6\tJohn\tSmith\tJohnSmith@example.com\t1999-12-31\t2000-01-01 12:00:00\n7\tJohn\tSmith\tJohnSmith@example.com\t1999-12-31\t2000-01-01 12:00:00\n8\tJohn\tSmith\tJohnSmith@example.com\t1999-12-31\t2000-01-01 12:00:00\n9\tJohn\tSmith\tJohnSmith@example.com\t1999-12-31\t2000-01-01 12:00:00\n10\tJohn\tSmith\tJohnSmith@example.com\t1999-12-31\t2000-01-01 12:00:00\n\\.\n\n\n--\n-- Data for Name: posts; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.posts (id, author_id, title, description, content, date) FROM stdin;\n1\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n2\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n3\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n4\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n5\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n6\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n7\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n8\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n9\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n10\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n11\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n12\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n13\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n14\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n15\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n16\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n17\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n18\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n19\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n20\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n21\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n22\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n23\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n24\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n25\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n26\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n27\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n28\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n29\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n30\t1\tanont_title\tanon_description\tanon_content\t2001-01-01 12:00:00\n\\.\n\n\n--\n-- Name: authors authors_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.authors\n    ADD CONSTRAINT authors_pkey PRIMARY KEY (id);\n\n\n--\n-- Name: posts posts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.posts\n    ADD CONSTRAINT posts_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "doc/examples/variables/Readme.md",
    "content": "# Example `variables`\n\nAn example of using nxs-data-anonymizer in a simple configuration with filters and variables blocks.\n\nIn order to use variables in the \"filters\" block, you need to describe the \"variables\" block:\n```yaml\nvariables:\n  some_variable: # Variable name\n    value: \"some_value\" # Variable value\n```\n\nIf you use a function to generate a value, then in this block it will be executed once and the resulting value will be the same for all its occurrences in the dump.\n\nAn example of a configuration:\n```yaml\nvariables:\n  var1:\n    value: \"<fixed_value_or_generation_function_of_value>\"\n  var2:\n    value: \"<fixed_value_or_generation_function_of_value>\"\n  var3:\n    value: \"<fixed_value_or_generation_function_of_value>\"\n\nfilters:\n  table1:\n    columns:\n      table1_col1:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n      table1_col2:\n        value: \"{{ .Variables.var1 }}\"\n      table1_col3:\n        value: \"{{ .Variables.var2 }}\"\n  table2:\n    columns:\n      table2_col1:\n        value: \"<fixed_value_or_generation_function_of_value>\"\n      table2_col2:\n        value: \"{{ .Variables.var1 }}\"\n      table2_col3:\n        value: \"{{ .Variables.var3 }}\"\n```\n\nWorking examples of configurations in the `./MySQL` and `./PostgreSQL` directories."
  },
  {
    "path": "ds/mysql/mysql.go",
    "content": "package mysql\n\nimport (\n\t\"fmt\"\n\n\tgmysql \"gorm.io/driver/mysql\"\n\t\"gorm.io/gorm\"\n)\n\ntype MySQL struct {\n\tclient *gorm.DB\n}\n\ntype Settings struct {\n\tHost     string\n\tPort     int\n\tUser     string\n\tPassword string\n\tDatabase string\n}\n\nfunc Connect(s Settings) (MySQL, error) {\n\n\tclient, err := gorm.Open(gmysql.Open(fmt.Sprintf(\"%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local\",\n\t\ts.User,\n\t\ts.Password,\n\t\ts.Host,\n\t\ts.Port,\n\t\ts.Database)), &gorm.Config{})\n\tif err != nil {\n\t\treturn MySQL{}, err\n\t}\n\n\treturn MySQL{\n\t\tclient: client,\n\t}, nil\n}\n\nfunc (m *MySQL) Close() error {\n\tdb, _ := m.client.DB()\n\treturn db.Close()\n}\n\nfunc (m *MySQL) DBCleanup() error {\n\n\ttables, err := m.client.Migrator().GetTables()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"drop tables, get tables: %w\", err)\n\t}\n\n\tfor _, t := range tables {\n\t\tif err := m.client.Migrator().DropTable(t); err != nil {\n\t\t\treturn fmt.Errorf(\"drop tables, table `%s`: %w\", t, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/nixys/nxs-data-anonymizer\n\ngo 1.21.1\n\nrequire (\n\tgithub.com/Masterminds/sprig/v3 v3.2.3\n\tgithub.com/docker/go-units v0.5.0\n\tgithub.com/go-sql-driver/mysql v1.7.1\n\tgithub.com/nixys/nxs-go-appctx/v3 v3.0.0\n\tgithub.com/nixys/nxs-go-conf v1.1.0\n\tgithub.com/nixys/nxs-go-fsm v1.0.0\n\tgithub.com/pborman/getopt/v2 v2.1.0\n\tgithub.com/sirupsen/logrus v1.9.3\n\tgorm.io/driver/mysql v1.5.1\n\tgorm.io/gorm v1.25.2\n)\n\nrequire (\n\tgithub.com/Masterminds/goutils v1.1.1 // indirect\n\tgithub.com/Masterminds/semver/v3 v3.2.1 // indirect\n\tgithub.com/cskr/pubsub v1.0.2 // indirect\n\tgithub.com/google/uuid v1.3.0 // indirect\n\tgithub.com/huandu/xstrings v1.4.0 // indirect\n\tgithub.com/imdario/mergo v0.3.16 // indirect\n\tgithub.com/jinzhu/inflection v1.0.0 // indirect\n\tgithub.com/jinzhu/now v1.1.5 // indirect\n\tgithub.com/mitchellh/copystructure v1.2.0 // indirect\n\tgithub.com/mitchellh/mapstructure v1.1.2 // indirect\n\tgithub.com/mitchellh/reflectwalk v1.0.2 // indirect\n\tgithub.com/shopspring/decimal v1.3.1 // indirect\n\tgithub.com/spf13/cast v1.5.1 // indirect\n\tgithub.com/stretchr/testify v1.8.0 // indirect\n\tgolang.org/x/crypto v0.11.0 // indirect\n\tgolang.org/x/sys v0.10.0 // indirect\n\tgopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect\n\tgopkg.in/yaml.v2 v2.4.0 // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=\ngithub.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=\ngithub.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=\ngithub.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=\ngithub.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=\ngithub.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=\ngithub.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=\ngithub.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0=\ngithub.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=\ngithub.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=\ngithub.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=\ngithub.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=\ngithub.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=\ngithub.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=\ngithub.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=\ngithub.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=\ngithub.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=\ngithub.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=\ngithub.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=\ngithub.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=\ngithub.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=\ngithub.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=\ngithub.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=\ngithub.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=\ngithub.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=\ngithub.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=\ngithub.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=\ngithub.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=\ngithub.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=\ngithub.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=\ngithub.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=\ngithub.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=\ngithub.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=\ngithub.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=\ngithub.com/nixys/nxs-go-appctx/v3 v3.0.0 h1:Uib9UpNVrAy2AArPfNo3LwV+269Sj1PrZqAYuZt+KGY=\ngithub.com/nixys/nxs-go-appctx/v3 v3.0.0/go.mod h1:+1l3Gjr1FW/rhmYXi7GaftFu0N6H6o8L13/fQUzhPIE=\ngithub.com/nixys/nxs-go-conf v1.1.0 h1:FGm9D/1gpFcfRIdvfrsup9if5PvyQxc/VhE/85+n5BQ=\ngithub.com/nixys/nxs-go-conf v1.1.0/go.mod h1:m2zxhmA7YfWdFdmTQZSqP0+C16oRUztfXss+yhbScgY=\ngithub.com/nixys/nxs-go-fsm v1.0.0 h1:BGxlFdzMSaqkaW3Q3Iikl1VkeyZ3L7idnQWbGMDOWW0=\ngithub.com/nixys/nxs-go-fsm v1.0.0/go.mod h1:di5WCie2YX6tL2262v/sq67lj49MVovw+A1WM++f4gI=\ngithub.com/pborman/getopt/v2 v2.1.0 h1:eNfR+r+dWLdWmV8g5OlpyrTYHkhVNxHBdN2cCrJmOEA=\ngithub.com/pborman/getopt/v2 v2.1.0/go.mod h1:4NtW75ny4eBw9fO1bhtNdYTlZKYX5/tBLtsOpwKIKd0=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=\ngithub.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=\ngithub.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=\ngithub.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=\ngithub.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=\ngithub.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=\ngithub.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=\ngithub.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=\ngithub.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=\ngithub.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=\ngolang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=\ngolang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=\ngolang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=\ngolang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=\ngolang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=\ngolang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=\ngolang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=\ngopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=\ngorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=\ngorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=\ngorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=\ngorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=\n"
  },
  {
    "path": "interfaces/anonymizer.go",
    "content": "package interfaces\n\nimport (\n\t\"context\"\n\t\"io\"\n)\n\ntype Anonymizer interface {\n\tRun(context.Context, io.Writer) error\n}\n"
  },
  {
    "path": "main.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"syscall\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/ctx\"\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n\t\"github.com/nixys/nxs-data-anonymizer/routines/anonymizer\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n\tappctx \"github.com/nixys/nxs-go-appctx/v3\"\n)\n\nfunc main() {\n\n\terr := appctx.Init(context.Background()).\n\t\tRoutinesSet(\n\t\t\tmap[string]appctx.RoutineParam{\n\t\t\t\t\"anonymizer\": {\n\t\t\t\t\tHandler: anonymizer.Runtime,\n\t\t\t\t},\n\t\t\t},\n\t\t).\n\t\tValueInitHandlerSet(ctx.AppCtxInit).\n\t\tSignalsSet([]appctx.SignalsParam{\n\t\t\t{\n\t\t\t\tSignals: []os.Signal{\n\t\t\t\t\tsyscall.SIGTERM,\n\t\t\t\t},\n\t\t\t\tHandler: sigHandlerTerm,\n\t\t\t},\n\t\t}).\n\t\tRun()\n\tif err != nil {\n\t\tswitch err {\n\t\tcase misc.ErrArgSuccessExit:\n\t\t\tos.Exit(0)\n\t\tdefault:\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n}\n\nfunc sigHandlerTerm(sig appctx.Signal) {\n\tsig.Shutdown(nil)\n}\n"
  },
  {
    "path": "misc/errors.go",
    "content": "package misc\n\nimport \"errors\"\n\nvar (\n\tErrNotFound       = errors.New(\"entity not found\")\n\tErrIDEmpty        = errors.New(\"empty id\")\n\tErrUsernameEmpty  = errors.New(\"empty username\")\n\tErrConig          = errors.New(\"incorrect config\")\n\tErrArgSuccessExit = errors.New(\"arg success exit\")\n\tErrRuntime        = errors.New(\"runtime error\")\n)\n"
  },
  {
    "path": "misc/security.go",
    "content": "package misc\n\ntype SecurityPolicyTablesType string\n\nconst (\n\tSecurityPolicyTablesUnknown SecurityPolicyTablesType = \"unknown\"\n\tSecurityPolicyTablesPass    SecurityPolicyTablesType = \"pass\"\n\tSecurityPolicyTablesSkip    SecurityPolicyTablesType = \"skip\"\n)\n\nfunc (v SecurityPolicyTablesType) String() string {\n\treturn string(v)\n}\n\nfunc SecurityPolicyTablesTypeFromString(v string) SecurityPolicyTablesType {\n\tswitch v {\n\tcase string(SecurityPolicyTablesPass):\n\t\treturn SecurityPolicyTablesPass\n\tcase string(SecurityPolicyTablesSkip):\n\t\treturn SecurityPolicyTablesSkip\n\tdefault:\n\t\treturn SecurityPolicyTablesUnknown\n\t}\n}\n\ntype SecurityPolicyColumnsType string\n\nconst (\n\tSecurityPolicyColumnsUnknown   SecurityPolicyColumnsType = \"unknown\"\n\tSecurityPolicyColumnsPass      SecurityPolicyColumnsType = \"pass\"\n\tSecurityPolicyColumnsRandomize SecurityPolicyColumnsType = \"randomize\"\n)\n\nfunc (v SecurityPolicyColumnsType) String() string {\n\treturn string(v)\n}\n\nfunc SecurityPolicyColumnsTypeFromString(v string) SecurityPolicyColumnsType {\n\tswitch v {\n\tcase string(SecurityPolicyColumnsPass):\n\t\treturn SecurityPolicyColumnsPass\n\tcase string(SecurityPolicyColumnsRandomize):\n\t\treturn SecurityPolicyColumnsRandomize\n\tdefault:\n\t\treturn SecurityPolicyColumnsUnknown\n\t}\n}\n"
  },
  {
    "path": "misc/template.go",
    "content": "package misc\n\nimport (\n\t\"bytes\"\n\tttemplate \"text/template\"\n\n\t\"github.com/Masterminds/sprig/v3\"\n)\n\nvar (\n\tTemplateNULL = \"::NULL::\"\n\tTemplateDrop = \"::DROP::\"\n)\n\ntype TemlateRes struct {\n\tValue   string\n\tDropRow bool\n}\n\n// TemplateExec makes message from given template `tpl` and data `d`\nfunc TemplateExec(tpl string, d any) (TemlateRes, error) {\n\n\tvar b bytes.Buffer\n\n\t// See http://masterminds.github.io/sprig/ for details\n\tt, err := ttemplate.New(\"template\").Funcs(func() ttemplate.FuncMap {\n\n\t\t// Get current sprig functions\n\t\tt := sprig.TxtFuncMap()\n\n\t\t// Add additional functions\n\t\tt[\"null\"] = func() string {\n\t\t\treturn TemplateNULL\n\t\t}\n\t\tt[\"isNull\"] = func(v string) bool {\n\t\t\tif v == TemplateNULL {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t\tt[\"drop\"] = func() string {\n\t\t\treturn TemplateDrop\n\t\t}\n\n\t\treturn t\n\t}()).Parse(tpl)\n\tif err != nil {\n\t\treturn TemlateRes{}, err\n\t}\n\n\terr = t.Execute(&b, d)\n\tif err != nil {\n\t\treturn TemlateRes{}, err\n\t}\n\n\t// Return empty line if buffer is nil\n\tif b.Bytes() == nil {\n\t\treturn TemlateRes{\n\t\t\t\tValue:   \"\",\n\t\t\t\tDropRow: false,\n\t\t\t},\n\t\t\tnil\n\t}\n\n\t// Return `drop` value if buffer is DROP (with special key)\n\tif bytes.Equal(b.Bytes(), []byte(TemplateDrop)) {\n\t\treturn TemlateRes{\n\t\t\t\tValue:   \"\",\n\t\t\t\tDropRow: true,\n\t\t\t},\n\t\t\tnil\n\t}\n\n\t// Return buffer content otherwise\n\treturn TemlateRes{\n\t\t\tValue:   b.String(),\n\t\t\tDropRow: false,\n\t\t},\n\t\tnil\n}\n"
  },
  {
    "path": "misc/token.go",
    "content": "package misc\n\nimport (\n\t\"math/rand\"\n\t\"time\"\n)\n\n// TokenGen generates token string\nfunc TokenGen(tokenLen int64) string {\n\n\tvar chars = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\")\n\n\trand.Seed(time.Now().UnixNano())\n\n\tb := make([]rune, tokenLen)\n\n\tfor i := range b {\n\t\tb[i] = chars[rand.Intn(len(chars))]\n\t}\n\n\treturn string(b)\n}\n"
  },
  {
    "path": "misc/values.go",
    "content": "package misc\n\ntype ValueType string\n\nconst (\n\tValueTypeUnknown  ValueType = \"unkonwn\"\n\tValueTypeTemplate ValueType = \"template\"\n\tValueTypeCommand  ValueType = \"command\"\n)\n\nfunc ValueTypeFromString(v string) ValueType {\n\tswitch v {\n\tcase string(ValueTypeTemplate):\n\t\treturn ValueTypeTemplate\n\tcase string(ValueTypeCommand):\n\t\treturn ValueTypeCommand\n\tdefault:\n\t\treturn ValueTypeUnknown\n\t}\n}\n\nfunc (v ValueType) String() string {\n\treturn string(v)\n}\n"
  },
  {
    "path": "modules/anonymizers/mysql/.testdata/mysql_test.dos.in.sql",
    "content": "-- MariaDB dump 10.19  Distrib 10.6.12-MariaDB, for debian-linux-gnu (x86_64)\r\n--\r\n-- Host: 127.0.0.1    Database: db\r\n-- ------------------------------------------------------\r\n-- Server version\t8.0.32\r\n\r\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\r\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\r\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\r\n/*!40101 SET NAMES utf8mb4 */;\r\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\r\n/*!40103 SET TIME_ZONE='+00:00' */;\r\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\r\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\r\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\r\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\r\n\r\n--\r\n-- Table structure for table `table1`\r\n--\r\n\r\nDROP TABLE IF EXISTS `table1`;\r\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\r\n/*!40101 SET character_set_client = utf8 */;\r\nCREATE TABLE `table1` (\r\n  `id` int NOT NULL AUTO_INCREMENT,\r\n  `name` varchar(50) NOT NULL,\r\n  `url` varchar(255) NOT NULL,\r\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\r\n  `auth_data` text NOT NULL,\r\n  `username` varchar(20) NOT NULL DEFAULT '',\r\n  `password` varchar(20) NOT NULL DEFAULT '',\r\n  PRIMARY KEY (`id`),\r\n  UNIQUE KEY `id` (`id`)\r\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\r\n/*!40101 SET character_set_client = @saved_cs_client */;\r\n\r\n--\r\n-- Dumping data for table `table1`\r\n--\r\n\r\nLOCK TABLES `table1` WRITE;\r\n/*!40000 ALTER TABLE `table1` DISABLE KEYS */;\r\nINSERT INTO `table1` VALUES (1,'test4','https://github.com/nixys/nxs-rbac-operator0.git','none','','',''),(2,'test5','https://github.com/nixys/nxs-rbac-operator.git','none','','',''),(3,'test6','https://github.com/nixys/nxs-rbac-operator2.git','none','','','');\r\n/*!40000 ALTER TABLE `table1` ENABLE KEYS */;\r\nUNLOCK TABLES;\r\n\r\n--\r\n-- Table structure for table `table2`\r\n--\r\n\r\nDROP TABLE IF EXISTS `table2`;\r\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\r\n/*!40101 SET character_set_client = utf8 */;\r\nCREATE TABLE `table2` (\r\n  `id` int NOT NULL AUTO_INCREMENT,\r\n  `name` varchar(50) NOT NULL,\r\n  `url` varchar(255) NOT NULL,\r\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\r\n  `auth_data` text NOT NULL,\r\n  `username` varchar(20) NOT NULL DEFAULT '',\r\n  `password` varchar(20) NOT NULL DEFAULT '',\r\n  PRIMARY KEY (`id`),\r\n  UNIQUE KEY `id` (`id`)\r\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\r\n/*!40101 SET character_set_client = @saved_cs_client */;\r\n\r\n--\r\n-- Dumping data for table `table2`\r\n--\r\n\r\nLOCK TABLES `table2` WRITE;\r\n/*!40000 ALTER TABLE `table2` DISABLE KEYS */;\r\nINSERT INTO `table2` VALUES (1,'test4','https://github.com/nixys/nxs-rbac-operator0.git','none','','',''),(2,'test5','https://github.com/nixys/nxs-rbac-operator.git','none','','',''),(3,'test6','https://github.com/nixys/nxs-rbac-operator2.git','none','','','');\r\n/*!40000 ALTER TABLE `table2` ENABLE KEYS */;\r\nUNLOCK TABLES;\r\n\r\n--\r\n-- Table structure for table `table3`\r\n--\r\n\r\nDROP TABLE IF EXISTS `table3`;\r\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\r\n/*!40101 SET character_set_client = utf8 */;\r\nCREATE TABLE `table3` (\r\n  `id` int NOT NULL AUTO_INCREMENT,\r\n  `name` varchar(50) NOT NULL,\r\n  `url` varchar(255) NOT NULL,\r\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\r\n  `auth_data` text NOT NULL,\r\n  `username` varchar(20) NOT NULL DEFAULT '',\r\n  `password` varchar(20) NOT NULL DEFAULT '',\r\n  PRIMARY KEY (`id`),\r\n  UNIQUE KEY `id` (`id`)\r\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\r\n/*!40101 SET character_set_client = @saved_cs_client */;\r\n\r\n--\r\n-- Dumping data for table `table3`\r\n--\r\n\r\nLOCK TABLES `table3` WRITE;\r\n/*!40000 ALTER TABLE `table3` DISABLE KEYS */;\r\nINSERT INTO `table3` VALUES (1,'test4','https://github.com/nixys/nxs-rbac-operator0.git','none','','',''),(2,'test5','https://github.com/nixys/nxs-rbac-operator.git','none','','',''),(3,'test6','https://github.com/nixys/nxs-rbac-operator2.git','none','','','');\r\n/*!40000 ALTER TABLE `table3` ENABLE KEYS */;\r\nUNLOCK TABLES;"
  },
  {
    "path": "modules/anonymizers/mysql/.testdata/mysql_test.dos.out.sql",
    "content": "-- MariaDB dump 10.19  Distrib 10.6.12-MariaDB, for debian-linux-gnu (x86_64)\r\n--\r\n-- Host: 127.0.0.1    Database: db\r\n-- ------------------------------------------------------\r\n-- Server version\t8.0.32\r\n\r\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\r\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\r\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\r\n/*!40101 SET NAMES utf8mb4 */;\r\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\r\n/*!40103 SET TIME_ZONE='+00:00' */;\r\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\r\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\r\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\r\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\r\n\r\n--\r\n-- Table structure for table `table1`\r\n--\r\n\r\nDROP TABLE IF EXISTS `table1`;\r\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\r\n/*!40101 SET character_set_client = utf8 */;\r\nCREATE TABLE `table1` (\r\n  `id` int NOT NULL AUTO_INCREMENT,\r\n  `name` varchar(50) NOT NULL,\r\n  `url` varchar(255) NOT NULL,\r\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\r\n  `auth_data` text NOT NULL,\r\n  `username` varchar(20) NOT NULL DEFAULT '',\r\n  `password` varchar(20) NOT NULL DEFAULT '',\r\n  PRIMARY KEY (`id`),\r\n  UNIQUE KEY `id` (`id`)\r\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\r\n/*!40101 SET character_set_client = @saved_cs_client */;\r\n\r\n--\r\n-- Dumping data for table `table1`\r\n--\r\n\r\nLOCK TABLES `table1` WRITE;\r\n/*!40000 ALTER TABLE `table1` DISABLE KEYS */;\r\nINSERT INTO `table1` VALUES (1,'test4','https://github.com/nixys/nxs-rbac-operator0.git','none','','',''),(3,'test6','https://github.com/nixys/nxs-rbac-operator2.git','none','','','');\r\n/*!40000 ALTER TABLE `table1` ENABLE KEYS */;\r\nUNLOCK TABLES;\r\n\r\n--\r\n-- Table structure for table `table2`\r\n--\r\n\r\nDROP TABLE IF EXISTS `table2`;\r\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\r\n/*!40101 SET character_set_client = utf8 */;\r\nCREATE TABLE `table2` (\r\n  `id` int NOT NULL AUTO_INCREMENT,\r\n  `name` varchar(50) NOT NULL,\r\n  `url` varchar(255) NOT NULL,\r\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\r\n  `auth_data` text NOT NULL,\r\n  `username` varchar(20) NOT NULL DEFAULT '',\r\n  `password` varchar(20) NOT NULL DEFAULT '',\r\n  PRIMARY KEY (`id`),\r\n  UNIQUE KEY `id` (`id`)\r\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\r\n/*!40101 SET character_set_client = @saved_cs_client */;\r\n\r\n--\r\n-- Dumping data for table `table2`\r\n--\r\n\r\nLOCK TABLES `table2` WRITE;\r\n/*!40000 ALTER TABLE `table2` DISABLE KEYS */;\r\n\r\n/*!40000 ALTER TABLE `table2` ENABLE KEYS */;\r\nUNLOCK TABLES;\r\n\r\n--\r\n-- Table structure for table `table3`\r\n--\r\n\r\nDROP TABLE IF EXISTS `table3`;\r\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\r\n/*!40101 SET character_set_client = utf8 */;\r\nCREATE TABLE `table3` (\r\n  `id` int NOT NULL AUTO_INCREMENT,\r\n  `name` varchar(50) NOT NULL,\r\n  `url` varchar(255) NOT NULL,\r\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\r\n  `auth_data` text NOT NULL,\r\n  `username` varchar(20) NOT NULL DEFAULT '',\r\n  `password` varchar(20) NOT NULL DEFAULT '',\r\n  PRIMARY KEY (`id`),\r\n  UNIQUE KEY `id` (`id`)\r\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\r\n/*!40101 SET character_set_client = @saved_cs_client */;\r\n\r\n--\r\n-- Dumping data for table `table3`\r\n--\r\n\r\nLOCK TABLES `table3` WRITE;\r\n/*!40000 ALTER TABLE `table3` DISABLE KEYS */;\r\nINSERT INTO `table3` VALUES (1,'test4','https://github.com/nixys/nxs-rbac-operator0.git','none','','',''),(2,'test5','https://github.com/nixys/nxs-rbac-operator.git','none','','',''),(3,'test6','https://github.com/nixys/nxs-rbac-operator2.git','none','','','');\r\n/*!40000 ALTER TABLE `table3` ENABLE KEYS */;\r\nUNLOCK TABLES;"
  },
  {
    "path": "modules/anonymizers/mysql/.testdata/mysql_test.in.sql",
    "content": "-- MariaDB dump 10.19  Distrib 10.6.12-MariaDB, for debian-linux-gnu (x86_64)\n--\n-- Host: 127.0.0.1    Database: db\n-- ------------------------------------------------------\n-- Server version\t8.0.32\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!40101 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `table1`\n--\n\nDROP TABLE IF EXISTS `table1`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `table1` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `name` varchar(50) NOT NULL,\n  `url` varchar(255) NOT NULL,\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\n  `auth_data` text NOT NULL,\n  `username` varchar(20) NOT NULL DEFAULT '',\n  `password` varchar(20) NOT NULL DEFAULT '',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `id` (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `table1`\n--\n\nLOCK TABLES `table1` WRITE;\n/*!40000 ALTER TABLE `table1` DISABLE KEYS */;\nINSERT INTO `table1` VALUES (1,'test4','https://github.com/nixys/nxs-rbac-operator0.git','none','','',''),(2,'test5','https://github.com/nixys/nxs-rbac-operator.git','none','','',''),(3,'test6','https://github.com/nixys/nxs-rbac-operator2.git','none','','','');\n/*!40000 ALTER TABLE `table1` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `table2`\n--\n\nDROP TABLE IF EXISTS `table2`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `table2` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `name` varchar(50) NOT NULL,\n  `url` varchar(255) NOT NULL,\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\n  `auth_data` text NOT NULL,\n  `username` varchar(20) NOT NULL DEFAULT '',\n  `password` varchar(20) NOT NULL DEFAULT '',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `id` (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `table2`\n--\n\nLOCK TABLES `table2` WRITE;\n/*!40000 ALTER TABLE `table2` DISABLE KEYS */;\nINSERT INTO `table2` VALUES (1,'test4','https://github.com/nixys/nxs-rbac-operator0.git','none','','',''),(2,'test5','https://github.com/nixys/nxs-rbac-operator.git','none','','',''),(3,'test6','https://github.com/nixys/nxs-rbac-operator2.git','none','','','');\n/*!40000 ALTER TABLE `table2` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `table3`\n--\n\nDROP TABLE IF EXISTS `table3`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `table3` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `name` varchar(50) NOT NULL,\n  `url` varchar(255) NOT NULL,\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\n  `auth_data` text NOT NULL,\n  `username` varchar(20) NOT NULL DEFAULT '',\n  `password` varchar(20) NOT NULL DEFAULT '',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `id` (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `table3`\n--\n\nLOCK TABLES `table3` WRITE;\n/*!40000 ALTER TABLE `table3` DISABLE KEYS */;\nINSERT INTO `table3` VALUES (1,'test4','https://github.com/nixys/nxs-rbac-operator0.git','none','','',''),(2,'test5','https://github.com/nixys/nxs-rbac-operator.git','none','','',''),(3,'test6','https://github.com/nixys/nxs-rbac-operator2.git','none','','','');\n/*!40000 ALTER TABLE `table3` ENABLE KEYS */;\nUNLOCK TABLES;"
  },
  {
    "path": "modules/anonymizers/mysql/.testdata/mysql_test.out.sql",
    "content": "-- MariaDB dump 10.19  Distrib 10.6.12-MariaDB, for debian-linux-gnu (x86_64)\n--\n-- Host: 127.0.0.1    Database: db\n-- ------------------------------------------------------\n-- Server version\t8.0.32\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!40101 SET NAMES utf8mb4 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `table1`\n--\n\nDROP TABLE IF EXISTS `table1`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `table1` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `name` varchar(50) NOT NULL,\n  `url` varchar(255) NOT NULL,\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\n  `auth_data` text NOT NULL,\n  `username` varchar(20) NOT NULL DEFAULT '',\n  `password` varchar(20) NOT NULL DEFAULT '',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `id` (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `table1`\n--\n\nLOCK TABLES `table1` WRITE;\n/*!40000 ALTER TABLE `table1` DISABLE KEYS */;\nINSERT INTO `table1` VALUES (1,'test4','https://github.com/nixys/nxs-rbac-operator0.git','none','','',''),(3,'test6','https://github.com/nixys/nxs-rbac-operator2.git','none','','','');\n/*!40000 ALTER TABLE `table1` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `table2`\n--\n\nDROP TABLE IF EXISTS `table2`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `table2` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `name` varchar(50) NOT NULL,\n  `url` varchar(255) NOT NULL,\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\n  `auth_data` text NOT NULL,\n  `username` varchar(20) NOT NULL DEFAULT '',\n  `password` varchar(20) NOT NULL DEFAULT '',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `id` (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `table2`\n--\n\nLOCK TABLES `table2` WRITE;\n/*!40000 ALTER TABLE `table2` DISABLE KEYS */;\n\n/*!40000 ALTER TABLE `table2` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `table3`\n--\n\nDROP TABLE IF EXISTS `table3`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `table3` (\n  `id` int NOT NULL AUTO_INCREMENT,\n  `name` varchar(50) NOT NULL,\n  `url` varchar(255) NOT NULL,\n  `auth_method` varchar(20) NOT NULL DEFAULT 'none',\n  `auth_data` text NOT NULL,\n  `username` varchar(20) NOT NULL DEFAULT '',\n  `password` varchar(20) NOT NULL DEFAULT '',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `id` (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `table3`\n--\n\nLOCK TABLES `table3` WRITE;\n/*!40000 ALTER TABLE `table3` DISABLE KEYS */;\nINSERT INTO `table3` VALUES (1,'test4','https://github.com/nixys/nxs-rbac-operator0.git','none','','',''),(2,'test5','https://github.com/nixys/nxs-rbac-operator.git','none','','',''),(3,'test6','https://github.com/nixys/nxs-rbac-operator2.git','none','','','');\n/*!40000 ALTER TABLE `table3` ENABLE KEYS */;\nUNLOCK TABLES;"
  },
  {
    "path": "modules/anonymizers/mysql/dh.go",
    "content": "package mysql_anonymize\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"regexp\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n)\n\nfunc dhSecurityInsertInto(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tuctx.security.tmpBuf = token\n\tuctx.insertIntoBuf = nil\n\n\treturn deferred, nil\n}\n\nfunc dhSecurityInsertIntoTableNameSearch(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tuctx.security.tmpBuf = append(uctx.security.tmpBuf, deferred...)\n\tuctx.security.tmpBuf = append(uctx.security.tmpBuf, token...)\n\n\treturn []byte{}, nil\n}\n\nfunc dhSecurityInsertIntoValues(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\tuctx.insertIntoBuf = append(uctx.insertIntoBuf, deferred...)\n\tuctx.insertIntoBuf = append(uctx.insertIntoBuf, token...)\n\n\treturn []byte{}, nil\n}\n\nfunc dhSecurityInsertIntoValueSearch(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\tuctx.insertIntoBuf = append(uctx.insertIntoBuf, deferred...)\n\n\treturn []byte{}, nil\n}\n\nfunc dhSecurityValuesEnd(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\tif uctx.insertIntoBuf != nil {\n\t\treturn []byte{}, nil\n\t}\n\n\treturn append(deferred, token...), nil\n}\n\nfunc dhCreateTableName(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\tuctx.filter.TableCreate(string(deferred))\n\n\treturn append(deferred, token...), nil\n}\n\nfunc dhCreateTableFieldName(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\tuctx.columnName = string(deferred)\n\n\treturn append(deferred, token...), nil\n}\n\n// checkGenerated returns true when specified type is `generated`\n// See: https://dev.mysql.com/blog-archive/generated-columns-in-mysql-5-7-5 for details\nfunc checkGenerated(t []byte) bool {\n\tif bytes.Contains(t, []byte{'A', 'S'}) == true {\n\t\tb, _ := regexp.Match(\"^([A-Z]+)((\\\\([0-9]+\\\\) )| )(GENERATED ALWAYS AS|AS)\", t)\n\t\treturn b\n\t}\n\treturn false\n}\n\nfunc dhCreateTableColumnAdd(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\ttraw := bytes.TrimSpace(deferred)\n\ttrawUpper := bytes.ToUpper(traw)\n\n\tif checkGenerated(trawUpper) == false {\n\n\t\tt, b := uctx.tables[uctx.filter.TableNameGet()]\n\t\tif !b {\n\t\t\tt = make(map[string]columnType)\n\t\t}\n\t\tt[uctx.columnName] = columnTypeNone\n\n\t\tfor _, ot := range uctx.optKinds {\n\t\t\tif ot.r.Match(trawUpper) == true {\n\t\t\t\tt[uctx.columnName] = ot.t\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tuctx.tables[uctx.filter.TableNameGet()] = t\n\t\tuctx.filter.ColumnAdd(uctx.columnName, string(traw))\n\t}\n\n\tuctx.columnName = \"\"\n\n\treturn append(deferred, token...), nil\n}\n\nfunc dhInsertIntoTableName(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\ttn := string(deferred)\n\n\t// Check table pass through security rules\n\tif !securityPolicyCheck(uctx, tn) {\n\n\t\t// If not: table will be skipped from result dump\n\n\t\tuctx.security.isSkip = true\n\t\tuctx.security.tmpBuf = []byte{}\n\t\treturn []byte{}, nil\n\t}\n\n\tuctx.insertIntoBuf = append(uctx.security.tmpBuf, append(deferred, token...)...)\n\n\tuctx.security.isSkip = false\n\tuctx.security.tmpBuf = []byte{}\n\n\t// Check insert into table name\n\tif tn != uctx.filter.TableNameGet() {\n\t\treturn []byte{}, fmt.Errorf(\"`create` and `insert into` table names are mismatch (create table: '%s', insert into table: '%s')\", uctx.filter.TableNameGet(), tn)\n\t}\n\n\treturn []byte{}, nil\n}\n\nfunc dhCreateTableValues(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\ts := string(deferred)\n\tif s == \"NULL\" {\n\t\tuctx.filter.ValueAdd(misc.TemplateNULL)\n\t} else {\n\t\tuctx.filter.ValueAdd(s)\n\t}\n\n\treturn []byte{}, nil\n}\n\nfunc dhCreateTableValuesString(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\ts := string(deferred)\n\tuctx.filter.ValueAdd(s)\n\n\treturn []byte{}, nil\n}\n\nfunc dhCreateTableValuesEnd(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\ts := string(deferred)\n\tif s == \"NULL\" {\n\t\tuctx.filter.ValueAdd(misc.TemplateNULL)\n\t} else {\n\t\tuctx.filter.ValueAdd(s)\n\t}\n\n\t// Apply filter for row\n\tif err := uctx.filter.Apply(); err != nil {\n\t\treturn []byte{}, err\n\t}\n\n\tb := rowDataGen(uctx)\n\tif b == nil {\n\t\treturn []byte{}, nil\n\t} else {\n\t\tif uctx.insertIntoBuf != nil {\n\t\t\tb = append(uctx.insertIntoBuf, b...)\n\t\t\tuctx.insertIntoBuf = nil\n\t\t} else {\n\t\t\tb = append([]byte{','}, b...)\n\t\t}\n\t}\n\n\treturn b, nil\n}\n\nfunc dhCreateTableValuesStringEnd(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\t// Apply filter for row\n\tif err := uctx.filter.Apply(); err != nil {\n\t\treturn []byte{}, err\n\t}\n\n\tb := rowDataGen(uctx)\n\tif b == nil {\n\t\treturn []byte{}, nil\n\t} else {\n\t\tif uctx.insertIntoBuf != nil {\n\t\t\tb = append(uctx.insertIntoBuf, b...)\n\t\t\tuctx.insertIntoBuf = nil\n\t\t} else {\n\t\t\tb = append([]byte{','}, b...)\n\t\t}\n\t}\n\n\treturn b, nil\n}\n\nfunc rowDataGen(uctx *userCtx) []byte {\n\n\tvar out string\n\n\trow := uctx.filter.ValuePop()\n\tif row.Values == nil {\n\t\treturn nil\n\t}\n\n\tfor i, v := range row.Values {\n\n\t\tif i > 0 {\n\t\t\tout += \",\"\n\t\t}\n\n\t\tif v.V == misc.TemplateNULL {\n\t\t\tout += \"NULL\"\n\t\t} else {\n\t\t\tswitch uctx.tables[uctx.filter.TableNameGet()][uctx.filter.ColumnGetName(i)] {\n\t\t\tcase columnTypeString:\n\t\t\t\tout += fmt.Sprintf(\"'%s'\", v.V)\n\t\t\tcase columnTypeBinary:\n\t\t\t\tout += fmt.Sprintf(\"_binary '%s'\", v.V)\n\t\t\tdefault:\n\t\t\t\tout += fmt.Sprintf(\"%s\", v.V)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn []byte(fmt.Sprintf(\"(%s)\", out))\n}\n\n// SecurityPolicyCheck checks the table passes the security rules\n// true:  pass\n// false: skip\nfunc securityPolicyCheck(uctx *userCtx, tname string) bool {\n\n\t// Continue if security policy is `skip`\n\tif uctx.security.tablesPolicy != misc.SecurityPolicyTablesSkip {\n\t\treturn true\n\t}\n\n\t// Check rules for specified table name\n\tif tr := uctx.filter.TableRulesLookup(tname); tr != nil {\n\t\treturn true\n\t}\n\n\t// Check specified table name in exceptions\n\tif _, b := uctx.security.tableExceptions[tname]; b == true {\n\t\treturn true\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "modules/anonymizers/mysql/mysql.go",
    "content": "package mysql_anonymize\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"regexp\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n\t\"github.com/nixys/nxs-data-anonymizer/modules/filters/relfilter\"\n\n\tfsm \"github.com/nixys/nxs-go-fsm\"\n)\n\ntype MySQL struct {\n\tuctx         *userCtx\n\tsourceReader io.Reader\n}\n\ntype InitOpts struct {\n\tVariables map[string]relfilter.VariableRuleOpts\n\tSecurity  SecurityOpts\n\tRules     RulesOpts\n\tLink      []relfilter.LinkOpts\n}\n\ntype RulesOpts struct {\n\tTableRules       map[string]map[string]relfilter.ColumnRuleOpts\n\tDefaultRules     map[string]relfilter.ColumnRuleOpts\n\tExceptionColumns []string\n\tTypeRuleCustom   []relfilter.TypeRuleOpts\n}\n\ntype SecurityOpts struct {\n\tTablesPolicy    misc.SecurityPolicyTablesType\n\tColumnsPolicy   misc.SecurityPolicyColumnsType\n\tTableExceptions []string\n}\n\ntype userCtx struct {\n\tfilter        *relfilter.Filter\n\tcolumnName    string\n\tsecurity      securityCtx\n\ttables        map[string]map[string]columnType\n\toptKinds      []optKind\n\tinsertIntoBuf []byte\n}\n\ntype securityCtx struct {\n\ttmpBuf []byte\n\tisSkip bool\n\n\ttablesPolicy    misc.SecurityPolicyTablesType\n\ttableExceptions map[string]any\n}\n\ntype optKind struct {\n\tr *regexp.Regexp\n\tt columnType\n}\n\ntype columnType string\n\nconst (\n\tcolumnTypeNone   columnType = \"none\"\n\tcolumnTypeString columnType = \"string\"\n\tcolumnTypeNum    columnType = \"numeric\"\n\tcolumnTypeBinary columnType = \"binary\"\n)\n\nfunc (c columnType) String() string {\n\treturn string(c)\n}\n\nvar typeKeys = map[string]columnType{\n\n\t// Strings\n\t\"^CHAR\":       columnTypeString,\n\t\"^VARCHAR\":    columnTypeString,\n\t\"^TINYTEXT\":   columnTypeString,\n\t\"^TEXT\":       columnTypeString,\n\t\"^MEDIUMTEXT\": columnTypeString,\n\t\"^LONGTEXT\":   columnTypeString,\n\t\"^ENUM\":       columnTypeString,\n\t\"^SET\":        columnTypeString,\n\t\"^DATE\":       columnTypeString,\n\t\"^DATETIME\":   columnTypeString,\n\t\"^TIME\":       columnTypeString,\n\t\"^YEAR\":       columnTypeString,\n\t\"^JSON\":       columnTypeString,\n\n\t// Numeric\n\t\"^BIT\":       columnTypeNum,\n\t\"^BOOL\":      columnTypeNum,\n\t\"^TINYINT\":   columnTypeNum,\n\t\"^SMALLINT\":  columnTypeNum,\n\t\"^MEDIUMINT\": columnTypeNum,\n\t\"^INT\":       columnTypeNum,\n\t\"^BIGINT\":    columnTypeNum,\n\t\"^FLOAT\":     columnTypeNum,\n\t\"^DOUBLE\":    columnTypeNum,\n\t\"^DEC\":       columnTypeNum,\n\n\t// Binary\n\t\"^BINARY\":     columnTypeBinary,\n\t\"^VARBINARY\":  columnTypeBinary,\n\t\"^TINYBLOB\":   columnTypeBinary,\n\t\"^BLOB\":       columnTypeBinary,\n\t\"^MEDIUMBLOB\": columnTypeBinary,\n\t\"^LONGBLOB\":   columnTypeBinary,\n}\n\nfunc userCtxInit(s InitOpts) (*userCtx, error) {\n\n\tf, err := relfilter.Init(\n\t\trelfilter.InitOpts{\n\t\t\tVariables:        s.Variables,\n\t\t\tLink:             s.Link,\n\t\t\tTableRules:       s.Rules.TableRules,\n\t\t\tDefaultRules:     s.Rules.DefaultRules,\n\t\t\tExceptionColumns: s.Rules.ExceptionColumns,\n\t\t\tTypeRuleCustom:   s.Rules.TypeRuleCustom,\n\t\t\tTypeRuleDefault:  typeRuleDefault,\n\t\t\tColumnsPolicy:    s.Security.ColumnsPolicy,\n\t\t},\n\t)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"user ctx init: %w\", err)\n\t}\n\n\tok := []optKind{}\n\tfor o, t := range typeKeys {\n\t\tr, err := regexp.Compile(o)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"user ctx init: %w\", err)\n\t\t}\n\t\tok = append(\n\t\t\tok,\n\t\t\toptKind{\n\t\t\t\tr: r,\n\t\t\t\tt: t,\n\t\t\t},\n\t\t)\n\t}\n\n\treturn &userCtx{\n\t\tfilter: f,\n\t\tsecurity: securityCtx{\n\t\t\ttablesPolicy: s.Security.TablesPolicy,\n\t\t\ttableExceptions: func() map[string]any {\n\t\t\t\texcs := make(map[string]any)\n\t\t\t\tfor _, e := range s.Security.TableExceptions {\n\t\t\t\t\texcs[e] = nil\n\t\t\t\t}\n\t\t\t\treturn excs\n\t\t\t}(),\n\t\t},\n\t\ttables:   make(map[string]map[string]columnType),\n\t\toptKinds: ok,\n\t}, nil\n}\n\nfunc Init(r io.Reader, s InitOpts) (*MySQL, error) {\n\n\tuctx, err := userCtxInit(s)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"mysql anonymizer init: %w\", err)\n\t}\n\n\treturn &MySQL{\n\t\tuctx:         uctx,\n\t\tsourceReader: r,\n\t}, nil\n}\n\nfunc (m *MySQL) Run(ctx context.Context, w io.Writer) error {\n\n\tar := fsm.Init(\n\t\tm.sourceReader,\n\t\tfsm.Description{\n\t\t\tCtx:       ctx,\n\t\t\tUserCtx:   m.uctx,\n\t\t\tInitState: stateCreateSearch,\n\t\t\tStates: map[fsm.StateName]fsm.State{\n\n\t\t\t\tstateCreateSearch: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateCreateTableSearch,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"CREATE\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{'\\n'},\n\t\t\t\t\t\t\t\t\tR: []byte{' '},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateCreateTableSearch: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateCreateTableNameSearch,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"TABLE\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{' '},\n\t\t\t\t\t\t\t\t\tR: []byte{' '},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateCreateTableNameSearch: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateCreateTableName,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"`\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateCreateTableName: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateFieldsDescriptionSearch,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"`\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhCreateTableName,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateFieldsDescriptionSearch: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateFieldsDescriptionBlock,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"(\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateFieldsDescriptionBlock: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Skip table keys description\n\t\t\t\t\t\t\tName: stateFieldDescriptionTailSkip,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"KEY\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{' '},\n\t\t\t\t\t\t\t\t\tR: []byte{' '},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Skip table keys description\n\t\t\t\t\t\t\tName: stateFieldDescriptionTailSkip,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"PRIMARY\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{' '},\n\t\t\t\t\t\t\t\t\tR: []byte{' '},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Skip table keys description\n\t\t\t\t\t\t\tName: stateFieldDescriptionTailSkip,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"UNIQUE\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{' '},\n\t\t\t\t\t\t\t\t\tR: []byte{' '},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Skip table keys description\n\t\t\t\t\t\t\tName: stateFieldDescriptionTailSkip,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"CONSTRAINT\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{' '},\n\t\t\t\t\t\t\t\t\tR: []byte{' '},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Skip table keys description\n\t\t\t\t\t\t\tName: stateFieldDescriptionTailSkip,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"FOREIGN\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{' '},\n\t\t\t\t\t\t\t\t\tR: []byte{' '},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateFieldsDescriptionName,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"`\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateFieldDescriptionTailSkip: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateFieldsDescriptionBlock,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\",\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tR: []byte{'\\n', '\\r'},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: statefFieldsDescriptionBlockEnd,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\")\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{'\\n'},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateFieldsDescriptionName: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateFieldsDescriptionNameTail,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"`\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhCreateTableFieldName,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateFieldsDescriptionNameTail: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateFieldsDescriptionBlock,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\",\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tR: []byte{'\\n', '\\r'},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhCreateTableColumnAdd,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: statefFieldsDescriptionBlockEnd,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\")\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{'\\n'},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhCreateTableColumnAdd,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstatefFieldsDescriptionBlockEnd: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateSomeIntermediateState,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\";\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tR: []byte{'\\n', '\\r'},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateSomeIntermediateState: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateCreateTableSearch,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"CREATE\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{'\\n'},\n\t\t\t\t\t\t\t\t\tR: []byte{' '},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateInsertIntoTableNameSearch,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"INSERT INTO\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{'\\n'},\n\t\t\t\t\t\t\t\t\tR: []byte{' '},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhSecurityInsertInto,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\tstateInsertIntoTableNameSearch: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateInsertIntoTableName,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"`\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhSecurityInsertIntoTableNameSearch,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateInsertIntoTableName: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateValuesSearchKeyword,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"`\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhInsertIntoTableName,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateValuesSearchKeyword: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateValuesSearch,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"VALUES\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{' ', '\\n'},\n\t\t\t\t\t\t\t\t\tR: []byte{' ', '\\n', '\\r'},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhSecurityInsertIntoValues,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateValuesSearch: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableValues,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"(\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhSecurityInsertIntoValueSearch,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateTableValues: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableValuesString,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"'\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: fsm.DataHandlerGenericVoid,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableValues,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\",\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhCreateTableValues,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableValuesEnd,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\")\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhCreateTableValuesEnd,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateTableValuesString: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableValuesStringEnd,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"'\"),\n\t\t\t\t\t\t\t\tEscape:  true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhCreateTableValuesString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateTableValuesStringEnd: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableValues,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\",\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: fsm.DataHandlerGenericVoid,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableValuesEnd,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\")\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhCreateTableValuesStringEnd,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateTableValuesEnd: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateValuesSearch,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\",\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: fsm.DataHandlerGenericVoid,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateSomeIntermediateState,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\";\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhSecurityValuesEnd,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t)\n\n\t_, err := io.Copy(w, ar)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"mysql anonymizer run: %w\", err)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "modules/anonymizers/mysql/mysql_test.go",
    "content": "package mysql_anonymize\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n\t\"github.com/nixys/nxs-data-anonymizer/modules/filters/relfilter\"\n)\n\nfunc TestMySQL(t *testing.T) {\n\n\tvar r, e bytes.Buffer\n\n\tfin, err := os.Open(\".testdata/mysql_test.in.sql\")\n\tif err != nil {\n\t\tt.Fatal(\"open input SQL:\", err)\n\t}\n\n\tm, err := Init(\n\t\tfin,\n\t\tInitOpts{\n\t\t\tRules: RulesOpts{\n\t\t\t\tTableRules: map[string]map[string]relfilter.ColumnRuleOpts{\n\n\t\t\t\t\t// Delete only row with id `2`\n\t\t\t\t\t\"table1\": {\n\t\t\t\t\t\t\"id\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ if eq .Values.id \\\"2\\\" }}{{ drop }}{{ else }}{{ .Values.id }}{{ end }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t// Delete all rows from table\n\t\t\t\t\t\"table2\": {\n\t\t\t\t\t\t\"id\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ drop }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t// Delete no rows\n\t\t\t\t\t\"table3\": {\n\t\t\t\t\t\t\"id\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ if eq .Values.id \\\"4\\\" }}{{ drop }}{{ else }}{{ .Values.id }}{{ end }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tt.Fatal(\"init MySQL:\", err)\n\t}\n\n\tif err := m.Run(context.Background(), &r); err != nil {\n\t\tt.Fatal(\"run MySQL:\", err)\n\t}\n\n\tfout, err := os.Open(\".testdata/mysql_test.out.sql\")\n\tif err != nil {\n\t\tt.Fatal(\"open output SQL:\", err)\n\t}\n\n\tif _, err := e.ReadFrom(fout); err != nil {\n\t\tt.Fatal(\"read output SQL:\", err)\n\t}\n\n\t// os.WriteFile(\".testdata/mysql_test.out.sql\", r.Bytes(), 0644)\n\n\tif r.String() != e.String() {\n\t\tt.Fatal(\"incorrect anonymization result\")\n\t}\n\n\tt.Logf(\"success\")\n}\n\nfunc TestMySQLDos(t *testing.T) {\n\n\tvar r, e bytes.Buffer\n\n\tfin, err := os.Open(\".testdata/mysql_test.dos.in.sql\")\n\tif err != nil {\n\t\tt.Fatal(\"open input SQL:\", err)\n\t}\n\n\tm, err := Init(\n\t\tfin,\n\t\tInitOpts{\n\t\t\tRules: RulesOpts{\n\t\t\t\tTableRules: map[string]map[string]relfilter.ColumnRuleOpts{\n\n\t\t\t\t\t// Delete only row with id `2`\n\t\t\t\t\t\"table1\": {\n\t\t\t\t\t\t\"id\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ if eq .Values.id \\\"2\\\" }}{{ drop }}{{ else }}{{ .Values.id }}{{ end }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t// Delete all rows from table\n\t\t\t\t\t\"table2\": {\n\t\t\t\t\t\t\"id\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ drop }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t// Delete no rows\n\t\t\t\t\t\"table3\": {\n\t\t\t\t\t\t\"id\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ if eq .Values.id \\\"4\\\" }}{{ drop }}{{ else }}{{ .Values.id }}{{ end }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tt.Fatal(\"init MySQL:\", err)\n\t}\n\n\tif err := m.Run(context.Background(), &r); err != nil {\n\t\tt.Fatal(\"run MySQL:\", err)\n\t}\n\n\tfout, err := os.Open(\".testdata/mysql_test.dos.out.sql\")\n\tif err != nil {\n\t\tt.Fatal(\"open output SQL:\", err)\n\t}\n\n\tif _, err := e.ReadFrom(fout); err != nil {\n\t\tt.Fatal(\"read output SQL:\", err)\n\t}\n\n\t// os.WriteFile(\".testdata/mysql_test.dos.out.sql\", r.Bytes(), 0644)\n\n\tif r.String() != e.String() {\n\t\tt.Fatal(\"incorrect anonymization result\")\n\t}\n\n\tt.Logf(\"success\")\n}\n"
  },
  {
    "path": "modules/anonymizers/mysql/security_types.go",
    "content": "package mysql_anonymize\n\nimport (\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n\t\"github.com/nixys/nxs-data-anonymizer/modules/filters/relfilter\"\n)\n\nvar typeRuleDefault = []relfilter.TypeRuleOpts{\n\n\t// String\n\t{\n\t\tSelector: \"(?i)^char\\\\((\\\\d+)\\\\)|^char\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"{{ trunc (index .ColumnTypeGroups 0 1 | int ) \\\"randomized char\\\" }}\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^varchar\\\\((\\\\d+)\\\\)|^varchar\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"{{ trunc (index .ColumnTypeGroups 0 1 | int ) \\\"randomized varchar\\\" }}\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^tinytext\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"randomized tinytext\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^text\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"randomized text\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^mediumtext\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"randomized mediumtext\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^longtext\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"randomized longtext\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^enum\\\\(.*'(.*)'.*\\\\)\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"{{ index .ColumnTypeGroups 0 1 }}\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^set\\\\(.*'(.*)'.*\\\\)\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"{{ index .ColumnTypeGroups 0 1 }}\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^datetime\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"2024-01-01 00:00:00\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^date\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"2024-01-01\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^timestamp\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"2024-01-01 00:00:00\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^time\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"00:00:00\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^year\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"2024\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^json\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"{\\\"randomized\\\": \\\"json_data\\\"}\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\n\t// Numeric\n\t{\n\t\tSelector: \"(?i)^bit\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^bool\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^boolean\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^tinyint\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^smallint\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^mediumint\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^int\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^integer\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^bigint\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^float\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0.0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^double\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0.0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^decimal\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0.0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^dec\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0.0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\n\t// Binary\n\t{\n\t\tSelector: \"(?i)^binary\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^varbinary\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=\",\n\t\t\tUnique: false,\n\t\t},\n\t}, {\n\t\tSelector: \"(?i)^tinyblob\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^blob\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^mediumblob\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=\",\n\t\t\tUnique: false,\n\t\t},\n\t}, {\n\t\tSelector: \"(?i)^longblob\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n}\n"
  },
  {
    "path": "modules/anonymizers/mysql/states.go",
    "content": "package mysql_anonymize\n\nimport fsm \"github.com/nixys/nxs-go-fsm\"\n\nvar (\n\tstateCreateSearch               = fsm.StateName(\"create search\")\n\tstateCreateTableSearch          = fsm.StateName(\"create table search\")\n\tstateCreateTableNameSearch      = fsm.StateName(\"create table name search\")\n\tstateCreateTableName            = fsm.StateName(\"create table name\")\n\tstateFieldsDescriptionSearch    = fsm.StateName(\"fields description search\")\n\tstateFieldsDescriptionBlock     = fsm.StateName(\"fields description block\")\n\tstateFieldsDescriptionName      = fsm.StateName(\"fields description name\")\n\tstateFieldsDescriptionNameTail  = fsm.StateName(\"fields description name tail\")\n\tstateFieldDescriptionTailSkip   = fsm.StateName(\"fields description tail skip\")\n\tstatefFieldsDescriptionBlockEnd = fsm.StateName(\"fields description block end\")\n\tstateSomeIntermediateState      = fsm.StateName(\"some intermediate state\")\n\tstateInsertIntoTableNameSearch  = fsm.StateName(\"insert into table name search\")\n\tstateInsertIntoTableName        = fsm.StateName(\"insert into table name\")\n\tstateValuesSearch               = fsm.StateName(\"values search\")\n\tstateTableValues                = fsm.StateName(\"table values\")\n\tstateTableValuesString          = fsm.StateName(\"table values string\")\n\tstateTableValuesBinary          = fsm.StateName(\"table values binary\")\n\tstateTableValuesEnd             = fsm.StateName(\"table values end\")\n\tstateTableValuesStringEnd       = fsm.StateName(\"table values string end\")\n\tstateValuesSearchKeyword        = fsm.StateName(\"values search key VALUES\")\n\tstateFieldsGenerated            = fsm.StateName(\"fields generated search\")\n)\n"
  },
  {
    "path": "modules/anonymizers/pgsql/.testdata/pgsql_test.dos.in.sql",
    "content": "--\r\n-- PostgreSQL database dump\r\n--\r\n\r\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\r\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\r\n\r\nSET statement_timeout = 0;\r\nSET lock_timeout = 0;\r\nSET idle_in_transaction_session_timeout = 0;\r\nSET client_encoding = 'UTF8';\r\nSET standard_conforming_strings = on;\r\nSELECT pg_catalog.set_config('search_path', '', false);\r\nSET check_function_bodies = false;\r\nSET xmloption = content;\r\nSET client_min_messages = warning;\r\nSET row_security = off;\r\n\r\nSET default_tablespace = '';\r\n\r\nSET default_table_access_method = heap;\r\n\r\n--\r\n-- Name: list_types; Type: TABLE; Schema: public; Owner: postgres\r\n--\r\n\r\nCREATE TABLE public.list_types (\r\n    integer_type integer,\r\n    numeric_type numeric,\r\n    double_precision_type double precision,\r\n    varchar_type character varying,\r\n    text_type text,\r\n    date_type date,\r\n    time_tz_type time with time zone,\r\n    boolean_type boolean,\r\n    xml_type xml,\r\n    jsonb_type jsonb,\r\n    id bigint NOT NULL\r\n);\r\n\r\n\r\nALTER TABLE public.list_types OWNER TO postgres;\r\n\r\n--\r\n-- Name: list_types2; Type: TABLE; Schema: public; Owner: postgres\r\n--\r\n\r\nCREATE TABLE public.list_types2 (\r\n    integer_type integer,\r\n    numeric_type numeric,\r\n    double_precision_type double precision,\r\n    varchar_type character varying,\r\n    text_type text,\r\n    date_type date,\r\n    time_tz_type time with time zone,\r\n    boolean_type boolean,\r\n    xml_type xml,\r\n    jsonb_type jsonb,\r\n    id bigint NOT NULL\r\n);\r\n\r\n\r\nALTER TABLE public.list_types2 OWNER TO postgres;\r\n\r\n--\r\n-- Name: list_types3; Type: TABLE; Schema: public; Owner: postgres\r\n--\r\n\r\nCREATE TABLE public.list_types3 (\r\n    integer_type integer,\r\n    numeric_type numeric,\r\n    double_precision_type double precision,\r\n    varchar_type character varying,\r\n    text_type text,\r\n    date_type date,\r\n    time_tz_type time with time zone,\r\n    boolean_type boolean,\r\n    xml_type xml,\r\n    jsonb_type jsonb,\r\n    id bigint NOT NULL\r\n);\r\n\r\n\r\nALTER TABLE public.list_types3 OWNER TO postgres;\r\n\r\n--\r\n-- Name: list_types_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres\r\n--\r\n\r\nCREATE SEQUENCE public.list_types_id_seq\r\n    START WITH 1\r\n    INCREMENT BY 1\r\n    NO MINVALUE\r\n    NO MAXVALUE\r\n    CACHE 1;\r\n\r\n\r\nALTER SEQUENCE public.list_types_id_seq OWNER TO postgres;\r\n\r\n--\r\n-- Name: list_types_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres\r\n--\r\n\r\nALTER SEQUENCE public.list_types_id_seq OWNED BY public.list_types.id;\r\n\r\n\r\n--\r\n-- Name: list_types id; Type: DEFAULT; Schema: public; Owner: postgres\r\n--\r\n\r\nALTER TABLE ONLY public.list_types ALTER COLUMN id SET DEFAULT nextval('public.list_types_id_seq'::regclass);\r\n\r\n\r\n--\r\n-- Data for Name: list_types; Type: TABLE DATA; Schema: public; Owner: postgres\r\n--\r\n\r\nCOPY public.list_types (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\r\n\\N\t42.99465\t\\N\tBiba\t\\N\t\\N\t19:51:50+00\t\\N\t\\N\t\\N\t6\r\n\\N\t-84.46685\t\\N\tPupa\t\\N\t\\N\t03:34:36+00\t\\N\t\\N\t\\N\t2\r\n\\N\t72.52040\t\\N\tLupa\t \t\\N\t15:17:37+00\tt\t\\N\t\\N\t4\r\n\\N\t99.37111\t\\N\tBoba\t \t\\N\t03:34:36+00\t\\N\t\\N\t\\N\t8\r\n\\N\t-90.90125\t\\N\tCerebla\t\\N\t\\N\t22:00:45+00\t\\N\t\\N\t\\N\t10\r\n8765542\t\\N\t7.84023409\t \tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel pretium lectus quam id leo in vitae. Dignissim cras tincidunt lobortis feugiat vivamus at augue. Sit amet aliquam id diam maecenas. Ornare lectus sit amet est placerat in egestas erat. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Orci sagittis eu volutpat odio facilisis. Mauris in aliquam sem fringilla ut morbi tincidunt augue interdum. Nisi porta lorem mollis aliquam ut porttitor leo a diam. Amet purus gravida quis blandit turpis cursus in. Risus feugiat in ante metus. Purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Faucibus nisl tincidunt eget nullam. Lectus quam id leo in vitae turpis massa. Nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit. Pretium lectus quam id leo in vitae turpis massa. Blandit aliquam etiam erat velit scelerisque in dictum non. Eu nisl nunc mi ipsum faucibus vitae.\t1996-06-15\t\\N\tt\t<root>\\n  <west>721744494.7994413</west>\\n  <top>-26197703.515699387</top>\\n  <or>event</or>\\n  <art>\\n    <layers>among</layers>\\n    <growth>couple</growth>\\n    <off>official</off>\\n    <made>spring</made>\\n    <poem>1032613367</poem>\\n  </art>\\n  <strong>198858711</strong>\\n</root>\t{\"truck\": 1563128845, \"little\": -1009907448.0705619, \"possible\": \"gave\"}\t1\r\n4562892\t\\N\t5.8024375\t\\N\tMassa sapien faucibus et molestie ac. Praesent elementum facilisis leo vel. Turpis egestas pretium aenean pharetra magna. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Auctor neque vitae tempus quam pellentesque. Ornare aenean euismod elementum nisi quis eleifend. Purus sit amet luctus venenatis lectus. Tortor consequat id porta nibh venenatis cras sed felis eget. Felis bibendum ut tristique et egestas quis ipsum. Pretium fusce id velit ut tortor pretium viverra. Nam aliquam sem et tortor consequat. Nisl pretium fusce id velit. Sem integer vitae justo eget magna fermentum iaculis. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae auctor eu augue ut lectus arcu. Malesuada fames ac turpis egestas. Ac odio tempor orci dapibus ultrices in. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Et malesuada fames ac turpis egestas integer. Sodales ut eu sem integer vitae justo eget.\t2031-07-14\t\\N\tf\t<root>\\n  <melted>\\n    <officer>-598731677.6283197</officer>\\n    <exist>variety</exist>\\n    <sitting>46234734.5525651</sitting>\\n    <period>rising</period>\\n    <rice>-1556052082.582368</rice>\\n  </melted>\\n  <got>eleven</got>\\n  <onlinetools>1863692621</onlinetools>\\n  <this>-139561185.33627748</this>\\n  <driver>funny</driver>\\n</root>\t[{\"ago\": {\"shut\": \"seven\", \"found\": 469996577.0459976, \"climate\": \"early\"}, \"scene\": \"slightly\", \"medicine\": true}, true, true]\t3\r\n87689278\t\\N\t-0.31813426\t \tId donec ultrices tincidunt arcu. Id nibh tortor id aliquet lectus. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Cursus vitae congue mauris rhoncus. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sed turpis tincidunt id aliquet. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. Scelerisque eu ultrices vitae auctor eu augue ut. Volutpat ac tincidunt vitae semper quis.\t1976-12-10\t\\N\tt\t<root>\\n  <mission>rise</mission>\\n  <layers>\\n    <wire>consist</wire>\\n    <dinner>someone</dinner>\\n    <electric>white</electric>\\n    <heavy>victory</heavy>\\n    <ice>-761134241.8632131</ice>\\n  </layers>\\n  <help>1111641157</help>\\n  <comfortable>744054503</comfortable>\\n  <highway>1876042205.1417785</highway>\\n</root>\t{\"torn\": [false, -1325125579, false], \"rising\": false, \"volume\": \"grow\"}\t9\r\n687527896\t\\N\t-1.81914025\t \tFacilisi etiam dignissim diam quis enim. Diam ut venenatis tellus in metus vulputate eu. Mattis rhoncus urna neque viverra justo nec ultrices. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Nec ullamcorper sit amet risus nullam eget felis eget. Fames ac turpis egestas maecenas pharetra convallis posuere. Eget arcu dictum varius duis at consectetur lorem. Porta lorem mollis aliquam ut porttitor leo a diam sollicitudin. Magna fermentum iaculis eu non diam phasellus vestibulum lorem sed. Etiam non quam lacus suspendisse. Parturient montes nascetur ridiculus mus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar.\t2051-05-16\t\\N\tt\t<root>\\n  <piece>\\n    <vertical>398209907.5902777</vertical>\\n    <prove>wind</prove>\\n    <fair>parallel</fair>\\n    <closely>paint</closely>\\n    <see>-1386172501</see>\\n  </piece>\\n  <hide>previous</hide>\\n  <among>skill</among>\\n  <our>conversation</our>\\n  <cell>keep</cell>\\n</root>\t[[-128477882.56726694, 1569798072.8967233, {\"us\": 438307927.6373253, \"think\": -870063635, \"product\": \"stuck\"}], [{\"name\": \"broad\", \"took\": \"brother\", \"alphabet\": -731303259}, [-1065068182.0998564, \"finish\", \"up\"], false], false]\t5\r\n8767542\t\\N\t5.08081291\t\\N\tFames ac turpis egestas maecenas. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Sit amet commodo nulla facilisi nullam vehicula. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Maecenas ultricies mi eget mauris pharetra. Sed faucibus turpis in eu mi bibendum. Massa ultricies mi quis hendrerit dolor magna. Non diam phasellus vestibulum lorem sed. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus.\t2058-03-29\t\\N\tf\t<root>\\n  <invented>concerned</invented>\\n  <feet>-1671936329.7007055</feet>\\n  <win>slept</win>\\n  <until>how</until>\\n  <lion>-1838021068</lion>\\n</root>\t{\"basis\": \"mine\", \"company\": {\"tired\": false, \"prevent\": false, \"suppose\": 735075799}, \"worried\": {\"iron\": 378563223.91183805, \"nest\": false, \"raise\": {\"date\": false, \"engineer\": true, \"television\": 136840736.65782642}}}\t7\r\n\\.\r\n\r\n\r\n--\r\n-- Data for Name: list_types2; Type: TABLE DATA; Schema: public; Owner: postgres\r\n--\r\n\r\nCOPY public.list_types2 (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\r\n8765542\t\\N\t7.84023409\t \tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel pretium lectus quam id leo in vitae. Dignissim cras tincidunt lobortis feugiat vivamus at augue. Sit amet aliquam id diam maecenas. Ornare lectus sit amet est placerat in egestas erat. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Orci sagittis eu volutpat odio facilisis. Mauris in aliquam sem fringilla ut morbi tincidunt augue interdum. Nisi porta lorem mollis aliquam ut porttitor leo a diam. Amet purus gravida quis blandit turpis cursus in. Risus feugiat in ante metus. Purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Faucibus nisl tincidunt eget nullam. Lectus quam id leo in vitae turpis massa. Nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit. Pretium lectus quam id leo in vitae turpis massa. Blandit aliquam etiam erat velit scelerisque in dictum non. Eu nisl nunc mi ipsum faucibus vitae.\t1996-06-15\t\\N\tt\t<root>\\n  <west>721744494.7994413</west>\\n  <top>-26197703.515699387</top>\\n  <or>event</or>\\n  <art>\\n    <layers>among</layers>\\n    <growth>couple</growth>\\n    <off>official</off>\\n    <made>spring</made>\\n    <poem>1032613367</poem>\\n  </art>\\n  <strong>198858711</strong>\\n</root>\t{\"truck\": 1563128845, \"little\": -1009907448.0705619, \"possible\": \"gave\"}\t1\r\n4562892\t\\N\t5.8024375\t\\N\tMassa sapien faucibus et molestie ac. Praesent elementum facilisis leo vel. Turpis egestas pretium aenean pharetra magna. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Auctor neque vitae tempus quam pellentesque. Ornare aenean euismod elementum nisi quis eleifend. Purus sit amet luctus venenatis lectus. Tortor consequat id porta nibh venenatis cras sed felis eget. Felis bibendum ut tristique et egestas quis ipsum. Pretium fusce id velit ut tortor pretium viverra. Nam aliquam sem et tortor consequat. Nisl pretium fusce id velit. Sem integer vitae justo eget magna fermentum iaculis. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae auctor eu augue ut lectus arcu. Malesuada fames ac turpis egestas. Ac odio tempor orci dapibus ultrices in. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Et malesuada fames ac turpis egestas integer. Sodales ut eu sem integer vitae justo eget.\t2031-07-14\t\\N\tf\t<root>\\n  <melted>\\n    <officer>-598731677.6283197</officer>\\n    <exist>variety</exist>\\n    <sitting>46234734.5525651</sitting>\\n    <period>rising</period>\\n    <rice>-1556052082.582368</rice>\\n  </melted>\\n  <got>eleven</got>\\n  <onlinetools>1863692621</onlinetools>\\n  <this>-139561185.33627748</this>\\n  <driver>funny</driver>\\n</root>\t[{\"ago\": {\"shut\": \"seven\", \"found\": 469996577.0459976, \"climate\": \"early\"}, \"scene\": \"slightly\", \"medicine\": true}, true, true]\t3\r\n87689278\t\\N\t-0.31813426\t \tId donec ultrices tincidunt arcu. Id nibh tortor id aliquet lectus. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Cursus vitae congue mauris rhoncus. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sed turpis tincidunt id aliquet. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. Scelerisque eu ultrices vitae auctor eu augue ut. Volutpat ac tincidunt vitae semper quis.\t1976-12-10\t\\N\tt\t<root>\\n  <mission>rise</mission>\\n  <layers>\\n    <wire>consist</wire>\\n    <dinner>someone</dinner>\\n    <electric>white</electric>\\n    <heavy>victory</heavy>\\n    <ice>-761134241.8632131</ice>\\n  </layers>\\n  <help>1111641157</help>\\n  <comfortable>744054503</comfortable>\\n  <highway>1876042205.1417785</highway>\\n</root>\t{\"torn\": [false, -1325125579, false], \"rising\": false, \"volume\": \"grow\"}\t9\r\n687527896\t\\N\t-1.81914025\t \tFacilisi etiam dignissim diam quis enim. Diam ut venenatis tellus in metus vulputate eu. Mattis rhoncus urna neque viverra justo nec ultrices. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Nec ullamcorper sit amet risus nullam eget felis eget. Fames ac turpis egestas maecenas pharetra convallis posuere. Eget arcu dictum varius duis at consectetur lorem. Porta lorem mollis aliquam ut porttitor leo a diam sollicitudin. Magna fermentum iaculis eu non diam phasellus vestibulum lorem sed. Etiam non quam lacus suspendisse. Parturient montes nascetur ridiculus mus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar.\t2051-05-16\t\\N\tt\t<root>\\n  <piece>\\n    <vertical>398209907.5902777</vertical>\\n    <prove>wind</prove>\\n    <fair>parallel</fair>\\n    <closely>paint</closely>\\n    <see>-1386172501</see>\\n  </piece>\\n  <hide>previous</hide>\\n  <among>skill</among>\\n  <our>conversation</our>\\n  <cell>keep</cell>\\n</root>\t[[-128477882.56726694, 1569798072.8967233, {\"us\": 438307927.6373253, \"think\": -870063635, \"product\": \"stuck\"}], [{\"name\": \"broad\", \"took\": \"brother\", \"alphabet\": -731303259}, [-1065068182.0998564, \"finish\", \"up\"], false], false]\t5\r\n8767542\t\\N\t5.08081291\t\\N\tFames ac turpis egestas maecenas. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Sit amet commodo nulla facilisi nullam vehicula. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Maecenas ultricies mi eget mauris pharetra. Sed faucibus turpis in eu mi bibendum. Massa ultricies mi quis hendrerit dolor magna. Non diam phasellus vestibulum lorem sed. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus.\t2058-03-29\t\\N\tf\t<root>\\n  <invented>concerned</invented>\\n  <feet>-1671936329.7007055</feet>\\n  <win>slept</win>\\n  <until>how</until>\\n  <lion>-1838021068</lion>\\n</root>\t{\"basis\": \"mine\", \"company\": {\"tired\": false, \"prevent\": false, \"suppose\": 735075799}, \"worried\": {\"iron\": 378563223.91183805, \"nest\": false, \"raise\": {\"date\": false, \"engineer\": true, \"television\": 136840736.65782642}}}\t7\r\n\\.\r\n\r\n\r\n--\r\n-- Data for Name: list_types3; Type: TABLE DATA; Schema: public; Owner: postgres\r\n--\r\n\r\nCOPY public.list_types3 (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\r\n8765542\t\\N\t7.84023409\t \tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel pretium lectus quam id leo in vitae. Dignissim cras tincidunt lobortis feugiat vivamus at augue. Sit amet aliquam id diam maecenas. Ornare lectus sit amet est placerat in egestas erat. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Orci sagittis eu volutpat odio facilisis. Mauris in aliquam sem fringilla ut morbi tincidunt augue interdum. Nisi porta lorem mollis aliquam ut porttitor leo a diam. Amet purus gravida quis blandit turpis cursus in. Risus feugiat in ante metus. Purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Faucibus nisl tincidunt eget nullam. Lectus quam id leo in vitae turpis massa. Nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit. Pretium lectus quam id leo in vitae turpis massa. Blandit aliquam etiam erat velit scelerisque in dictum non. Eu nisl nunc mi ipsum faucibus vitae.\t1996-06-15\t\\N\tt\t<root>\\n  <west>721744494.7994413</west>\\n  <top>-26197703.515699387</top>\\n  <or>event</or>\\n  <art>\\n    <layers>among</layers>\\n    <growth>couple</growth>\\n    <off>official</off>\\n    <made>spring</made>\\n    <poem>1032613367</poem>\\n  </art>\\n  <strong>198858711</strong>\\n</root>\t{\"truck\": 1563128845, \"little\": -1009907448.0705619, \"possible\": \"gave\"}\t1\r\n4562892\t\\N\t5.8024375\t\\N\tMassa sapien faucibus et molestie ac. Praesent elementum facilisis leo vel. Turpis egestas pretium aenean pharetra magna. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Auctor neque vitae tempus quam pellentesque. Ornare aenean euismod elementum nisi quis eleifend. Purus sit amet luctus venenatis lectus. Tortor consequat id porta nibh venenatis cras sed felis eget. Felis bibendum ut tristique et egestas quis ipsum. Pretium fusce id velit ut tortor pretium viverra. Nam aliquam sem et tortor consequat. Nisl pretium fusce id velit. Sem integer vitae justo eget magna fermentum iaculis. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae auctor eu augue ut lectus arcu. Malesuada fames ac turpis egestas. Ac odio tempor orci dapibus ultrices in. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Et malesuada fames ac turpis egestas integer. Sodales ut eu sem integer vitae justo eget.\t2031-07-14\t\\N\tf\t<root>\\n  <melted>\\n    <officer>-598731677.6283197</officer>\\n    <exist>variety</exist>\\n    <sitting>46234734.5525651</sitting>\\n    <period>rising</period>\\n    <rice>-1556052082.582368</rice>\\n  </melted>\\n  <got>eleven</got>\\n  <onlinetools>1863692621</onlinetools>\\n  <this>-139561185.33627748</this>\\n  <driver>funny</driver>\\n</root>\t[{\"ago\": {\"shut\": \"seven\", \"found\": 469996577.0459976, \"climate\": \"early\"}, \"scene\": \"slightly\", \"medicine\": true}, true, true]\t3\r\n87689278\t\\N\t-0.31813426\t \tId donec ultrices tincidunt arcu. Id nibh tortor id aliquet lectus. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Cursus vitae congue mauris rhoncus. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sed turpis tincidunt id aliquet. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. Scelerisque eu ultrices vitae auctor eu augue ut. Volutpat ac tincidunt vitae semper quis.\t1976-12-10\t\\N\tt\t<root>\\n  <mission>rise</mission>\\n  <layers>\\n    <wire>consist</wire>\\n    <dinner>someone</dinner>\\n    <electric>white</electric>\\n    <heavy>victory</heavy>\\n    <ice>-761134241.8632131</ice>\\n  </layers>\\n  <help>1111641157</help>\\n  <comfortable>744054503</comfortable>\\n  <highway>1876042205.1417785</highway>\\n</root>\t{\"torn\": [false, -1325125579, false], \"rising\": false, \"volume\": \"grow\"}\t9\r\n687527896\t\\N\t-1.81914025\t \tFacilisi etiam dignissim diam quis enim. Diam ut venenatis tellus in metus vulputate eu. Mattis rhoncus urna neque viverra justo nec ultrices. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Nec ullamcorper sit amet risus nullam eget felis eget. Fames ac turpis egestas maecenas pharetra convallis posuere. Eget arcu dictum varius duis at consectetur lorem. Porta lorem mollis aliquam ut porttitor leo a diam sollicitudin. Magna fermentum iaculis eu non diam phasellus vestibulum lorem sed. Etiam non quam lacus suspendisse. Parturient montes nascetur ridiculus mus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar.\t2051-05-16\t\\N\tt\t<root>\\n  <piece>\\n    <vertical>398209907.5902777</vertical>\\n    <prove>wind</prove>\\n    <fair>parallel</fair>\\n    <closely>paint</closely>\\n    <see>-1386172501</see>\\n  </piece>\\n  <hide>previous</hide>\\n  <among>skill</among>\\n  <our>conversation</our>\\n  <cell>keep</cell>\\n</root>\t[[-128477882.56726694, 1569798072.8967233, {\"us\": 438307927.6373253, \"think\": -870063635, \"product\": \"stuck\"}], [{\"name\": \"broad\", \"took\": \"brother\", \"alphabet\": -731303259}, [-1065068182.0998564, \"finish\", \"up\"], false], false]\t5\r\n8767542\t\\N\t5.08081291\t\\N\tFames ac turpis egestas maecenas. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Sit amet commodo nulla facilisi nullam vehicula. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Maecenas ultricies mi eget mauris pharetra. Sed faucibus turpis in eu mi bibendum. Massa ultricies mi quis hendrerit dolor magna. Non diam phasellus vestibulum lorem sed. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus.\t2058-03-29\t\\N\tf\t<root>\\n  <invented>concerned</invented>\\n  <feet>-1671936329.7007055</feet>\\n  <win>slept</win>\\n  <until>how</until>\\n  <lion>-1838021068</lion>\\n</root>\t{\"basis\": \"mine\", \"company\": {\"tired\": false, \"prevent\": false, \"suppose\": 735075799}, \"worried\": {\"iron\": 378563223.91183805, \"nest\": false, \"raise\": {\"date\": false, \"engineer\": true, \"television\": 136840736.65782642}}}\t7\r\n\\.\r\n\r\n\r\n--\r\n-- Name: list_types_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres\r\n--\r\n\r\nSELECT pg_catalog.setval('public.list_types_id_seq', 10, true);\r\n\r\n\r\n--\r\n-- Name: list_types list_types_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\r\n--\r\n\r\nALTER TABLE ONLY public.list_types\r\n    ADD CONSTRAINT list_types_pkey PRIMARY KEY (id);\r\n\r\n\r\n--\r\n-- PostgreSQL database dump complete\r\n--\r\n\r\n"
  },
  {
    "path": "modules/anonymizers/pgsql/.testdata/pgsql_test.dos.out.sql",
    "content": "--\r\n-- PostgreSQL database dump\r\n--\r\n\r\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\r\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\r\n\r\nSET statement_timeout = 0;\r\nSET lock_timeout = 0;\r\nSET idle_in_transaction_session_timeout = 0;\r\nSET client_encoding = 'UTF8';\r\nSET standard_conforming_strings = on;\r\nSELECT pg_catalog.set_config('search_path', '', false);\r\nSET check_function_bodies = false;\r\nSET xmloption = content;\r\nSET client_min_messages = warning;\r\nSET row_security = off;\r\n\r\nSET default_tablespace = '';\r\n\r\nSET default_table_access_method = heap;\r\n\r\n--\r\n-- Name: list_types; Type: TABLE; Schema: public; Owner: postgres\r\n--\r\n\r\nCREATE TABLE public.list_types (\r\n    integer_type integer,\r\n    numeric_type numeric,\r\n    double_precision_type double precision,\r\n    varchar_type character varying,\r\n    text_type text,\r\n    date_type date,\r\n    time_tz_type time with time zone,\r\n    boolean_type boolean,\r\n    xml_type xml,\r\n    jsonb_type jsonb,\r\n    id bigint NOT NULL\r\n);\r\n\r\n\r\nALTER TABLE public.list_types OWNER TO postgres;\r\n\r\n--\r\n-- Name: list_types2; Type: TABLE; Schema: public; Owner: postgres\r\n--\r\n\r\nCREATE TABLE public.list_types2 (\r\n    integer_type integer,\r\n    numeric_type numeric,\r\n    double_precision_type double precision,\r\n    varchar_type character varying,\r\n    text_type text,\r\n    date_type date,\r\n    time_tz_type time with time zone,\r\n    boolean_type boolean,\r\n    xml_type xml,\r\n    jsonb_type jsonb,\r\n    id bigint NOT NULL\r\n);\r\n\r\n\r\nALTER TABLE public.list_types2 OWNER TO postgres;\r\n\r\n--\r\n-- Name: list_types3; Type: TABLE; Schema: public; Owner: postgres\r\n--\r\n\r\nCREATE TABLE public.list_types3 (\r\n    integer_type integer,\r\n    numeric_type numeric,\r\n    double_precision_type double precision,\r\n    varchar_type character varying,\r\n    text_type text,\r\n    date_type date,\r\n    time_tz_type time with time zone,\r\n    boolean_type boolean,\r\n    xml_type xml,\r\n    jsonb_type jsonb,\r\n    id bigint NOT NULL\r\n);\r\n\r\n\r\nALTER TABLE public.list_types3 OWNER TO postgres;\r\n\r\n--\r\n-- Name: list_types_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres\r\n--\r\n\r\nCREATE SEQUENCE public.list_types_id_seq\r\n    START WITH 1\r\n    INCREMENT BY 1\r\n    NO MINVALUE\r\n    NO MAXVALUE\r\n    CACHE 1;\r\n\r\n\r\nALTER SEQUENCE public.list_types_id_seq OWNER TO postgres;\r\n\r\n--\r\n-- Name: list_types_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres\r\n--\r\n\r\nALTER SEQUENCE public.list_types_id_seq OWNED BY public.list_types.id;\r\n\r\n\r\n--\r\n-- Name: list_types id; Type: DEFAULT; Schema: public; Owner: postgres\r\n--\r\n\r\nALTER TABLE ONLY public.list_types ALTER COLUMN id SET DEFAULT nextval('public.list_types_id_seq'::regclass);\r\n\r\n\r\n--\r\n-- Data for Name: list_types; Type: TABLE DATA; Schema: public; Owner: postgres\r\n--\r\n\r\nCOPY public.list_types (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\r\n\\N\t42.99465\t\\N\tBiba\t\\N\t\\N\t19:51:50+00\t\\N\t\\N\t\\N\t6\r\n\\N\t-84.46685\t\\N\tPupa\t\\N\t\\N\t03:34:36+00\t\\N\t\\N\t\\N\t2\r\n\\N\t72.52040\t\\N\tLupa\t \t\\N\t15:17:37+00\tt\t\\N\t\\N\t4\r\n\\N\t99.37111\t\\N\tBoba\t \t\\N\t03:34:36+00\t\\N\t\\N\t\\N\t8\r\n\\N\t-90.90125\t\\N\tCerebla\t\\N\t\\N\t22:00:45+00\t\\N\t\\N\t\\N\t10\r\n4562892\t\\N\t5.8024375\t\\N\tMassa sapien faucibus et molestie ac. Praesent elementum facilisis leo vel. Turpis egestas pretium aenean pharetra magna. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Auctor neque vitae tempus quam pellentesque. Ornare aenean euismod elementum nisi quis eleifend. Purus sit amet luctus venenatis lectus. Tortor consequat id porta nibh venenatis cras sed felis eget. Felis bibendum ut tristique et egestas quis ipsum. Pretium fusce id velit ut tortor pretium viverra. Nam aliquam sem et tortor consequat. Nisl pretium fusce id velit. Sem integer vitae justo eget magna fermentum iaculis. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae auctor eu augue ut lectus arcu. Malesuada fames ac turpis egestas. Ac odio tempor orci dapibus ultrices in. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Et malesuada fames ac turpis egestas integer. Sodales ut eu sem integer vitae justo eget.\t2031-07-14\t\\N\tf\t<root>\\n  <melted>\\n    <officer>-598731677.6283197</officer>\\n    <exist>variety</exist>\\n    <sitting>46234734.5525651</sitting>\\n    <period>rising</period>\\n    <rice>-1556052082.582368</rice>\\n  </melted>\\n  <got>eleven</got>\\n  <onlinetools>1863692621</onlinetools>\\n  <this>-139561185.33627748</this>\\n  <driver>funny</driver>\\n</root>\t[{\"ago\": {\"shut\": \"seven\", \"found\": 469996577.0459976, \"climate\": \"early\"}, \"scene\": \"slightly\", \"medicine\": true}, true, true]\t3\r\n87689278\t\\N\t-0.31813426\t \tId donec ultrices tincidunt arcu. Id nibh tortor id aliquet lectus. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Cursus vitae congue mauris rhoncus. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sed turpis tincidunt id aliquet. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. Scelerisque eu ultrices vitae auctor eu augue ut. Volutpat ac tincidunt vitae semper quis.\t1976-12-10\t\\N\tt\t<root>\\n  <mission>rise</mission>\\n  <layers>\\n    <wire>consist</wire>\\n    <dinner>someone</dinner>\\n    <electric>white</electric>\\n    <heavy>victory</heavy>\\n    <ice>-761134241.8632131</ice>\\n  </layers>\\n  <help>1111641157</help>\\n  <comfortable>744054503</comfortable>\\n  <highway>1876042205.1417785</highway>\\n</root>\t{\"torn\": [false, -1325125579, false], \"rising\": false, \"volume\": \"grow\"}\t9\r\n687527896\t\\N\t-1.81914025\t \tFacilisi etiam dignissim diam quis enim. Diam ut venenatis tellus in metus vulputate eu. Mattis rhoncus urna neque viverra justo nec ultrices. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Nec ullamcorper sit amet risus nullam eget felis eget. Fames ac turpis egestas maecenas pharetra convallis posuere. Eget arcu dictum varius duis at consectetur lorem. Porta lorem mollis aliquam ut porttitor leo a diam sollicitudin. Magna fermentum iaculis eu non diam phasellus vestibulum lorem sed. Etiam non quam lacus suspendisse. Parturient montes nascetur ridiculus mus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar.\t2051-05-16\t\\N\tt\t<root>\\n  <piece>\\n    <vertical>398209907.5902777</vertical>\\n    <prove>wind</prove>\\n    <fair>parallel</fair>\\n    <closely>paint</closely>\\n    <see>-1386172501</see>\\n  </piece>\\n  <hide>previous</hide>\\n  <among>skill</among>\\n  <our>conversation</our>\\n  <cell>keep</cell>\\n</root>\t[[-128477882.56726694, 1569798072.8967233, {\"us\": 438307927.6373253, \"think\": -870063635, \"product\": \"stuck\"}], [{\"name\": \"broad\", \"took\": \"brother\", \"alphabet\": -731303259}, [-1065068182.0998564, \"finish\", \"up\"], false], false]\t5\r\n8767542\t\\N\t5.08081291\t\\N\tFames ac turpis egestas maecenas. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Sit amet commodo nulla facilisi nullam vehicula. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Maecenas ultricies mi eget mauris pharetra. Sed faucibus turpis in eu mi bibendum. Massa ultricies mi quis hendrerit dolor magna. Non diam phasellus vestibulum lorem sed. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus.\t2058-03-29\t\\N\tf\t<root>\\n  <invented>concerned</invented>\\n  <feet>-1671936329.7007055</feet>\\n  <win>slept</win>\\n  <until>how</until>\\n  <lion>-1838021068</lion>\\n</root>\t{\"basis\": \"mine\", \"company\": {\"tired\": false, \"prevent\": false, \"suppose\": 735075799}, \"worried\": {\"iron\": 378563223.91183805, \"nest\": false, \"raise\": {\"date\": false, \"engineer\": true, \"television\": 136840736.65782642}}}\t7\r\n\\.\r\n\r\n\r\n--\r\n-- Data for Name: list_types2; Type: TABLE DATA; Schema: public; Owner: postgres\r\n--\r\n\r\n\r\n\r\n\r\n--\r\n-- Data for Name: list_types3; Type: TABLE DATA; Schema: public; Owner: postgres\r\n--\r\n\r\nCOPY public.list_types3 (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\r\n8765542\t\\N\t7.84023409\t \tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel pretium lectus quam id leo in vitae. Dignissim cras tincidunt lobortis feugiat vivamus at augue. Sit amet aliquam id diam maecenas. Ornare lectus sit amet est placerat in egestas erat. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Orci sagittis eu volutpat odio facilisis. Mauris in aliquam sem fringilla ut morbi tincidunt augue interdum. Nisi porta lorem mollis aliquam ut porttitor leo a diam. Amet purus gravida quis blandit turpis cursus in. Risus feugiat in ante metus. Purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Faucibus nisl tincidunt eget nullam. Lectus quam id leo in vitae turpis massa. Nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit. Pretium lectus quam id leo in vitae turpis massa. Blandit aliquam etiam erat velit scelerisque in dictum non. Eu nisl nunc mi ipsum faucibus vitae.\t1996-06-15\t\\N\tt\t<root>\\n  <west>721744494.7994413</west>\\n  <top>-26197703.515699387</top>\\n  <or>event</or>\\n  <art>\\n    <layers>among</layers>\\n    <growth>couple</growth>\\n    <off>official</off>\\n    <made>spring</made>\\n    <poem>1032613367</poem>\\n  </art>\\n  <strong>198858711</strong>\\n</root>\t{\"truck\": 1563128845, \"little\": -1009907448.0705619, \"possible\": \"gave\"}\t1\r\n4562892\t\\N\t5.8024375\t\\N\tMassa sapien faucibus et molestie ac. Praesent elementum facilisis leo vel. Turpis egestas pretium aenean pharetra magna. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Auctor neque vitae tempus quam pellentesque. Ornare aenean euismod elementum nisi quis eleifend. Purus sit amet luctus venenatis lectus. Tortor consequat id porta nibh venenatis cras sed felis eget. Felis bibendum ut tristique et egestas quis ipsum. Pretium fusce id velit ut tortor pretium viverra. Nam aliquam sem et tortor consequat. Nisl pretium fusce id velit. Sem integer vitae justo eget magna fermentum iaculis. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae auctor eu augue ut lectus arcu. Malesuada fames ac turpis egestas. Ac odio tempor orci dapibus ultrices in. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Et malesuada fames ac turpis egestas integer. Sodales ut eu sem integer vitae justo eget.\t2031-07-14\t\\N\tf\t<root>\\n  <melted>\\n    <officer>-598731677.6283197</officer>\\n    <exist>variety</exist>\\n    <sitting>46234734.5525651</sitting>\\n    <period>rising</period>\\n    <rice>-1556052082.582368</rice>\\n  </melted>\\n  <got>eleven</got>\\n  <onlinetools>1863692621</onlinetools>\\n  <this>-139561185.33627748</this>\\n  <driver>funny</driver>\\n</root>\t[{\"ago\": {\"shut\": \"seven\", \"found\": 469996577.0459976, \"climate\": \"early\"}, \"scene\": \"slightly\", \"medicine\": true}, true, true]\t3\r\n87689278\t\\N\t-0.31813426\t \tId donec ultrices tincidunt arcu. Id nibh tortor id aliquet lectus. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Cursus vitae congue mauris rhoncus. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sed turpis tincidunt id aliquet. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. Scelerisque eu ultrices vitae auctor eu augue ut. Volutpat ac tincidunt vitae semper quis.\t1976-12-10\t\\N\tt\t<root>\\n  <mission>rise</mission>\\n  <layers>\\n    <wire>consist</wire>\\n    <dinner>someone</dinner>\\n    <electric>white</electric>\\n    <heavy>victory</heavy>\\n    <ice>-761134241.8632131</ice>\\n  </layers>\\n  <help>1111641157</help>\\n  <comfortable>744054503</comfortable>\\n  <highway>1876042205.1417785</highway>\\n</root>\t{\"torn\": [false, -1325125579, false], \"rising\": false, \"volume\": \"grow\"}\t9\r\n687527896\t\\N\t-1.81914025\t \tFacilisi etiam dignissim diam quis enim. Diam ut venenatis tellus in metus vulputate eu. Mattis rhoncus urna neque viverra justo nec ultrices. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Nec ullamcorper sit amet risus nullam eget felis eget. Fames ac turpis egestas maecenas pharetra convallis posuere. Eget arcu dictum varius duis at consectetur lorem. Porta lorem mollis aliquam ut porttitor leo a diam sollicitudin. Magna fermentum iaculis eu non diam phasellus vestibulum lorem sed. Etiam non quam lacus suspendisse. Parturient montes nascetur ridiculus mus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar.\t2051-05-16\t\\N\tt\t<root>\\n  <piece>\\n    <vertical>398209907.5902777</vertical>\\n    <prove>wind</prove>\\n    <fair>parallel</fair>\\n    <closely>paint</closely>\\n    <see>-1386172501</see>\\n  </piece>\\n  <hide>previous</hide>\\n  <among>skill</among>\\n  <our>conversation</our>\\n  <cell>keep</cell>\\n</root>\t[[-128477882.56726694, 1569798072.8967233, {\"us\": 438307927.6373253, \"think\": -870063635, \"product\": \"stuck\"}], [{\"name\": \"broad\", \"took\": \"brother\", \"alphabet\": -731303259}, [-1065068182.0998564, \"finish\", \"up\"], false], false]\t5\r\n8767542\t\\N\t5.08081291\t\\N\tFames ac turpis egestas maecenas. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Sit amet commodo nulla facilisi nullam vehicula. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Maecenas ultricies mi eget mauris pharetra. Sed faucibus turpis in eu mi bibendum. Massa ultricies mi quis hendrerit dolor magna. Non diam phasellus vestibulum lorem sed. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus.\t2058-03-29\t\\N\tf\t<root>\\n  <invented>concerned</invented>\\n  <feet>-1671936329.7007055</feet>\\n  <win>slept</win>\\n  <until>how</until>\\n  <lion>-1838021068</lion>\\n</root>\t{\"basis\": \"mine\", \"company\": {\"tired\": false, \"prevent\": false, \"suppose\": 735075799}, \"worried\": {\"iron\": 378563223.91183805, \"nest\": false, \"raise\": {\"date\": false, \"engineer\": true, \"television\": 136840736.65782642}}}\t7\r\n\\.\r\n\r\n\r\n--\r\n-- Name: list_types_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres\r\n--\r\n\r\nSELECT pg_catalog.setval('public.list_types_id_seq', 10, true);\r\n\r\n\r\n--\r\n-- Name: list_types list_types_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\r\n--\r\n\r\nALTER TABLE ONLY public.list_types\r\n    ADD CONSTRAINT list_types_pkey PRIMARY KEY (id);\r\n\r\n\r\n--\r\n-- PostgreSQL database dump complete\r\n--\r\n\r\n"
  },
  {
    "path": "modules/anonymizers/pgsql/.testdata/pgsql_test.in.sql",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: list_types; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.list_types (\n    integer_type integer,\n    numeric_type numeric,\n    double_precision_type double precision,\n    varchar_type character varying,\n    text_type text,\n    date_type date,\n    time_tz_type time with time zone,\n    boolean_type boolean,\n    xml_type xml,\n    jsonb_type jsonb,\n    id bigint NOT NULL\n);\n\n\nALTER TABLE public.list_types OWNER TO postgres;\n\n--\n-- Name: list_types2; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.list_types2 (\n    integer_type integer,\n    numeric_type numeric,\n    double_precision_type double precision,\n    varchar_type character varying,\n    text_type text,\n    date_type date,\n    time_tz_type time with time zone,\n    boolean_type boolean,\n    xml_type xml,\n    jsonb_type jsonb,\n    id bigint NOT NULL\n);\n\n\nALTER TABLE public.list_types2 OWNER TO postgres;\n\n--\n-- Name: list_types3; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.list_types3 (\n    integer_type integer,\n    numeric_type numeric,\n    double_precision_type double precision,\n    varchar_type character varying,\n    text_type text,\n    date_type date,\n    time_tz_type time with time zone,\n    boolean_type boolean,\n    xml_type xml,\n    jsonb_type jsonb,\n    id bigint NOT NULL\n);\n\n\nALTER TABLE public.list_types3 OWNER TO postgres;\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres\n--\n\nCREATE SEQUENCE public.list_types_id_seq\n    START WITH 1\n    INCREMENT BY 1\n    NO MINVALUE\n    NO MAXVALUE\n    CACHE 1;\n\n\nALTER SEQUENCE public.list_types_id_seq OWNER TO postgres;\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres\n--\n\nALTER SEQUENCE public.list_types_id_seq OWNED BY public.list_types.id;\n\n\n--\n-- Name: list_types id; Type: DEFAULT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.list_types ALTER COLUMN id SET DEFAULT nextval('public.list_types_id_seq'::regclass);\n\n\n--\n-- Data for Name: list_types; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.list_types (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\n\\N\t42.99465\t\\N\tBiba\t\\N\t\\N\t19:51:50+00\t\\N\t\\N\t\\N\t6\n\\N\t-84.46685\t\\N\tPupa\t\\N\t\\N\t03:34:36+00\t\\N\t\\N\t\\N\t2\n\\N\t72.52040\t\\N\tLupa\t \t\\N\t15:17:37+00\tt\t\\N\t\\N\t4\n\\N\t99.37111\t\\N\tBoba\t \t\\N\t03:34:36+00\t\\N\t\\N\t\\N\t8\n\\N\t-90.90125\t\\N\tCerebla\t\\N\t\\N\t22:00:45+00\t\\N\t\\N\t\\N\t10\n8765542\t\\N\t7.84023409\t \tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel pretium lectus quam id leo in vitae. Dignissim cras tincidunt lobortis feugiat vivamus at augue. Sit amet aliquam id diam maecenas. Ornare lectus sit amet est placerat in egestas erat. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Orci sagittis eu volutpat odio facilisis. Mauris in aliquam sem fringilla ut morbi tincidunt augue interdum. Nisi porta lorem mollis aliquam ut porttitor leo a diam. Amet purus gravida quis blandit turpis cursus in. Risus feugiat in ante metus. Purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Faucibus nisl tincidunt eget nullam. Lectus quam id leo in vitae turpis massa. Nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit. Pretium lectus quam id leo in vitae turpis massa. Blandit aliquam etiam erat velit scelerisque in dictum non. Eu nisl nunc mi ipsum faucibus vitae.\t1996-06-15\t\\N\tt\t<root>\\n  <west>721744494.7994413</west>\\n  <top>-26197703.515699387</top>\\n  <or>event</or>\\n  <art>\\n    <layers>among</layers>\\n    <growth>couple</growth>\\n    <off>official</off>\\n    <made>spring</made>\\n    <poem>1032613367</poem>\\n  </art>\\n  <strong>198858711</strong>\\n</root>\t{\"truck\": 1563128845, \"little\": -1009907448.0705619, \"possible\": \"gave\"}\t1\n4562892\t\\N\t5.8024375\t\\N\tMassa sapien faucibus et molestie ac. Praesent elementum facilisis leo vel. Turpis egestas pretium aenean pharetra magna. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Auctor neque vitae tempus quam pellentesque. Ornare aenean euismod elementum nisi quis eleifend. Purus sit amet luctus venenatis lectus. Tortor consequat id porta nibh venenatis cras sed felis eget. Felis bibendum ut tristique et egestas quis ipsum. Pretium fusce id velit ut tortor pretium viverra. Nam aliquam sem et tortor consequat. Nisl pretium fusce id velit. Sem integer vitae justo eget magna fermentum iaculis. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae auctor eu augue ut lectus arcu. Malesuada fames ac turpis egestas. Ac odio tempor orci dapibus ultrices in. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Et malesuada fames ac turpis egestas integer. Sodales ut eu sem integer vitae justo eget.\t2031-07-14\t\\N\tf\t<root>\\n  <melted>\\n    <officer>-598731677.6283197</officer>\\n    <exist>variety</exist>\\n    <sitting>46234734.5525651</sitting>\\n    <period>rising</period>\\n    <rice>-1556052082.582368</rice>\\n  </melted>\\n  <got>eleven</got>\\n  <onlinetools>1863692621</onlinetools>\\n  <this>-139561185.33627748</this>\\n  <driver>funny</driver>\\n</root>\t[{\"ago\": {\"shut\": \"seven\", \"found\": 469996577.0459976, \"climate\": \"early\"}, \"scene\": \"slightly\", \"medicine\": true}, true, true]\t3\n87689278\t\\N\t-0.31813426\t \tId donec ultrices tincidunt arcu. Id nibh tortor id aliquet lectus. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Cursus vitae congue mauris rhoncus. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sed turpis tincidunt id aliquet. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. Scelerisque eu ultrices vitae auctor eu augue ut. Volutpat ac tincidunt vitae semper quis.\t1976-12-10\t\\N\tt\t<root>\\n  <mission>rise</mission>\\n  <layers>\\n    <wire>consist</wire>\\n    <dinner>someone</dinner>\\n    <electric>white</electric>\\n    <heavy>victory</heavy>\\n    <ice>-761134241.8632131</ice>\\n  </layers>\\n  <help>1111641157</help>\\n  <comfortable>744054503</comfortable>\\n  <highway>1876042205.1417785</highway>\\n</root>\t{\"torn\": [false, -1325125579, false], \"rising\": false, \"volume\": \"grow\"}\t9\n687527896\t\\N\t-1.81914025\t \tFacilisi etiam dignissim diam quis enim. Diam ut venenatis tellus in metus vulputate eu. Mattis rhoncus urna neque viverra justo nec ultrices. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Nec ullamcorper sit amet risus nullam eget felis eget. Fames ac turpis egestas maecenas pharetra convallis posuere. Eget arcu dictum varius duis at consectetur lorem. Porta lorem mollis aliquam ut porttitor leo a diam sollicitudin. Magna fermentum iaculis eu non diam phasellus vestibulum lorem sed. Etiam non quam lacus suspendisse. Parturient montes nascetur ridiculus mus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar.\t2051-05-16\t\\N\tt\t<root>\\n  <piece>\\n    <vertical>398209907.5902777</vertical>\\n    <prove>wind</prove>\\n    <fair>parallel</fair>\\n    <closely>paint</closely>\\n    <see>-1386172501</see>\\n  </piece>\\n  <hide>previous</hide>\\n  <among>skill</among>\\n  <our>conversation</our>\\n  <cell>keep</cell>\\n</root>\t[[-128477882.56726694, 1569798072.8967233, {\"us\": 438307927.6373253, \"think\": -870063635, \"product\": \"stuck\"}], [{\"name\": \"broad\", \"took\": \"brother\", \"alphabet\": -731303259}, [-1065068182.0998564, \"finish\", \"up\"], false], false]\t5\n8767542\t\\N\t5.08081291\t\\N\tFames ac turpis egestas maecenas. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Sit amet commodo nulla facilisi nullam vehicula. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Maecenas ultricies mi eget mauris pharetra. Sed faucibus turpis in eu mi bibendum. Massa ultricies mi quis hendrerit dolor magna. Non diam phasellus vestibulum lorem sed. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus.\t2058-03-29\t\\N\tf\t<root>\\n  <invented>concerned</invented>\\n  <feet>-1671936329.7007055</feet>\\n  <win>slept</win>\\n  <until>how</until>\\n  <lion>-1838021068</lion>\\n</root>\t{\"basis\": \"mine\", \"company\": {\"tired\": false, \"prevent\": false, \"suppose\": 735075799}, \"worried\": {\"iron\": 378563223.91183805, \"nest\": false, \"raise\": {\"date\": false, \"engineer\": true, \"television\": 136840736.65782642}}}\t7\n\\.\n\n\n--\n-- Data for Name: list_types2; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.list_types2 (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\n8765542\t\\N\t7.84023409\t \tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel pretium lectus quam id leo in vitae. Dignissim cras tincidunt lobortis feugiat vivamus at augue. Sit amet aliquam id diam maecenas. Ornare lectus sit amet est placerat in egestas erat. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Orci sagittis eu volutpat odio facilisis. Mauris in aliquam sem fringilla ut morbi tincidunt augue interdum. Nisi porta lorem mollis aliquam ut porttitor leo a diam. Amet purus gravida quis blandit turpis cursus in. Risus feugiat in ante metus. Purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Faucibus nisl tincidunt eget nullam. Lectus quam id leo in vitae turpis massa. Nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit. Pretium lectus quam id leo in vitae turpis massa. Blandit aliquam etiam erat velit scelerisque in dictum non. Eu nisl nunc mi ipsum faucibus vitae.\t1996-06-15\t\\N\tt\t<root>\\n  <west>721744494.7994413</west>\\n  <top>-26197703.515699387</top>\\n  <or>event</or>\\n  <art>\\n    <layers>among</layers>\\n    <growth>couple</growth>\\n    <off>official</off>\\n    <made>spring</made>\\n    <poem>1032613367</poem>\\n  </art>\\n  <strong>198858711</strong>\\n</root>\t{\"truck\": 1563128845, \"little\": -1009907448.0705619, \"possible\": \"gave\"}\t1\n4562892\t\\N\t5.8024375\t\\N\tMassa sapien faucibus et molestie ac. Praesent elementum facilisis leo vel. Turpis egestas pretium aenean pharetra magna. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Auctor neque vitae tempus quam pellentesque. Ornare aenean euismod elementum nisi quis eleifend. Purus sit amet luctus venenatis lectus. Tortor consequat id porta nibh venenatis cras sed felis eget. Felis bibendum ut tristique et egestas quis ipsum. Pretium fusce id velit ut tortor pretium viverra. Nam aliquam sem et tortor consequat. Nisl pretium fusce id velit. Sem integer vitae justo eget magna fermentum iaculis. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae auctor eu augue ut lectus arcu. Malesuada fames ac turpis egestas. Ac odio tempor orci dapibus ultrices in. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Et malesuada fames ac turpis egestas integer. Sodales ut eu sem integer vitae justo eget.\t2031-07-14\t\\N\tf\t<root>\\n  <melted>\\n    <officer>-598731677.6283197</officer>\\n    <exist>variety</exist>\\n    <sitting>46234734.5525651</sitting>\\n    <period>rising</period>\\n    <rice>-1556052082.582368</rice>\\n  </melted>\\n  <got>eleven</got>\\n  <onlinetools>1863692621</onlinetools>\\n  <this>-139561185.33627748</this>\\n  <driver>funny</driver>\\n</root>\t[{\"ago\": {\"shut\": \"seven\", \"found\": 469996577.0459976, \"climate\": \"early\"}, \"scene\": \"slightly\", \"medicine\": true}, true, true]\t3\n87689278\t\\N\t-0.31813426\t \tId donec ultrices tincidunt arcu. Id nibh tortor id aliquet lectus. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Cursus vitae congue mauris rhoncus. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sed turpis tincidunt id aliquet. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. Scelerisque eu ultrices vitae auctor eu augue ut. Volutpat ac tincidunt vitae semper quis.\t1976-12-10\t\\N\tt\t<root>\\n  <mission>rise</mission>\\n  <layers>\\n    <wire>consist</wire>\\n    <dinner>someone</dinner>\\n    <electric>white</electric>\\n    <heavy>victory</heavy>\\n    <ice>-761134241.8632131</ice>\\n  </layers>\\n  <help>1111641157</help>\\n  <comfortable>744054503</comfortable>\\n  <highway>1876042205.1417785</highway>\\n</root>\t{\"torn\": [false, -1325125579, false], \"rising\": false, \"volume\": \"grow\"}\t9\n687527896\t\\N\t-1.81914025\t \tFacilisi etiam dignissim diam quis enim. Diam ut venenatis tellus in metus vulputate eu. Mattis rhoncus urna neque viverra justo nec ultrices. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Nec ullamcorper sit amet risus nullam eget felis eget. Fames ac turpis egestas maecenas pharetra convallis posuere. Eget arcu dictum varius duis at consectetur lorem. Porta lorem mollis aliquam ut porttitor leo a diam sollicitudin. Magna fermentum iaculis eu non diam phasellus vestibulum lorem sed. Etiam non quam lacus suspendisse. Parturient montes nascetur ridiculus mus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar.\t2051-05-16\t\\N\tt\t<root>\\n  <piece>\\n    <vertical>398209907.5902777</vertical>\\n    <prove>wind</prove>\\n    <fair>parallel</fair>\\n    <closely>paint</closely>\\n    <see>-1386172501</see>\\n  </piece>\\n  <hide>previous</hide>\\n  <among>skill</among>\\n  <our>conversation</our>\\n  <cell>keep</cell>\\n</root>\t[[-128477882.56726694, 1569798072.8967233, {\"us\": 438307927.6373253, \"think\": -870063635, \"product\": \"stuck\"}], [{\"name\": \"broad\", \"took\": \"brother\", \"alphabet\": -731303259}, [-1065068182.0998564, \"finish\", \"up\"], false], false]\t5\n8767542\t\\N\t5.08081291\t\\N\tFames ac turpis egestas maecenas. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Sit amet commodo nulla facilisi nullam vehicula. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Maecenas ultricies mi eget mauris pharetra. Sed faucibus turpis in eu mi bibendum. Massa ultricies mi quis hendrerit dolor magna. Non diam phasellus vestibulum lorem sed. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus.\t2058-03-29\t\\N\tf\t<root>\\n  <invented>concerned</invented>\\n  <feet>-1671936329.7007055</feet>\\n  <win>slept</win>\\n  <until>how</until>\\n  <lion>-1838021068</lion>\\n</root>\t{\"basis\": \"mine\", \"company\": {\"tired\": false, \"prevent\": false, \"suppose\": 735075799}, \"worried\": {\"iron\": 378563223.91183805, \"nest\": false, \"raise\": {\"date\": false, \"engineer\": true, \"television\": 136840736.65782642}}}\t7\n\\.\n\n\n--\n-- Data for Name: list_types3; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.list_types3 (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\n8765542\t\\N\t7.84023409\t \tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel pretium lectus quam id leo in vitae. Dignissim cras tincidunt lobortis feugiat vivamus at augue. Sit amet aliquam id diam maecenas. Ornare lectus sit amet est placerat in egestas erat. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Orci sagittis eu volutpat odio facilisis. Mauris in aliquam sem fringilla ut morbi tincidunt augue interdum. Nisi porta lorem mollis aliquam ut porttitor leo a diam. Amet purus gravida quis blandit turpis cursus in. Risus feugiat in ante metus. Purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Faucibus nisl tincidunt eget nullam. Lectus quam id leo in vitae turpis massa. Nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit. Pretium lectus quam id leo in vitae turpis massa. Blandit aliquam etiam erat velit scelerisque in dictum non. Eu nisl nunc mi ipsum faucibus vitae.\t1996-06-15\t\\N\tt\t<root>\\n  <west>721744494.7994413</west>\\n  <top>-26197703.515699387</top>\\n  <or>event</or>\\n  <art>\\n    <layers>among</layers>\\n    <growth>couple</growth>\\n    <off>official</off>\\n    <made>spring</made>\\n    <poem>1032613367</poem>\\n  </art>\\n  <strong>198858711</strong>\\n</root>\t{\"truck\": 1563128845, \"little\": -1009907448.0705619, \"possible\": \"gave\"}\t1\n4562892\t\\N\t5.8024375\t\\N\tMassa sapien faucibus et molestie ac. Praesent elementum facilisis leo vel. Turpis egestas pretium aenean pharetra magna. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Auctor neque vitae tempus quam pellentesque. Ornare aenean euismod elementum nisi quis eleifend. Purus sit amet luctus venenatis lectus. Tortor consequat id porta nibh venenatis cras sed felis eget. Felis bibendum ut tristique et egestas quis ipsum. Pretium fusce id velit ut tortor pretium viverra. Nam aliquam sem et tortor consequat. Nisl pretium fusce id velit. Sem integer vitae justo eget magna fermentum iaculis. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae auctor eu augue ut lectus arcu. Malesuada fames ac turpis egestas. Ac odio tempor orci dapibus ultrices in. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Et malesuada fames ac turpis egestas integer. Sodales ut eu sem integer vitae justo eget.\t2031-07-14\t\\N\tf\t<root>\\n  <melted>\\n    <officer>-598731677.6283197</officer>\\n    <exist>variety</exist>\\n    <sitting>46234734.5525651</sitting>\\n    <period>rising</period>\\n    <rice>-1556052082.582368</rice>\\n  </melted>\\n  <got>eleven</got>\\n  <onlinetools>1863692621</onlinetools>\\n  <this>-139561185.33627748</this>\\n  <driver>funny</driver>\\n</root>\t[{\"ago\": {\"shut\": \"seven\", \"found\": 469996577.0459976, \"climate\": \"early\"}, \"scene\": \"slightly\", \"medicine\": true}, true, true]\t3\n87689278\t\\N\t-0.31813426\t \tId donec ultrices tincidunt arcu. Id nibh tortor id aliquet lectus. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Cursus vitae congue mauris rhoncus. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sed turpis tincidunt id aliquet. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. Scelerisque eu ultrices vitae auctor eu augue ut. Volutpat ac tincidunt vitae semper quis.\t1976-12-10\t\\N\tt\t<root>\\n  <mission>rise</mission>\\n  <layers>\\n    <wire>consist</wire>\\n    <dinner>someone</dinner>\\n    <electric>white</electric>\\n    <heavy>victory</heavy>\\n    <ice>-761134241.8632131</ice>\\n  </layers>\\n  <help>1111641157</help>\\n  <comfortable>744054503</comfortable>\\n  <highway>1876042205.1417785</highway>\\n</root>\t{\"torn\": [false, -1325125579, false], \"rising\": false, \"volume\": \"grow\"}\t9\n687527896\t\\N\t-1.81914025\t \tFacilisi etiam dignissim diam quis enim. Diam ut venenatis tellus in metus vulputate eu. Mattis rhoncus urna neque viverra justo nec ultrices. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Nec ullamcorper sit amet risus nullam eget felis eget. Fames ac turpis egestas maecenas pharetra convallis posuere. Eget arcu dictum varius duis at consectetur lorem. Porta lorem mollis aliquam ut porttitor leo a diam sollicitudin. Magna fermentum iaculis eu non diam phasellus vestibulum lorem sed. Etiam non quam lacus suspendisse. Parturient montes nascetur ridiculus mus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar.\t2051-05-16\t\\N\tt\t<root>\\n  <piece>\\n    <vertical>398209907.5902777</vertical>\\n    <prove>wind</prove>\\n    <fair>parallel</fair>\\n    <closely>paint</closely>\\n    <see>-1386172501</see>\\n  </piece>\\n  <hide>previous</hide>\\n  <among>skill</among>\\n  <our>conversation</our>\\n  <cell>keep</cell>\\n</root>\t[[-128477882.56726694, 1569798072.8967233, {\"us\": 438307927.6373253, \"think\": -870063635, \"product\": \"stuck\"}], [{\"name\": \"broad\", \"took\": \"brother\", \"alphabet\": -731303259}, [-1065068182.0998564, \"finish\", \"up\"], false], false]\t5\n8767542\t\\N\t5.08081291\t\\N\tFames ac turpis egestas maecenas. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Sit amet commodo nulla facilisi nullam vehicula. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Maecenas ultricies mi eget mauris pharetra. Sed faucibus turpis in eu mi bibendum. Massa ultricies mi quis hendrerit dolor magna. Non diam phasellus vestibulum lorem sed. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus.\t2058-03-29\t\\N\tf\t<root>\\n  <invented>concerned</invented>\\n  <feet>-1671936329.7007055</feet>\\n  <win>slept</win>\\n  <until>how</until>\\n  <lion>-1838021068</lion>\\n</root>\t{\"basis\": \"mine\", \"company\": {\"tired\": false, \"prevent\": false, \"suppose\": 735075799}, \"worried\": {\"iron\": 378563223.91183805, \"nest\": false, \"raise\": {\"date\": false, \"engineer\": true, \"television\": 136840736.65782642}}}\t7\n\\.\n\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres\n--\n\nSELECT pg_catalog.setval('public.list_types_id_seq', 10, true);\n\n\n--\n-- Name: list_types list_types_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.list_types\n    ADD CONSTRAINT list_types_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "modules/anonymizers/pgsql/.testdata/pgsql_test.out.sql",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 16.3 (Debian 16.3-1.pgdg120+1)\n-- Dumped by pg_dump version 16.3 (Debian 16.3-1.pgdg120+1)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\nSET default_tablespace = '';\n\nSET default_table_access_method = heap;\n\n--\n-- Name: list_types; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.list_types (\n    integer_type integer,\n    numeric_type numeric,\n    double_precision_type double precision,\n    varchar_type character varying,\n    text_type text,\n    date_type date,\n    time_tz_type time with time zone,\n    boolean_type boolean,\n    xml_type xml,\n    jsonb_type jsonb,\n    id bigint NOT NULL\n);\n\n\nALTER TABLE public.list_types OWNER TO postgres;\n\n--\n-- Name: list_types2; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.list_types2 (\n    integer_type integer,\n    numeric_type numeric,\n    double_precision_type double precision,\n    varchar_type character varying,\n    text_type text,\n    date_type date,\n    time_tz_type time with time zone,\n    boolean_type boolean,\n    xml_type xml,\n    jsonb_type jsonb,\n    id bigint NOT NULL\n);\n\n\nALTER TABLE public.list_types2 OWNER TO postgres;\n\n--\n-- Name: list_types3; Type: TABLE; Schema: public; Owner: postgres\n--\n\nCREATE TABLE public.list_types3 (\n    integer_type integer,\n    numeric_type numeric,\n    double_precision_type double precision,\n    varchar_type character varying,\n    text_type text,\n    date_type date,\n    time_tz_type time with time zone,\n    boolean_type boolean,\n    xml_type xml,\n    jsonb_type jsonb,\n    id bigint NOT NULL\n);\n\n\nALTER TABLE public.list_types3 OWNER TO postgres;\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres\n--\n\nCREATE SEQUENCE public.list_types_id_seq\n    START WITH 1\n    INCREMENT BY 1\n    NO MINVALUE\n    NO MAXVALUE\n    CACHE 1;\n\n\nALTER SEQUENCE public.list_types_id_seq OWNER TO postgres;\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres\n--\n\nALTER SEQUENCE public.list_types_id_seq OWNED BY public.list_types.id;\n\n\n--\n-- Name: list_types id; Type: DEFAULT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.list_types ALTER COLUMN id SET DEFAULT nextval('public.list_types_id_seq'::regclass);\n\n\n--\n-- Data for Name: list_types; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.list_types (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\n\\N\t42.99465\t\\N\tBiba\t\\N\t\\N\t19:51:50+00\t\\N\t\\N\t\\N\t6\n\\N\t-84.46685\t\\N\tPupa\t\\N\t\\N\t03:34:36+00\t\\N\t\\N\t\\N\t2\n\\N\t72.52040\t\\N\tLupa\t \t\\N\t15:17:37+00\tt\t\\N\t\\N\t4\n\\N\t99.37111\t\\N\tBoba\t \t\\N\t03:34:36+00\t\\N\t\\N\t\\N\t8\n\\N\t-90.90125\t\\N\tCerebla\t\\N\t\\N\t22:00:45+00\t\\N\t\\N\t\\N\t10\n4562892\t\\N\t5.8024375\t\\N\tMassa sapien faucibus et molestie ac. Praesent elementum facilisis leo vel. Turpis egestas pretium aenean pharetra magna. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Auctor neque vitae tempus quam pellentesque. Ornare aenean euismod elementum nisi quis eleifend. Purus sit amet luctus venenatis lectus. Tortor consequat id porta nibh venenatis cras sed felis eget. Felis bibendum ut tristique et egestas quis ipsum. Pretium fusce id velit ut tortor pretium viverra. Nam aliquam sem et tortor consequat. Nisl pretium fusce id velit. Sem integer vitae justo eget magna fermentum iaculis. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae auctor eu augue ut lectus arcu. Malesuada fames ac turpis egestas. Ac odio tempor orci dapibus ultrices in. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Et malesuada fames ac turpis egestas integer. Sodales ut eu sem integer vitae justo eget.\t2031-07-14\t\\N\tf\t<root>\\n  <melted>\\n    <officer>-598731677.6283197</officer>\\n    <exist>variety</exist>\\n    <sitting>46234734.5525651</sitting>\\n    <period>rising</period>\\n    <rice>-1556052082.582368</rice>\\n  </melted>\\n  <got>eleven</got>\\n  <onlinetools>1863692621</onlinetools>\\n  <this>-139561185.33627748</this>\\n  <driver>funny</driver>\\n</root>\t[{\"ago\": {\"shut\": \"seven\", \"found\": 469996577.0459976, \"climate\": \"early\"}, \"scene\": \"slightly\", \"medicine\": true}, true, true]\t3\n87689278\t\\N\t-0.31813426\t \tId donec ultrices tincidunt arcu. Id nibh tortor id aliquet lectus. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Cursus vitae congue mauris rhoncus. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sed turpis tincidunt id aliquet. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. Scelerisque eu ultrices vitae auctor eu augue ut. Volutpat ac tincidunt vitae semper quis.\t1976-12-10\t\\N\tt\t<root>\\n  <mission>rise</mission>\\n  <layers>\\n    <wire>consist</wire>\\n    <dinner>someone</dinner>\\n    <electric>white</electric>\\n    <heavy>victory</heavy>\\n    <ice>-761134241.8632131</ice>\\n  </layers>\\n  <help>1111641157</help>\\n  <comfortable>744054503</comfortable>\\n  <highway>1876042205.1417785</highway>\\n</root>\t{\"torn\": [false, -1325125579, false], \"rising\": false, \"volume\": \"grow\"}\t9\n687527896\t\\N\t-1.81914025\t \tFacilisi etiam dignissim diam quis enim. Diam ut venenatis tellus in metus vulputate eu. Mattis rhoncus urna neque viverra justo nec ultrices. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Nec ullamcorper sit amet risus nullam eget felis eget. Fames ac turpis egestas maecenas pharetra convallis posuere. Eget arcu dictum varius duis at consectetur lorem. Porta lorem mollis aliquam ut porttitor leo a diam sollicitudin. Magna fermentum iaculis eu non diam phasellus vestibulum lorem sed. Etiam non quam lacus suspendisse. Parturient montes nascetur ridiculus mus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar.\t2051-05-16\t\\N\tt\t<root>\\n  <piece>\\n    <vertical>398209907.5902777</vertical>\\n    <prove>wind</prove>\\n    <fair>parallel</fair>\\n    <closely>paint</closely>\\n    <see>-1386172501</see>\\n  </piece>\\n  <hide>previous</hide>\\n  <among>skill</among>\\n  <our>conversation</our>\\n  <cell>keep</cell>\\n</root>\t[[-128477882.56726694, 1569798072.8967233, {\"us\": 438307927.6373253, \"think\": -870063635, \"product\": \"stuck\"}], [{\"name\": \"broad\", \"took\": \"brother\", \"alphabet\": -731303259}, [-1065068182.0998564, \"finish\", \"up\"], false], false]\t5\n8767542\t\\N\t5.08081291\t\\N\tFames ac turpis egestas maecenas. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Sit amet commodo nulla facilisi nullam vehicula. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Maecenas ultricies mi eget mauris pharetra. Sed faucibus turpis in eu mi bibendum. Massa ultricies mi quis hendrerit dolor magna. Non diam phasellus vestibulum lorem sed. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus.\t2058-03-29\t\\N\tf\t<root>\\n  <invented>concerned</invented>\\n  <feet>-1671936329.7007055</feet>\\n  <win>slept</win>\\n  <until>how</until>\\n  <lion>-1838021068</lion>\\n</root>\t{\"basis\": \"mine\", \"company\": {\"tired\": false, \"prevent\": false, \"suppose\": 735075799}, \"worried\": {\"iron\": 378563223.91183805, \"nest\": false, \"raise\": {\"date\": false, \"engineer\": true, \"television\": 136840736.65782642}}}\t7\n\\.\n\n\n--\n-- Data for Name: list_types2; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\n\n\n\n--\n-- Data for Name: list_types3; Type: TABLE DATA; Schema: public; Owner: postgres\n--\n\nCOPY public.list_types3 (integer_type, numeric_type, double_precision_type, varchar_type, text_type, date_type, time_tz_type, boolean_type, xml_type, jsonb_type, id) FROM stdin;\n8765542\t\\N\t7.84023409\t \tLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel pretium lectus quam id leo in vitae. Dignissim cras tincidunt lobortis feugiat vivamus at augue. Sit amet aliquam id diam maecenas. Ornare lectus sit amet est placerat in egestas erat. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Orci sagittis eu volutpat odio facilisis. Mauris in aliquam sem fringilla ut morbi tincidunt augue interdum. Nisi porta lorem mollis aliquam ut porttitor leo a diam. Amet purus gravida quis blandit turpis cursus in. Risus feugiat in ante metus. Purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Faucibus nisl tincidunt eget nullam. Lectus quam id leo in vitae turpis massa. Nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit. Pretium lectus quam id leo in vitae turpis massa. Blandit aliquam etiam erat velit scelerisque in dictum non. Eu nisl nunc mi ipsum faucibus vitae.\t1996-06-15\t\\N\tt\t<root>\\n  <west>721744494.7994413</west>\\n  <top>-26197703.515699387</top>\\n  <or>event</or>\\n  <art>\\n    <layers>among</layers>\\n    <growth>couple</growth>\\n    <off>official</off>\\n    <made>spring</made>\\n    <poem>1032613367</poem>\\n  </art>\\n  <strong>198858711</strong>\\n</root>\t{\"truck\": 1563128845, \"little\": -1009907448.0705619, \"possible\": \"gave\"}\t1\n4562892\t\\N\t5.8024375\t\\N\tMassa sapien faucibus et molestie ac. Praesent elementum facilisis leo vel. Turpis egestas pretium aenean pharetra magna. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Auctor neque vitae tempus quam pellentesque. Ornare aenean euismod elementum nisi quis eleifend. Purus sit amet luctus venenatis lectus. Tortor consequat id porta nibh venenatis cras sed felis eget. Felis bibendum ut tristique et egestas quis ipsum. Pretium fusce id velit ut tortor pretium viverra. Nam aliquam sem et tortor consequat. Nisl pretium fusce id velit. Sem integer vitae justo eget magna fermentum iaculis. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Vitae auctor eu augue ut lectus arcu. Malesuada fames ac turpis egestas. Ac odio tempor orci dapibus ultrices in. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Et malesuada fames ac turpis egestas integer. Sodales ut eu sem integer vitae justo eget.\t2031-07-14\t\\N\tf\t<root>\\n  <melted>\\n    <officer>-598731677.6283197</officer>\\n    <exist>variety</exist>\\n    <sitting>46234734.5525651</sitting>\\n    <period>rising</period>\\n    <rice>-1556052082.582368</rice>\\n  </melted>\\n  <got>eleven</got>\\n  <onlinetools>1863692621</onlinetools>\\n  <this>-139561185.33627748</this>\\n  <driver>funny</driver>\\n</root>\t[{\"ago\": {\"shut\": \"seven\", \"found\": 469996577.0459976, \"climate\": \"early\"}, \"scene\": \"slightly\", \"medicine\": true}, true, true]\t3\n87689278\t\\N\t-0.31813426\t \tId donec ultrices tincidunt arcu. Id nibh tortor id aliquet lectus. Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin. Cursus vitae congue mauris rhoncus. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sed turpis tincidunt id aliquet. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. Scelerisque eu ultrices vitae auctor eu augue ut. Volutpat ac tincidunt vitae semper quis.\t1976-12-10\t\\N\tt\t<root>\\n  <mission>rise</mission>\\n  <layers>\\n    <wire>consist</wire>\\n    <dinner>someone</dinner>\\n    <electric>white</electric>\\n    <heavy>victory</heavy>\\n    <ice>-761134241.8632131</ice>\\n  </layers>\\n  <help>1111641157</help>\\n  <comfortable>744054503</comfortable>\\n  <highway>1876042205.1417785</highway>\\n</root>\t{\"torn\": [false, -1325125579, false], \"rising\": false, \"volume\": \"grow\"}\t9\n687527896\t\\N\t-1.81914025\t \tFacilisi etiam dignissim diam quis enim. Diam ut venenatis tellus in metus vulputate eu. Mattis rhoncus urna neque viverra justo nec ultrices. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Nec ullamcorper sit amet risus nullam eget felis eget. Fames ac turpis egestas maecenas pharetra convallis posuere. Eget arcu dictum varius duis at consectetur lorem. Porta lorem mollis aliquam ut porttitor leo a diam sollicitudin. Magna fermentum iaculis eu non diam phasellus vestibulum lorem sed. Etiam non quam lacus suspendisse. Parturient montes nascetur ridiculus mus. Ornare suspendisse sed nisi lacus sed viverra tellus in. Interdum velit euismod in pellentesque massa placerat duis ultricies lacus. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar.\t2051-05-16\t\\N\tt\t<root>\\n  <piece>\\n    <vertical>398209907.5902777</vertical>\\n    <prove>wind</prove>\\n    <fair>parallel</fair>\\n    <closely>paint</closely>\\n    <see>-1386172501</see>\\n  </piece>\\n  <hide>previous</hide>\\n  <among>skill</among>\\n  <our>conversation</our>\\n  <cell>keep</cell>\\n</root>\t[[-128477882.56726694, 1569798072.8967233, {\"us\": 438307927.6373253, \"think\": -870063635, \"product\": \"stuck\"}], [{\"name\": \"broad\", \"took\": \"brother\", \"alphabet\": -731303259}, [-1065068182.0998564, \"finish\", \"up\"], false], false]\t5\n8767542\t\\N\t5.08081291\t\\N\tFames ac turpis egestas maecenas. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Sit amet commodo nulla facilisi nullam vehicula. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Maecenas ultricies mi eget mauris pharetra. Sed faucibus turpis in eu mi bibendum. Massa ultricies mi quis hendrerit dolor magna. Non diam phasellus vestibulum lorem sed. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus.\t2058-03-29\t\\N\tf\t<root>\\n  <invented>concerned</invented>\\n  <feet>-1671936329.7007055</feet>\\n  <win>slept</win>\\n  <until>how</until>\\n  <lion>-1838021068</lion>\\n</root>\t{\"basis\": \"mine\", \"company\": {\"tired\": false, \"prevent\": false, \"suppose\": 735075799}, \"worried\": {\"iron\": 378563223.91183805, \"nest\": false, \"raise\": {\"date\": false, \"engineer\": true, \"television\": 136840736.65782642}}}\t7\n\\.\n\n\n--\n-- Name: list_types_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres\n--\n\nSELECT pg_catalog.setval('public.list_types_id_seq', 10, true);\n\n\n--\n-- Name: list_types list_types_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres\n--\n\nALTER TABLE ONLY public.list_types\n    ADD CONSTRAINT list_types_pkey PRIMARY KEY (id);\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "modules/anonymizers/pgsql/dh.go",
    "content": "package pgsql_anonymize\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n\t\"github.com/nixys/nxs-data-anonymizer/modules/filters/relfilter\"\n)\n\nfunc dhSecurityCopy(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tuctx.security.tmpBuf = append(uctx.security.tmpBuf, token...)\n\tuctx.insertIntoBuf = nil\n\n\treturn deferred, nil\n}\n\nfunc dhCopyValuesEnd(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\tif uctx.insertIntoBuf != nil {\n\t\treturn []byte{}, nil\n\t}\n\n\treturn append(deferred, token...), nil\n}\n\nfunc dhCreateTableName(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\ttname := string(bytes.TrimSpace(deferred))\n\n\tuctx := usrCtx.(*userCtx)\n\tuctx.tn = &tname\n\n\treturn append(deferred, token...), nil\n}\n\nfunc dhCreateTableDesc(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tclmns := make(map[string]string)\n\n\tss := bytes.Split(deferred, []byte{'\\n'})\n\n\tfor _, v := range ss {\n\n\t\ts := strings.TrimSuffix(strings.TrimSpace(string(v)), \",\")\n\n\t\tif len(s) > 0 {\n\n\t\t\tu := strings.SplitN(s, \" \", 2)\n\n\t\t\t// If column type does not specified within the dump\n\t\t\tif len(u) < 2 {\n\t\t\t\tclmns[u[0]] = \"\"\n\t\t\t} else {\n\t\t\t\tclmns[u[0]] = u[1]\n\t\t\t}\n\t\t}\n\t}\n\n\tuctx.tables[*uctx.tn] = clmns\n\tuctx.tn = nil\n\n\treturn append(deferred, token...), nil\n}\n\nfunc dhTableName(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\ttname := string(bytes.TrimSpace(deferred))\n\n\tif !securityPolicyCheck(uctx, tname) {\n\n\t\t// If not: table will be skipped from result dump\n\n\t\tuctx.security.isSkip = true\n\t\tuctx.security.tmpBuf = []byte{}\n\n\t\treturn []byte{}, nil\n\t}\n\n\tuctx.filter.TableCreate(tname)\n\n\tuctx.insertIntoBuf = append(uctx.security.tmpBuf, append(deferred, token...)...)\n\n\tuctx.security.isSkip = false\n\tuctx.security.tmpBuf = []byte{}\n\n\treturn []byte{}, nil\n}\n\nfunc dhFieldName(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tfname := bytes.Trim(bytes.TrimSpace(deferred), \"\\\"\")\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\tuctx.filter.ColumnAdd(\n\t\tstring(fname),\n\t\tuctx.tables[uctx.filter.TableNameGet()][string(fname)],\n\t)\n\n\tuctx.insertIntoBuf = append(uctx.insertIntoBuf, append(deferred, token...)...)\n\n\treturn []byte{}, nil\n}\n\nfunc dhTableCopyTail(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\tuctx.insertIntoBuf = append(uctx.insertIntoBuf, append(deferred, token...)...)\n\n\treturn []byte{}, nil\n}\n\nfunc dhValue(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\ts := string(deferred)\n\tif s == \"\\\\N\" {\n\t\tuctx.filter.ValueAdd(misc.TemplateNULL)\n\t} else {\n\t\tuctx.filter.ValueAdd(s)\n\t}\n\n\treturn []byte{}, nil\n}\n\nfunc dhValueEnd(usrCtx any, deferred, token []byte) ([]byte, error) {\n\n\tuctx := usrCtx.(*userCtx)\n\n\tif uctx.security.isSkip == true {\n\t\treturn []byte{}, nil\n\t}\n\n\ts := string(deferred)\n\tif s == \"\\\\N\" {\n\t\tuctx.filter.ValueAdd(misc.TemplateNULL)\n\t} else {\n\t\tuctx.filter.ValueAdd(s)\n\t}\n\n\t// Apply filter for row\n\tif err := uctx.filter.Apply(); err != nil {\n\t\treturn []byte{}, err\n\t}\n\n\tb := rowDataGen(uctx.filter)\n\tif b == nil {\n\t\treturn []byte{}, nil\n\t} else {\n\t\tif uctx.insertIntoBuf != nil {\n\t\t\tb = append(uctx.insertIntoBuf, b...)\n\t\t\tuctx.insertIntoBuf = nil\n\t\t}\n\t}\n\n\treturn b, nil\n}\n\nfunc rowDataGen(filter *relfilter.Filter) []byte {\n\n\tvar out string\n\n\trow := filter.ValuePop()\n\tif row.Values == nil {\n\t\treturn nil\n\t}\n\n\tfor i, v := range row.Values {\n\n\t\tif i > 0 {\n\t\t\tout += \"\\t\"\n\t\t}\n\n\t\tif v.V == misc.TemplateNULL {\n\t\t\tout += \"\\\\N\"\n\t\t} else {\n\t\t\tout += fmt.Sprintf(\"%s\", v.V)\n\t\t}\n\t}\n\n\treturn fmt.Appendf([]byte(out), \"\\n\")\n}\n\n// SecurityPolicyCheck checks the table passes the security rules\n// true:  pass\n// false: skip\nfunc securityPolicyCheck(uctx *userCtx, tname string) bool {\n\n\t// Continue if security policy is `skip`\n\tif uctx.security.tablesPolicy != misc.SecurityPolicyTablesSkip {\n\t\treturn true\n\t}\n\n\t// Check rules for specified table name\n\tif tr := uctx.filter.TableRulesLookup(tname); tr != nil {\n\t\treturn true\n\t}\n\n\t// Check specified table name in exceptions\n\tif _, b := uctx.security.tableExceptions[tname]; b == true {\n\t\treturn true\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "modules/anonymizers/pgsql/pgsql.go",
    "content": "package pgsql_anonymize\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n\t\"github.com/nixys/nxs-data-anonymizer/modules/filters/relfilter\"\n\n\tfsm \"github.com/nixys/nxs-go-fsm\"\n)\n\ntype PgSQL struct {\n\tuctx         *userCtx\n\tsourceReader io.Reader\n}\n\ntype InitOpts struct {\n\tVariables map[string]relfilter.VariableRuleOpts\n\tSecurity  SecurityOpts\n\tRules     RulesOpts\n\tLink      []relfilter.LinkOpts\n}\n\ntype RulesOpts struct {\n\tTableRules       map[string]map[string]relfilter.ColumnRuleOpts\n\tDefaultRules     map[string]relfilter.ColumnRuleOpts\n\tExceptionColumns []string\n\tTypeRuleCustom   []relfilter.TypeRuleOpts\n}\n\ntype SecurityOpts struct {\n\tTablesPolicy    misc.SecurityPolicyTablesType\n\tColumnsPolicy   misc.SecurityPolicyColumnsType\n\tTableExceptions []string\n}\n\ntype userCtx struct {\n\tfilter        *relfilter.Filter\n\ttn            *string\n\tsecurity      securityCtx\n\ttables        map[string]map[string]string\n\tinsertIntoBuf []byte\n}\n\ntype securityCtx struct {\n\ttmpBuf []byte\n\tisSkip bool\n\n\ttablesPolicy    misc.SecurityPolicyTablesType\n\ttableExceptions map[string]any\n}\n\nfunc userCtxInit(s InitOpts) (*userCtx, error) {\n\n\tf, err := relfilter.Init(\n\t\trelfilter.InitOpts{\n\t\t\tVariables:        s.Variables,\n\t\t\tLink:             s.Link,\n\t\t\tTableRules:       s.Rules.TableRules,\n\t\t\tDefaultRules:     s.Rules.DefaultRules,\n\t\t\tExceptionColumns: s.Rules.ExceptionColumns,\n\t\t\tTypeRuleCustom:   s.Rules.TypeRuleCustom,\n\t\t\tTypeRuleDefault:  typeRuleDefault,\n\t\t\tColumnsPolicy:    s.Security.ColumnsPolicy,\n\t\t},\n\t)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"user ctx init: %w\", err)\n\t}\n\n\treturn &userCtx{\n\t\tfilter: f,\n\t\tsecurity: securityCtx{\n\t\t\ttablesPolicy: s.Security.TablesPolicy,\n\t\t\ttableExceptions: func() map[string]any {\n\t\t\t\texcs := make(map[string]any)\n\t\t\t\tfor _, e := range s.Security.TableExceptions {\n\t\t\t\t\texcs[e] = nil\n\t\t\t\t}\n\t\t\t\treturn excs\n\t\t\t}(),\n\t\t},\n\t\ttables: make(map[string]map[string]string),\n\t}, nil\n}\n\nfunc Init(r io.Reader, s InitOpts) (*PgSQL, error) {\n\n\tuctx, err := userCtxInit(s)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"pgsql anonymizer init: %w\", err)\n\t}\n\n\treturn &PgSQL{\n\t\tuctx:         uctx,\n\t\tsourceReader: r,\n\t}, nil\n}\n\nfunc (p *PgSQL) Run(ctx context.Context, w io.Writer) error {\n\n\tar := fsm.Init(\n\t\tp.sourceReader,\n\t\tfsm.Description{\n\t\t\tCtx:       ctx,\n\t\t\tUserCtx:   p.uctx,\n\t\t\tInitState: stateInit,\n\t\t\tStates: map[fsm.StateName]fsm.State{\n\n\t\t\t\tstateInit: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableName,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"COPY\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{'\\n'},\n\t\t\t\t\t\t\t\t\tR: []byte{' '},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhSecurityCopy,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateCreateTableName,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"CREATE TABLE\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{'\\n'},\n\t\t\t\t\t\t\t\t\tR: []byte{' '},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\tstateCreateTableName: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateCreateTableTail,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"(\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tR: []byte{'\\n', '\\r'},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhCreateTableName,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\tstateCreateTableTail: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateInit,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\");\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tR: []byte{'\\n', '\\r'},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhCreateTableDesc,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\tstateTableName: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateFieldName,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"(\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhTableName,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateFieldName: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateFieldName,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\",\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhFieldName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateCopyTail,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\")\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhFieldName,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateCopyTail: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableValues,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\";\\r\\n\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhTableCopyTail,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableValues,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\";\\n\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhTableCopyTail,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tstateTableValues: {\n\t\t\t\t\tNextStates: []fsm.NextState{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateInit,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte(\"\\\\.\"),\n\t\t\t\t\t\t\t\tDelimiters: fsm.Delimiters{\n\t\t\t\t\t\t\t\t\tL: []byte{'\\n'},\n\t\t\t\t\t\t\t\t\tR: []byte{'\\n', '\\r'},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tEscape: false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhCopyValuesEnd,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableValues,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte{'\\t'},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhValue,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: stateTableValues,\n\t\t\t\t\t\t\tSwitch: fsm.Switch{\n\t\t\t\t\t\t\t\tTrigger: []byte{'\\n'},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tDataHandler: dhValueEnd,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t)\n\n\t_, err := io.Copy(w, ar)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"pgsql anonymizer run: %w\", err)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "modules/anonymizers/pgsql/pgsql_test.go",
    "content": "package pgsql_anonymize\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n\t\"github.com/nixys/nxs-data-anonymizer/modules/filters/relfilter\"\n)\n\nfunc TestPgSQL(t *testing.T) {\n\n\tvar r, e bytes.Buffer\n\n\tfin, err := os.Open(\".testdata/pgsql_test.in.sql\")\n\tif err != nil {\n\t\tt.Fatal(\"open input SQL:\", err)\n\t}\n\n\tm, err := Init(\n\t\tfin,\n\t\tInitOpts{\n\t\t\tRules: RulesOpts{\n\t\t\t\tTableRules: map[string]map[string]relfilter.ColumnRuleOpts{\n\n\t\t\t\t\t// Delete only row with id `2`\n\t\t\t\t\t\"public.list_types\": {\n\t\t\t\t\t\t\"integer_type\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ if eq .Values.integer_type \\\"8765542\\\" }}{{ drop }}{{ else }}{{ .Values.integer_type }}{{ end }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t// Delete all rows from table\n\t\t\t\t\t\"public.list_types2\": {\n\t\t\t\t\t\t\"integer_type\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ drop }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t// Delete no rows\n\t\t\t\t\t\"public.list_types3\": {\n\t\t\t\t\t\t\"integer_type\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ if eq .Values.integer_type \\\"0\\\" }}{{ drop }}{{ else }}{{ .Values.integer_type }}{{ end }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tt.Fatal(\"init PgSQL:\", err)\n\t}\n\n\tif err := m.Run(context.Background(), &r); err != nil {\n\t\tt.Fatal(\"run PgSQL:\", err)\n\t}\n\n\tfout, err := os.Open(\".testdata/pgsql_test.out.sql\")\n\tif err != nil {\n\t\tt.Fatal(\"open output SQL:\", err)\n\t}\n\n\tif _, err := e.ReadFrom(fout); err != nil {\n\t\tt.Fatal(\"read output SQL:\", err)\n\t}\n\n\t// os.WriteFile(\".testdata/pgsql_test.out.sql\", r.Bytes(), 0644)\n\n\tif r.String() != e.String() {\n\t\tt.Fatal(\"incorrect anonymization result\")\n\t}\n\n\tt.Logf(\"success\")\n}\n\nfunc TestPgSQLDos(t *testing.T) {\n\n\tvar r, e bytes.Buffer\n\n\tfin, err := os.Open(\".testdata/pgsql_test.dos.in.sql\")\n\tif err != nil {\n\t\tt.Fatal(\"open input SQL:\", err)\n\t}\n\n\tm, err := Init(\n\t\tfin,\n\t\tInitOpts{\n\t\t\tRules: RulesOpts{\n\t\t\t\tTableRules: map[string]map[string]relfilter.ColumnRuleOpts{\n\n\t\t\t\t\t// Delete only row with id `2`\n\t\t\t\t\t\"public.list_types\": {\n\t\t\t\t\t\t\"integer_type\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ if eq .Values.integer_type \\\"8765542\\\" }}{{ drop }}{{ else }}{{ .Values.integer_type }}{{ end }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t// Delete all rows from table\n\t\t\t\t\t\"public.list_types2\": {\n\t\t\t\t\t\t\"integer_type\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ drop }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t// Delete no rows\n\t\t\t\t\t\"public.list_types3\": {\n\t\t\t\t\t\t\"integer_type\": relfilter.ColumnRuleOpts{\n\t\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\t\tValue:  \"{{ if eq .Values.integer_type \\\"0\\\" }}{{ drop }}{{ else }}{{ .Values.integer_type }}{{ end }}\",\n\t\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tt.Fatal(\"init PgSQL:\", err)\n\t}\n\n\tif err := m.Run(context.Background(), &r); err != nil {\n\t\tt.Fatal(\"run PgSQL:\", err)\n\t}\n\n\tfout, err := os.Open(\".testdata/pgsql_test.dos.out.sql\")\n\tif err != nil {\n\t\tt.Fatal(\"open output SQL:\", err)\n\t}\n\n\tif _, err := e.ReadFrom(fout); err != nil {\n\t\tt.Fatal(\"read output SQL:\", err)\n\t}\n\n\t// os.WriteFile(\".testdata/pgsql_test.dos.out.sql\", r.Bytes(), 0644)\n\n\tif r.String() != e.String() {\n\t\tt.Fatal(\"incorrect anonymization result\")\n\t}\n\n\tt.Logf(\"success\")\n}\n"
  },
  {
    "path": "modules/anonymizers/pgsql/security_types.go",
    "content": "package pgsql_anonymize\n\nimport (\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n\t\"github.com/nixys/nxs-data-anonymizer/modules/filters/relfilter\"\n)\n\nvar typeRuleDefault = []relfilter.TypeRuleOpts{\n\n\t// Integer\n\t{\n\t\tSelector: \"(?i)^boolean\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^smallint\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^integer\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^bigint\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^smallserial\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^serial\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^bigserial\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\n\t// Float\n\t{\n\t\tSelector: \"(?i)^decimal\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0.0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^numeric\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0.0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^real\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0.0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^double\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"0.0\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\n\t// Strings\n\t{\n\t\tSelector: \"(?i)^character\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"randomized character data\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^bpchar\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"randomized bpchar data\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^text\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"randomized text data\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\n\t// Date & time\n\t{\n\t\tSelector: \"(?i)^date\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"2024-01-01\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^time\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"00:00:00\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\n\t// Structures\n\t{\n\t\tSelector: \"(?i)^jsonb\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"{\\\"randomized\\\": \\\"json_data\\\"}\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n\t{\n\t\tSelector: \"(?i)^xml\",\n\t\tRule: relfilter.ColumnRuleOpts{\n\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\tValue:  \"<note><body>Randomized XML</body></note>\",\n\t\t\tUnique: false,\n\t\t},\n\t},\n}\n"
  },
  {
    "path": "modules/anonymizers/pgsql/states.go",
    "content": "package pgsql_anonymize\n\nimport fsm \"github.com/nixys/nxs-go-fsm\"\n\nvar (\n\tstateInit            = fsm.StateName(\"init\")\n\tstateCreateTableName = fsm.StateName(\"create table name\")\n\tstateCreateTableTail = fsm.StateName(\"create table tail\")\n\tstateTableName       = fsm.StateName(\"table name\")\n\tstateFieldName       = fsm.StateName(\"field name\")\n\tstateCopyTail        = fsm.StateName(\"copy tail\")\n\tstateTableValues     = fsm.StateName(\"table values\")\n)\n"
  },
  {
    "path": "modules/filters/relfilter/column.go",
    "content": "package relfilter\n\nimport \"fmt\"\n\ntype columns struct {\n\tcc []*column\n\tm  map[string]*column\n}\n\ntype column struct {\n\tn string\n\tt columnTypes\n}\n\ntype columnTypes struct {\n\traw    string\n\tgroups [][]string\n\tr      *ColumnRuleOpts\n\tenv    []string\n}\n\nfunc columnsInit() columns {\n\treturn columns{\n\t\tcc: []*column{},\n\t\tm:  make(map[string]*column),\n\t}\n}\n\nfunc (c *columns) add(name string, rt string, pts [][]string, r *ColumnRuleOpts) {\n\n\tenv := []string{fmt.Sprintf(\"%s=%s\", envVarColumnTypeRAW, rt)}\n\n\tfor i, g := range pts {\n\t\tfor j, sg := range g {\n\n\t\t\tif j == 0 {\n\t\t\t\tenv = append(\n\t\t\t\t\tenv,\n\t\t\t\t\tfmt.Sprintf(\"%s%d=%s\", envVarColumnTypeGroupPrefix, i, sg),\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tenv = append(\n\t\t\t\t\tenv,\n\t\t\t\t\tfmt.Sprintf(\"%s%d_%d=%s\", envVarColumnTypeGroupPrefix, i, j-1, sg),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\tv := column{\n\t\tn: name,\n\t\tt: columnTypes{\n\t\t\traw:    rt,\n\t\t\tgroups: pts,\n\t\t\tr:      r,\n\t\t\tenv:    env,\n\t\t},\n\t}\n\n\tc.cc = append(c.cc, &v)\n\tc.m[name] = &v\n}\n\nfunc (c *columns) getNameByIndex(index int) string {\n\tif index >= len(c.cc) {\n\t\treturn \"\"\n\t}\n\treturn c.cc[index].n\n}\n\nfunc (c *columns) delByName(name string) {\n\n\t// Get current column element\n\tv := c.m[name]\n\n\t// Delete element from map\n\tdelete(c.m, name)\n\n\t// Delete element from slice\n\tfor k, e := range c.cc {\n\t\tif e == v {\n\t\t\tc.cc = append(c.cc[:k], c.cc[k+1:]...)\n\t\t\tbreak\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/filters/relfilter/filter.go",
    "content": "package relfilter\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n)\n\ntype InitOpts struct {\n\tVariables map[string]VariableRuleOpts\n\n\tLink []LinkOpts\n\n\tTableRules       map[string]map[string]ColumnRuleOpts\n\tDefaultRules     map[string]ColumnRuleOpts\n\tExceptionColumns []string\n\n\tColumnsPolicy misc.SecurityPolicyColumnsType\n\n\tTypeRuleCustom  []TypeRuleOpts\n\tTypeRuleDefault []TypeRuleOpts\n}\n\ntype TypeRuleOpts struct {\n\tSelector string\n\tRule     ColumnRuleOpts\n}\n\ntype ColumnRuleOpts struct {\n\tType   misc.ValueType\n\tValue  string\n\tUnique bool\n}\n\ntype VariableRuleOpts struct {\n\tType  misc.ValueType\n\tValue string\n}\n\ntype LinkOpts struct {\n\tRule ColumnRuleOpts\n\tWith map[string][]string\n}\n\ntype Filter struct {\n\n\t// Rules for filter a table values\n\trules rules\n\n\t// Temp table data for filtering\n\ttableData tableData\n}\n\ntype Row struct {\n\tValues []rowValue\n}\n\ntype rules struct {\n\tvariables map[string]string\n\n\ttableRules       map[string]map[string]ColumnRuleOpts\n\tdefaultRules     map[string]ColumnRuleOpts\n\texceptionColumns map[string]any\n\n\tcolumnsPolicy misc.SecurityPolicyColumnsType\n\n\ttypeRuleCustom  []typeRule\n\ttypeRuleDefault []typeRule\n\n\tlink []linkValues\n}\n\ntype typeRule struct {\n\tRgx  *regexp.Regexp\n\tRule ColumnRuleOpts\n}\n\ntype tableData struct {\n\tname    string\n\tcolumns columns\n\tvalues  []rowValue\n\tuniques map[string]map[string]any\n}\n\ntype rowValue struct {\n\tV string\n}\n\ntype linkValues struct {\n\n\t// Linked tables and columns\n\tt map[string]map[string]any\n\n\t// Map old:new values\n\tv map[string]string\n\n\t// Unique map\n\tu map[string]any\n\n\t// Rule\n\tr ColumnRuleOpts\n}\n\ntype execFilterOpts struct {\n\tt misc.ValueType\n\tv string\n}\n\nconst uniqueAttempts = 5\n\nconst (\n\tenvVarGlobalPrefix          = \"ENVVARGLOBAL_\"\n\tenvVarTable                 = \"ENVVARTABLE\"\n\tenvVarColumnPrefix          = \"ENVVARCOLUMN_\"\n\tenvVarCurColumn             = \"ENVVARCURCOLUMN\"\n\tenvVarColumnTypeRAW         = \"ENVVARCOLUMNTYPERAW\"\n\tenvVarColumnTypeGroupPrefix = \"ENVVARCOLUMNTYPEGROUP_\"\n)\n\ntype applyRule struct {\n\tc  *column\n\ti  int\n\tcr ColumnRuleOpts\n\tlv map[string]string\n\tu  map[string]any\n}\n\nfunc Init(opts InitOpts) (*Filter, error) {\n\n\ttrc := []typeRule{}\n\ttrd := []typeRule{}\n\n\t// Make custom type rules\n\tfor _, r := range opts.TypeRuleCustom {\n\n\t\tre, err := regexp.Compile(r.Selector)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"filter init: %w\", err)\n\t\t}\n\n\t\ttrc = append(\n\t\t\ttrc,\n\t\t\ttypeRule{\n\t\t\t\tRgx:  re,\n\t\t\t\tRule: r.Rule,\n\t\t\t},\n\t\t)\n\t}\n\n\t// Make default type rules\n\tfor _, r := range opts.TypeRuleDefault {\n\n\t\tre, err := regexp.Compile(r.Selector)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"filter init: %w\", err)\n\t\t}\n\n\t\ttrd = append(\n\t\t\ttrd,\n\t\t\ttypeRule{\n\t\t\t\tRgx:  re,\n\t\t\t\tRule: r.Rule,\n\t\t\t},\n\t\t)\n\t}\n\n\t// Make exceptions\n\texcpts := make(map[string]any)\n\tfor _, e := range opts.ExceptionColumns {\n\t\texcpts[e] = nil\n\t}\n\n\tvars := make(map[string]string)\n\tfor n, f := range opts.Variables {\n\t\tv, _, err := execFilter(\n\t\t\texecFilterOpts{\n\t\t\t\tt: f.Type,\n\t\t\t\tv: f.Value,\n\t\t\t},\n\t\t\tnil,\n\t\t\tnil,\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"filter init: %w\", err)\n\t\t}\n\t\tvars[n] = v\n\t}\n\n\tlvs := []linkValues{}\n\t// Make links\n\tfor _, l := range opts.Link {\n\n\t\tlv := linkValues{\n\t\t\tt: make(map[string]map[string]any),\n\t\t\tv: make(map[string]string),\n\t\t\tu: func() map[string]any {\n\t\t\t\tif l.Rule.Unique {\n\t\t\t\t\treturn make(map[string]any)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}(),\n\t\t\tr: l.Rule,\n\t\t}\n\n\t\tfor t, cs := range l.With {\n\t\t\tm := make(map[string]any)\n\t\t\tfor _, c := range cs {\n\t\t\t\tm[c] = nil\n\t\t\t}\n\t\t\tlv.t[t] = m\n\t\t}\n\n\t\tlvs = append(lvs, lv)\n\t}\n\n\treturn &Filter{\n\t\trules: rules{\n\t\t\tvariables:        vars,\n\t\t\tlink:             lvs,\n\t\t\ttableRules:       opts.TableRules,\n\t\t\tdefaultRules:     opts.DefaultRules,\n\t\t\texceptionColumns: excpts,\n\t\t\ttypeRuleCustom:   trc,\n\t\t\ttypeRuleDefault:  trd,\n\t\t\tcolumnsPolicy:    opts.ColumnsPolicy,\n\t\t},\n\t}, nil\n}\n\n// TableCreate creates new data set for table `name`\nfunc (filter *Filter) TableCreate(name string) {\n\tfilter.tableData = tableData{\n\t\tname:    name,\n\t\tcolumns: columnsInit(),\n\t\tuniques: make(map[string]map[string]any),\n\t\tvalues:  []rowValue{},\n\t}\n}\n\nfunc (filter *Filter) TableNameGet() string {\n\treturn filter.tableData.name\n}\n\n// TableRulesLookup looks up filters for specified table name\nfunc (filter *Filter) TableRulesLookup(name string) map[string]ColumnRuleOpts {\n\tif t, b := filter.rules.tableRules[name]; b {\n\t\treturn t\n\t}\n\treturn nil\n}\n\n// ColumnAdd adds new column into current data set\nfunc (filter *Filter) ColumnAdd(name string, rt string) {\n\n\t//var rl *ColumnRuleOpts\n\n\tfor _, r := range filter.rules.typeRuleCustom {\n\t\tgd := r.Rgx.FindAllStringSubmatch(rt, -1)\n\t\tif len(gd) > 0 {\n\t\t\tfilter.tableData.columns.add(name, rt, gd, &r.Rule)\n\t\t\treturn\n\t\t}\n\t}\n\n\tfor _, r := range filter.rules.typeRuleDefault {\n\t\tgd := r.Rgx.FindAllStringSubmatch(rt, -1)\n\t\tif len(gd) > 0 {\n\t\t\tfilter.tableData.columns.add(name, rt, gd, &r.Rule)\n\t\t\treturn\n\t\t}\n\t}\n\n\tfilter.tableData.columns.add(name, rt, nil, nil)\n}\n\nfunc (filter *Filter) ColumnGetName(index int) string {\n\treturn filter.tableData.columns.getNameByIndex(index)\n}\n\nfunc (filter *Filter) ValueAdd(b string) {\n\tfilter.tableData.values = append(\n\t\tfilter.tableData.values,\n\t\trowValue{\n\t\t\tV: b,\n\t\t},\n\t)\n}\n\n// ValuePop pops the last values row from current data set\nfunc (filter *Filter) ValuePop() Row {\n\n\t// Save current values\n\tr := filter.tableData.values\n\n\tfilter.rowCleanup()\n\n\treturn Row{\n\t\tValues: r,\n\t}\n}\n\nfunc (filter *Filter) Apply() error {\n\n\tvar rls []applyRule\n\n\ttname := filter.tableData.name\n\n\t// Check rules exist for current table\n\ttr := filter.TableRulesLookup(tname)\n\n\t// Create rules for every column within current table\n\tfor i, c := range filter.tableData.columns.cc {\n\n\t\t// Check linked column\n\t\tt := false\n\t\tfor _, l := range filter.rules.link {\n\t\t\tif e, b := l.t[tname]; b == true {\n\t\t\t\tif _, u := e[c.n]; u == true {\n\t\t\t\t\trls = append(\n\t\t\t\t\t\trls,\n\t\t\t\t\t\tapplyRule{\n\t\t\t\t\t\t\tc:  c,\n\t\t\t\t\t\t\ti:  i,\n\t\t\t\t\t\t\tcr: l.r,\n\t\t\t\t\t\t\tlv: l.v,\n\t\t\t\t\t\t\tu:  l.u,\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t\tt = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif t {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check direct rules for column\n\t\tif tr != nil {\n\t\t\tif cr, e := tr[c.n]; e {\n\n\t\t\t\trls = append(\n\t\t\t\t\trls,\n\t\t\t\t\tapplyRule{\n\t\t\t\t\t\tc:  c,\n\t\t\t\t\t\ti:  i,\n\t\t\t\t\t\tcr: cr,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\t// Check default rules for column\n\t\tif cr, e := filter.rules.defaultRules[c.n]; e {\n\t\t\trls = append(\n\t\t\t\trls,\n\t\t\t\tapplyRule{\n\t\t\t\t\tc:  c,\n\t\t\t\t\ti:  i,\n\t\t\t\t\tcr: cr,\n\t\t\t\t},\n\t\t\t)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check column is excepted\n\t\tif _, b := filter.rules.exceptionColumns[c.n]; b {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Other rules if required\n\n\t\t// Default rules for types\n\t\tif filter.rules.columnsPolicy == misc.SecurityPolicyColumnsRandomize {\n\t\t\tif c.t.r != nil {\n\t\t\t\trls = append(\n\t\t\t\t\trls,\n\t\t\t\t\tapplyRule{\n\t\t\t\t\t\tc:  c,\n\t\t\t\t\t\ti:  i,\n\t\t\t\t\t\tcr: *c.t.r,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Apply rules\n\tif err := filter.applyRules(tname, rls); err != nil {\n\t\treturn fmt.Errorf(\"filters apply: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (filter *Filter) applyRules(tname string, rls []applyRule) error {\n\n\t// If no columns has rules\n\tif len(rls) == 0 {\n\t\treturn nil\n\t}\n\n\tvalEnvGlob := []string{}\n\tfor n, v := range filter.rules.variables {\n\t\tvalEnvGlob = append(\n\t\t\tvalEnvGlob,\n\t\t\tfmt.Sprintf(\"%s%s=%s\", envVarGlobalPrefix, n, v),\n\t\t)\n\t}\n\n\tvalOld := make(map[string]string)\n\tvalEnvOld := []string{}\n\tfor i, c := range filter.tableData.columns.cc {\n\n\t\tvalOld[c.n] = filter.tableData.values[i].V\n\n\t\t// Set env var only for columns with non-nil values\n\t\tvalEnvOld = append(\n\t\t\tvalEnvOld,\n\t\t\tfmt.Sprintf(\"%s%s=%s\", envVarColumnPrefix, c.n, filter.tableData.values[i].V),\n\t\t)\n\t}\n\n\t// Apply rule for each specified column\n\tfor _, r := range rls {\n\n\t\tvar (\n\t\t\tv   string\n\t\t\td   bool\n\t\t\terr error\n\t\t)\n\n\t\tif r.lv != nil {\n\n\t\t\t// For linked columns\n\n\t\t\ttd := struct {\n\t\t\t\tVariables map[string]string\n\t\t\t}{\n\t\t\t\tVariables: filter.rules.variables,\n\t\t\t}\n\n\t\t\tif vo := valOld[r.c.n]; vo == misc.TemplateNULL {\n\n\t\t\t\t// If old value for this cell is NULL\n\n\t\t\t\tv, d, err = filter.applyLinkFilter(r.c.n, r.cr, r.u, td, valEnvGlob)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"rules: %w\", err)\n\t\t\t\t}\n\n\t\t\t\tif d {\n\t\t\t\t\tfilter.tableData.values = nil\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Check linked value for this column already exist\n\t\t\t\tif e, b := r.lv[vo]; b {\n\t\t\t\t\tv = e\n\t\t\t\t} else {\n\t\t\t\t\tv, d, err = filter.applyLinkFilter(r.c.n, r.cr, r.u, td, valEnvGlob)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn fmt.Errorf(\"rules: %w\", err)\n\t\t\t\t\t}\n\n\t\t\t\t\tif d {\n\t\t\t\t\t\tfilter.tableData.values = nil\n\t\t\t\t\t\treturn nil\n\t\t\t\t\t}\n\n\t\t\t\t\tr.lv[vo] = v\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\n\t\t\ttype tplData struct {\n\t\t\t\tTableName        string\n\t\t\t\tCurColumnName    string\n\t\t\t\tValues           map[string]string\n\t\t\t\tVariables        map[string]string\n\t\t\t\tColumnTypeRaw    string\n\t\t\t\tColumnTypeGroups [][]string\n\t\t\t}\n\n\t\t\ttd := tplData{\n\t\t\t\tTableName:        tname,\n\t\t\t\tCurColumnName:    r.c.n,\n\t\t\t\tValues:           valOld,\n\t\t\t\tVariables:        filter.rules.variables,\n\t\t\t\tColumnTypeRaw:    r.c.t.raw,\n\t\t\t\tColumnTypeGroups: r.c.t.groups,\n\t\t\t}\n\n\t\t\ttde := []string{\n\t\t\t\tfmt.Sprintf(\"%s=%s\", envVarTable, tname),\n\t\t\t\tfmt.Sprintf(\"%s=%s\", envVarCurColumn, r.c.n),\n\t\t\t}\n\n\t\t\ttde = append(tde, valEnvOld...)\n\t\t\ttde = append(tde, valEnvGlob...)\n\t\t\ttde = append(tde, r.c.t.env...)\n\n\t\t\tv, d, err = filter.applyColumnFilter(r.c.n, r.cr, td, tde)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"rules: %w\", err)\n\t\t\t}\n\n\t\t\tif d {\n\t\t\t\tfilter.tableData.values = nil\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\n\t\t// Set specified value in accordance with filter\n\t\tfilter.tableData.values[r.i].V = v\n\t}\n\n\treturn nil\n}\n\nfunc (filter *Filter) applyColumnFilter(cn string, cr ColumnRuleOpts, td any, tde []string) (string, bool, error) {\n\n\tfor i := 0; i < uniqueAttempts; i++ {\n\n\t\tv, d, err := execFilter(\n\t\t\texecFilterOpts{\n\t\t\t\tt: cr.Type,\n\t\t\t\tv: cr.Value,\n\t\t\t},\n\t\t\ttd,\n\t\t\ttde)\n\t\tif err != nil {\n\t\t\treturn \"\", false, fmt.Errorf(\"apply filter: %w\", err)\n\t\t}\n\n\t\tif d {\n\t\t\treturn \"\", true, nil\n\t\t}\n\n\t\tif v == misc.TemplateNULL {\n\t\t\treturn v, false, nil\n\t\t}\n\n\t\tif !cr.Unique {\n\t\t\treturn v, false, nil\n\t\t}\n\n\t\tvar uv map[string]any\n\t\tif _, b := filter.tableData.uniques[cn]; !b {\n\t\t\t// For first values\n\t\t\tuv = make(map[string]any)\n\t\t} else {\n\t\t\tuv = filter.tableData.uniques[cn]\n\t\t}\n\n\t\tif _, b := uv[v]; !b {\n\t\t\tuv[v] = nil\n\t\t\tfilter.tableData.uniques[cn] = uv\n\t\t\treturn v, false, nil\n\t\t}\n\t}\n\n\treturn \"\", false, fmt.Errorf(\"filter: unable to generate unique value for column `%s.%s`, check filter value for this column in config\", filter.tableData.name, cn)\n}\n\nfunc (filter *Filter) applyLinkFilter(cn string, cr ColumnRuleOpts, u map[string]any, td any, tde []string) (string, bool, error) {\n\n\tfor i := 0; i < uniqueAttempts; i++ {\n\n\t\tv, d, err := execFilter(\n\t\t\texecFilterOpts{\n\t\t\t\tt: cr.Type,\n\t\t\t\tv: cr.Value,\n\t\t\t},\n\t\t\ttd,\n\t\t\ttde)\n\t\tif err != nil {\n\t\t\treturn \"\", false, fmt.Errorf(\"apply link filter: %w\", err)\n\t\t}\n\n\t\tif d {\n\t\t\treturn \"\", true, nil\n\t\t}\n\n\t\tif v == misc.TemplateNULL {\n\t\t\treturn v, false, nil\n\t\t}\n\n\t\tif cr.Unique == false {\n\t\t\treturn v, false, nil\n\t\t}\n\n\t\tif _, b := u[v]; b == false {\n\t\t\tu[v] = nil\n\t\t\treturn v, false, nil\n\t\t}\n\t}\n\n\treturn \"\", false, fmt.Errorf(\"apply link filter: unable to generate unique value for column `%s.%s`, check filter value for this column in config\", filter.tableData.name, cn)\n}\n\n// rowCleanup cleanups current row values\nfunc (filter *Filter) rowCleanup() {\n\tfilter.tableData.values = []rowValue{}\n}\n\nfunc execFilter(f execFilterOpts, td any, tde []string) (string, bool, error) {\n\n\tvar (\n\t\tr   string\n\t\td   bool\n\t\terr error\n\t)\n\n\tswitch f.t {\n\tcase misc.ValueTypeTemplate:\n\t\tvar t misc.TemlateRes\n\t\tt, err = misc.TemplateExec(\n\t\t\tf.v,\n\t\t\ttd,\n\t\t)\n\t\tif err != nil {\n\t\t\treturn \"\", false, fmt.Errorf(\"filter: value compile template: %w\", err)\n\t\t}\n\n\t\tr = t.Value\n\t\td = t.DropRow\n\tcase misc.ValueTypeCommand:\n\n\t\tvar stderr, stdout bytes.Buffer\n\n\t\tparsed_cmd := strings.Split(f.v, \" \")\n\t\tname := parsed_cmd[0]\n\t\targs := parsed_cmd[1:]\n\t\tcmd := exec.Command(name, args...)\n\n\t\tcmd.Stdout = &stdout\n\t\tcmd.Stderr = &stderr\n\n\t\tcmd.Env = tde\n\n\t\tif err := cmd.Run(); err != nil {\n\n\t\t\te, b := err.(*exec.ExitError)\n\t\t\tif b == false {\n\t\t\t\treturn \"\", false, fmt.Errorf(\"filter: value exec command: %w\", err)\n\t\t\t}\n\n\t\t\treturn \"\", false, fmt.Errorf(\"filter: value exec command: bad exit code %d: %s\", e.ExitCode(), stderr.String())\n\t\t}\n\n\t\tr = stdout.String()\n\n\tdefault:\n\t\treturn \"\", false, fmt.Errorf(\"filter: value compile: unknown type\")\n\t}\n\n\treturn strings.ReplaceAll(r, \"\\n\", \"\\\\n\"), d, nil\n}\n"
  },
  {
    "path": "modules/filters/relfilter/filter_test.go",
    "content": "package relfilter\n\nimport (\n\t\"testing\"\n\n\t\"github.com/nixys/nxs-data-anonymizer/misc\"\n)\n\nfunc TestExecFilter(t *testing.T) {\n\n\t// Test `drop` template function\n\tv, d, err := execFilter(\n\t\texecFilterOpts{\n\t\t\tt: misc.ValueTypeTemplate,\n\t\t\tv: \"{{- drop -}}\",\n\t\t},\n\t\tnil,\n\t\tnil)\n\tif err != nil {\n\t\tt.Fatal(\"`drop` function:\", err)\n\t}\n\tif v != \"\" || d == false {\n\t\tt.Fatal(\"`drop` function: incorrect return value\")\n\t}\n\tt.Logf(\"`drop` function: success\")\n\n\t// Test `null` template function\n\tv, d, err = execFilter(\n\t\texecFilterOpts{\n\t\t\tt: misc.ValueTypeTemplate,\n\t\t\tv: \"{{- null -}}\",\n\t\t},\n\t\tnil,\n\t\tnil)\n\tif err != nil {\n\t\tt.Fatal(\"`null` function:\", err)\n\t}\n\tif v != misc.TemplateNULL || d == true {\n\t\tt.Fatal(\"`null` function: incorrect return value\")\n\t}\n\tt.Logf(\"`null` function: success\")\n}\n\nfunc TestFilterApply(t *testing.T) {\n\tTestFilterApplyDropFunction(t)\n\tTestFilterApplyNullFunction(t)\n\tTestLinkFilterApplyDropFunction(t)\n}\n\nfunc TestFilterApplyDropFunction(t *testing.T) {\n\n\tf, err := Init(\n\t\tInitOpts{\n\t\t\tTableRules: map[string]map[string]ColumnRuleOpts{\n\t\t\t\t\"testTable\": {\n\t\t\t\t\t\"testColumn1\": ColumnRuleOpts{\n\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\tValue:  \"{{- drop -}}\",\n\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tt.Fatal(\"init:\", err)\n\t}\n\n\ttestFilterTableInit(f)\n\n\t// Apply filters for row\n\tif err := f.Apply(); err != nil {\n\t\tt.Fatal(\"apply:\", err)\n\t}\n\n\t// Get row values\n\tr := f.ValuePop()\n\n\tif r.Values != nil {\n\t\tt.Fatal(\"`drop` function: unexpected behaviour\")\n\t}\n\tt.Logf(\"`drop` function: success\")\n}\n\nfunc TestFilterApplyNullFunction(t *testing.T) {\n\n\tf, err := Init(\n\t\tInitOpts{\n\t\t\tTableRules: map[string]map[string]ColumnRuleOpts{\n\t\t\t\t\"testTable\": {\n\t\t\t\t\t\"testColumn1\": ColumnRuleOpts{\n\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\tValue:  \"{{- null -}}\",\n\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tt.Fatal(\"init:\", err)\n\t}\n\n\ttestFilterTableInit(f)\n\n\t// Apply filters for row\n\tif err := f.Apply(); err != nil {\n\t\tt.Fatal(\"apply:\", err)\n\t}\n\n\t// Get row values\n\tr := f.ValuePop()\n\n\tif len(r.Values) < 2 || r.Values[0].V != misc.TemplateNULL {\n\t\tt.Fatal(\"`null` function: unexpected behaviour\")\n\t}\n\tt.Logf(\"`null` function: success\")\n}\n\nfunc TestLinkFilterApply(t *testing.T) {\n\n\tf, err := Init(\n\t\tInitOpts{\n\t\t\tTableRules: map[string]map[string]ColumnRuleOpts{\n\t\t\t\t\"testTable1\": {\n\t\t\t\t\t\"testColumn1\": ColumnRuleOpts{\n\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\tValue:  \"{{- 11 -}}\",\n\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"testTable2\": {\n\t\t\t\t\t\"testColumn1\": ColumnRuleOpts{\n\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\tValue:  \"{{- 22 -}}\",\n\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\n\t\t\tLink: []LinkOpts{\n\t\t\t\t{\n\t\t\t\t\tRule: ColumnRuleOpts{\n\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\tValue:  \"{{- uuidv4 -}}\",\n\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t},\n\t\t\t\t\tWith: map[string][]string{\n\t\t\t\t\t\t\"testTable1\": {\n\t\t\t\t\t\t\t\"testColumn2\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"testTable2\": {\n\t\t\t\t\t\t\t\"testColumn2\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tt.Fatal(\"init:\", err)\n\t}\n\n\t// Fill table 1\n\ttestLinkFilterTable1Init(f)\n\n\t// Apply filters for row\n\tif err := f.Apply(); err != nil {\n\t\tt.Fatal(\"apply:\", err)\n\t}\n\n\t// Get row values\n\tr1 := f.ValuePop()\n\n\tif len(r1.Values) < 2 {\n\t\tt.Fatal(\"incorrect row len for table 1\")\n\t}\n\n\tif r1.Values[1].V == misc.TemplateNULL {\n\t\tt.Fatal(\"NULL cell value in table 1\")\n\t}\n\tv1 := r1.Values[1].V\n\n\t// Fill table 2\n\ttestLinkFilterTable2Init(f)\n\n\t// Apply filters for row\n\tif err := f.Apply(); err != nil {\n\t\tt.Fatal(\"apply:\", err)\n\t}\n\n\t// Get row values\n\tr2 := f.ValuePop()\n\n\tif len(r2.Values) < 2 {\n\t\tt.Fatal(\"incorrect row len for table 2\")\n\t}\n\n\tif r2.Values[1].V == misc.TemplateNULL {\n\t\tt.Fatal(\"NULL cell value in table 2\")\n\t}\n\tv2 := r2.Values[1].V\n\n\tif v1 != v2 {\n\t\tt.Fatal(\"incorrect values for tables after filter apply\")\n\t}\n\n\tt.Logf(\"success\")\n}\n\nfunc TestLinkFilterApplyDropFunction(t *testing.T) {\n\n\tf, err := Init(\n\t\tInitOpts{\n\t\t\tTableRules: map[string]map[string]ColumnRuleOpts{\n\t\t\t\t\"testTable1\": {\n\t\t\t\t\t\"testColumn1\": ColumnRuleOpts{\n\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\tValue:  \"{{- 1 -}}\",\n\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\n\t\t\tLink: []LinkOpts{\n\t\t\t\t{\n\t\t\t\t\tRule: ColumnRuleOpts{\n\t\t\t\t\t\tType:   misc.ValueTypeTemplate,\n\t\t\t\t\t\tValue:  \"{{- drop -}}\",\n\t\t\t\t\t\tUnique: false,\n\t\t\t\t\t},\n\t\t\t\t\tWith: map[string][]string{\n\t\t\t\t\t\t\"testTable1\": {\n\t\t\t\t\t\t\t\"testColumn2\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"testTable2\": {\n\t\t\t\t\t\t\t\"testColumn2\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tt.Fatal(\"init:\", err)\n\t}\n\n\t// Fill table 1\n\ttestLinkFilterTable1Init(f)\n\n\t// Apply filters for row\n\tif err := f.Apply(); err != nil {\n\t\tt.Fatal(\"apply:\", err)\n\t}\n\n\t// Get row values\n\tr1 := f.ValuePop()\n\n\tif r1.Values != nil {\n\t\tt.Fatal(\"`drop` function: unexpected behaviour for table 1\")\n\t}\n\n\t// Fill table 2\n\ttestLinkFilterTable2Init(f)\n\n\t// Apply filters for row\n\tif err := f.Apply(); err != nil {\n\t\tt.Fatal(\"apply:\", err)\n\t}\n\n\t// Get row values\n\tr2 := f.ValuePop()\n\n\tif r2.Values != nil {\n\t\tt.Fatal(\"`drop` function: unexpected behaviour for table 2\")\n\t}\n\n\tt.Logf(\"`drop` function: success\")\n}\n\nfunc testFilterTableInit(f *Filter) {\n\t// Create table\n\tf.TableCreate(\"testTable\")\n\n\t// Add column `testColumn1` with value\n\tf.ColumnAdd(\"testColumn1\", \"int\")\n\tf.ValueAdd(\"0\")\n\n\t// Add column `testColumn2` with value\n\tf.ColumnAdd(\"testColumn2\", \"varchar(10)\")\n\tf.ValueAdd(\"a\")\n}\n\nfunc testLinkFilterTable1Init(f *Filter) {\n\t// Create table\n\tf.TableCreate(\"testTable1\")\n\n\t// Add column `testColumn1` with value\n\tf.ColumnAdd(\"testColumn1\", \"int\")\n\tf.ValueAdd(\"1\")\n\n\t// Add column `testColumn2` with value\n\tf.ColumnAdd(\"testColumn2\", \"varchar(100)\")\n\tf.ValueAdd(\"a\")\n}\n\nfunc testLinkFilterTable2Init(f *Filter) {\n\t// Create table\n\tf.TableCreate(\"testTable2\")\n\n\t// Add column `testColumn1` with value\n\tf.ColumnAdd(\"testColumn1\", \"int\")\n\tf.ValueAdd(\"2\")\n\n\t// Add column `testColumn2` with value\n\tf.ColumnAdd(\"testColumn2\", \"varchar(100)\")\n\tf.ValueAdd(\"a\")\n}\n"
  },
  {
    "path": "modules/progress_reader/progress_reader.go",
    "content": "package progressreader\n\nimport \"io\"\n\ntype ProgressReader struct {\n\n\t// Source reader\n\tr io.Reader\n\n\t// Total read bytes\n\ttb int64\n}\n\nfunc Init(r io.Reader) *ProgressReader {\n\treturn &ProgressReader{\n\t\tr:  r,\n\t\ttb: 0,\n\t}\n}\n\nfunc (pr *ProgressReader) Read(dst []byte) (int, error) {\n\n\t// Proxy data from source reader to anonymizer\n\tn, err := pr.r.Read(dst)\n\n\t// Save read bytes count\n\tpr.tb += int64(n)\n\n\treturn n, err\n}\n\n// Bytes returns total read bytes from source reader\nfunc (pr *ProgressReader) Bytes() int64 {\n\treturn pr.tb\n}\n"
  },
  {
    "path": "routines/anonymizer/anonymizer.go",
    "content": "package anonymizer\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/docker/go-units\"\n\t\"github.com/nixys/nxs-data-anonymizer/ctx\"\n\t\"github.com/nixys/nxs-data-anonymizer/interfaces\"\n\t\"github.com/sirupsen/logrus\"\n\n\tappctx \"github.com/nixys/nxs-go-appctx/v3\"\n)\n\ntype anonymizeOpts struct {\n\tc  context.Context\n\tl  *logrus.Logger\n\tch chan error\n\tdb ctx.DBCtx\n\tw  io.Writer\n\ta  interfaces.Anonymizer\n}\n\nfunc Runtime(app appctx.App) error {\n\n\tvar (\n\t\t// Bytes count printed in log last time\n\t\tlb int64\n\n\t\t// Timer to print log read bytes count\n\t\ttimer *time.Timer\n\t)\n\n\tcc := app.ValueGet().(*ctx.Ctx)\n\n\tcx, cf := context.WithCancel(app.SelfCtx())\n\tdefer cf()\n\n\tch := make(chan error, 1)\n\n\ttimer = time.NewTimer(cc.Progress.Rhythm)\n\tif cc.Progress.Rhythm == 0 {\n\t\tif !timer.Stop() {\n\t\t\t<-timer.C\n\t\t}\n\t}\n\n\tif err := anonymize(\n\t\tanonymizeOpts{\n\t\t\tc:  cx,\n\t\t\tl:  cc.Log,\n\t\t\tch: ch,\n\t\t\tdb: cc.DB,\n\t\t\tw:  cc.Output,\n\t\t\ta:  cc.Anonymizer,\n\t\t},\n\t); err != nil {\n\t\treturn err\n\t}\n\n\tfor {\n\t\tselect {\n\t\tcase <-app.SelfCtxDone():\n\n\t\t\t// Log reader progress if necessary\n\t\t\tif cc.Progress.Rhythm != 0 && lb != cc.PR.Bytes() {\n\t\t\t\tprogressLog(cc.Log, cc.PR.Bytes(), cc.Progress.Humanize)\n\t\t\t}\n\n\t\t\tcc.Log.Info(\"anonymizer routine done\")\n\t\t\treturn nil\n\t\tcase err := <-ch:\n\n\t\t\t// Log reader progress if necessary\n\t\t\tif cc.Progress.Rhythm != 0 && lb != cc.PR.Bytes() {\n\t\t\t\tprogressLog(cc.Log, cc.PR.Bytes(), cc.Progress.Humanize)\n\t\t\t}\n\n\t\t\tif err != nil {\n\n\t\t\t\tcc.Log.WithFields(logrus.Fields{\n\t\t\t\t\t\"details\": err,\n\t\t\t\t}).Errorf(\"anonymize\")\n\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tcc.Log.Info(\"anonymizer routine done\")\n\t\t\treturn nil\n\t\tcase <-timer.C:\n\n\t\t\t// Save bytes count printed in log last time\n\t\t\tlb = cc.PR.Bytes()\n\n\t\t\t// Log reader progress\n\t\t\tprogressLog(cc.Log, lb, cc.Progress.Humanize)\n\n\t\t\ttimer.Reset(cc.Progress.Rhythm)\n\t\t}\n\t}\n}\n\nfunc anonymize(st anonymizeOpts) error {\n\n\tif st.db.Type == ctx.DBTypeMySQL && st.db.Cleanup == true && st.db.MySQL != nil {\n\t\tif err := st.db.MySQL.DBCleanup(); err != nil {\n\n\t\t\tst.l.WithFields(logrus.Fields{\n\t\t\t\t\"details\": err,\n\t\t\t}).Errorf(\"anonymize: MySQL clean up\")\n\n\t\t\treturn err\n\t\t}\n\t}\n\n\tgo func() {\n\t\tst.ch <- st.a.Run(st.c, st.w)\n\t}()\n\n\treturn nil\n}\n\nfunc progressLog(l *logrus.Logger, b int64, h bool) {\n\n\tvar s string\n\n\t// Prepare output bytes string\n\tif h == true {\n\t\ts = units.BytesSize(float64(b))\n\t} else {\n\t\ts = strconv.FormatInt(b, 10)\n\t}\n\n\tl.WithFields(\n\t\tlogrus.Fields{\n\t\t\t\"read bytes\": s,\n\t\t},\n\t).Info(\"anonymization progress\")\n}\n"
  }
]