diff --git a/.github/.kodiak.toml b/.github/.kodiak.toml index a963117a..f642dba8 100644 --- a/.github/.kodiak.toml +++ b/.github/.kodiak.toml @@ -1,7 +1,7 @@ version = 1 [approve] -auto_approve_usernames = ["cq-bot"] +auto_approve_usernames = ["cloudquery-ci"] [merge.message] body = "pull_request_body" diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..733537c3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: CloudQuery Central Issues Tracker + url: https://github.com/cloudquery/cloudquery/issues + about: Please file any issue with regards to any of CloudQuery repo in the main repository with the right labels. + - name: CloudQuery Discord Support + url: https://cloudquery.io/discord + about: Join our discord to get live support from us and the community. diff --git a/.github/renovate.json5 b/.github/renovate.json5 index df06f334..c0dec848 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,3 +1,9 @@ { extends: ["github>cloudquery/.github//.github/renovate-java-default.json5"], + packageRules: [ + { + matchPackageNames: ["/junit/"], + groupName: "junit", + }, + ], } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2dcbd3f9..0284d5ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,25 +8,32 @@ on: branches: - main +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: distribution: "temurin" java-version: "18" cache: "gradle" + - # Required for the package command tests to work + name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 + uses: gradle/actions/wrapper-validation@11d4d83c63a6ce61b32d8a9c4faddbdb04fe9917 - name: Build package run: ./gradlew build env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_ACTOR: ${{ github.actor }} - name: Publish Test Report - uses: mikepenz/action-junit-report@v3 + uses: mikepenz/action-junit-report@bccf2e31636835cf0874589931c4116687171386 # v6 if: success() || failure() # always run even if the previous step fails with: report_paths: "**/build/test-results/test/TEST-*.xml" diff --git a/.github/workflows/pr_title.yml b/.github/workflows/pr_title.yml index c7c8e476..d052afdc 100644 --- a/.github/workflows/pr_title.yml +++ b/.github/workflows/pr_title.yml @@ -1,12 +1,15 @@ name: "Validate PR title" on: - pull_request_target: + pull_request: types: - opened - edited - synchronize +permissions: + pull-requests: read + jobs: main: name: Validate PR title @@ -14,7 +17,7 @@ jobs: steps: # Please look up the latest version from # https://github.com/amannn/action-semantic-pull-request/releases - - uses: amannn/action-semantic-pull-request@v5 + - uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -41,7 +44,7 @@ jobs: # special "[WIP]" prefix to indicate this state. This will avoid the # validation of the PR title and the pull request checks remain pending. # Note that a second check will be reported if this is enabled. - wip: true + wip: false # When using "Squash and merge" on a PR with only one commit, GitHub # will suggest using that commit message instead of the PR title for the # merge commit, and it's easy to commit this by mistake. Enable this option diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 27671c9d..6294f61c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,24 +2,28 @@ name: publish on: push: tags: - - 'v*.*.*' + - "v*.*.*" + +permissions: + contents: read + packages: write jobs: - publish: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: '18' - cache: 'gradle' - - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 - - name: Publish package - uses: gradle/gradle-build-action@a4cf152f482c7ca97ef56ead29bf08bcd953284c - with: - arguments: publish - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + publish: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + distribution: "temurin" + java-version: "18" + cache: "gradle" + - name: Validate Gradle wrapper + uses: gradle/actions/wrapper-validation@11d4d83c63a6ce61b32d8a9c4faddbdb04fe9917 + - name: Setup Gradle + uses: gradle/actions/setup-gradle@11d4d83c63a6ce61b32d8a9c4faddbdb04fe9917 + - name: Publish Package + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: ./gradlew publish diff --git a/.github/workflows/release_pr.yml b/.github/workflows/release_pr.yml index b4f779d6..17134c92 100644 --- a/.github/workflows/release_pr.yml +++ b/.github/workflows/release_pr.yml @@ -4,20 +4,22 @@ on: branches: - main +permissions: + contents: read + jobs: release-please: runs-on: ubuntu-latest steps: - - uses: google-github-actions/release-please-action@v3 + - name: Generate GitHub App token + id: app-token + uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3 + with: + app-id: ${{ secrets.CQ_APP_ID }} + private-key: ${{ secrets.CQ_APP_PRIVATE_KEY }} + permission-contents: write + permission-pull-requests: write + - uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5 id: release with: - release-type: simple - package-name: plugin-sdk-java - token: ${{ secrets.GH_CQ_BOT }} - pull-request-title-pattern: "chore${scope}: Release${component} v${version}" - # Should breaking changes before 1.0.0 produce minor bumps? - bump-minor-pre-major: true - # Should feat changes before 1.0.0 produce patch bumps instead of minor bumps? - bump-patch-for-minor-pre-major: true - extra-files: | - lib/build.gradle + token: ${{ steps.app-token.outputs.token }} diff --git a/.gitignore b/.gitignore index 4c348d6d..1f85c677 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ build # Intellij .idea +.cq + +dist \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..7af0671e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,11 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.2.0 + hooks: + - id: check-added-large-files + + - repo: https://github.com/jguttman94/pre-commit-gradle + rev: v0.3.0 + hooks: + - id: gradle-spotless + args: ["-w"] diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 00000000..c0ab9f11 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.50" +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..7889b630 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,587 @@ +# Changelog + +## [0.0.50](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.49...v0.0.50) (2026-04-01) + + +### Bug Fixes + +* **deps:** Pin dependencies ([#428](https://github.com/cloudquery/plugin-sdk-java/issues/428)) ([348d4f2](https://github.com/cloudquery/plugin-sdk-java/commit/348d4f2c3fccc69227f2f79ff1eabdad4f4cc758)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.21.2 ([#430](https://github.com/cloudquery/plugin-sdk-java/issues/430)) ([9700fdb](https://github.com/cloudquery/plugin-sdk-java/commit/9700fdbc18b813546c08ef4e38518c942ae98032)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.43 ([#423](https://github.com/cloudquery/plugin-sdk-java/issues/423)) ([61bf310](https://github.com/cloudquery/plugin-sdk-java/commit/61bf31019ea0896ec15fa73d035149a5a517292d)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.44 ([#441](https://github.com/cloudquery/plugin-sdk-java/issues/441)) ([15246c6](https://github.com/cloudquery/plugin-sdk-java/commit/15246c68ad36e41c5eda49e1c9c961ca24a0f44e)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.45 ([#442](https://github.com/cloudquery/plugin-sdk-java/issues/442)) ([e0e403a](https://github.com/cloudquery/plugin-sdk-java/commit/e0e403a7d68acbd91ea60f5f35b9017d8cb15a52)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v4.4 ([#421](https://github.com/cloudquery/plugin-sdk-java/issues/421)) ([d78cb38](https://github.com/cloudquery/plugin-sdk-java/commit/d78cb38268b76054c96fc8231c7854903d829f35)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v4.4.1 ([#431](https://github.com/cloudquery/plugin-sdk-java/issues/431)) ([5917944](https://github.com/cloudquery/plugin-sdk-java/commit/591794424c8415598b932f205e7b4bc03b756ed8)) +* **deps:** Update dependency org.apache.arrow:arrow-memory-core to v19 ([#437](https://github.com/cloudquery/plugin-sdk-java/issues/437)) ([c02cbd7](https://github.com/cloudquery/plugin-sdk-java/commit/c02cbd78d72a840736216231e731f5fc7f81e3f8)) +* **deps:** Update dependency org.apache.arrow:arrow-memory-netty to v19 ([#438](https://github.com/cloudquery/plugin-sdk-java/issues/438)) ([e3f3811](https://github.com/cloudquery/plugin-sdk-java/commit/e3f38117cbd4b60822a780e6166a78a759c0e345)) +* **deps:** Update dependency org.apache.arrow:arrow-vector to v19 ([#439](https://github.com/cloudquery/plugin-sdk-java/issues/439)) ([284a6ff](https://github.com/cloudquery/plugin-sdk-java/commit/284a6ff1a331eeafeb838fcf4790dc00e4927f61)) +* **deps:** Update dependency org.mockito:mockito-core to v5.23.0 ([#432](https://github.com/cloudquery/plugin-sdk-java/issues/432)) ([24da588](https://github.com/cloudquery/plugin-sdk-java/commit/24da58803bcab2addd875b6542c60e808b3b0588)) +* **deps:** Update eclipse-temurin Docker tag to v21.0.10_7-jre ([#419](https://github.com/cloudquery/plugin-sdk-java/issues/419)) ([61cbcdd](https://github.com/cloudquery/plugin-sdk-java/commit/61cbcdd0ba29cf290e6814d0d4f64aa731b20ef0)) +* **deps:** Update eclipse-temurin Docker tag to v25 ([#440](https://github.com/cloudquery/plugin-sdk-java/issues/440)) ([1e16f27](https://github.com/cloudquery/plugin-sdk-java/commit/1e16f273b6a9f63ac4d45ee83279f705e8eb2e16)) +* **deps:** Update Gradle to v9.4.1 ([#433](https://github.com/cloudquery/plugin-sdk-java/issues/433)) ([55f1c17](https://github.com/cloudquery/plugin-sdk-java/commit/55f1c17af681c5e47c7fc5ff4d06743e1b29f133)) +* **deps:** Update grpc-java monorepo to v1.80.0 ([#434](https://github.com/cloudquery/plugin-sdk-java/issues/434)) ([9a20a3e](https://github.com/cloudquery/plugin-sdk-java/commit/9a20a3e5690ef1a276d1d2c49b43615c13a60ef3)) +* **deps:** Update junit to v6.0.3 ([#420](https://github.com/cloudquery/plugin-sdk-java/issues/420)) ([9e9cc74](https://github.com/cloudquery/plugin-sdk-java/commit/9e9cc74899035d5a8998bfbeda55f301b15e2e18)) +* **deps:** Update plugin com.diffplug.spotless to v8.4.0 ([#435](https://github.com/cloudquery/plugin-sdk-java/issues/435)) ([cd2fc4f](https://github.com/cloudquery/plugin-sdk-java/commit/cd2fc4f0d67fe6f147607dd6f1736e1714d850b9)) + +## [0.0.49](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.48...v0.0.49) (2026-02-04) + + +### Bug Fixes + +* **deps:** Update dependency gradle to v9.3.0 ([#403](https://github.com/cloudquery/plugin-sdk-java/issues/403)) ([8996e95](https://github.com/cloudquery/plugin-sdk-java/commit/8996e95d65ce159f416ece647459490072a71c43)) +* **deps:** Update dependency gradle to v9.3.1 ([#414](https://github.com/cloudquery/plugin-sdk-java/issues/414)) ([71bb584](https://github.com/cloudquery/plugin-sdk-java/commit/71bb5842bf29a0d6c4e4a1ba8b32e92470d67764)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.42 ([#413](https://github.com/cloudquery/plugin-sdk-java/issues/413)) ([af92a67](https://github.com/cloudquery/plugin-sdk-java/commit/af92a67d39b9d215a060c84ac2e7ec6a6ed8e3da)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v4.3.1 ([#404](https://github.com/cloudquery/plugin-sdk-java/issues/404)) ([1dedd94](https://github.com/cloudquery/plugin-sdk-java/commit/1dedd948e7c3516c8b90fd481d0037316da4fd9c)) +* **deps:** Update dependency org.assertj:assertj-core to v3.27.7 ([#402](https://github.com/cloudquery/plugin-sdk-java/issues/402)) ([a616bc4](https://github.com/cloudquery/plugin-sdk-java/commit/a616bc4a0dfa0dad426a4a6f45e54ec332ead2f8)) +* **deps:** Update dependency org.mockito:mockito-core to v5.21.0 ([#405](https://github.com/cloudquery/plugin-sdk-java/issues/405)) ([b43d75c](https://github.com/cloudquery/plugin-sdk-java/commit/b43d75ce21b5cf9c655994aecaadddfbf262d758)) +* **deps:** Update grpc-java monorepo to v1.78.0 ([#406](https://github.com/cloudquery/plugin-sdk-java/issues/406)) ([731a8f7](https://github.com/cloudquery/plugin-sdk-java/commit/731a8f7c1dec6c2b755ff0fab65369ae90598dcc)) +* **deps:** Update grpc-java monorepo to v1.79.0 ([#416](https://github.com/cloudquery/plugin-sdk-java/issues/416)) ([34d5591](https://github.com/cloudquery/plugin-sdk-java/commit/34d559160bbff639eb3ed58c78a9a7c46c150eb0)) +* **deps:** Update jackson monorepo ([#407](https://github.com/cloudquery/plugin-sdk-java/issues/407)) ([5ca69de](https://github.com/cloudquery/plugin-sdk-java/commit/5ca69de1872c5540c1f2470cdff8d30ea8540160)) +* **deps:** Update junit ([#408](https://github.com/cloudquery/plugin-sdk-java/issues/408)) ([5ba92df](https://github.com/cloudquery/plugin-sdk-java/commit/5ba92dfc18e12267206eb22d532163aa823aa10b)) +* **deps:** Update plugin com.diffplug.spotless to v8.2.0 ([#409](https://github.com/cloudquery/plugin-sdk-java/issues/409)) ([061fc4b](https://github.com/cloudquery/plugin-sdk-java/commit/061fc4b2aa5a35296bff34c66216d679a45490cb)) +* **deps:** Update plugin com.diffplug.spotless to v8.2.1 ([#415](https://github.com/cloudquery/plugin-sdk-java/issues/415)) ([35f210a](https://github.com/cloudquery/plugin-sdk-java/commit/35f210a33602dc4dc97294fd6b19d607169260d5)) +* **deps:** Update plugin io.freefair.lombok to v9.2.0 ([#410](https://github.com/cloudquery/plugin-sdk-java/issues/410)) ([7e8da5b](https://github.com/cloudquery/plugin-sdk-java/commit/7e8da5b3f21d12eae26488c05f1ad36155bd0621)) + +## [0.0.48](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.47...v0.0.48) (2026-01-02) + + +### Bug Fixes + +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.20.1 ([#391](https://github.com/cloudquery/plugin-sdk-java/issues/391)) ([9fe07de](https://github.com/cloudquery/plugin-sdk-java/commit/9fe07de8c1a445fd7c877e0d4509b457d78a6a44)) +* **deps:** Update dependency commons-io:commons-io to v2.21.0 ([#398](https://github.com/cloudquery/plugin-sdk-java/issues/398)) ([d1ad94f](https://github.com/cloudquery/plugin-sdk-java/commit/d1ad94fb3be963b170d89faff7db9a7dce6feb79)) +* **deps:** Update dependency gradle to v9.2.1 ([#399](https://github.com/cloudquery/plugin-sdk-java/issues/399)) ([48ec0ce](https://github.com/cloudquery/plugin-sdk-java/commit/48ec0ce5b3ff321096218f44cb9ff6fdb5037381)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.41 ([#400](https://github.com/cloudquery/plugin-sdk-java/issues/400)) ([6c93ede](https://github.com/cloudquery/plugin-sdk-java/commit/6c93ede13f72eac0b0e52d9ceb167e00d4235b0f)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v4.2 ([#387](https://github.com/cloudquery/plugin-sdk-java/issues/387)) ([5dc3164](https://github.com/cloudquery/plugin-sdk-java/commit/5dc316419a12bf6b707eb6fb266f8cb768d40eef)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v4.2.3 ([#392](https://github.com/cloudquery/plugin-sdk-java/issues/392)) ([4aff709](https://github.com/cloudquery/plugin-sdk-java/commit/4aff709e71a95b459861b46caf0c973f57a231b7)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v4.2.5 ([#395](https://github.com/cloudquery/plugin-sdk-java/issues/395)) ([18f8dca](https://github.com/cloudquery/plugin-sdk-java/commit/18f8dca46347540f3698dca7f0681512a80c16d6)) +* **deps:** Update dependency org.jooq:joou to v0.9.5 ([#396](https://github.com/cloudquery/plugin-sdk-java/issues/396)) ([8c0b996](https://github.com/cloudquery/plugin-sdk-java/commit/8c0b996d585580a4a1d3d4f1d59cca07c02ea88d)) +* **deps:** Update eclipse-temurin Docker tag to v21.0.9_10-jre ([#393](https://github.com/cloudquery/plugin-sdk-java/issues/393)) ([4154089](https://github.com/cloudquery/plugin-sdk-java/commit/4154089a9133d38a3d8f43dbf7b6f3cbb0f0083a)) +* **deps:** Update grpc-java monorepo to v1.76.0 ([#389](https://github.com/cloudquery/plugin-sdk-java/issues/389)) ([5c0c9ce](https://github.com/cloudquery/plugin-sdk-java/commit/5c0c9ce0e1cf283ca58c1100e5f4e85ecaa1c29f)) +* **deps:** Update log4j2 monorepo to v2.25.3 ([#397](https://github.com/cloudquery/plugin-sdk-java/issues/397)) ([64338a3](https://github.com/cloudquery/plugin-sdk-java/commit/64338a3132df1ee522c8b62b8ffc842b5b8da545)) + +## [0.0.47](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.46...v0.0.47) (2025-10-16) + + +### Bug Fixes + +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.40 ([#384](https://github.com/cloudquery/plugin-sdk-java/issues/384)) ([ff6ce30](https://github.com/cloudquery/plugin-sdk-java/commit/ff6ce309d1a428b860552d696e3d70c69d5bead6)) + +## [0.0.46](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.45...v0.0.46) (2025-10-01) + + +### Bug Fixes + +* **deps:** Update junit ([#379](https://github.com/cloudquery/plugin-sdk-java/issues/379)) ([0c0be66](https://github.com/cloudquery/plugin-sdk-java/commit/0c0be66971add6c9143779d8c514ad2c85b27aca)) +* **deps:** Update junit to v6 (major) ([#380](https://github.com/cloudquery/plugin-sdk-java/issues/380)) ([7706ec7](https://github.com/cloudquery/plugin-sdk-java/commit/7706ec71b6a03c7c07c269a9be548d14ea78d81f)) +* **deps:** Update plugin com.diffplug.spotless to v8 ([#381](https://github.com/cloudquery/plugin-sdk-java/issues/381)) ([119c9b1](https://github.com/cloudquery/plugin-sdk-java/commit/119c9b16059f1e2bb88e6f1013e5c177f4ee695a)) +* **deps:** Update plugin io.freefair.lombok to v9 ([#382](https://github.com/cloudquery/plugin-sdk-java/issues/382)) ([b023d40](https://github.com/cloudquery/plugin-sdk-java/commit/b023d4064da2d93bd142f2133bf9bd5cab8697b6)) + +## [0.0.45](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.44...v0.0.45) (2025-10-01) + + +### Bug Fixes + +* **deps:** Update dependency gradle to v9 ([#374](https://github.com/cloudquery/plugin-sdk-java/issues/374)) ([ec34114](https://github.com/cloudquery/plugin-sdk-java/commit/ec34114c214270e0a76cbc0c0b59d3bf12b5966f)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v4 ([#375](https://github.com/cloudquery/plugin-sdk-java/issues/375)) ([ff6972d](https://github.com/cloudquery/plugin-sdk-java/commit/ff6972d5691e173845c24c74a45a49cedb75daf5)) +* **deps:** Update dependency org.mockito:mockito-core to v5.20.0 ([#368](https://github.com/cloudquery/plugin-sdk-java/issues/368)) ([14791e2](https://github.com/cloudquery/plugin-sdk-java/commit/14791e27b2cca4d0bae855d2beb395ce06f4b304)) +* **deps:** Update plugin com.diffplug.spotless to v7 ([#376](https://github.com/cloudquery/plugin-sdk-java/issues/376)) ([d38c03e](https://github.com/cloudquery/plugin-sdk-java/commit/d38c03e16e92f26fa884b0058e26fa5d483a39e8)) +* **deps:** Update plugin org.gradle.toolchains.foojay-resolver-convention to v1 ([#377](https://github.com/cloudquery/plugin-sdk-java/issues/377)) ([0c0c48c](https://github.com/cloudquery/plugin-sdk-java/commit/0c0c48cab9196fd21b5f97925fc87e6ab4d5a75a)) + +## [0.0.44](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.43...v0.0.44) (2025-10-01) + + +### Bug Fixes + +* **deps:** Update dependency com.google.guava:guava to v33.5.0-jre ([#358](https://github.com/cloudquery/plugin-sdk-java/issues/358)) ([e60eb99](https://github.com/cloudquery/plugin-sdk-java/commit/e60eb99b2ea35bbd45ed88d439e1db1e27ba7752)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.35 ([#353](https://github.com/cloudquery/plugin-sdk-java/issues/353)) ([fbb196c](https://github.com/cloudquery/plugin-sdk-java/commit/fbb196cfb7268e3209cfa99997055e77deb75c8c)) +* **deps:** Update dependency org.assertj:assertj-core to v3.27.6 ([#357](https://github.com/cloudquery/plugin-sdk-java/issues/357)) ([af74a56](https://github.com/cloudquery/plugin-sdk-java/commit/af74a56160220e58d901db67961b3bd3f95d43d2)) +* **deps:** Update grpc-java monorepo to v1.75.0 ([#365](https://github.com/cloudquery/plugin-sdk-java/issues/365)) ([cd8f5fa](https://github.com/cloudquery/plugin-sdk-java/commit/cd8f5fa719f99abf70d3e96ec54fa675792974d1)) +* **deps:** Update jackson monorepo ([#366](https://github.com/cloudquery/plugin-sdk-java/issues/366)) ([05df6b2](https://github.com/cloudquery/plugin-sdk-java/commit/05df6b2e6984b48d1e2997b3438903d291a9601c)) +* **deps:** Update log4j2 monorepo to v2.25.2 ([#367](https://github.com/cloudquery/plugin-sdk-java/issues/367)) ([a978959](https://github.com/cloudquery/plugin-sdk-java/commit/a97895901f8dac1cbd0155e2b85a9c3f87e977fd)) +* **deps:** Update plugin io.freefair.lombok to v8.14.2 ([#369](https://github.com/cloudquery/plugin-sdk-java/issues/369)) ([94dd81c](https://github.com/cloudquery/plugin-sdk-java/commit/94dd81c2d396cdaa425cb1b020415b117fcc1520)) +* **deps:** Update plugin org.gradle.toolchains.foojay-resolver-convention to v0.10.0 ([#370](https://github.com/cloudquery/plugin-sdk-java/issues/370)) ([fbe0ce7](https://github.com/cloudquery/plugin-sdk-java/commit/fbe0ce7b8969add19d555dd17368349729b35047)) + +## [0.0.43](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.42...v0.0.43) (2025-09-01) + + +### Bug Fixes + +* **deps:** Update dependency commons-io:commons-io to v2.20.0 ([#343](https://github.com/cloudquery/plugin-sdk-java/issues/343)) ([a8781df](https://github.com/cloudquery/plugin-sdk-java/commit/a8781df5d3498638eab256e31fb95fce89f821e7)) +* **deps:** Update dependency gradle to v8.14.3 ([#344](https://github.com/cloudquery/plugin-sdk-java/issues/344)) ([9bfb2ba](https://github.com/cloudquery/plugin-sdk-java/commit/9bfb2baac9d8ce480c1cde1647c7efcce110a708)) +* **deps:** Update dependency org.apache.arrow:arrow-memory-core to v18.3.0 ([#346](https://github.com/cloudquery/plugin-sdk-java/issues/346)) ([7a72630](https://github.com/cloudquery/plugin-sdk-java/commit/7a72630fd95ac3f7c0e6a45f08d6015cc7e256e1)) +* **deps:** Update dependency org.apache.arrow:arrow-memory-netty to v18.3.0 ([#347](https://github.com/cloudquery/plugin-sdk-java/issues/347)) ([a842d83](https://github.com/cloudquery/plugin-sdk-java/commit/a842d833b1876a43424b01e849a9b72e75705b74)) +* **deps:** Update dependency org.apache.arrow:arrow-vector to v18.3.0 ([#352](https://github.com/cloudquery/plugin-sdk-java/issues/352)) ([5b81081](https://github.com/cloudquery/plugin-sdk-java/commit/5b81081f171853d2beffe3daae900b02f919f6de)) +* **deps:** Update dependency org.assertj:assertj-core to v3.27.4 ([#350](https://github.com/cloudquery/plugin-sdk-java/issues/350)) ([8812244](https://github.com/cloudquery/plugin-sdk-java/commit/8812244e2dd808027a76b71c15e6d980910b3878)) +* **deps:** Update eclipse-temurin Docker tag to v21.0.8_9-jre ([#351](https://github.com/cloudquery/plugin-sdk-java/issues/351)) ([52b6f5f](https://github.com/cloudquery/plugin-sdk-java/commit/52b6f5f3d94536f6284504aa9dc4faf85e621056)) + +## [0.0.42](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.41...v0.0.42) (2025-07-01) + + +### Bug Fixes + +* **deps:** Update dependency commons-io:commons-io to v2.19.0 ([#339](https://github.com/cloudquery/plugin-sdk-java/issues/339)) ([f99a5aa](https://github.com/cloudquery/plugin-sdk-java/commit/f99a5aa606f2114fd3711fc01063510911629441)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.33 ([#337](https://github.com/cloudquery/plugin-sdk-java/issues/337)) ([44b294c](https://github.com/cloudquery/plugin-sdk-java/commit/44b294c9903aed0354bc23226d3a1c7eb2dcc32e)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.34 ([#341](https://github.com/cloudquery/plugin-sdk-java/issues/341)) ([2eb3a83](https://github.com/cloudquery/plugin-sdk-java/commit/2eb3a83feef57382c79c36c2f74235465b7e3147)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.19.4 ([#338](https://github.com/cloudquery/plugin-sdk-java/issues/338)) ([41b66b7](https://github.com/cloudquery/plugin-sdk-java/commit/41b66b78b33d9839d5a9851e5ddd5f0dfaac6d7f)) + +## [0.0.41](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.40...v0.0.41) (2025-05-09) + + +### Bug Fixes + +* **deps:** Update dependency com.google.guava:guava to v33.4.8-jre ([#331](https://github.com/cloudquery/plugin-sdk-java/issues/331)) ([becd515](https://github.com/cloudquery/plugin-sdk-java/commit/becd515da6ff4786d2a733d87294d3814f2cd89e)) +* **deps:** Update dependency info.picocli:picocli to v4.7.7 ([#332](https://github.com/cloudquery/plugin-sdk-java/issues/332)) ([0e12831](https://github.com/cloudquery/plugin-sdk-java/commit/0e12831cf0663b2abdced91eabd406e4bf4c4440)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.32 ([#336](https://github.com/cloudquery/plugin-sdk-java/issues/336)) ([24ef423](https://github.com/cloudquery/plugin-sdk-java/commit/24ef423ef0497b92c83a950a2728d5baa3956cd6)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.19.3 ([#334](https://github.com/cloudquery/plugin-sdk-java/issues/334)) ([a541e73](https://github.com/cloudquery/plugin-sdk-java/commit/a541e73db6eafcc656a3c0e00e79624c4a314418)) +* **deps:** Update eclipse-temurin Docker tag to v21.0.7_6-jre ([#335](https://github.com/cloudquery/plugin-sdk-java/issues/335)) ([97b296b](https://github.com/cloudquery/plugin-sdk-java/commit/97b296b828c9b13c2a0eca430457e0ef75019f21)) + +## [0.0.40](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.39...v0.0.40) (2025-04-01) + + +### Bug Fixes + +* **deps:** Update dependency com.google.guava:guava to v33.4.5-jre ([#327](https://github.com/cloudquery/plugin-sdk-java/issues/327)) ([ba04bd3](https://github.com/cloudquery/plugin-sdk-java/commit/ba04bd3a666fe4146cab45259acfd7d716d56945)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.31 ([#330](https://github.com/cloudquery/plugin-sdk-java/issues/330)) ([cf7fc42](https://github.com/cloudquery/plugin-sdk-java/commit/cf7fc42c19128ade5819fae3455e98a24d008eee)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.19.2 ([#328](https://github.com/cloudquery/plugin-sdk-java/issues/328)) ([8928df4](https://github.com/cloudquery/plugin-sdk-java/commit/8928df4817126f752e2867f5128fef577a53a8e8)) + +## [0.0.39](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.38...v0.0.39) (2025-03-01) + + +### Bug Fixes + +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.19.1 ([#322](https://github.com/cloudquery/plugin-sdk-java/issues/322)) ([fd4d455](https://github.com/cloudquery/plugin-sdk-java/commit/fd4d4557529c38d1ea7ca2cbc7df41690b29c3f1)) +* **deps:** Update dependency org.apache.arrow:arrow-memory-core to v18.2.0 ([#323](https://github.com/cloudquery/plugin-sdk-java/issues/323)) ([db4448c](https://github.com/cloudquery/plugin-sdk-java/commit/db4448c1b2d473153c254fe3073508077c4b295d)) +* **deps:** Update dependency org.apache.arrow:arrow-memory-netty to v18.2.0 ([#325](https://github.com/cloudquery/plugin-sdk-java/issues/325)) ([efa937d](https://github.com/cloudquery/plugin-sdk-java/commit/efa937d7c0ad245177589580647da9816649cb8f)) +* **deps:** Update dependency org.apache.arrow:arrow-vector to v18.2.0 ([#326](https://github.com/cloudquery/plugin-sdk-java/issues/326)) ([5c884bd](https://github.com/cloudquery/plugin-sdk-java/commit/5c884bd91260bb118d3e8353b589c69800538a8c)) + +## [0.0.38](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.37...v0.0.38) (2025-02-03) + + +### Bug Fixes + +* **deps:** Update dependency gradle to v8.12.1 ([#314](https://github.com/cloudquery/plugin-sdk-java/issues/314)) ([0b29ccd](https://github.com/cloudquery/plugin-sdk-java/commit/0b29ccd5940d660f5e471e5055b5d2d1e98c2d29)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.30 ([#321](https://github.com/cloudquery/plugin-sdk-java/issues/321)) ([b875a01](https://github.com/cloudquery/plugin-sdk-java/commit/b875a01de78de0d68d4655614fb542672cb62790)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.18.1 ([#317](https://github.com/cloudquery/plugin-sdk-java/issues/317)) ([c1d543d](https://github.com/cloudquery/plugin-sdk-java/commit/c1d543d755c5328d9d6f970dbf0191d4d6738e01)) +* **deps:** Update dependency org.assertj:assertj-core to v3.27.3 ([#318](https://github.com/cloudquery/plugin-sdk-java/issues/318)) ([f321084](https://github.com/cloudquery/plugin-sdk-java/commit/f3210842975ca24d4cff089e29539450360adbcd)) +* **deps:** Update eclipse-temurin Docker tag to v21.0.6_7-jre ([#315](https://github.com/cloudquery/plugin-sdk-java/issues/315)) ([c888a38](https://github.com/cloudquery/plugin-sdk-java/commit/c888a38482089def2a7bbbcef61b72d562a94268)) +* **deps:** Update grpc-java monorepo to v1.70.0 ([#319](https://github.com/cloudquery/plugin-sdk-java/issues/319)) ([97b3b6c](https://github.com/cloudquery/plugin-sdk-java/commit/97b3b6c2ffce1d61b0966ce29304a4faee39866d)) +* **deps:** Update mockito monorepo to v5.15.2 ([#320](https://github.com/cloudquery/plugin-sdk-java/issues/320)) ([5110a9a](https://github.com/cloudquery/plugin-sdk-java/commit/5110a9a8f2a93cf808f58b20ca27b1e4a02806a7)) + +## [0.0.37](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.36...v0.0.37) (2025-01-07) + + +### Bug Fixes + +* **deps:** Update dependency com.google.guava:guava to v33.4.0-jre ([#310](https://github.com/cloudquery/plugin-sdk-java/issues/310)) ([1a54ac6](https://github.com/cloudquery/plugin-sdk-java/commit/1a54ac6b4c9acb68b6803bc194f55ecb9a963621)) +* **deps:** Update dependency gradle to v8.12 ([#311](https://github.com/cloudquery/plugin-sdk-java/issues/311)) ([1b6dd6f](https://github.com/cloudquery/plugin-sdk-java/commit/1b6dd6fa730135bb1e45a62af5c2bc91341127cf)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.29 ([#312](https://github.com/cloudquery/plugin-sdk-java/issues/312)) ([b0b06e3](https://github.com/cloudquery/plugin-sdk-java/commit/b0b06e3e534122c26ca56e325f6eef20e7c863e0)) +* **deps:** Update junit5 monorepo to v5.11.4 ([#307](https://github.com/cloudquery/plugin-sdk-java/issues/307)) ([16989e5](https://github.com/cloudquery/plugin-sdk-java/commit/16989e548d7a9fdc91be48321ff9383fec81c9ed)) +* **deps:** Update log4j2 monorepo to v2.24.3 ([#308](https://github.com/cloudquery/plugin-sdk-java/issues/308)) ([5967f90](https://github.com/cloudquery/plugin-sdk-java/commit/5967f9092724e2b8bbdf798c7dfdaf2779f11b52)) + +## [0.0.36](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.35...v0.0.36) (2024-12-02) + + +### Bug Fixes + +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-annotations to v2.18.2 ([#299](https://github.com/cloudquery/plugin-sdk-java/issues/299)) ([d2e2095](https://github.com/cloudquery/plugin-sdk-java/commit/d2e2095eb81241c4edff82e2bdb64476198fb4d1)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.18.2 ([#300](https://github.com/cloudquery/plugin-sdk-java/issues/300)) ([0f19754](https://github.com/cloudquery/plugin-sdk-java/commit/0f19754aa03ef90fc6716c04607ef6ee0029419b)) +* **deps:** Update dependency commons-io:commons-io to v2.18.0 ([#293](https://github.com/cloudquery/plugin-sdk-java/issues/293)) ([b3a12bf](https://github.com/cloudquery/plugin-sdk-java/commit/b3a12bf81d9e34fca594720e634b1037b83f13ff)) +* **deps:** Update dependency gradle to v8.11.1 ([#294](https://github.com/cloudquery/plugin-sdk-java/issues/294)) ([6a16d10](https://github.com/cloudquery/plugin-sdk-java/commit/6a16d108d97a9d6397c0053f0082ad4c88eddfe9)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.28 ([#301](https://github.com/cloudquery/plugin-sdk-java/issues/301)) ([8f34697](https://github.com/cloudquery/plugin-sdk-java/commit/8f34697509c5749f7c9db03afe8d14ace09728b2)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.17.3 ([#290](https://github.com/cloudquery/plugin-sdk-java/issues/290)) ([92919c2](https://github.com/cloudquery/plugin-sdk-java/commit/92919c2ac8c1c207ad04600f59ac189a9a1982e8)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.17.4 ([#302](https://github.com/cloudquery/plugin-sdk-java/issues/302)) ([475e096](https://github.com/cloudquery/plugin-sdk-java/commit/475e0965bfeb5d379a644170b55d2b59006cc666)) +* **deps:** Update dependency org.apache.arrow:arrow-memory-core to v18 ([#296](https://github.com/cloudquery/plugin-sdk-java/issues/296)) ([5d89dc7](https://github.com/cloudquery/plugin-sdk-java/commit/5d89dc7e76f5548f58727bd7e5d1315062dd15cf)) +* **deps:** Update dependency org.apache.arrow:arrow-memory-netty to v18 ([#297](https://github.com/cloudquery/plugin-sdk-java/issues/297)) ([0373336](https://github.com/cloudquery/plugin-sdk-java/commit/0373336d6f0bba3bd16ae82d6f52378969246292)) +* **deps:** Update dependency org.apache.arrow:arrow-vector to v18 ([#298](https://github.com/cloudquery/plugin-sdk-java/issues/298)) ([0c65f98](https://github.com/cloudquery/plugin-sdk-java/commit/0c65f98a18f751d5773494fcf0f68c55713a1638)) +* **deps:** Update grpc-java monorepo to v1.68.2 ([#303](https://github.com/cloudquery/plugin-sdk-java/issues/303)) ([9e2369e](https://github.com/cloudquery/plugin-sdk-java/commit/9e2369eee4c89b781c87a4c1e6719f1d2a516b98)) +* **deps:** Update log4j2 monorepo to v2.24.2 ([#291](https://github.com/cloudquery/plugin-sdk-java/issues/291)) ([4afac67](https://github.com/cloudquery/plugin-sdk-java/commit/4afac671f175df6222cf94a9826e6d6c5fcf0a8a)) +* **deps:** Update mockito monorepo to v5.14.2 ([#295](https://github.com/cloudquery/plugin-sdk-java/issues/295)) ([4556dbf](https://github.com/cloudquery/plugin-sdk-java/commit/4556dbf2f86d819c68d585736cf0a6dca08a80c0)) +* **deps:** Update plugin io.freefair.lombok to v8.11 ([#304](https://github.com/cloudquery/plugin-sdk-java/issues/304)) ([39d00d8](https://github.com/cloudquery/plugin-sdk-java/commit/39d00d8b5e76ab18335daa6cb0675b413a2674ef)) +* **deps:** Update plugin org.gradle.toolchains.foojay-resolver-convention to v0.9.0 ([#305](https://github.com/cloudquery/plugin-sdk-java/issues/305)) ([612917d](https://github.com/cloudquery/plugin-sdk-java/commit/612917d43ba46a2d6572964811fe5e14703fa606)) + +## [0.0.35](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.34...v0.0.35) (2024-11-04) + + +### Bug Fixes + +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-annotations to v2.18.1 ([#280](https://github.com/cloudquery/plugin-sdk-java/issues/280)) ([4b4d603](https://github.com/cloudquery/plugin-sdk-java/commit/4b4d60310dadfdb7f3efa6f257c923c84a753172)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.18.1 ([#281](https://github.com/cloudquery/plugin-sdk-java/issues/281)) ([62ba6f0](https://github.com/cloudquery/plugin-sdk-java/commit/62ba6f08e72e4c831a2d4819b69c321459a0241f)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.27 ([#289](https://github.com/cloudquery/plugin-sdk-java/issues/289)) ([ac66f9f](https://github.com/cloudquery/plugin-sdk-java/commit/ac66f9f5310a1f7454692fb3f3ee5990d2902400)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.17.1 ([#283](https://github.com/cloudquery/plugin-sdk-java/issues/283)) ([a327de7](https://github.com/cloudquery/plugin-sdk-java/commit/a327de7cd6aa1d65a8743cadd4ee8d52c5bb6076)) +* **deps:** Update eclipse-temurin Docker tag to v21.0.5_11-jre ([#284](https://github.com/cloudquery/plugin-sdk-java/issues/284)) ([7ebc6db](https://github.com/cloudquery/plugin-sdk-java/commit/7ebc6db3f7068914a98d5ccdfe385c167b6104a2)) +* **deps:** Update grpc-java monorepo to v1.68.1 ([#285](https://github.com/cloudquery/plugin-sdk-java/issues/285)) ([569f427](https://github.com/cloudquery/plugin-sdk-java/commit/569f4274dbe44c1ee54dbf2391e9f7ed8f55eaba)) +* **deps:** Update junit5 monorepo to v5.11.3 ([#286](https://github.com/cloudquery/plugin-sdk-java/issues/286)) ([18e0644](https://github.com/cloudquery/plugin-sdk-java/commit/18e0644d7d45aca0571d14ee48b2c360ddbab8ea)) +* **deps:** Update log4j2 monorepo to v2.24.1 ([#288](https://github.com/cloudquery/plugin-sdk-java/issues/288)) ([671e747](https://github.com/cloudquery/plugin-sdk-java/commit/671e7474411f3f9c14a5b144b3b5b2353bc28eeb)) +* **deps:** Update plugin io.freefair.lombok to v8.10.2 ([#287](https://github.com/cloudquery/plugin-sdk-java/issues/287)) ([e69b87f](https://github.com/cloudquery/plugin-sdk-java/commit/e69b87fec058c791b0314d239625b628800fb90c)) + +## [0.0.34](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.33...v0.0.34) (2024-10-01) + + +### Bug Fixes + +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-annotations to v2.18.0 ([#274](https://github.com/cloudquery/plugin-sdk-java/issues/274)) ([06e1ace](https://github.com/cloudquery/plugin-sdk-java/commit/06e1ace0d3a3530de3774936c27f67abfc7a6688)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.18.0 ([#275](https://github.com/cloudquery/plugin-sdk-java/issues/275)) ([aabdca2](https://github.com/cloudquery/plugin-sdk-java/commit/aabdca2c13416bc40ec31fa9306ed39ea52c823d)) +* **deps:** Update dependency com.google.guava:guava to v33.3.0-jre ([#263](https://github.com/cloudquery/plugin-sdk-java/issues/263)) ([b49373c](https://github.com/cloudquery/plugin-sdk-java/commit/b49373c7823a579d528a12cd0d87bbe96b4baa57)) +* **deps:** Update dependency com.google.guava:guava to v33.3.1-jre ([#271](https://github.com/cloudquery/plugin-sdk-java/issues/271)) ([6f20717](https://github.com/cloudquery/plugin-sdk-java/commit/6f2071765a38a007f938a0ce3e0709573318256d)) +* **deps:** Update dependency commons-io:commons-io to v2.17.0 ([#276](https://github.com/cloudquery/plugin-sdk-java/issues/276)) ([a6772ee](https://github.com/cloudquery/plugin-sdk-java/commit/a6772ee8d6113f0ecd703c49d484a3341da3915b)) +* **deps:** Update dependency gradle to v8.10 ([#264](https://github.com/cloudquery/plugin-sdk-java/issues/264)) ([aa13b26](https://github.com/cloudquery/plugin-sdk-java/commit/aa13b26b1b5be3b805bbc6af42a57cc9d2b34fe6)) +* **deps:** Update dependency gradle to v8.10.2 ([#272](https://github.com/cloudquery/plugin-sdk-java/issues/272)) ([db4ff77](https://github.com/cloudquery/plugin-sdk-java/commit/db4ff77224f790e9c4af5bd2996d245b64b54c0a)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.24 ([#269](https://github.com/cloudquery/plugin-sdk-java/issues/269)) ([eb838d5](https://github.com/cloudquery/plugin-sdk-java/commit/eb838d5cabc34fa869889fdb7b757060bf071272)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.25 ([#270](https://github.com/cloudquery/plugin-sdk-java/issues/270)) ([94bcb9f](https://github.com/cloudquery/plugin-sdk-java/commit/94bcb9fa7fb54fca5b91b66a4d9c2ad6f0550049)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.26 ([#279](https://github.com/cloudquery/plugin-sdk-java/issues/279)) ([f1c9521](https://github.com/cloudquery/plugin-sdk-java/commit/f1c952117ae09cf0a6cb37686c2edbbcd7b4bb76)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.16.2 ([#261](https://github.com/cloudquery/plugin-sdk-java/issues/261)) ([4804e5e](https://github.com/cloudquery/plugin-sdk-java/commit/4804e5e75d0c0bd6cf76667baf3d44bcb240d716)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.17 ([#277](https://github.com/cloudquery/plugin-sdk-java/issues/277)) ([174a527](https://github.com/cloudquery/plugin-sdk-java/commit/174a527a9450ab4c48af3e42542689cacb12ed19)) +* **deps:** Update grpc-java monorepo to v1.66.0 ([#265](https://github.com/cloudquery/plugin-sdk-java/issues/265)) ([0ec09c0](https://github.com/cloudquery/plugin-sdk-java/commit/0ec09c056ae5a72a8f77a2135d2a1ee76bfac275)) +* **deps:** Update grpc-java monorepo to v1.68.0 ([#278](https://github.com/cloudquery/plugin-sdk-java/issues/278)) ([ba2ca97](https://github.com/cloudquery/plugin-sdk-java/commit/ba2ca973335113feef3489a61955ccb2283b8517)) +* **deps:** Update junit5 monorepo to v5.11.0 ([#266](https://github.com/cloudquery/plugin-sdk-java/issues/266)) ([72ea770](https://github.com/cloudquery/plugin-sdk-java/commit/72ea770a1c0d5254368c930d17a4d6d5fb2cc936)) +* **deps:** Update junit5 monorepo to v5.11.1 ([#273](https://github.com/cloudquery/plugin-sdk-java/issues/273)) ([5aca422](https://github.com/cloudquery/plugin-sdk-java/commit/5aca4224c1b181fe71b41219d74e995e971e62de)) +* **deps:** Update mockito monorepo to v5.13.0 ([#267](https://github.com/cloudquery/plugin-sdk-java/issues/267)) ([3bed68c](https://github.com/cloudquery/plugin-sdk-java/commit/3bed68c93b4264d8999add7ad50cc4b1b89cc44b)) +* **deps:** Update plugin io.freefair.lombok to v8.10 ([#268](https://github.com/cloudquery/plugin-sdk-java/issues/268)) ([8ca46c9](https://github.com/cloudquery/plugin-sdk-java/commit/8ca46c9ad61fb0dfb63f5cc1ce97305086f37896)) + +## [0.0.33](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.32...v0.0.33) (2024-08-01) + + +### Bug Fixes + +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-annotations to v2.17.2 ([#251](https://github.com/cloudquery/plugin-sdk-java/issues/251)) ([d4abe8a](https://github.com/cloudquery/plugin-sdk-java/commit/d4abe8a3a8d7e8841018d7284efe224ab522764c)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.17.2 ([#253](https://github.com/cloudquery/plugin-sdk-java/issues/253)) ([d124e60](https://github.com/cloudquery/plugin-sdk-java/commit/d124e60dc1d3f3b88cc03a583cdf3b2be28fae4a)) +* **deps:** Update dependency gradle to v8.9 ([#257](https://github.com/cloudquery/plugin-sdk-java/issues/257)) ([1ae048e](https://github.com/cloudquery/plugin-sdk-java/commit/1ae048e323aedee872c06ac0e5e097756e1fca8b)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.23 ([#259](https://github.com/cloudquery/plugin-sdk-java/issues/259)) ([21f5c43](https://github.com/cloudquery/plugin-sdk-java/commit/21f5c43c470d7b0b3e20218eb447ccd10fd33568)) +* **deps:** Update dependency org.apache.arrow:arrow-memory-core to v17 ([#258](https://github.com/cloudquery/plugin-sdk-java/issues/258)) ([07b5f5b](https://github.com/cloudquery/plugin-sdk-java/commit/07b5f5bdf6dab06b54fb08cbe3d6bd6fce6d9a3e)) +* **deps:** Update dependency org.assertj:assertj-core to v3.26.3 ([#254](https://github.com/cloudquery/plugin-sdk-java/issues/254)) ([7084ec1](https://github.com/cloudquery/plugin-sdk-java/commit/7084ec1fb38c8a3fd329069d6eb7f455b238a785)) +* **deps:** Update eclipse-temurin Docker tag to v21.0.4_7-jre ([#255](https://github.com/cloudquery/plugin-sdk-java/issues/255)) ([8e0ba2f](https://github.com/cloudquery/plugin-sdk-java/commit/8e0ba2fff1b8c209df67df5416043c131b9c8b1d)) +* **deps:** Update grpc-java monorepo to v1.65.1 ([#256](https://github.com/cloudquery/plugin-sdk-java/issues/256)) ([909e42e](https://github.com/cloudquery/plugin-sdk-java/commit/909e42e4a17b8fd4e54430409cf739c67f43c449)) + +## [0.0.32](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.31...v0.0.32) (2024-07-30) + + +### Bug Fixes + +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.21 ([#247](https://github.com/cloudquery/plugin-sdk-java/issues/247)) ([4841a15](https://github.com/cloudquery/plugin-sdk-java/commit/4841a15ad58da5292ebd3c7737291394a46bb9f0)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.22 ([#249](https://github.com/cloudquery/plugin-sdk-java/issues/249)) ([76980e2](https://github.com/cloudquery/plugin-sdk-java/commit/76980e25f2e3b815093d8a1a97badc0c59465303)) + +## [0.0.31](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.30...v0.0.31) (2024-07-17) + + +### Bug Fixes + +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.20 ([#245](https://github.com/cloudquery/plugin-sdk-java/issues/245)) ([e851ef8](https://github.com/cloudquery/plugin-sdk-java/commit/e851ef872ee0b27f3c9888591ff7930370114a89)) + +## [0.0.30](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.29...v0.0.30) (2024-07-08) + + +### Bug Fixes + +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.19 ([#243](https://github.com/cloudquery/plugin-sdk-java/issues/243)) ([27c8044](https://github.com/cloudquery/plugin-sdk-java/commit/27c804403f38f12e6bca568057888c4f61871e0e)) +* **deps:** Update grpc-java monorepo to v1.65.0 ([#242](https://github.com/cloudquery/plugin-sdk-java/issues/242)) ([79ad2c5](https://github.com/cloudquery/plugin-sdk-java/commit/79ad2c50d96dd4d6e4e5a1a2091ce32b12245006)) +* **deps:** Update junit5 monorepo to v5.10.3 ([#240](https://github.com/cloudquery/plugin-sdk-java/issues/240)) ([1863b62](https://github.com/cloudquery/plugin-sdk-java/commit/1863b62ee6fe2e8d8b9504db81604cbc33178b0e)) + +## [0.0.29](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.28...v0.0.29) (2024-06-02) + + +### Bug Fixes + +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-annotations to v2.17.1 ([#229](https://github.com/cloudquery/plugin-sdk-java/issues/229)) ([838b81b](https://github.com/cloudquery/plugin-sdk-java/commit/838b81b45c22dc93e0cb6833b481300f49ee361a)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.17.1 ([#230](https://github.com/cloudquery/plugin-sdk-java/issues/230)) ([2266863](https://github.com/cloudquery/plugin-sdk-java/commit/2266863f941764485606805c70c7a3e407c19fb8)) +* **deps:** Update dependency com.google.guava:guava to v33.2.1-jre ([#233](https://github.com/cloudquery/plugin-sdk-java/issues/233)) ([c98b5f3](https://github.com/cloudquery/plugin-sdk-java/commit/c98b5f37e7cd2fb5656b0baa8d8862fa5fd5b925)) +* **deps:** Update dependency gradle to v8.8 ([#234](https://github.com/cloudquery/plugin-sdk-java/issues/234)) ([f8cd80c](https://github.com/cloudquery/plugin-sdk-java/commit/f8cd80cbb48e2951f22fdad544f580696364ea83)) +* **deps:** Update dependency info.picocli:picocli to v4.7.6 ([#232](https://github.com/cloudquery/plugin-sdk-java/issues/232)) ([c66f061](https://github.com/cloudquery/plugin-sdk-java/commit/c66f061f1bf03906bbb58b39b5ca107050191063)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.18 ([#238](https://github.com/cloudquery/plugin-sdk-java/issues/238)) ([2df653e](https://github.com/cloudquery/plugin-sdk-java/commit/2df653e35924848f1e3c37f278e44efb10244514)) +* **deps:** Update dependency org.assertj:assertj-core to v3.26.0 ([#235](https://github.com/cloudquery/plugin-sdk-java/issues/235)) ([a17d68b](https://github.com/cloudquery/plugin-sdk-java/commit/a17d68b4fc8483269b2d3aee8c3bf4caa6da4b8d)) +* **deps:** Update grpc-java monorepo to v1.64.0 ([#236](https://github.com/cloudquery/plugin-sdk-java/issues/236)) ([263359b](https://github.com/cloudquery/plugin-sdk-java/commit/263359bef71d5861d8f9e13c3a0f2d2753069d49)) +* **deps:** Update mockito monorepo to v5.12.0 ([#237](https://github.com/cloudquery/plugin-sdk-java/issues/237)) ([ae93cd0](https://github.com/cloudquery/plugin-sdk-java/commit/ae93cd036b3f64a1ec9fafc894c4379ff241817c)) + +## [0.0.28](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.27...v0.0.28) (2024-05-06) + + +### Bug Fixes + +* **deps:** Update dependency commons-io:commons-io to v2.16.1 ([#220](https://github.com/cloudquery/plugin-sdk-java/issues/220)) ([75c9203](https://github.com/cloudquery/plugin-sdk-java/commit/75c9203d3253898ae77de0885e9d93fe19eb2647)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.17 ([#228](https://github.com/cloudquery/plugin-sdk-java/issues/228)) ([1358a54](https://github.com/cloudquery/plugin-sdk-java/commit/1358a54fb53afd9633fc62e90e12270150c4de92)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.16.1 ([#222](https://github.com/cloudquery/plugin-sdk-java/issues/222)) ([753fbe1](https://github.com/cloudquery/plugin-sdk-java/commit/753fbe1121f53267154957a3e7d0c628f2e28f7f)) +* **deps:** Update eclipse-temurin Docker tag to v21.0.3_9-jre ([#223](https://github.com/cloudquery/plugin-sdk-java/issues/223)) ([5cf512e](https://github.com/cloudquery/plugin-sdk-java/commit/5cf512eaf9c18560474d9a115777fa87f102a5e3)) +* **deps:** Update grpc-java monorepo to v1.63.0 ([#224](https://github.com/cloudquery/plugin-sdk-java/issues/224)) ([1b69fb6](https://github.com/cloudquery/plugin-sdk-java/commit/1b69fb67a2b15827fe1a23ec6cd96c848d5e513e)) + +## [0.0.27](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.26...v0.0.27) (2024-04-11) + + +### Bug Fixes + +* Call setParents on `MemDB` tables ([#217](https://github.com/cloudquery/plugin-sdk-java/issues/217)) ([4015cb5](https://github.com/cloudquery/plugin-sdk-java/commit/4015cb59625f6cb7269b47ae3421f499d9879ac0)) + +## [0.0.26](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.25...v0.0.26) (2024-04-01) + + +### Bug Fixes + +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.16 ([#215](https://github.com/cloudquery/plugin-sdk-java/issues/215)) ([9af1ce3](https://github.com/cloudquery/plugin-sdk-java/commit/9af1ce3c3696e08a476d1c2fa5039d8d32de9bc5)) + +## [0.0.25](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.24...v0.0.25) (2024-04-01) + + +### Bug Fixes + +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-annotations to v2.17.0 ([#201](https://github.com/cloudquery/plugin-sdk-java/issues/201)) ([2722410](https://github.com/cloudquery/plugin-sdk-java/commit/2722410c86bc5faa018e8a4f4dd98efe940e8551)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.17.0 ([#202](https://github.com/cloudquery/plugin-sdk-java/issues/202)) ([b8ccd92](https://github.com/cloudquery/plugin-sdk-java/commit/b8ccd92e4e8d554c2d86311ad434a975247a87ac)) +* **deps:** Update dependency com.google.guava:guava to v33 ([#208](https://github.com/cloudquery/plugin-sdk-java/issues/208)) ([a264e2e](https://github.com/cloudquery/plugin-sdk-java/commit/a264e2ec4f00b285e80db9a5ba60647e0a34d164)) +* **deps:** Update dependency commons-io:commons-io to v2.16.0 ([#203](https://github.com/cloudquery/plugin-sdk-java/issues/203)) ([3e92081](https://github.com/cloudquery/plugin-sdk-java/commit/3e92081d7ec5518d0148dd91cf0c81d49530795b)) +* **deps:** Update dependency gradle ([#204](https://github.com/cloudquery/plugin-sdk-java/issues/204)) ([1861a6c](https://github.com/cloudquery/plugin-sdk-java/commit/1861a6cb239c98e21e55a558424e89ebdd3709d1)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.16 ([#205](https://github.com/cloudquery/plugin-sdk-java/issues/205)) ([9083c89](https://github.com/cloudquery/plugin-sdk-java/commit/9083c89a73d8861b864df5a822555e9b2fdce513)) +* **deps:** Update dependency org.apache.arrow:arrow-memory-core to v15 ([#209](https://github.com/cloudquery/plugin-sdk-java/issues/209)) ([688f627](https://github.com/cloudquery/plugin-sdk-java/commit/688f627a8093d42d9ae621134bdb6fcd3ba38f08)) +* **deps:** Update dependency org.apache.arrow:arrow-memory-netty to v15 ([#210](https://github.com/cloudquery/plugin-sdk-java/issues/210)) ([ac5aec4](https://github.com/cloudquery/plugin-sdk-java/commit/ac5aec4eb46874a19d70553606ac4d3aea7d1a79)) +* **deps:** Update dependency org.apache.arrow:arrow-vector to v15 ([#211](https://github.com/cloudquery/plugin-sdk-java/issues/211)) ([a205c1c](https://github.com/cloudquery/plugin-sdk-java/commit/a205c1ce1db1d9658794e0881f666eee4bcd9dcb)) +* **deps:** Update eclipse-temurin Docker tag to v21 ([#212](https://github.com/cloudquery/plugin-sdk-java/issues/212)) ([6e950c7](https://github.com/cloudquery/plugin-sdk-java/commit/6e950c77302ab9a227df65798f5eaa2f1e4f791a)) +* **deps:** Update log4j2 monorepo to v2.23.1 ([#199](https://github.com/cloudquery/plugin-sdk-java/issues/199)) ([29ca1d3](https://github.com/cloudquery/plugin-sdk-java/commit/29ca1d31020a7083d71a781b512f24c0999df469)) +* **deps:** Update mockito monorepo to v5.11.0 ([#206](https://github.com/cloudquery/plugin-sdk-java/issues/206)) ([2ce7c14](https://github.com/cloudquery/plugin-sdk-java/commit/2ce7c1423b97e9a250ea98ccc4134aa0f4781aaf)) +* **deps:** Update plugin org.gradle.toolchains.foojay-resolver-convention to v0.8.0 ([#207](https://github.com/cloudquery/plugin-sdk-java/issues/207)) ([2ab7da7](https://github.com/cloudquery/plugin-sdk-java/commit/2ab7da7af1f19992c3dc04d4a2d6bbe96146d51b)) + +## [0.0.24](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.23...v0.0.24) (2024-03-26) + + +### Bug Fixes + +* Add missing docker_image_tag in package json ([#196](https://github.com/cloudquery/plugin-sdk-java/issues/196)) ([bd32518](https://github.com/cloudquery/plugin-sdk-java/commit/bd32518bae6fc0761b3a0319fb39c0067a1cf840)) + +## [0.0.23](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.22...v0.0.23) (2024-03-26) + + +### Features + +* Add package command ([#194](https://github.com/cloudquery/plugin-sdk-java/issues/194)) ([05407bb](https://github.com/cloudquery/plugin-sdk-java/commit/05407bbec19f2e782aafc21ec6f7511840cccc2d)) + +## [0.0.22](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.21...v0.0.22) (2024-03-05) + + +### Bug Fixes + +* **deps:** Update actions/setup-java action to v4 ([#192](https://github.com/cloudquery/plugin-sdk-java/issues/192)) ([d919222](https://github.com/cloudquery/plugin-sdk-java/commit/d919222afa1908a4c74f337ac15528a15faa0fa4)) +* **deps:** Update dependency gradle to v8.6 ([#186](https://github.com/cloudquery/plugin-sdk-java/issues/186)) ([0325779](https://github.com/cloudquery/plugin-sdk-java/commit/032577937cafd9980853d7fed3ef125c37ea807e)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.15 ([#190](https://github.com/cloudquery/plugin-sdk-java/issues/190)) ([a35a6e6](https://github.com/cloudquery/plugin-sdk-java/commit/a35a6e64787b00488874f29c7a9a3a32407f9dbe)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.15.7 ([#182](https://github.com/cloudquery/plugin-sdk-java/issues/182)) ([611c8a7](https://github.com/cloudquery/plugin-sdk-java/commit/611c8a7dff6e279bde190ba3227652e25d8e934e)) +* **deps:** Update dependency org.assertj:assertj-core to v3.25.3 ([#184](https://github.com/cloudquery/plugin-sdk-java/issues/184)) ([c1ab19c](https://github.com/cloudquery/plugin-sdk-java/commit/c1ab19c1b45174561e90ba79609c205375333c44)) +* **deps:** Update grpc-java monorepo to v1.62.2 ([#187](https://github.com/cloudquery/plugin-sdk-java/issues/187)) ([ec009d7](https://github.com/cloudquery/plugin-sdk-java/commit/ec009d7721940b9cb5481c8b81b2287cb4defe80)) +* **deps:** Update junit5 monorepo to v5.10.2 ([#185](https://github.com/cloudquery/plugin-sdk-java/issues/185)) ([144b687](https://github.com/cloudquery/plugin-sdk-java/commit/144b6879c1d4f2b11d31aca19646e8bd6b1313a1)) +* **deps:** Update log4j2 monorepo to v2.23.0 ([#188](https://github.com/cloudquery/plugin-sdk-java/issues/188)) ([04c740c](https://github.com/cloudquery/plugin-sdk-java/commit/04c740c39ea3a4ef3fe40b28d1b4e8d0841e098d)) +* **deps:** Update plugin io.freefair.lombok to v8.6 ([#189](https://github.com/cloudquery/plugin-sdk-java/issues/189)) ([0f5568f](https://github.com/cloudquery/plugin-sdk-java/commit/0f5568f8bdecb251bf13303d2faf368cdeba0da9)) + +## [0.0.21](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.20...v0.0.21) (2024-02-09) + + +### Features + +* Implement `GetSpecSchema` ([#180](https://github.com/cloudquery/plugin-sdk-java/issues/180)) ([9eeb976](https://github.com/cloudquery/plugin-sdk-java/commit/9eeb976c868b1a206230b6285d666671a18682a7)) + + +### Bug Fixes + +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.14 ([#178](https://github.com/cloudquery/plugin-sdk-java/issues/178)) ([6871551](https://github.com/cloudquery/plugin-sdk-java/commit/6871551de650ee36464699ec6cbb0f124676f282)) +* **deps:** Update grpc-java monorepo to v1.61.1 ([#172](https://github.com/cloudquery/plugin-sdk-java/issues/172)) ([4ada7bc](https://github.com/cloudquery/plugin-sdk-java/commit/4ada7bcade9cf94043a9ba99c86c2fef43c3a645)) + +## [0.0.20](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.19...v0.0.20) (2024-02-06) + + +### Bug Fixes + +* Update artifact & group ID ([#176](https://github.com/cloudquery/plugin-sdk-java/issues/176)) ([46db086](https://github.com/cloudquery/plugin-sdk-java/commit/46db08666cad988460288c433db327f4f0a3b49c)) + +## [0.0.19](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.18...v0.0.19) (2024-02-01) + + +### Bug Fixes + +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.12 ([#168](https://github.com/cloudquery/plugin-sdk-java/issues/168)) ([02663c1](https://github.com/cloudquery/plugin-sdk-java/commit/02663c1ea7f5dd664ff2eb66d26648ea6e26bf1d)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.15.6 ([#170](https://github.com/cloudquery/plugin-sdk-java/issues/170)) ([20d4830](https://github.com/cloudquery/plugin-sdk-java/commit/20d48303122f04f2f578e345dcb5d0722502efce)) +* **deps:** Update dependency org.assertj:assertj-core to v3.25.2 ([#171](https://github.com/cloudquery/plugin-sdk-java/issues/171)) ([96d0b66](https://github.com/cloudquery/plugin-sdk-java/commit/96d0b661452b9a8557da9dfe8e52f3fa6212da59)) +* **deps:** Update log4j2 monorepo to v2.22.1 ([#173](https://github.com/cloudquery/plugin-sdk-java/issues/173)) ([60ba1c6](https://github.com/cloudquery/plugin-sdk-java/commit/60ba1c6731a310a9aa84638f60794491e64e1c85)) +* **deps:** Update mockito monorepo to v5.10.0 ([#174](https://github.com/cloudquery/plugin-sdk-java/issues/174)) ([477e6a5](https://github.com/cloudquery/plugin-sdk-java/commit/477e6a5f52c20e9539f76c9cfc6c5d1482ed1a49)) +* **deps:** Update plugin com.diffplug.spotless to v6.25.0 ([#175](https://github.com/cloudquery/plugin-sdk-java/issues/175)) ([1f38c22](https://github.com/cloudquery/plugin-sdk-java/commit/1f38c2285a4580d3d78954c5f73d4ad4649a4892)) + +## [0.0.18](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.17...v0.0.18) (2024-01-02) + + +### Bug Fixes + +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-annotations to v2.16.1 ([#159](https://github.com/cloudquery/plugin-sdk-java/issues/159)) ([bd1e79b](https://github.com/cloudquery/plugin-sdk-java/commit/bd1e79b736c0bbae8cb75b27d58e9c21a79211b4)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.16.1 ([#160](https://github.com/cloudquery/plugin-sdk-java/issues/160)) ([d663db8](https://github.com/cloudquery/plugin-sdk-java/commit/d663db8376ea63bb6244a285f2d8fd70622bffd8)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.11 ([#131](https://github.com/cloudquery/plugin-sdk-java/issues/131)) ([6ae7381](https://github.com/cloudquery/plugin-sdk-java/commit/6ae738194c71d12e7f92b0756110aa5fcb61e0aa)) +* **deps:** Update dependency io.grpc:grpc-protobuf to v1.60.1 ([#163](https://github.com/cloudquery/plugin-sdk-java/issues/163)) ([8dfcccd](https://github.com/cloudquery/plugin-sdk-java/commit/8dfcccd4eea048d53be3f02c09ee22946dd22a5c)) +* **deps:** Update dependency io.grpc:grpc-services to v1.60.1 ([#139](https://github.com/cloudquery/plugin-sdk-java/issues/139)) ([6fc59f2](https://github.com/cloudquery/plugin-sdk-java/commit/6fc59f264e3e544db07459644c29c8bdb1f93391)) +* **deps:** Update dependency io.grpc:grpc-stub to v1.60.1 ([#164](https://github.com/cloudquery/plugin-sdk-java/issues/164)) ([b8b96bd](https://github.com/cloudquery/plugin-sdk-java/commit/b8b96bda65595be115e777e2e9a9ac6c7dabffea)) +* **deps:** Update dependency io.grpc:grpc-testing to v1.60.1 ([#165](https://github.com/cloudquery/plugin-sdk-java/issues/165)) ([f889c39](https://github.com/cloudquery/plugin-sdk-java/commit/f889c3959850cdb2cdc37413791276c0f703983b)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.15.5 ([#161](https://github.com/cloudquery/plugin-sdk-java/issues/161)) ([9057cdf](https://github.com/cloudquery/plugin-sdk-java/commit/9057cdfdb08ebe21ae6edf4df2bb48e210355f45)) +* **deps:** Update dependency org.assertj:assertj-core to v3.25.0 ([#166](https://github.com/cloudquery/plugin-sdk-java/issues/166)) ([54dc63f](https://github.com/cloudquery/plugin-sdk-java/commit/54dc63fa72713f3bbca85fc5654b24a5e4d93d60)) + +## [0.0.17](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.16...v0.0.17) (2023-12-29) + + +### Bug Fixes + +* Add --license placeholder for future use ([#156](https://github.com/cloudquery/plugin-sdk-java/issues/156)) ([4159df8](https://github.com/cloudquery/plugin-sdk-java/commit/4159df84c52fc6db8b7fbad112bdb04fe06d53d6)) + +## [0.0.16](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.15...v0.0.16) (2023-12-06) + + +### Bug Fixes + +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-annotations to v2.16.0 ([#152](https://github.com/cloudquery/plugin-sdk-java/issues/152)) ([13e9fb1](https://github.com/cloudquery/plugin-sdk-java/commit/13e9fb1a7fe0e6eb69424949e338f5a1c57c42e2)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.16.0 ([#153](https://github.com/cloudquery/plugin-sdk-java/issues/153)) ([9ae481f](https://github.com/cloudquery/plugin-sdk-java/commit/9ae481fa49b3a5e0344dc0dff6b74e4f157f8f9a)) +* **deps:** Update dependency gradle to v8.5 ([#154](https://github.com/cloudquery/plugin-sdk-java/issues/154)) ([586dc32](https://github.com/cloudquery/plugin-sdk-java/commit/586dc3295595af31a82c7b65cfd803c6677815e6)) +* **deps:** Update dependency io.grpc:grpc-protobuf to v1.59.1 ([#147](https://github.com/cloudquery/plugin-sdk-java/issues/147)) ([0400750](https://github.com/cloudquery/plugin-sdk-java/commit/0400750e1ad6368c8c4e70107d8a4c728071f303)) +* **deps:** Update dependency io.grpc:grpc-stub to v1.59.1 ([#149](https://github.com/cloudquery/plugin-sdk-java/issues/149)) ([977b9cf](https://github.com/cloudquery/plugin-sdk-java/commit/977b9cfb3c427531a44f7bbaff4d4122ef947dfc)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.15.4 ([#150](https://github.com/cloudquery/plugin-sdk-java/issues/150)) ([893c8da](https://github.com/cloudquery/plugin-sdk-java/commit/893c8dad0d353e5e1cf28d3c4c71652cf0fdaba2)) +* **deps:** Update junit5 monorepo to v5.10.1 ([#151](https://github.com/cloudquery/plugin-sdk-java/issues/151)) ([9b93ae7](https://github.com/cloudquery/plugin-sdk-java/commit/9b93ae7a14c61489bdd638143582f52636d2df97)) +* Use correct param name for `--no-sentry` (not `--disable-sentry`) ([#155](https://github.com/cloudquery/plugin-sdk-java/issues/155)) ([363299b](https://github.com/cloudquery/plugin-sdk-java/commit/363299be40564ee690a3e70d752a01d84dfe8b34)) + +## [0.0.15](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.14...v0.0.15) (2023-11-27) + + +### Bug Fixes + +* **test:** Register extensions in tests ([#144](https://github.com/cloudquery/plugin-sdk-java/issues/144)) ([530e2b2](https://github.com/cloudquery/plugin-sdk-java/commit/530e2b2ceb869abaf7f50c35c1dc3cced084f733)) + +## [0.0.14](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.13...v0.0.14) (2023-11-27) + + +### Features + +* Add better roundtrip support ([#142](https://github.com/cloudquery/plugin-sdk-java/issues/142)) ([d59f91a](https://github.com/cloudquery/plugin-sdk-java/commit/d59f91a76b33c8a311bbc6584ca9d4dd43d627bf)) + +## [0.0.13](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.12...v0.0.13) (2023-11-26) + + +### Bug Fixes + +* add date types to ArrowHelper ([#141](https://github.com/cloudquery/plugin-sdk-java/issues/141)) ([21e4981](https://github.com/cloudquery/plugin-sdk-java/commit/21e49818c8a3e55f6b0316750cc8026151ea40d1)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-annotations to v2.15.3 ([#133](https://github.com/cloudquery/plugin-sdk-java/issues/133)) ([627b49d](https://github.com/cloudquery/plugin-sdk-java/commit/627b49de71ab9e3fa90a3b930970a2b9f1d97a4f)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.15.3 ([#135](https://github.com/cloudquery/plugin-sdk-java/issues/135)) ([235781d](https://github.com/cloudquery/plugin-sdk-java/commit/235781df38e59ff9ae0257a0827561c9bfc26341)) +* **deps:** Update dependency com.google.guava:guava to v32.1.3-jre ([#136](https://github.com/cloudquery/plugin-sdk-java/issues/136)) ([eb7b853](https://github.com/cloudquery/plugin-sdk-java/commit/eb7b853ee48ca2dacb6f03b4b6f4d6cb1898a92f)) +* **deps:** Update dependency gradle to v8.4 ([#137](https://github.com/cloudquery/plugin-sdk-java/issues/137)) ([8675852](https://github.com/cloudquery/plugin-sdk-java/commit/8675852d77cf6676c1a6d214c4b53ad3ef3112e8)) +* **deps:** Update dependency io.grpc:grpc-protobuf to v1.59.0 ([#138](https://github.com/cloudquery/plugin-sdk-java/issues/138)) ([88d3e71](https://github.com/cloudquery/plugin-sdk-java/commit/88d3e713338339dc9fd0dd1c23f55f7c0e508ac5)) +* **deps:** Update dependency io.grpc:grpc-stub to v1.59.0 ([#140](https://github.com/cloudquery/plugin-sdk-java/issues/140)) ([556b91b](https://github.com/cloudquery/plugin-sdk-java/commit/556b91bf28fc21df9b1e1e7e6b42fe1396f505a8)) + +## [0.0.12](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.11...v0.0.12) (2023-10-01) + + +### Bug Fixes + +* **deps:** Update dependency gradle to v8.3 ([#128](https://github.com/cloudquery/plugin-sdk-java/issues/128)) ([567a6f3](https://github.com/cloudquery/plugin-sdk-java/commit/567a6f3ee3cc14af2417c2f2ca64c701eb69d3fa)) +* **deps:** Update dependency io.cloudquery:plugin-pb-java to v0.0.7 ([#125](https://github.com/cloudquery/plugin-sdk-java/issues/125)) ([9307c76](https://github.com/cloudquery/plugin-sdk-java/commit/9307c76e0a1bd0ae0b965ecb72b82ad72d76ebc3)) +* **deps:** Update dependency io.grpc:grpc-protobuf to v1.58.0 ([#129](https://github.com/cloudquery/plugin-sdk-java/issues/129)) ([674b9b8](https://github.com/cloudquery/plugin-sdk-java/commit/674b9b81f92d8b847e43f6049adb7c285dafb966)) +* **deps:** Update dependency nl.jqno.equalsverifier:equalsverifier to v3.15.2 ([#127](https://github.com/cloudquery/plugin-sdk-java/issues/127)) ([4050638](https://github.com/cloudquery/plugin-sdk-java/commit/405063845f83017b6adea4cbc7997ec4ec6d5441)) + +## [0.0.11](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.10...v0.0.11) (2023-09-01) + + +### Bug Fixes + +* remove unused data types ([#122](https://github.com/cloudquery/plugin-sdk-java/issues/122)) ([acbceda](https://github.com/cloudquery/plugin-sdk-java/commit/acbcedab5f3c1ffa00c648fd1ff5f5542c372466)) + +## [0.0.10](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.9...v0.0.10) (2023-09-01) + + +### Bug Fixes + +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-annotations to v2.15.2 ([#114](https://github.com/cloudquery/plugin-sdk-java/issues/114)) ([9784f43](https://github.com/cloudquery/plugin-sdk-java/commit/9784f43df5c53dcc36b1fd48354537d68ac137b3)) +* **deps:** Update dependency com.fasterxml.jackson.core:jackson-core to v2.15.2 ([#116](https://github.com/cloudquery/plugin-sdk-java/issues/116)) ([ba041d9](https://github.com/cloudquery/plugin-sdk-java/commit/ba041d9e79b87671dc38e238b6e5dcd7dffe64e8)) +* **deps:** Update dependency info.picocli:picocli to v4.7.5 ([#117](https://github.com/cloudquery/plugin-sdk-java/issues/117)) ([e6ebb84](https://github.com/cloudquery/plugin-sdk-java/commit/e6ebb84d33842517e9f9709a648d014ddb1d3d91)) +* **deps:** Update dependency io.grpc:grpc-protobuf to v1.57.2 ([#118](https://github.com/cloudquery/plugin-sdk-java/issues/118)) ([59687cd](https://github.com/cloudquery/plugin-sdk-java/commit/59687cd98bffce0b7396babcede5ae07f426ee03)) +* **deps:** Update dependency io.grpc:grpc-services to v1.57.2 ([#119](https://github.com/cloudquery/plugin-sdk-java/issues/119)) ([83ac40b](https://github.com/cloudquery/plugin-sdk-java/commit/83ac40bcb307cb671279db0a600b5aaa66c0a5fb)) +* **deps:** Update dependency io.grpc:grpc-stub to v1.57.2 ([#120](https://github.com/cloudquery/plugin-sdk-java/issues/120)) ([a3bb02c](https://github.com/cloudquery/plugin-sdk-java/commit/a3bb02c24c4dc7978554a4e95131a8194286003d)) +* **deps:** Update dependency io.grpc:grpc-testing to v1.57.2 ([#121](https://github.com/cloudquery/plugin-sdk-java/issues/121)) ([0df4a4f](https://github.com/cloudquery/plugin-sdk-java/commit/0df4a4f4c17ae3bf963c92d7fe5861889f0cdf26)) + +## [0.0.9](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.8...v0.0.9) (2023-08-31) + + +### Features + +* Add `null` client ([3896982](https://github.com/cloudquery/plugin-sdk-java/commit/3896982b5e5b6eda9e529468195a413f60a8d454)) + +## [0.0.8](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.7...v0.0.8) (2023-08-30) + + +### Bug Fixes + +* check for extension type before built-in arrow types ([#109](https://github.com/cloudquery/plugin-sdk-java/issues/109)) ([5484316](https://github.com/cloudquery/plugin-sdk-java/commit/5484316f61b9fe0d978b5d212aeb6443e977abb7)) + +## [0.0.7](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.6...v0.0.7) (2023-08-30) + + +### Bug Fixes + +* make the type transformer consistent with scalar units ([#107](https://github.com/cloudquery/plugin-sdk-java/issues/107)) ([0428c7d](https://github.com/cloudquery/plugin-sdk-java/commit/0428c7d271e2d44238368b11814c0b1f7da67a06)) + +## [0.0.6](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.5...v0.0.6) (2023-08-29) + + +### Bug Fixes + +* make the underlying timestamp consistent ([#105](https://github.com/cloudquery/plugin-sdk-java/issues/105)) ([d97dabd](https://github.com/cloudquery/plugin-sdk-java/commit/d97dabd95e0a91d43dd921d9c646290b1a3b13c9)) + +## [0.0.5](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.4...v0.0.5) (2023-08-29) + + +### Bug Fixes + +* convert a boolean to a bit vector ([#102](https://github.com/cloudquery/plugin-sdk-java/issues/102)) ([d35f9be](https://github.com/cloudquery/plugin-sdk-java/commit/d35f9be408db7a9510348b0bcce2ba2dc1be28d5)) + +## [0.0.4](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.3...v0.0.4) (2023-08-24) + + +### Features + +* Add source jar to published artifacts ([616b561](https://github.com/cloudquery/plugin-sdk-java/commit/616b5615ad22c3f871f14b6d8f63989364a10e1e)) + +## [0.0.3](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.2...v0.0.3) (2023-08-24) + + +### Features + +* Add write delete stale logic ([8b1bb1b](https://github.com/cloudquery/plugin-sdk-java/commit/8b1bb1b597af67bcece71dd6b0a1bba5f13908ee)) + +## [0.0.2](https://github.com/cloudquery/plugin-sdk-java/compare/v0.0.1...v0.0.2) (2023-08-24) + + +### Bug Fixes + +* Package group ([#96](https://github.com/cloudquery/plugin-sdk-java/issues/96)) ([274339d](https://github.com/cloudquery/plugin-sdk-java/commit/274339d74c3b9928ddbf1efd0429d425ae1ad268)) + +## 0.0.1 (2023-08-24) + + +### Features + +* `io.cloudquery.scalar.Binary` implementation ([#20](https://github.com/cloudquery/plugin-sdk-java/issues/20)) ([b9b73d1](https://github.com/cloudquery/plugin-sdk-java/commit/b9b73d1d577d8daddb0b705bb53c5827df0ac7b7)) +* `io.cloudquery.scalar.Bool` ([#27](https://github.com/cloudquery/plugin-sdk-java/issues/27)) ([2a91c92](https://github.com/cloudquery/plugin-sdk-java/commit/2a91c92bcf74057bca0877f1ba7c5538ba7c4f5a)), closes [#26](https://github.com/cloudquery/plugin-sdk-java/issues/26) +* adding basic support for tables ([#19](https://github.com/cloudquery/plugin-sdk-java/issues/19)) ([22b2350](https://github.com/cloudquery/plugin-sdk-java/commit/22b235093539f77d3591a7edccdbf22f7335ad6b)) +* adding JSON scalar ([#82](https://github.com/cloudquery/plugin-sdk-java/issues/82)) ([fc92542](https://github.com/cloudquery/plugin-sdk-java/commit/fc92542cb402d1ac0241aa781847eb8f2d211f87)), closes [#63](https://github.com/cloudquery/plugin-sdk-java/issues/63) +* adding Table filterDFS functionaility ([#21](https://github.com/cloudquery/plugin-sdk-java/issues/21)) ([02d8515](https://github.com/cloudquery/plugin-sdk-java/commit/02d85152da9731f021d58abf5f6575f87374e7f6)) +* Date scalars ([#36](https://github.com/cloudquery/plugin-sdk-java/issues/36)) ([adc6ba2](https://github.com/cloudquery/plugin-sdk-java/commit/adc6ba2c76bd257cda99b0e0e7c2e17c95e1968e)), closes [#34](https://github.com/cloudquery/plugin-sdk-java/issues/34) +* Duration scalar ([#42](https://github.com/cloudquery/plugin-sdk-java/issues/42)) ([7529438](https://github.com/cloudquery/plugin-sdk-java/commit/7529438472b2a537940c68276fcd3f2348710f85)), closes [#39](https://github.com/cloudquery/plugin-sdk-java/issues/39) +* Encode resources with data ([#88](https://github.com/cloudquery/plugin-sdk-java/issues/88)) ([2c7060f](https://github.com/cloudquery/plugin-sdk-java/commit/2c7060f9d75d0159334b57256a86778499303743)) +* Generics in scalars ([#56](https://github.com/cloudquery/plugin-sdk-java/issues/56)) ([bc7d6e3](https://github.com/cloudquery/plugin-sdk-java/commit/bc7d6e390c89c46c544514f27168c057806797f9)) +* Implement `getTables` ([#71](https://github.com/cloudquery/plugin-sdk-java/issues/71)) ([085c51f](https://github.com/cloudquery/plugin-sdk-java/commit/085c51f4792a24a121079073cfeaf984f422a681)) +* Implement concurrency and relations resolving ([#91](https://github.com/cloudquery/plugin-sdk-java/issues/91)) ([0a470b7](https://github.com/cloudquery/plugin-sdk-java/commit/0a470b7277fb2aed0c306022e6a11f45147cb5c6)) +* Init logger, add initial MemDB plugin ([#70](https://github.com/cloudquery/plugin-sdk-java/issues/70)) ([20ebb42](https://github.com/cloudquery/plugin-sdk-java/commit/20ebb422ccf2a56a02a90d50d7f03d131ff99d01)) +* int/uint/float/string scalars ([#59](https://github.com/cloudquery/plugin-sdk-java/issues/59)) ([39ec6e6](https://github.com/cloudquery/plugin-sdk-java/commit/39ec6e69383629b1bd9ec80274bd05f271afb99e)), closes [#53](https://github.com/cloudquery/plugin-sdk-java/issues/53) [#54](https://github.com/cloudquery/plugin-sdk-java/issues/54) [#58](https://github.com/cloudquery/plugin-sdk-java/issues/58) [#60](https://github.com/cloudquery/plugin-sdk-java/issues/60) +* Resolve CQId, add CQIds to MemDB plugin ([#95](https://github.com/cloudquery/plugin-sdk-java/issues/95)) ([9d7f1bd](https://github.com/cloudquery/plugin-sdk-java/commit/9d7f1bd1bfee2ba3fa3fb25baf519a77d0961f44)) +* Scalar Timestamp ([#46](https://github.com/cloudquery/plugin-sdk-java/issues/46)) ([4220e92](https://github.com/cloudquery/plugin-sdk-java/commit/4220e9295b9def7ffd8154a3706ae152c12427a7)), closes [#44](https://github.com/cloudquery/plugin-sdk-java/issues/44) +* **sync:** Initial insert message support ([#81](https://github.com/cloudquery/plugin-sdk-java/issues/81)) ([bd729bb](https://github.com/cloudquery/plugin-sdk-java/commit/bd729bbb7c18a9767f238027d38cc76f956c9eec)) +* **sync:** Send migrate messages ([#79](https://github.com/cloudquery/plugin-sdk-java/issues/79)) ([dd2c1a5](https://github.com/cloudquery/plugin-sdk-java/commit/dd2c1a5c590b8d828f12d3b95d6b58b2ef095bef)) + + +### Bug Fixes + +* Add `jackson-annotations` to `build.gradle` ([#83](https://github.com/cloudquery/plugin-sdk-java/issues/83)) ([ead7dd9](https://github.com/cloudquery/plugin-sdk-java/commit/ead7dd90e52f4b6277d1e4c1410aeab331451f96)) +* **deps:** Update dependency com.google.guava:guava to v32 ([#15](https://github.com/cloudquery/plugin-sdk-java/issues/15)) ([ce8028b](https://github.com/cloudquery/plugin-sdk-java/commit/ce8028b72d3e0d6dcf1733481d3115c6c6cf0b54)) +* **deps:** Update dependency io.grpc:grpc-protobuf to v1.57.1 ([#10](https://github.com/cloudquery/plugin-sdk-java/issues/10)) ([bcfa29c](https://github.com/cloudquery/plugin-sdk-java/commit/bcfa29c0161030b8c01da8e22ab2ba08fee76d52)) +* **deps:** Update dependency io.grpc:grpc-services to v1.57.1 ([#11](https://github.com/cloudquery/plugin-sdk-java/issues/11)) ([71c2ea1](https://github.com/cloudquery/plugin-sdk-java/commit/71c2ea1e97d9749731e90cec726cd2389c5606b2)) +* **deps:** Update dependency io.grpc:grpc-stub to v1.57.1 ([#12](https://github.com/cloudquery/plugin-sdk-java/issues/12)) ([c65e5d6](https://github.com/cloudquery/plugin-sdk-java/commit/c65e5d631962572b5d85a3dbb001af502ef9d7e7)) +* **deps:** Update dependency io.grpc:grpc-testing to v1.57.1 ([#13](https://github.com/cloudquery/plugin-sdk-java/issues/13)) ([a7b1fa6](https://github.com/cloudquery/plugin-sdk-java/commit/a7b1fa65d901237319ff045623fc46ec9725a485)) +* **deps:** Update plugin org.gradle.toolchains.foojay-resolver-convention to v0.6.0 ([#14](https://github.com/cloudquery/plugin-sdk-java/issues/14)) ([443990c](https://github.com/cloudquery/plugin-sdk-java/commit/443990c7b46be5cf00bd4b65d5f545b6b441c9ec)) +* Flatten tables in getTables gRPC call ([#80](https://github.com/cloudquery/plugin-sdk-java/issues/80)) ([8c9872a](https://github.com/cloudquery/plugin-sdk-java/commit/8c9872a463b689b9ddb57c520bdee488ce7fdf72)) +* Pass options to tables method ([#78](https://github.com/cloudquery/plugin-sdk-java/issues/78)) ([4b77a2f](https://github.com/cloudquery/plugin-sdk-java/commit/4b77a2fd29da9b81346303588f741b42a828e988)) + + +### Miscellaneous Chores + +* Release 0.0.1 ([e169dbc](https://github.com/cloudquery/plugin-sdk-java/commit/e169dbcd0745390a27778da4ae1789ef0649da5d)) diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..17e56b39 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,5 @@ +* @cloudquery/backend + +lib/build.gradle +.release-please-manifest.json +CHANGELOG.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..823c7463 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM --platform=$BUILDPLATFORM gradle:8.4-jdk20 as build +ARG GITHUB_ACTOR +ARG GITHUB_TOKEN + +WORKDIR /code + +COPY . . + +RUN gradle jar --no-daemon + +FROM eclipse-temurin:25.0.2_10-jre + +COPY --from=build /code/lib/build/libs/*.jar /app/app.jar + +EXPOSE 7777 + +ENV _JAVA_OPTIONS="--add-opens=java.base/java.nio=ALL-UNNAMED" + +ENTRYPOINT ["java", "-jar", "/app/app.jar"] + +CMD [ "serve", "--address", "localhost:7777", "--log-format", "json", "--log-level", "info" ] diff --git a/README.md b/README.md index 8bf0ffe8..5af09dca 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ This is the high-level package to use for developing CloudQuery plugins in Java. ## Setup +### Authenticate to GitHub Packages + ```bash # Set up authentication to GitHub Packages, more in https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry#authenticating-to-github-packages export GITHUB_ACTOR= @@ -11,6 +13,11 @@ export GITHUB_ACTOR= export GITHUB_TOKEN= ``` +### Install pre-commit hooks + +- Install `pre-commit` from +- Run `pre-commit install` to install the hooks + ## Build ```bash diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 00000000..027ec107 --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,3 @@ +# MemDB Plugin + +Test docs for the MemDB plugin. diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 033e24c4..61285a65 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9f4197d5..c61a118f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index fcb6fca1..adff685a 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +85,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -111,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -144,7 +146,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +154,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -169,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -201,16 +202,15 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f..c4bdd3ab 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,22 +59,21 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/lib/build.gradle b/lib/build.gradle index 9fb4ca4a..cd12e067 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -1,12 +1,13 @@ plugins { id 'java-library' - id "io.freefair.lombok" version "8.2.2" + id "io.freefair.lombok" version "9.4.0" id "maven-publish" + id "com.diffplug.spotless" version "8.4.0" } group 'io.cloudquery' // x-release-please-start-version -version = '0.0.1' +version = '0.0.50' // x-release-please-end repositories { @@ -25,47 +26,65 @@ dependencies { api 'org.apache.commons:commons-math3:3.6.1' // This dependency is used internally, and not exposed to consumers on their own compile classpath. - implementation 'org.jooq:joou:0.9.4' - implementation 'com.google.guava:guava:32.1.2-jre' - implementation 'info.picocli:picocli:4.7.4' - implementation 'com.google.guava:guava:32.1.2-jre' - implementation "io.grpc:grpc-protobuf:1.57.1" - implementation "io.grpc:grpc-stub:1.57.1" - implementation "io.grpc:grpc-services:1.57.1" - implementation "io.grpc:grpc-testing:1.57.1" - implementation "io.cloudquery:plugin-pb-java:0.0.5" - implementation "org.apache.arrow:arrow-vector:12.0.1" + implementation 'org.jooq:joou:0.9.5' + implementation 'com.google.guava:guava:33.6.0-jre' + implementation 'info.picocli:picocli:4.7.7' + implementation 'com.google.guava:guava:33.6.0-jre' + implementation 'io.grpc:grpc-protobuf:1.80.0' + implementation 'io.grpc:grpc-stub:1.80.0' + implementation 'io.grpc:grpc-services:1.80.0' + implementation 'io.cloudquery:plugin-pb-java:0.0.45' + implementation 'org.apache.arrow:arrow-memory-core:19.0.0' + implementation 'org.apache.arrow:arrow-vector:19.0.0' + implementation 'commons-io:commons-io:2.22.0' - implementation 'org.apache.logging.log4j:log4j-api:2.20.0' - implementation 'org.apache.logging.log4j:log4j-core:2.20.0' + implementation "com.fasterxml.jackson.core:jackson-core:2.21.2" + implementation "com.fasterxml.jackson.core:jackson-annotations:2.21" - testImplementation(platform('org.junit:junit-bom:5.10.0')) - testImplementation('org.junit.jupiter:junit-jupiter:5.10.0') - testImplementation('org.junit.jupiter:junit-jupiter-api:5.10.0') - testImplementation('org.mockito:mockito-core:5.4.0') - testImplementation('org.mockito:mockito-junit-jupiter:5.4.0') - testImplementation('org.apache.arrow:arrow-memory-netty:12.0.1') - testImplementation('nl.jqno.equalsverifier:equalsverifier:3.15') - testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.10.0') + implementation 'org.apache.logging.log4j:log4j-api:2.25.4' + implementation 'org.apache.logging.log4j:log4j-core:2.25.4' - testImplementation 'org.assertj:assertj-core:3.24.2' + testImplementation 'io.grpc:grpc-testing:1.80.0' + testImplementation 'io.grpc:grpc-inprocess:1.80.0' + testImplementation platform('org.junit:junit-bom:6.0.3') + testImplementation 'org.junit.jupiter:junit-jupiter:6.0.3' + testImplementation 'org.junit.jupiter:junit-jupiter-api:6.0.3' + testImplementation 'org.mockito:mockito-core:5.23.0' + testImplementation 'org.mockito:mockito-junit-jupiter:5.23.0' + testImplementation 'nl.jqno.equalsverifier:equalsverifier:4.5' + testImplementation 'org.assertj:assertj-core:3.27.7' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + runtimeOnly "org.apache.arrow:arrow-memory-netty:19.0.0" } test { useJUnitPlatform() testLogging { - events "passed", "skipped", "failed" + events "skipped", "failed" } jvmArgs("--add-opens=java.base/java.nio=ALL-UNNAMED") } // Apply a specific Java toolchain to ease working on different environments. java { + withSourcesJar() toolchain { languageVersion = JavaLanguageVersion.of(20) } } +jar { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + manifest { + attributes "Main-Class": "io.cloudquery.MainClass" + } + + from { + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + } +} + publishing { repositories { maven { @@ -79,7 +98,23 @@ publishing { } publications { gpr(MavenPublication) { + artifactId = 'plugin-sdk-java' from(components.java) } } } + +task runMemDBServe(type: JavaExec) { + mainClass.set("io.cloudquery.MainClass") + group = "Execution" + description = "Start the MemDB plugin server" + classpath = sourceSets.main.runtimeClasspath + args = ["serve"] + jvmArgs = ["--add-opens=java.base/java.nio=ALL-UNNAMED"] +} + +spotless { + java { + googleJavaFormat() + } +} diff --git a/lib/src/main/java/io/cloudquery/Main.java b/lib/src/main/java/io/cloudquery/Main.java deleted file mode 100644 index c4dfbac5..00000000 --- a/lib/src/main/java/io/cloudquery/Main.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.cloudquery; - -import io.cloudquery.memdb.MemDB; -import io.cloudquery.server.PluginServe; - -public class Main { - public static void main(String[] args) { - PluginServe serve = PluginServe.builder().plugin(new MemDB()).args(args).build(); - int exitCode = serve.Serve(); - System.exit(exitCode); - } -} diff --git a/lib/src/main/java/io/cloudquery/MainClass.java b/lib/src/main/java/io/cloudquery/MainClass.java new file mode 100644 index 00000000..c2674553 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/MainClass.java @@ -0,0 +1,12 @@ +package io.cloudquery; + +import io.cloudquery.memdb.MemDB; +import io.cloudquery.server.PluginServe; + +public class MainClass { + public static void main(String[] args) { + PluginServe serve = PluginServe.builder().plugin(new MemDB()).args(args).build(); + int exitCode = serve.Serve(); + System.exit(exitCode); + } +} diff --git a/lib/src/main/java/io/cloudquery/caser/Caser.java b/lib/src/main/java/io/cloudquery/caser/Caser.java index 937f1f82..1432afc2 100644 --- a/lib/src/main/java/io/cloudquery/caser/Caser.java +++ b/lib/src/main/java/io/cloudquery/caser/Caser.java @@ -1,6 +1,7 @@ package io.cloudquery.caser; -import lombok.Builder; +import static io.cloudquery.caser.Initialisms.*; +import static io.cloudquery.caser.Initialisms.COMMON_INITIALISMS; import java.util.ArrayList; import java.util.Arrays; @@ -9,200 +10,197 @@ import java.util.List; import java.util.Map; import java.util.Set; - -import static io.cloudquery.caser.Initialisms.*; -import static io.cloudquery.caser.Initialisms.COMMON_INITIALISMS; +import lombok.Builder; @Builder public class Caser { - @Builder.Default - private Set initialisms = new HashSet<>(COMMON_INITIALISMS); - - @Builder.Default - private Map snakeToCamelExceptions = new HashMap<>(); - - @Builder.Default - private Map camelToSnakeExceptions = new HashMap<>(); - - @Builder.Default - private Map customExceptions = new HashMap<>(); - - @Builder.Default - private Set customInitialisms = new HashSet<>(); - - public Caser(Set initialisms, - Map snakeToCamelExceptions, - Map camelToSnakeExceptions, - Map customExceptions, - Set customInitialisms) { - this.initialisms = initialisms; - this.snakeToCamelExceptions = snakeToCamelExceptions; - this.camelToSnakeExceptions = camelToSnakeExceptions; - this.customExceptions = customExceptions; - this.customInitialisms = customInitialisms; - - - HashMap combinedExceptions = new HashMap<>(COMMON_EXCEPTIONS); - combinedExceptions.putAll(customExceptions); - for (String key : combinedExceptions.keySet()) { - snakeToCamelExceptions.put(key, combinedExceptions.get(key)); - camelToSnakeExceptions.put(combinedExceptions.get(key), key); - } + @Builder.Default private Set initialisms = new HashSet<>(COMMON_INITIALISMS); - initialisms.addAll(customInitialisms); - } + @Builder.Default private Map snakeToCamelExceptions = new HashMap<>(); - public String toSnake(String s) { - List words = new ArrayList<>(); - int lastPos = 0; - for (int i = 0; i < s.length(); i++) { - if (i > 0 && Character.isUpperCase(s.charAt(i))) { - - String initialism = startsWithInitialism(s.substring(lastPos)); - if (!initialism.isEmpty()) { - words.add(initialism); - i = lastPos + initialism.length(); - lastPos = i; - continue; - } - - String capWord = getCapWord(s.substring(lastPos)); - if (!capWord.isEmpty()) { - words.add(capWord); - i = lastPos + capWord.length(); - lastPos = i; - continue; - } - - words.add(s.substring(lastPos, i)); - lastPos = i; - } - } + @Builder.Default private Map camelToSnakeExceptions = new HashMap<>(); - if (!s.substring(lastPos).isEmpty()) { - String w = s.substring(lastPos); - if (w.equals("s")) { - String lastWord = words.remove(words.size() - 1); - words.add(lastWord + w); - } else { - words.add(s.substring(lastPos)); - } - } + @Builder.Default private Map customExceptions = new HashMap<>(); - return String.join("_", words).toLowerCase(); - } + @Builder.Default private Set customInitialisms = new HashSet<>(); - /** - * Returns a string converted from snake case to camel case. - *

- * - * @param s The input string - * @return The string converted to camel case - */ - public String toCamel(String s) { - if (s.isEmpty()) { - return s; - } - List words = Arrays.asList(s.split("_")); - return String.join("", capitalize(words)); + public Caser( + Set initialisms, + Map snakeToCamelExceptions, + Map camelToSnakeExceptions, + Map customExceptions, + Set customInitialisms) { + this.initialisms = initialisms; + this.snakeToCamelExceptions = snakeToCamelExceptions; + this.camelToSnakeExceptions = camelToSnakeExceptions; + this.customExceptions = customExceptions; + this.customInitialisms = customInitialisms; + + HashMap combinedExceptions = new HashMap<>(COMMON_EXCEPTIONS); + combinedExceptions.putAll(customExceptions); + for (String key : combinedExceptions.keySet()) { + snakeToCamelExceptions.put(key, combinedExceptions.get(key)); + camelToSnakeExceptions.put(combinedExceptions.get(key), key); } - /** - * Returns a string converted from snake case to title case. - *

- * Title case is similar to camel case, but spaces are used in between words. - * - * @param s The input string - * @return The string converted to title case - */ - public String toTitle(String s) { - if (s.isEmpty()) { - return s; + initialisms.addAll(customInitialisms); + } + + public String toSnake(String s) { + List words = new ArrayList<>(); + int lastPos = 0; + for (int i = 0; i < s.length(); i++) { + if (i > 0 && Character.isUpperCase(s.charAt(i))) { + + String initialism = startsWithInitialism(s.substring(lastPos)); + if (!initialism.isEmpty()) { + words.add(initialism); + i = lastPos + initialism.length(); + lastPos = i; + continue; } - String[] words = s.split("_"); - if (!snakeToCamelExceptions.containsKey(words[0].toLowerCase())) { - words[0] = words[0].substring(0, 1).toUpperCase() + words[0].substring(1).toLowerCase(); + + String capWord = getCapWord(s.substring(lastPos)); + if (!capWord.isEmpty()) { + words.add(capWord); + i = lastPos + capWord.length(); + lastPos = i; + continue; } - return String.join(" ", capitalize(Arrays.asList(words))); + + words.add(s.substring(lastPos, i)); + lastPos = i; + } } - /** - * Returns a string converted from snake case to pascal case - * - * @param s The input string - * @return The string converted to pascal case - */ - public String toPascal(String s) { - if (s.isEmpty()) { - return s; - } - String camel = toCamel(s); - return camel.substring(0, 1).toUpperCase() + camel.substring(1); + if (!s.substring(lastPos).isEmpty()) { + String w = s.substring(lastPos); + if (w.equals("s")) { + String lastWord = words.remove(words.size() - 1); + words.add(lastWord + w); + } else { + words.add(s.substring(lastPos)); + } } - /** - * gets the next sequence of capitalized letters as a single word. - *

- * If there is a word after capitalized sequence it leaves one letter as beginning of the next word - * - * @param s The input string - * @return A single word - */ - private String getCapWord(String s) { - for (int i = 0; i < s.length(); i++) { - if (!Character.isUpperCase(s.charAt(i))) { - if (i == 0) { - return ""; - } - return s.substring(0, i - 1); - } + return String.join("_", words).toLowerCase(); + } + + /** + * Returns a string converted from snake case to camel case. + * + *

+ * + * @param s The input string + * @return The string converted to camel case + */ + public String toCamel(String s) { + if (s.isEmpty()) { + return s; + } + List words = Arrays.asList(s.split("_")); + return String.join("", capitalize(words)); + } + + /** + * Returns a string converted from snake case to title case. + * + *

Title case is similar to camel case, but spaces are used in between words. + * + * @param s The input string + * @return The string converted to title case + */ + public String toTitle(String s) { + if (s.isEmpty()) { + return s; + } + String[] words = s.split("_"); + if (!snakeToCamelExceptions.containsKey(words[0].toLowerCase())) { + words[0] = words[0].substring(0, 1).toUpperCase() + words[0].substring(1).toLowerCase(); + } + return String.join(" ", capitalize(Arrays.asList(words))); + } + + /** + * Returns a string converted from snake case to pascal case + * + * @param s The input string + * @return The string converted to pascal case + */ + public String toPascal(String s) { + if (s.isEmpty()) { + return s; + } + String camel = toCamel(s); + return camel.substring(0, 1).toUpperCase() + camel.substring(1); + } + + /** + * gets the next sequence of capitalized letters as a single word. + * + *

If there is a word after capitalized sequence it leaves one letter as beginning of the next + * word + * + * @param s The input string + * @return A single word + */ + private String getCapWord(String s) { + for (int i = 0; i < s.length(); i++) { + if (!Character.isUpperCase(s.charAt(i))) { + if (i == 0) { + return ""; } - return s; + return s.substring(0, i - 1); + } + } + return s; + } + + /** + * Returns the initialism if the given string begins with it + * + * @param s The input string + * @return The initialism if the given string begins with it, otherwise an empty string + */ + private String startsWithInitialism(String s) { + String initialism = ""; + + // the longest initialism is 5 char, the shortest 2 we choose the longest match + for (int i = 1; i <= s.length() && i <= 5; i++) { + if (s.length() > i - 1 + && this.initialisms.contains(s.substring(0, i)) + && s.substring(0, i).length() > initialism.length()) { + initialism = s.substring(0, i); + } } - /** - * Returns the initialism if the given string begins with it - * - * @param s The input string - * @return The initialism if the given string begins with it, otherwise an empty string - */ - private String startsWithInitialism(String s) { - String initialism = ""; - - // the longest initialism is 5 char, the shortest 2 we choose the longest match - for (int i = 1; i <= s.length() && i <= 5; i++) { - if (s.length() > i - 1 && this.initialisms.contains(s.substring(0, i)) && s.substring(0, i).length() > initialism.length()) { - initialism = s.substring(0, i); - } - } + return initialism; + } - return initialism; - } + private List capitalize(List words) { + int n = words.stream().map(String::length).reduce(0, Integer::sum); + + List results = new ArrayList<>(); + for (int i = 0; i < words.size(); i++) { + if (snakeToCamelExceptions.containsKey(words.get(i))) { + results.add(snakeToCamelExceptions.get(words.get(i))); + continue; + } - private List capitalize(List words) { - int n = words.stream().map(String::length).reduce(0, Integer::sum); - - List results = new ArrayList<>(); - for (int i = 0; i < words.size(); i++) { - if (snakeToCamelExceptions.containsKey(words.get(i))) { - results.add(snakeToCamelExceptions.get(words.get(i))); - continue; - } - - if (i > 0) { - String upper = words.get(i).toUpperCase(); - if (n > i - 1 && initialisms.contains(upper)) { - results.add(upper); - continue; - } - } - - if (i > 0 && !words.get(i).isEmpty()) { - results.add(words.get(i).substring(0, 1).toUpperCase()+words.get(i).substring(1)); - } else { - results.add(words.get(i)); - } + if (i > 0) { + String upper = words.get(i).toUpperCase(); + if (n > i - 1 && initialisms.contains(upper)) { + results.add(upper); + continue; } - return results; + } + + if (i > 0 && !words.get(i).isEmpty()) { + results.add(words.get(i).substring(0, 1).toUpperCase() + words.get(i).substring(1)); + } else { + results.add(words.get(i)); + } } -} \ No newline at end of file + return results; + } +} diff --git a/lib/src/main/java/io/cloudquery/caser/Initialisms.java b/lib/src/main/java/io/cloudquery/caser/Initialisms.java index ffe498e1..42fcb15d 100644 --- a/lib/src/main/java/io/cloudquery/caser/Initialisms.java +++ b/lib/src/main/java/io/cloudquery/caser/Initialisms.java @@ -4,60 +4,18 @@ import java.util.Set; public class Initialisms { - public static final Set COMMON_INITIALISMS = Set.of( - "ACL", - "API", - "ASCII", - "CIDR", - "CPU", - "CSS", - "DNS", - "EOF", - "FQDN", - "GUID", - "HTML", - "HTTP", - "HTTPS", - "ID", - "IP", - "IPC", - "IPv4", - "IPv6", - "JSON", - "LHS", - "PID", - "QOS", - "QPS", - "RAM", - "RHS", - "RPC", - "SLA", - "SMTP", - "SQL", - "SSH", - "TCP", - "TLS", - "TTL", - "UDP", - "UI", - "UID", - "UUID", - "URI", - "URL", - "UTF8", - "VM", - "XML", - "XMPP", - "XSRF", - "XSS" - ); + public static final Set COMMON_INITIALISMS = + Set.of( + "ACL", "API", "ASCII", "CIDR", "CPU", "CSS", "DNS", "EOF", "FQDN", "GUID", "HTML", "HTTP", + "HTTPS", "ID", "IP", "IPC", "IPv4", "IPv6", "JSON", "LHS", "PID", "QOS", "QPS", "RAM", + "RHS", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "UID", + "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS"); - public static final Map COMMON_EXCEPTIONS = Map.of( - "oauth", "OAuth", - "ipv4", "IPv4", - "ipv6", "IPv6" - ); + public static final Map COMMON_EXCEPTIONS = + Map.of( + "oauth", "OAuth", + "ipv4", "IPv4", + "ipv6", "IPv6"); - private Initialisms() { - } + private Initialisms() {} } diff --git a/lib/src/main/java/io/cloudquery/glob/Glob.java b/lib/src/main/java/io/cloudquery/glob/Glob.java index 14eb3551..58ccd2de 100644 --- a/lib/src/main/java/io/cloudquery/glob/Glob.java +++ b/lib/src/main/java/io/cloudquery/glob/Glob.java @@ -1,42 +1,42 @@ package io.cloudquery.glob; public class Glob { - public static final String GLOB = "*"; + public static final String GLOB = "*"; - public static boolean match(String pattern, String subject) { - if (pattern.isEmpty()) { - return subject.equals(pattern); - } - - if (pattern.equals(GLOB)) { - return true; - } + public static boolean match(String pattern, String subject) { + if (pattern.isEmpty()) { + return subject.equals(pattern); + } - String[] parts = pattern.split("\\" + GLOB, -1); - if (parts.length == 1) { - return subject.equals(pattern); - } + if (pattern.equals(GLOB)) { + return true; + } - boolean leadingGlob = pattern.startsWith(GLOB); - boolean trailingGlob = pattern.endsWith(GLOB); - int end = parts.length - 1; + String[] parts = pattern.split("\\" + GLOB, -1); + if (parts.length == 1) { + return subject.equals(pattern); + } - for (int i = 0; i < end; i++) { - int idx = subject.indexOf(parts[i]); + boolean leadingGlob = pattern.startsWith(GLOB); + boolean trailingGlob = pattern.endsWith(GLOB); + int end = parts.length - 1; - if (i == 0) { - if (!leadingGlob && idx != 0) { - return false; - } - } else { - if (idx < 0) { - return false; - } - } + for (int i = 0; i < end; i++) { + int idx = subject.indexOf(parts[i]); - subject = subject.substring(idx + parts[i].length()); + if (i == 0) { + if (!leadingGlob && idx != 0) { + return false; } + } else { + if (idx < 0) { + return false; + } + } - return trailingGlob || subject.endsWith(parts[end]); + subject = subject.substring(idx + parts[i].length()); } + + return trailingGlob || subject.endsWith(parts[end]); + } } diff --git a/lib/src/main/java/io/cloudquery/helper/ArrowHelper.java b/lib/src/main/java/io/cloudquery/helper/ArrowHelper.java new file mode 100644 index 00000000..10661df7 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/helper/ArrowHelper.java @@ -0,0 +1,316 @@ +package io.cloudquery.helper; + +import static java.util.Arrays.asList; + +import com.google.protobuf.ByteString; +import io.cloudquery.scalar.ValidationException; +import io.cloudquery.schema.Column; +import io.cloudquery.schema.Resource; +import io.cloudquery.schema.Table; +import io.cloudquery.schema.Table.TableBuilder; +import io.cloudquery.types.JSONType.JSONVector; +import io.cloudquery.types.UUIDType.UUIDVector; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.channels.Channels; +import java.time.Duration; +import java.util.*; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.*; +import org.apache.arrow.vector.ipc.ArrowReader; +import org.apache.arrow.vector.ipc.ArrowStreamReader; +import org.apache.arrow.vector.ipc.ArrowStreamWriter; +import org.apache.arrow.vector.types.pojo.Field; +import org.apache.arrow.vector.types.pojo.FieldType; +import org.apache.arrow.vector.types.pojo.Schema; +import org.apache.arrow.vector.util.Text; +import org.joou.UByte; +import org.joou.UInteger; +import org.joou.ULong; +import org.joou.UShort; + +public class ArrowHelper { + public static final String CQ_EXTENSION_INCREMENTAL = "cq:extension:incremental"; + public static final String CQ_EXTENSION_CONSTRAINT_NAME = "cq:extension:constraint_name"; + public static final String CQ_EXTENSION_PRIMARY_KEY = "cq:extension:primary_key"; + public static final String CQ_EXTENSION_UNIQUE = "cq:extension:unique"; + public static final String CQ_TABLE_NAME = "cq:table_name"; + public static final String CQ_TABLE_TITLE = "cq:table_title"; + public static final String CQ_TABLE_DESCRIPTION = "cq:table_description"; + public static final String CQ_TABLE_DEPENDS_ON = "cq:table_depends_on"; + + private static void setVectorData(FieldVector vector, Object data) { + vector.allocateNew(); + if (data == null) { + vector.setNull(0); + return; + } + if (vector instanceof BigIntVector bigIntVector) { + bigIntVector.set(0, (long) data); + return; + } + if (vector instanceof BitVector bitVector) { + bitVector.set(0, (boolean) data ? 1 : 0); + return; + } + if (vector instanceof DateDayVector dayDateVector) { + dayDateVector.set(0, (int) data); + return; + } + if (vector instanceof DateMilliVector dateMilliVector) { + dateMilliVector.set(0, (long) data); + return; + } + if (vector instanceof DurationVector durationVector) { + Duration duration = (Duration) data; + switch (durationVector.getUnit()) { + case SECOND -> { + durationVector.set(0, duration.toSeconds()); + } + case MILLISECOND -> { + durationVector.set(0, duration.toMillis()); + } + case MICROSECOND -> { + durationVector.set(0, duration.toNanos() / 1000); + } + case NANOSECOND -> { + durationVector.set(0, duration.toNanos()); + } + } + return; + } + if (vector instanceof FixedSizeBinaryVector fixedSizeBinaryVector) { + fixedSizeBinaryVector.set(0, (byte[]) data); + return; + } + if (vector instanceof Float4Vector float4Vector) { + float4Vector.set(0, (float) data); + return; + } + if (vector instanceof Float8Vector float8Vector) { + float8Vector.set(0, (double) data); + return; + } + if (vector instanceof IntVector intVector) { + intVector.set(0, (int) data); + return; + } + if (vector instanceof LargeVarBinaryVector largeVarBinaryVector) { + largeVarBinaryVector.set(0, (byte[]) data); + return; + } + if (vector instanceof LargeVarCharVector largeVarCharVector) { + largeVarCharVector.set(0, (Text) data); + return; + } + if (vector instanceof SmallIntVector smallIntVector) { + smallIntVector.set(0, (short) data); + return; + } + if (vector instanceof TimeMicroVector timeMicroVector) { + timeMicroVector.set(0, (long) data); + return; + } + if (vector instanceof TimeMilliVector timeMilliVector) { + timeMilliVector.set(0, (int) data); + return; + } + if (vector instanceof TimeNanoVector timeNanoVector) { + timeNanoVector.set(0, (long) data); + return; + } + if (vector instanceof TimeSecVector timeSecVector) { + timeSecVector.set(0, (int) data); + return; + } + if (vector instanceof TimeStampVector timeStampVector) { + timeStampVector.set(0, (long) data); + return; + } + if (vector instanceof TinyIntVector tinyIntVector) { + tinyIntVector.set(0, (byte) data); + return; + } + if (vector instanceof UInt1Vector uInt1Vector) { + uInt1Vector.set(0, ((UByte) data).shortValue()); + return; + } + if (vector instanceof UInt2Vector uInt2Vector) { + uInt2Vector.set(0, ((UShort) data).intValue()); + return; + } + if (vector instanceof UInt4Vector uInt4Vector) { + uInt4Vector.set(0, ((UInteger) data).intValue()); + return; + } + if (vector instanceof UInt8Vector uInt8Vector) { + uInt8Vector.set(0, ((ULong) data).longValue()); + return; + } + if (vector instanceof VarBinaryVector varBinaryVector) { + varBinaryVector.set(0, (byte[]) data); + return; + } + if (vector instanceof VarCharVector vectorCharVector) { + vectorCharVector.set(0, (Text) data); + return; + } + // CloudQuery-specific + if (vector instanceof JSONVector jsonVector) { + jsonVector.setSafe(0, (byte[]) data); + return; + } + // CloudQuery-specific + if (vector instanceof UUIDVector uuidVector) { + uuidVector.set(0, (java.util.UUID) data); + return; + } + + throw new IllegalArgumentException("Unsupported vector type: " + vector.getClass()); + } + + public static ByteString encode(Table table) throws IOException { + try (BufferAllocator bufferAllocator = new RootAllocator()) { + Schema schema = toArrowSchema(table); + try (VectorSchemaRoot schemaRoot = VectorSchemaRoot.create(schema, bufferAllocator)) { + try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { + try (ArrowStreamWriter writer = + new ArrowStreamWriter(schemaRoot, null, Channels.newChannel(out))) { + writer.start(); + writer.end(); + return ByteString.copyFrom(out.toByteArray()); + } + } + } + } + } + + public static Table decode(ByteString byteString) throws IOException { + try (BufferAllocator bufferAllocator = new RootAllocator()) { + try (ArrowReader reader = new ArrowStreamReader(byteString.newInput(), bufferAllocator)) { + VectorSchemaRoot vectorSchemaRoot = reader.getVectorSchemaRoot(); + return fromArrowSchema(vectorSchemaRoot.getSchema()); + } + } + } + + public static Schema toArrowSchema(Table table) { + List columns = table.getColumns(); + Field[] fields = new Field[columns.size()]; + for (int i = 0; i < columns.size(); i++) { + fields[i] = getField(columns.get(i)); + } + Map metadata = new HashMap<>(); + metadata.put(CQ_TABLE_NAME, table.getName()); + if (table.getTitle() != null) { + metadata.put(CQ_TABLE_TITLE, table.getTitle()); + } + if (table.getDescription() != null) { + metadata.put(CQ_TABLE_DESCRIPTION, table.getDescription()); + } + if (table.getParent() != null) { + metadata.put(CQ_TABLE_DEPENDS_ON, table.getParent().getName()); + } + metadata.put(CQ_EXTENSION_CONSTRAINT_NAME, table.getConstraintName()); + return new Schema(asList(fields), metadata); + } + + private static Field getField(Column column) { + Map metadata = new HashMap<>(); + metadata.put(CQ_EXTENSION_UNIQUE, Boolean.toString(column.isUnique())); + metadata.put(CQ_EXTENSION_PRIMARY_KEY, Boolean.toString(column.isPrimaryKey())); + metadata.put(CQ_EXTENSION_INCREMENTAL, Boolean.toString(column.isIncrementalKey())); + return new Field( + column.getName(), + new FieldType(!column.isNotNull(), column.getType(), null, metadata), + null); + } + + public static Table fromArrowSchema(Schema schema) { + List columns = new ArrayList<>(); + for (Field field : schema.getFields()) { + columns.add(getColumn(field)); + } + + Map metaData = schema.getCustomMetadata(); + String name = metaData.get(CQ_TABLE_NAME); + String title = metaData.get(CQ_TABLE_TITLE); + String description = metaData.get(CQ_TABLE_DESCRIPTION); + String parent = metaData.get(CQ_TABLE_DEPENDS_ON); + String constraintName = metaData.get(CQ_EXTENSION_CONSTRAINT_NAME); + + TableBuilder tableBuilder = + Table.builder() + .name(name) + .constraintName(constraintName) + .columns(columns) + .title(title) + .description(description); + if (parent != null) { + tableBuilder.parent(Table.builder().name(parent).build()); + } + + return tableBuilder.build(); + } + + private static Column getColumn(Field field) { + boolean isUnique = Objects.equals(field.getMetadata().get(CQ_EXTENSION_UNIQUE), "true"); + boolean isPrimaryKey = + Objects.equals(field.getMetadata().get(CQ_EXTENSION_PRIMARY_KEY), "true"); + boolean isIncrementalKey = + Objects.equals(field.getMetadata().get(CQ_EXTENSION_INCREMENTAL), "true"); + + return Column.builder() + .name(field.getName()) + .unique(isUnique) + .primaryKey(isPrimaryKey) + .incrementalKey(isIncrementalKey) + .type(field.getType()) + .build(); + } + + public static ByteString encode(Resource resource) throws IOException { + try (BufferAllocator bufferAllocator = new RootAllocator()) { + Table table = resource.getTable(); + Schema schema = toArrowSchema(table); + try (VectorSchemaRoot vectorRoot = VectorSchemaRoot.create(schema, bufferAllocator)) { + for (int i = 0; i < table.getColumns().size(); i++) { + FieldVector vector = vectorRoot.getVector(i); + Object data = resource.getData().get(i).get(); + setVectorData(vector, data); + } + // TODO: Support encoding multiple resources + vectorRoot.setRowCount(1); + try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { + try (ArrowStreamWriter writer = + new ArrowStreamWriter(vectorRoot, null, Channels.newChannel(out))) { + writer.start(); + writer.writeBatch(); + writer.end(); + return ByteString.copyFrom(out.toByteArray()); + } + } + } + } + } + + public static Resource decodeResource(ByteString byteString) + throws IOException, ValidationException { + try (BufferAllocator bufferAllocator = new RootAllocator()) { + try (ArrowStreamReader reader = + new ArrowStreamReader(byteString.newInput(), bufferAllocator)) { + VectorSchemaRoot vectorSchemaRoot = reader.getVectorSchemaRoot(); + reader.loadNextBatch(); + Resource resource = + Resource.builder().table(fromArrowSchema(vectorSchemaRoot.getSchema())).build(); + for (int i = 0; i < vectorSchemaRoot.getSchema().getFields().size(); i++) { + FieldVector vector = vectorSchemaRoot.getVector(i); + // TODO: We currently only support a single row + resource.set(vector.getName(), vector.getObject(0)); + } + return resource; + } + } + } +} diff --git a/lib/src/main/java/io/cloudquery/helper/ReflectionPathResolver.java b/lib/src/main/java/io/cloudquery/helper/ReflectionPathResolver.java index 6ad605bc..bb40dd7d 100644 --- a/lib/src/main/java/io/cloudquery/helper/ReflectionPathResolver.java +++ b/lib/src/main/java/io/cloudquery/helper/ReflectionPathResolver.java @@ -2,56 +2,53 @@ import java.lang.reflect.Field; -/** - * A simple reflection-based path resolver. - */ +/** A simple reflection-based path resolver. */ public class ReflectionPathResolver { - - public static class PathResolverException extends Exception { - public PathResolverException(String message, Throwable ex) { - super(message, ex); - } + + public static class PathResolverException extends Exception { + public PathResolverException(String message, Throwable ex) { + super(message, ex); } + } - /** - * Resolve a path of an object using reflection. - *

- * e.g. if we have a class: - *

-     *      class TestClass {
-     *          private String name;
-     *          private TestClass child;
-     *      }
-     * 
- *

- * Then the following are valid paths to retrieve the associated values: - *

- * `name` - * `child.name` - *

- * NOTE: this implementation is currently very simplistic and only supports simple field and nested field resolution. - * It does not support collection resolution - unlike the Go SDK which uses go-funk. - * - * @param object The object to resolve the path on - * @param path The path to resolve - * @return The value of the property at the resolved path - * @throws PathResolverException If the path cannot be resolved - */ - public static Object resolve(Object object, String path) throws PathResolverException { - Object current = object; + /** + * Resolve a path of an object using reflection. + * + *

e.g. if we have a class: + * + *

+   *      class TestClass {
+   *          private String name;
+   *          private TestClass child;
+   *      }
+   * 
+ * + *

Then the following are valid paths to retrieve the associated values: + * + *

`name` `child.name` NOTE: this implementation is currently very simplistic and only supports + * simple field and nested field resolution. It does not support collection resolution - unlike + * the Go SDK which uses go-funk. + * + * @param object The object to resolve the path on + * @param path The path to resolve + * @return The value of the property at the resolved path + * @throws PathResolverException If the path cannot be resolved + */ + public static Object resolve(Object object, String path) throws PathResolverException { + Object current = object; - for (String currentPath : path.split("\\.")) { - try { - Field currentField = object.getClass().getDeclaredField(currentPath); - if (!currentField.canAccess(current)) { - currentField.setAccessible(true); - } - object = currentField.get(object); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new PathResolverException("Unable to resolve path " + currentPath, e); - } + for (String currentPath : path.split("\\.")) { + try { + Field currentField = object.getClass().getDeclaredField(currentPath); + if (!currentField.canAccess(current)) { + currentField.setAccessible(true); } - - return object; + object = currentField.get(object); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new PathResolverException("Unable to resolve path " + currentPath, e); + } } + + return object; + } } diff --git a/lib/src/main/java/io/cloudquery/internal/servers/discovery/v1/DiscoverServer.java b/lib/src/main/java/io/cloudquery/internal/servers/discovery/v1/DiscoverServer.java index 676ed44f..26140d33 100644 --- a/lib/src/main/java/io/cloudquery/internal/servers/discovery/v1/DiscoverServer.java +++ b/lib/src/main/java/io/cloudquery/internal/servers/discovery/v1/DiscoverServer.java @@ -4,19 +4,18 @@ import io.cloudquery.discovery.v1.GetVersions.Request; import io.cloudquery.discovery.v1.GetVersions.Response; import io.grpc.stub.StreamObserver; - import java.util.List; public class DiscoverServer extends DiscoveryImplBase { - private final List versions; + private final List versions; - public DiscoverServer(List versions) { - this.versions = versions; - } + public DiscoverServer(List versions) { + this.versions = versions; + } - @Override - public void getVersions(Request request, StreamObserver responseObserver) { - responseObserver.onNext(Response.newBuilder().addAllVersions(versions).build()); - responseObserver.onCompleted(); - } + @Override + public void getVersions(Request request, StreamObserver responseObserver) { + responseObserver.onNext(Response.newBuilder().addAllVersions(versions).build()); + responseObserver.onCompleted(); + } } diff --git a/lib/src/main/java/io/cloudquery/internal/servers/plugin/v3/PluginServer.java b/lib/src/main/java/io/cloudquery/internal/servers/plugin/v3/PluginServer.java index 78faa56e..6bada6a3 100644 --- a/lib/src/main/java/io/cloudquery/internal/servers/plugin/v3/PluginServer.java +++ b/lib/src/main/java/io/cloudquery/internal/servers/plugin/v3/PluginServer.java @@ -1,12 +1,198 @@ package io.cloudquery.internal.servers.plugin.v3; -import io.cloudquery.plugin.v3.PluginGrpc.PluginImplBase; +import com.google.protobuf.ByteString; +import io.cloudquery.helper.ArrowHelper; +import io.cloudquery.messages.WriteDeleteStale; +import io.cloudquery.messages.WriteInsert; +import io.cloudquery.messages.WriteMessage; +import io.cloudquery.messages.WriteMigrateTable; +import io.cloudquery.plugin.BackendOptions; +import io.cloudquery.plugin.NewClientOptions; import io.cloudquery.plugin.Plugin; +import io.cloudquery.plugin.v3.PluginGrpc.PluginImplBase; +import io.cloudquery.plugin.v3.Write; +import io.cloudquery.plugin.v3.Write.MessageMigrateTable; +import io.cloudquery.scalar.ValidationException; +import io.cloudquery.schema.Table; +import io.grpc.stub.StreamObserver; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; public class PluginServer extends PluginImplBase { - private final Plugin plugin; + private final Plugin plugin; + + public PluginServer(Plugin plugin) { + this.plugin = plugin; + } + + @Override + public void getName( + io.cloudquery.plugin.v3.GetName.Request request, + StreamObserver responseObserver) { + responseObserver.onNext( + io.cloudquery.plugin.v3.GetName.Response.newBuilder().setName(plugin.getName()).build()); + responseObserver.onCompleted(); + } + + @Override + public void getVersion( + io.cloudquery.plugin.v3.GetVersion.Request request, + StreamObserver responseObserver) { + responseObserver.onNext( + io.cloudquery.plugin.v3.GetVersion.Response.newBuilder() + .setVersion(plugin.getVersion()) + .build()); + responseObserver.onCompleted(); + } + + @Override + public void init( + io.cloudquery.plugin.v3.Init.Request request, + StreamObserver responseObserver) { + try { + plugin.init( + request.getSpec().toStringUtf8(), + NewClientOptions.builder().noConnection(request.getNoConnection()).build()); + responseObserver.onNext(io.cloudquery.plugin.v3.Init.Response.newBuilder().build()); + responseObserver.onCompleted(); + } catch (Exception e) { + plugin.getLogger().error("Error initializing plugin", e); + responseObserver.onError(e); + } + } + + @Override + public void getTables( + io.cloudquery.plugin.v3.GetTables.Request request, + StreamObserver responseObserver) { + try { + List tables = + plugin.tables( + request.getTablesList(), + request.getSkipTablesList(), + request.getSkipDependentTables()); + List byteStrings = new ArrayList<>(); + for (Table table : Table.flattenTables(tables)) { + byteStrings.add(ArrowHelper.encode(table)); + } + responseObserver.onNext( + io.cloudquery.plugin.v3.GetTables.Response.newBuilder() + .addAllTables(byteStrings) + .build()); + responseObserver.onCompleted(); + } catch (Exception e) { + plugin.getLogger().error("Error getting tables", e); + responseObserver.onError(e); + } + } + + @Override + public void sync( + io.cloudquery.plugin.v3.Sync.Request request, + StreamObserver responseObserver) { + try { + plugin.sync( + request.getTablesList(), + request.getSkipTablesList(), + request.getSkipDependentTables(), + request.getDeterministicCqId(), + new BackendOptions( + request.getBackend().getTableName(), request.getBackend().getConnection()), + responseObserver); + } catch (Exception e) { + plugin.getLogger().error("Error syncing tables", e); + responseObserver.onError(e); + } + } + + @Override + public void read( + io.cloudquery.plugin.v3.Read.Request request, + StreamObserver responseObserver) { + plugin.read(); + responseObserver.onNext(io.cloudquery.plugin.v3.Read.Response.newBuilder().build()); + responseObserver.onCompleted(); + } + + @Override + public StreamObserver write(StreamObserver responseObserver) { + return new StreamObserver<>() { + @Override + public void onNext(Write.Request request) { + Write.Request.MessageCase messageCase = request.getMessageCase(); + try { + if (messageCase == Write.Request.MessageCase.MIGRATE_TABLE) { + plugin.write(processMigrateTableRequest(request)); + } else if (messageCase == Write.Request.MessageCase.INSERT) { + plugin.write(processInsertRequest(request)); + } else if (messageCase == Write.Request.MessageCase.DELETE) { + plugin.write(processDeleteStaleRequest(request)); + } else { + throw new IllegalArgumentException("Unknown message type: " + messageCase); + } + } catch (IOException | ValidationException ex) { + onError(ex); + } + } + + @Override + public void onError(Throwable t) { + responseObserver.onError(t); + } + + @Override + public void onCompleted() { + responseObserver.onNext(Write.Response.newBuilder().build()); + responseObserver.onCompleted(); + } + }; + } + + @Override + public void close( + io.cloudquery.plugin.v3.Close.Request request, + StreamObserver responseObserver) { + plugin.close(); + responseObserver.onNext(io.cloudquery.plugin.v3.Close.Response.newBuilder().build()); + responseObserver.onCompleted(); + } + + private WriteMigrateTable processMigrateTableRequest(Write.Request request) throws IOException { + MessageMigrateTable migrateTable = request.getMigrateTable(); + ByteString byteString = migrateTable.getTable(); + boolean migrateForce = request.getMigrateTable().getMigrateForce(); + return new WriteMigrateTable(ArrowHelper.decode(byteString), migrateForce); + } + + private WriteMessage processInsertRequest(Write.Request request) + throws IOException, ValidationException { + Write.MessageInsert insert = request.getInsert(); + ByteString record = insert.getRecord(); + return new WriteInsert(ArrowHelper.decodeResource(record)); + } + + private WriteMessage processDeleteStaleRequest(Write.Request request) + throws IOException, ValidationException { + Write.MessageDeleteStale messageDeleteStale = request.getDelete(); + return new WriteDeleteStale( + messageDeleteStale.getTableName(), + messageDeleteStale.getSourceName(), + new Date(messageDeleteStale.getSyncTime().getSeconds() * 1000)); + } - public PluginServer(Plugin plugin) { - this.plugin = plugin; + @Override + public void getSpecSchema( + io.cloudquery.plugin.v3.GetSpecSchema.Request request, + StreamObserver responseObserver) { + io.cloudquery.plugin.v3.GetSpecSchema.Response.Builder builder = + io.cloudquery.plugin.v3.GetSpecSchema.Response.newBuilder(); + String schema = this.plugin.getJsonSchema(); + if (schema != null && !schema.isBlank()) { + builder.setJsonSchema(schema); } + responseObserver.onNext(builder.build()); + responseObserver.onCompleted(); + } } diff --git a/lib/src/main/java/io/cloudquery/memdb/MemDB.java b/lib/src/main/java/io/cloudquery/memdb/MemDB.java index a0c8f925..799b8f80 100644 --- a/lib/src/main/java/io/cloudquery/memdb/MemDB.java +++ b/lib/src/main/java/io/cloudquery/memdb/MemDB.java @@ -1,9 +1,167 @@ package io.cloudquery.memdb; +import io.cloudquery.messages.WriteMessage; +import io.cloudquery.plugin.BackendOptions; +import io.cloudquery.plugin.ClientNotInitializedException; +import io.cloudquery.plugin.NewClientOptions; import io.cloudquery.plugin.Plugin; +import io.cloudquery.plugin.PluginKind; +import io.cloudquery.plugin.TableOutputStream; +import io.cloudquery.scheduler.Scheduler; +import io.cloudquery.schema.ClientMeta; +import io.cloudquery.schema.Resource; +import io.cloudquery.schema.SchemaException; +import io.cloudquery.schema.Table; +import io.cloudquery.schema.TableResolver; +import io.cloudquery.transformers.Tables; +import io.cloudquery.transformers.TransformWithClass; +import io.grpc.stub.StreamObserver; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.UUID; public class MemDB extends Plugin { - public MemDB() { - super("memdb", "0.0.1"); + private static List
getTables() { + List
tables = + List.of( + Table.builder() + .name("table1") + .resolver( + new TableResolver() { + @Override + public void resolve( + ClientMeta clientMeta, Resource parent, TableOutputStream stream) { + stream.write( + Table1Data.builder() + .id(UUID.fromString("46b2b6e6-8f3e-4340-a721-4aa0786b1cc0")) + .name("name1") + .timestamp(LocalDateTime.now()) + .json(Map.of("key1", "value1", "key2", "value2")) + .build()); + stream.write( + Table1Data.builder() + .id(UUID.fromString("e89f95df-a389-4f1b-9ba6-1fab565523d6")) + .name("name2") + .build()); + } + }) + .transform(TransformWithClass.builder(Table1Data.class).pkField("id").build()) + .build(), + Table.builder() + .name("table2") + .resolver( + new TableResolver() { + @Override + public void resolve( + ClientMeta clientMeta, Resource parent, TableOutputStream stream) { + stream.write(Table2Data.builder().id(1).name("name1").build()); + stream.write(Table2Data.builder().id(2).name("name2").build()); + } + }) + .transform(TransformWithClass.builder(Table2Data.class).pkField("id").build()) + .relations( + List.of( + Table.builder() + .name("table2_child") + .resolver( + new TableResolver() { + + @Override + public void resolve( + ClientMeta clientMeta, + Resource parent, + TableOutputStream stream) { + String parentName = parent.get("name").toString(); + stream.write( + Table2ChildData.builder() + .name(parentName + "_name1") + .build()); + stream.write( + Table2ChildData.builder() + .name(parentName + "_name2") + .build()); + } + }) + .transform(TransformWithClass.builder(Table2ChildData.class).build()) + .build())) + .build()); + Tables.setParents(tables, null); + return tables; + } + + private List
allTables; + + private Spec spec; + + public MemDB() { + super("memdb", "0.0.1"); + setTeam("cloudquery"); + setKind(PluginKind.Source); + } + + @Override + public List
tables( + List includeList, List skipList, boolean skipDependentTables) + throws SchemaException, ClientNotInitializedException { + if (this.client == null) { + throw new ClientNotInitializedException(); + } + return Table.filterDFS(allTables, includeList, skipList, skipDependentTables); + } + + @Override + public void sync( + List includeList, + List skipList, + boolean skipDependentTables, + boolean deterministicCqId, + BackendOptions backendOptions, + StreamObserver syncStream) + throws SchemaException, ClientNotInitializedException { + if (this.client == null) { + throw new ClientNotInitializedException(); + } + + List
filtered = Table.filterDFS(allTables, includeList, skipList, skipDependentTables); + Scheduler.builder() + .client(client) + .tables(filtered) + .syncStream(syncStream) + .deterministicCqId(deterministicCqId) + .logger(getLogger()) + .concurrency(this.spec.getConcurrency()) + .build() + .sync(); + } + + @Override + public void read() { + throw new UnsupportedOperationException("Unimplemented method 'Read'"); + } + + @Override + public void write(WriteMessage message) { + client.write(message); + } + + @Override + public void close() { + if (this.client != null) { + ((MemDBClient) this.client).close(); + } + } + + @Override + public ClientMeta newClient(String spec, NewClientOptions options) throws Exception { + this.allTables = getTables(); + Tables.transformTables(this.allTables); + for (Table table : this.allTables) { + table.addCQIDs(); + } + if (!options.isNoConnection()) { + this.spec = Spec.fromJSON(spec); } + return new MemDBClient(); + } } diff --git a/lib/src/main/java/io/cloudquery/memdb/MemDBClient.java b/lib/src/main/java/io/cloudquery/memdb/MemDBClient.java new file mode 100644 index 00000000..1f5a27b0 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/memdb/MemDBClient.java @@ -0,0 +1,140 @@ +package io.cloudquery.memdb; + +import io.cloudquery.messages.WriteDeleteStale; +import io.cloudquery.messages.WriteInsert; +import io.cloudquery.messages.WriteMessage; +import io.cloudquery.messages.WriteMigrateTable; +import io.cloudquery.scalar.Timestamp; +import io.cloudquery.schema.ClientMeta; +import io.cloudquery.schema.Column; +import io.cloudquery.schema.Resource; +import io.cloudquery.schema.Table; +import io.cloudquery.schema.TableColumnChange; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class MemDBClient implements ClientMeta { + private static final String id = "memdb"; + + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + private final Map tables = new HashMap<>(); + private final Map> memDB = new HashMap<>(); + + public MemDBClient() {} + + @Override + public String getId() { + return id; + } + + @Override + public void write(WriteMessage message) { + lock.writeLock().lock(); + try { + if (message instanceof WriteMigrateTable migrateTable) { + migrate(migrateTable); + } + if (message instanceof WriteInsert insert) { + insert(insert); + } + if (message instanceof WriteDeleteStale deleteStale) { + deleteStale(deleteStale); + } + } finally { + lock.writeLock().unlock(); + } + } + + private void insert(WriteInsert insert) { + String tableName = insert.getResource().getTable().getName(); + Table table = tables.get(tableName); + overwrite(table, insert.getResource()); + } + + private void overwrite(Table table, Resource resource) { + String tableName = table.getName(); + List pkIndexes = table.primaryKeyIndexes(); + if (pkIndexes.isEmpty()) { + memDB.get(tableName).add(resource); + return; + } + + for (int i = 0; i < memDB.get(tableName).size(); i++) { + boolean found = true; + for (int pkIndex : pkIndexes) { + String s1 = resource.getTable().getColumns().get(pkIndex).getName(); + String s2 = memDB.get(tableName).get(i).getTable().getColumns().get(pkIndex).getName(); + if (!s1.equals(s2)) { + found = false; + } + } + if (found) { + memDB.get(tableName).remove(i); + memDB.get(tableName).add(resource); + return; + } + } + memDB.get(tableName).add(resource); + } + + private void deleteStale(WriteDeleteStale deleteStale) { + String tableName = deleteStale.getTableName(); + + List filteredList = new ArrayList<>(); + + for (int i = 0; i < memDB.get(tableName).size(); i++) { + Resource row = memDB.get(tableName).get(i); + Optional sourceColumn = row.getTable().getColumn(Column.CQ_SOURCE_NAME); + if (sourceColumn.isEmpty()) { + continue; + } + Optional syncColumn = row.getTable().getColumn(Column.CQ_SYNC_TIME); + if (syncColumn.isEmpty()) { + continue; + } + + String sourceName = ""; + if (row.get(Column.CQ_SOURCE_NAME) != null) { + sourceName = row.get(Column.CQ_SOURCE_NAME).toString(); + } + + if (Objects.equals(sourceName, deleteStale.getSourceName())) { + Date rowSyncTime = new Date(0); + if (row.get(Column.CQ_SYNC_TIME) != null) { + rowSyncTime = new Date(((Timestamp) row.get(Column.CQ_SYNC_TIME)).get()); + } + if (!rowSyncTime.before(deleteStale.getTimestamp())) { + filteredList.add(row); + } + } + } + memDB.put(tableName, filteredList); + } + + public void close() { + // do nothing + } + + private void migrate(WriteMigrateTable migrateTable) { + Table table = migrateTable.getTable(); + String tableName = table.getName(); + if (!memDB.containsKey(tableName)) { + memDB.put(tableName, new ArrayList<>()); + tables.put(tableName, table); + return; + } + + List changes = table.getChanges(tables.get(tableName)); + if (changes.isEmpty()) { + return; + } + memDB.put(tableName, new ArrayList<>()); + tables.put(tableName, table); + } +} diff --git a/lib/src/main/java/io/cloudquery/memdb/Spec.java b/lib/src/main/java/io/cloudquery/memdb/Spec.java new file mode 100644 index 00000000..359360e1 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/memdb/Spec.java @@ -0,0 +1,24 @@ +package io.cloudquery.memdb; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class Spec { + public static Spec fromJSON(String json) throws JsonMappingException, JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + Spec spec = objectMapper.readValue(json, Spec.class); + if (spec.getConcurrency() == 0) { + spec.setConcurrency(100); + } + return spec; + } + + private int concurrency; + + public Spec() {} +} diff --git a/lib/src/main/java/io/cloudquery/memdb/Table1Data.java b/lib/src/main/java/io/cloudquery/memdb/Table1Data.java new file mode 100644 index 00000000..786aff17 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/memdb/Table1Data.java @@ -0,0 +1,16 @@ +package io.cloudquery.memdb; + +import java.time.LocalDateTime; +import java.util.Map; +import java.util.UUID; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Table1Data { + private UUID id; + private String name; + private LocalDateTime timestamp; + private Map json; +} diff --git a/lib/src/main/java/io/cloudquery/memdb/Table2ChildData.java b/lib/src/main/java/io/cloudquery/memdb/Table2ChildData.java new file mode 100644 index 00000000..4597b670 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/memdb/Table2ChildData.java @@ -0,0 +1,10 @@ +package io.cloudquery.memdb; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Table2ChildData { + private String name; +} diff --git a/lib/src/main/java/io/cloudquery/memdb/Table2Data.java b/lib/src/main/java/io/cloudquery/memdb/Table2Data.java new file mode 100644 index 00000000..494b3319 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/memdb/Table2Data.java @@ -0,0 +1,11 @@ +package io.cloudquery.memdb; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class Table2Data { + private int id; + private String name; +} diff --git a/lib/src/main/java/io/cloudquery/messages/WriteDeleteStale.java b/lib/src/main/java/io/cloudquery/messages/WriteDeleteStale.java new file mode 100644 index 00000000..afea7c64 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/messages/WriteDeleteStale.java @@ -0,0 +1,13 @@ +package io.cloudquery.messages; + +import java.util.Date; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class WriteDeleteStale extends WriteMessage { + private String tableName; + private String sourceName; + private Date timestamp; +} diff --git a/lib/src/main/java/io/cloudquery/messages/WriteInsert.java b/lib/src/main/java/io/cloudquery/messages/WriteInsert.java new file mode 100644 index 00000000..58ed31a3 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/messages/WriteInsert.java @@ -0,0 +1,11 @@ +package io.cloudquery.messages; + +import io.cloudquery.schema.Resource; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class WriteInsert extends WriteMessage { + private Resource resource; +} diff --git a/lib/src/main/java/io/cloudquery/messages/WriteMessage.java b/lib/src/main/java/io/cloudquery/messages/WriteMessage.java new file mode 100644 index 00000000..81e61296 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/messages/WriteMessage.java @@ -0,0 +1,3 @@ +package io.cloudquery.messages; + +public abstract class WriteMessage {} diff --git a/lib/src/main/java/io/cloudquery/messages/WriteMigrateTable.java b/lib/src/main/java/io/cloudquery/messages/WriteMigrateTable.java new file mode 100644 index 00000000..bf8123b7 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/messages/WriteMigrateTable.java @@ -0,0 +1,12 @@ +package io.cloudquery.messages; + +import io.cloudquery.schema.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class WriteMigrateTable extends WriteMessage { + private Table table; + private boolean migrateForce; +} diff --git a/lib/src/main/java/io/cloudquery/plugin/BackendOptions.java b/lib/src/main/java/io/cloudquery/plugin/BackendOptions.java new file mode 100644 index 00000000..d5ebdab3 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/plugin/BackendOptions.java @@ -0,0 +1,11 @@ +package io.cloudquery.plugin; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class BackendOptions { + private final String tableName; + private final String connection; +} diff --git a/lib/src/main/java/io/cloudquery/plugin/BuildArch.java b/lib/src/main/java/io/cloudquery/plugin/BuildArch.java new file mode 100644 index 00000000..ee4a3501 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/plugin/BuildArch.java @@ -0,0 +1,16 @@ +package io.cloudquery.plugin; + +public enum BuildArch { + AMD64("amd64"), + ARM64("arm64"); + + public final String arch; + + private BuildArch(String arch) { + this.arch = arch; + } + + public String toString() { + return this.arch; + } +} diff --git a/lib/src/main/java/io/cloudquery/plugin/BuildOS.java b/lib/src/main/java/io/cloudquery/plugin/BuildOS.java new file mode 100644 index 00000000..41b05e0b --- /dev/null +++ b/lib/src/main/java/io/cloudquery/plugin/BuildOS.java @@ -0,0 +1,17 @@ +package io.cloudquery.plugin; + +public enum BuildOS { + Windows("windows"), + Linux("linux"), + Darwin("darwin"); + + public final String os; + + private BuildOS(String os) { + this.os = os; + } + + public String toString() { + return this.os; + } +} diff --git a/lib/src/main/java/io/cloudquery/plugin/BuildTarget.java b/lib/src/main/java/io/cloudquery/plugin/BuildTarget.java new file mode 100644 index 00000000..f9780a19 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/plugin/BuildTarget.java @@ -0,0 +1,12 @@ +package io.cloudquery.plugin; + +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public class BuildTarget { + @NonNull protected final BuildOS os; + @NonNull protected final BuildArch arch; +} diff --git a/lib/src/main/java/io/cloudquery/plugin/ClientNotInitializedException.java b/lib/src/main/java/io/cloudquery/plugin/ClientNotInitializedException.java new file mode 100644 index 00000000..650012b6 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/plugin/ClientNotInitializedException.java @@ -0,0 +1,6 @@ +package io.cloudquery.plugin; + +public class ClientNotInitializedException extends Exception { + + public ClientNotInitializedException() {} +} diff --git a/lib/src/main/java/io/cloudquery/plugin/NewClientOptions.java b/lib/src/main/java/io/cloudquery/plugin/NewClientOptions.java new file mode 100644 index 00000000..051d2e68 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/plugin/NewClientOptions.java @@ -0,0 +1,10 @@ +package io.cloudquery.plugin; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class NewClientOptions { + private final boolean noConnection; +} diff --git a/lib/src/main/java/io/cloudquery/plugin/Plugin.java b/lib/src/main/java/io/cloudquery/plugin/Plugin.java index 918981eb..9f2ef6f7 100644 --- a/lib/src/main/java/io/cloudquery/plugin/Plugin.java +++ b/lib/src/main/java/io/cloudquery/plugin/Plugin.java @@ -1,14 +1,61 @@ package io.cloudquery.plugin; -import lombok.AllArgsConstructor; +import io.cloudquery.messages.WriteMessage; +import io.cloudquery.schema.ClientMeta; +import io.cloudquery.schema.SchemaException; +import io.cloudquery.schema.Table; +import io.grpc.stub.StreamObserver; +import java.util.List; import lombok.Getter; import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.apache.logging.log4j.Logger; +@RequiredArgsConstructor @Getter -@AllArgsConstructor public abstract class Plugin { - @NonNull - protected final String name; - @NonNull - protected final String version; + @NonNull protected final String name; + @NonNull protected final String version; + + @Setter protected Logger logger; + @Setter protected String jsonSchema; + + @Setter protected String team; + @Setter protected PluginKind kind; + @Setter protected String dockerfile = "Dockerfile"; + + @Setter + protected BuildTarget[] buildTargets = + new BuildTarget[] { + new BuildTarget(BuildOS.Linux, BuildArch.ARM64), + new BuildTarget(BuildOS.Linux, BuildArch.AMD64), + }; + + protected ClientMeta client; + + public void init(String spec, NewClientOptions options) throws Exception { + client = newClient(spec, options); + } + + public abstract ClientMeta newClient(String spec, NewClientOptions options) throws Exception; + + public abstract List
tables( + List includeList, List skipList, boolean skipDependentTables) + throws SchemaException, ClientNotInitializedException; + + public abstract void sync( + List includeList, + List skipList, + boolean skipDependentTables, + boolean deterministicCqId, + BackendOptions backendOptions, + StreamObserver syncStream) + throws SchemaException, ClientNotInitializedException; + + public abstract void read(); + + public abstract void write(WriteMessage message); + + public abstract void close(); } diff --git a/lib/src/main/java/io/cloudquery/plugin/PluginKind.java b/lib/src/main/java/io/cloudquery/plugin/PluginKind.java new file mode 100644 index 00000000..e4e94334 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/plugin/PluginKind.java @@ -0,0 +1,16 @@ +package io.cloudquery.plugin; + +public enum PluginKind { + Source("source"), + Destination("destination"); + + public final String kind; + + private PluginKind(String kind) { + this.kind = kind; + } + + public String toString() { + return this.kind; + } +} diff --git a/lib/src/main/java/io/cloudquery/plugin/SyncStream.java b/lib/src/main/java/io/cloudquery/plugin/SyncStream.java new file mode 100644 index 00000000..684e82d2 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/plugin/SyncStream.java @@ -0,0 +1,5 @@ +package io.cloudquery.plugin; + +import io.grpc.stub.StreamObserver; + +public interface SyncStream extends StreamObserver {} diff --git a/lib/src/main/java/io/cloudquery/plugin/TableOutputStream.java b/lib/src/main/java/io/cloudquery/plugin/TableOutputStream.java new file mode 100644 index 00000000..328c4d02 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/plugin/TableOutputStream.java @@ -0,0 +1,5 @@ +package io.cloudquery.plugin; + +public interface TableOutputStream { + public void write(Object data); +} diff --git a/lib/src/main/java/io/cloudquery/scalar/Binary.java b/lib/src/main/java/io/cloudquery/scalar/Binary.java index e24927eb..9135631f 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Binary.java +++ b/lib/src/main/java/io/cloudquery/scalar/Binary.java @@ -1,76 +1,76 @@ package io.cloudquery.scalar; +import java.util.Arrays; import org.apache.arrow.vector.types.pojo.ArrowType; import org.apache.commons.codec.binary.Base64; -import java.util.Arrays; - public class Binary extends Scalar { - public Binary() { - super(); + public Binary() { + super(); + } + + public Binary(Object value) throws ValidationException { + super(value); + } + + @Override + public java.lang.String toString() { + if (this.value != null) { + return Base64.encodeBase64String(this.value); } + return NULL_VALUE_STRING; + } - public Binary(Object value) throws ValidationException { - super(value); + @Override + public ArrowType dataType() { + return ArrowType.Binary.INSTANCE; + } + + @Override + public void setValue(Object value) throws ValidationException { + if (value instanceof byte[] bytes) { + this.value = bytes; + return; } - @Override - public java.lang.String toString() { - if (this.value != null) { - return Base64.encodeBase64String(this.value); - } - return NULL_VALUE_STRING; + if (value instanceof CharSequence sequence) { + this.value = Base64.decodeBase64(sequence.toString()); + return; } - @Override - public ArrowType dataType() { - return ArrowType.Binary.INSTANCE; + if (value instanceof char[] chars) { + this.value = Base64.decodeBase64(new java.lang.String(chars)); + return; } - @Override - public void setValue(Object value) throws ValidationException { - if (value instanceof byte[] bytes) { - this.value = bytes; - return; - } + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } - if (value instanceof CharSequence sequence) { - this.value = Base64.decodeBase64(sequence.toString()); - return; - } + @Override + public boolean equals(Object other) { + if (other instanceof Binary o) { + if (this.value == null) { + return o.value == null; + } + return Arrays.equals(this.value, o.value); + } + return false; + } - if (value instanceof char[] chars) { - this.value = Base64.decodeBase64(new java.lang.String(chars)); - return; - } + public static class LargeBinary extends Binary { - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + public LargeBinary() { + super(); } - @Override - public boolean equals(Object other) { - if (other instanceof Binary o) { - if (this.value == null) { - return o.value == null; - } - return Arrays.equals(this.value, o.value); - } - return false; + public LargeBinary(Object value) throws ValidationException { + super(value); } - public static class LargeBinary extends Binary { - - public LargeBinary() { - super(); - } - - public LargeBinary(Object value) throws ValidationException { - super(value); - } - - @Override - public ArrowType dataType() { - return ArrowType.LargeBinary.INSTANCE; - } + @Override + public ArrowType dataType() { + return ArrowType.LargeBinary.INSTANCE; } -} \ No newline at end of file + } +} diff --git a/lib/src/main/java/io/cloudquery/scalar/Bool.java b/lib/src/main/java/io/cloudquery/scalar/Bool.java index d92fda78..d8a242af 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Bool.java +++ b/lib/src/main/java/io/cloudquery/scalar/Bool.java @@ -3,31 +3,32 @@ import org.apache.arrow.vector.types.pojo.ArrowType; public class Bool extends Scalar { - public Bool() { - super(); - } - - public Bool(Object value) throws ValidationException { - super(value); - } + public Bool() { + super(); + } - @Override - public ArrowType dataType() { - return ArrowType.Bool.INSTANCE; - } + public Bool(Object value) throws ValidationException { + super(value); + } - @Override - public void setValue(Object value) throws ValidationException { - if (value instanceof Boolean b) { - this.value = b; - return; - } + @Override + public ArrowType dataType() { + return ArrowType.Bool.INSTANCE; + } - if (value instanceof CharSequence sequence) { - this.value = Boolean.parseBoolean(sequence.toString()); - return; - } + @Override + public void setValue(Object value) throws ValidationException { + if (value instanceof Boolean b) { + this.value = b; + return; + } - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + if (value instanceof CharSequence sequence) { + this.value = Boolean.parseBoolean(sequence.toString()); + return; } + + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } } diff --git a/lib/src/main/java/io/cloudquery/scalar/DateDay.java b/lib/src/main/java/io/cloudquery/scalar/DateDay.java index 2781c824..5a872f9f 100644 --- a/lib/src/main/java/io/cloudquery/scalar/DateDay.java +++ b/lib/src/main/java/io/cloudquery/scalar/DateDay.java @@ -4,31 +4,32 @@ import org.apache.arrow.vector.types.pojo.ArrowType; public class DateDay extends Scalar { - public DateDay() { - super(); - } - - public DateDay(Object value) throws ValidationException { - super(value); - } + public DateDay() { + super(); + } - @Override - public ArrowType dataType() { - return new ArrowType.Date(DateUnit.DAY); - } + public DateDay(Object value) throws ValidationException { + super(value); + } - @Override - public void setValue(Object value) throws ValidationException { - if (value instanceof Integer b) { - this.value = b; - return; - } + @Override + public ArrowType dataType() { + return new ArrowType.Date(DateUnit.DAY); + } - if (value instanceof CharSequence sequence) { - this.value = Integer.parseInt(sequence.toString()); - return; - } + @Override + public void setValue(Object value) throws ValidationException { + if (value instanceof Integer b) { + this.value = b; + return; + } - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + if (value instanceof CharSequence sequence) { + this.value = Integer.parseInt(sequence.toString()); + return; } + + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } } diff --git a/lib/src/main/java/io/cloudquery/scalar/DateMilli.java b/lib/src/main/java/io/cloudquery/scalar/DateMilli.java index d3cc0f8a..97aec0f9 100644 --- a/lib/src/main/java/io/cloudquery/scalar/DateMilli.java +++ b/lib/src/main/java/io/cloudquery/scalar/DateMilli.java @@ -1,39 +1,47 @@ package io.cloudquery.scalar; +import java.time.LocalDateTime; import org.apache.arrow.vector.types.DateUnit; import org.apache.arrow.vector.types.pojo.ArrowType; public class DateMilli extends Scalar { - public DateMilli() { - super(); + public DateMilli() { + super(); + } + + public DateMilli(Object value) throws ValidationException { + super(value); + } + + @Override + public ArrowType dataType() { + return new ArrowType.Date(DateUnit.MILLISECOND); + } + + @Override + public void setValue(Object value) throws ValidationException { + if (value instanceof Long b) { + this.value = b; + return; } - public DateMilli(Object value) throws ValidationException { - super(value); + if (value instanceof Integer b) { + this.value = Long.valueOf(b); + return; } - @Override - public ArrowType dataType() { - return new ArrowType.Date(DateUnit.MILLISECOND); + if (value instanceof CharSequence sequence) { + this.value = Long.parseLong(sequence.toString()); + return; } - @Override - public void setValue(Object value) throws ValidationException { - if (value instanceof Long b) { - this.value = b; - return; - } - - if (value instanceof Integer b) { - this.value = Long.valueOf(b); - return; - } - - if (value instanceof CharSequence sequence) { - this.value = Long.parseLong(sequence.toString()); - return; - } - - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + if (value instanceof LocalDateTime localDateTime) { + // we actually store only date + this.value = localDateTime.toLocalDate().toEpochDay(); + return; } + + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } } diff --git a/lib/src/main/java/io/cloudquery/scalar/Duration.java b/lib/src/main/java/io/cloudquery/scalar/Duration.java index 56edac01..d5bcb77d 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Duration.java +++ b/lib/src/main/java/io/cloudquery/scalar/Duration.java @@ -4,44 +4,45 @@ import org.apache.arrow.vector.types.pojo.ArrowType; public class Duration extends Scalar { - // TODO: add more units support later - private static final ArrowType dt = new ArrowType.Duration(TimeUnit.MILLISECOND); - - public Duration() { - super(); + // TODO: add more units support later + private static final ArrowType dt = new ArrowType.Duration(TimeUnit.MILLISECOND); + + public Duration() { + super(); + } + + public Duration(Object value) throws ValidationException { + super(value); + } + + @Override + public ArrowType dataType() { + return dt; + } + + @Override + public void setValue(Object value) throws ValidationException { + if (value instanceof java.time.Duration duration) { + this.value = duration; + return; } - public Duration(Object value) throws ValidationException { - super(value); + if (value instanceof Integer integer) { + this.value = java.time.Duration.ofMillis(integer); + return; } - @Override - public ArrowType dataType() { - return dt; + if (value instanceof Long longValue) { + this.value = java.time.Duration.ofMillis(longValue); + return; } - @Override - public void setValue(Object value) throws ValidationException { - if (value instanceof java.time.Duration duration) { - this.value = duration; - return; - } - - if (value instanceof Integer integer) { - this.value = java.time.Duration.ofMillis(integer); - return; - } - - if (value instanceof Long longValue) { - this.value = java.time.Duration.ofMillis(longValue); - return; - } - - if (value instanceof CharSequence sequence) { - this.value = java.time.Duration.parse(sequence); - return; - } - - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + if (value instanceof CharSequence sequence) { + this.value = java.time.Duration.parse(sequence); + return; } + + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } } diff --git a/lib/src/main/java/io/cloudquery/scalar/JSON.java b/lib/src/main/java/io/cloudquery/scalar/JSON.java new file mode 100644 index 00000000..66f50a56 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/scalar/JSON.java @@ -0,0 +1,82 @@ +package io.cloudquery.scalar; + +import static io.cloudquery.scalar.ValidationException.NO_CONVERSION_AVAILABLE; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.cloudquery.types.JSONType; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; +import org.apache.arrow.vector.types.pojo.ArrowType; + +public class JSON extends Scalar { + private static final JSONType dt = new JSONType(); + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + public JSON() { + super(); + } + + public JSON(Object value) throws ValidationException { + super(value); + } + + @Override + protected void setValue(Object value) throws ValidationException { + if (value instanceof byte[] bytes) { + if (bytes.length == 0) { + return; + } + if (!isValidJSON(bytes)) { + throw new ValidationException("invalid json", dt, value); + } + this.value = bytes; + } else if (value instanceof java.lang.String string) { + set(string.getBytes()); + } else { + set(parseAsJSONBytes(value)); + } + } + + @Override + public ArrowType dataType() { + return dt; + } + + @Override + public boolean equals(Object other) { + if (other instanceof JSON o) { + if (this.value == null) { + return o.value == null; + } + return Arrays.equals(this.value, o.value); + } + return super.equals(other); + } + + @Override + public java.lang.String toString() { + if (this.value != null) { + return new java.lang.String(this.value); + } + return NULL_VALUE_STRING; + } + + private byte[] parseAsJSONBytes(Object value) throws ValidationException { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + OBJECT_MAPPER.writeValue(outputStream, value); + return outputStream.toByteArray(); + } catch (IOException e) { + throw new ValidationException(NO_CONVERSION_AVAILABLE, this.dataType(), value); + } + } + + private boolean isValidJSON(byte[] bytes) { + try { + OBJECT_MAPPER.readTree(bytes); + return true; + } catch (IOException ex) { + return false; + } + } +} diff --git a/lib/src/main/java/io/cloudquery/scalar/Number.java b/lib/src/main/java/io/cloudquery/scalar/Number.java index 50b96e36..6c668f25 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Number.java +++ b/lib/src/main/java/io/cloudquery/scalar/Number.java @@ -8,330 +8,346 @@ import org.joou.UShort; public abstract class Number extends Scalar { - public Number() { + public Number() {} + + public Number(Object value) throws ValidationException { + this.set(value); + } + + public static class Int8 extends Number { + protected static final ArrowType dt = new ArrowType.Int(Byte.SIZE, true); + + public Int8() { + super(); } - public Number(Object value) throws ValidationException { - this.set(value); + public Int8(Object value) throws ValidationException { + super(value); } - public static class Int8 extends Number { - protected static final ArrowType dt = new ArrowType.Int(Byte.SIZE, true); + @Override + public ArrowType dataType() { + return dt; + } - public Int8() { - super(); - } + @Override + protected void setValue(Object value) throws ValidationException { + if (value instanceof CharSequence sequence) { + this.value = Byte.valueOf(sequence.toString()); + return; + } - public Int8(Object value) throws ValidationException { - super(value); - } + if (value instanceof java.lang.Number number) { + this.value = number.byteValue(); + return; + } - @Override - public ArrowType dataType() { - return dt; - } + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } + } - @Override - protected void setValue(Object value) throws ValidationException { - if (value instanceof CharSequence sequence) { - this.value = Byte.valueOf(sequence.toString()); - return; - } + public static class Int16 extends Number { + protected static final ArrowType dt = new ArrowType.Int(Short.SIZE, true); - if (value instanceof java.lang.Number number) { - this.value = number.byteValue(); - return; - } + public Int16() { + super(); + } - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); - } + public Int16(Object value) throws ValidationException { + super(value); } - public static class Int16 extends Number { - protected static final ArrowType dt = new ArrowType.Int(Short.SIZE, true); + @Override + public ArrowType dataType() { + return dt; + } - public Int16() { - super(); - } + @Override + protected void setValue(Object value) throws ValidationException { + if (value instanceof CharSequence sequence) { + this.value = Short.valueOf(sequence.toString()); + return; + } - public Int16(Object value) throws ValidationException { - super(value); - } + if (value instanceof java.lang.Number number) { + this.value = number.shortValue(); + return; + } - @Override - public ArrowType dataType() { - return dt; - } + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } + } - @Override - protected void setValue(Object value) throws ValidationException { - if (value instanceof CharSequence sequence) { - this.value = Short.valueOf(sequence.toString()); - return; - } + public static class Int32 extends Number { + protected static final ArrowType dt = new ArrowType.Int(Integer.SIZE, true); - if (value instanceof java.lang.Number number) { - this.value = number.shortValue(); - return; - } + public Int32() { + super(); + } - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); - } + public Int32(Object value) throws ValidationException { + super(value); } - public static class Int32 extends Number { - protected static final ArrowType dt = new ArrowType.Int(Integer.SIZE, true); + @Override + public ArrowType dataType() { + return dt; + } - public Int32() { - super(); - } + @Override + protected void setValue(Object value) throws ValidationException { + if (value instanceof CharSequence sequence) { + this.value = Integer.valueOf(sequence.toString()); + return; + } - public Int32(Object value) throws ValidationException { - super(value); - } + if (value instanceof java.lang.Number number) { + this.value = number.intValue(); + return; + } - @Override - public ArrowType dataType() { - return dt; - } + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } + } - @Override - protected void setValue(Object value) throws ValidationException { - if (value instanceof CharSequence sequence) { - this.value = Integer.valueOf(sequence.toString()); - return; - } + public static class Int64 extends Number { + protected static final ArrowType dt = new ArrowType.Int(Long.SIZE, true); - if (value instanceof java.lang.Number number) { - this.value = number.intValue(); - return; - } + public Int64() { + super(); + } - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); - } + public Int64(Object value) throws ValidationException { + super(value); } - public static class Int64 extends Number { - protected static final ArrowType dt = new ArrowType.Int(Long.SIZE, true); + @Override + public ArrowType dataType() { + return dt; + } - public Int64() { - super(); - } + @Override + protected void setValue(Object value) throws ValidationException { + if (value instanceof CharSequence sequence) { + this.value = Long.valueOf(sequence.toString()); + return; + } - public Int64(Object value) throws ValidationException { - super(value); - } + if (value instanceof java.lang.Number number) { + this.value = number.longValue(); + return; + } + + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } + } - @Override - public ArrowType dataType() { - return dt; - } - - @Override - protected void setValue(Object value) throws ValidationException { - if (value instanceof CharSequence sequence) { - this.value = Long.valueOf(sequence.toString()); - return; - } - - if (value instanceof java.lang.Number number) { - this.value = number.longValue(); - return; - } + public static class UInt8 extends Number { + protected static final ArrowType dt = new ArrowType.Int(Byte.SIZE, false); - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); - } + public UInt8() { + super(); } - public static class UInt8 extends Number { - protected static final ArrowType dt = new ArrowType.Int(Byte.SIZE, false); + public UInt8(Object value) throws ValidationException { + super(value); + } - public UInt8() { - super(); - } + @Override + public ArrowType dataType() { + return dt; + } - public UInt8(Object value) throws ValidationException { - super(value); - } + @Override + protected void setValue(Object value) throws ValidationException { + if (value instanceof CharSequence sequence) { + this.value = UByte.valueOf(sequence.toString()); + return; + } - @Override - public ArrowType dataType() { - return dt; - } - - @Override - protected void setValue(Object value) throws ValidationException { - if (value instanceof CharSequence sequence) { - this.value = UByte.valueOf(sequence.toString()); - return; - } - - if (value instanceof java.lang.Number number) { - this.value = UByte.valueOf(number.byteValue()); - return; - } + if (value instanceof java.lang.Number number) { + this.value = UByte.valueOf(number.byteValue()); + return; + } - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); - } + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); } + } - public static class UInt16 extends Number { - protected static final ArrowType dt = new ArrowType.Int(Short.SIZE, false); + public static class UInt16 extends Number { + protected static final ArrowType dt = new ArrowType.Int(Short.SIZE, false); - public UInt16() { - super(); - } + public UInt16() { + super(); + } - public UInt16(Object value) throws ValidationException { - super(value); - } + public UInt16(Object value) throws ValidationException { + super(value); + } - @Override - public ArrowType dataType() { - return dt; - } - - @Override - protected void setValue(Object value) throws ValidationException { - if (value instanceof CharSequence sequence) { - this.value = UShort.valueOf(sequence.toString()); - return; - } - - if (value instanceof java.lang.Number number) { - this.value = UShort.valueOf(number.shortValue()); - return; - } + @Override + public ArrowType dataType() { + return dt; + } - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); - } + @Override + protected void setValue(Object value) throws ValidationException { + if (value instanceof CharSequence sequence) { + this.value = UShort.valueOf(sequence.toString()); + return; + } + + if (value instanceof java.lang.Number number) { + this.value = UShort.valueOf(number.shortValue()); + return; + } + + if (value instanceof Character character) { + this.value = UShort.valueOf(character); + return; + } + + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); } + } - public static class UInt32 extends Number { - protected static final ArrowType dt = new ArrowType.Int(Integer.SIZE, false); + public static class UInt32 extends Number { + protected static final ArrowType dt = new ArrowType.Int(Integer.SIZE, false); - public UInt32() { - super(); - } + public UInt32() { + super(); + } - public UInt32(Object value) throws ValidationException { - super(value); - } + public UInt32(Object value) throws ValidationException { + super(value); + } + + @Override + public ArrowType dataType() { + return dt; + } - @Override - public ArrowType dataType() { - return dt; - } - - @Override - protected void setValue(Object value) throws ValidationException { - if (value instanceof CharSequence sequence) { - this.value = UInteger.valueOf(sequence.toString()); - return; - } - - if (value instanceof java.lang.Number number) { - this.value = UInteger.valueOf(number.intValue()); - return; - } + @Override + protected void setValue(Object value) throws ValidationException { + if (value instanceof CharSequence sequence) { + this.value = UInteger.valueOf(sequence.toString()); + return; + } - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); - } + if (value instanceof java.lang.Number number) { + this.value = UInteger.valueOf(number.intValue()); + return; + } + + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); } + } + + public static class UInt64 extends Number { + protected static final ArrowType dt = new ArrowType.Int(Long.SIZE, false); - public static class UInt64 extends Number { - protected static final ArrowType dt = new ArrowType.Int(Long.SIZE, false); + public UInt64() { + super(); + } - public UInt64() { - super(); - } + public UInt64(Object value) throws ValidationException { + super(value); + } - public UInt64(Object value) throws ValidationException { - super(value); - } + @Override + public ArrowType dataType() { + return dt; + } - @Override - public ArrowType dataType() { - return dt; - } - - @Override - protected void setValue(Object value) throws ValidationException { - if (value instanceof CharSequence sequence) { - this.value = ULong.valueOf(sequence.toString()); - return; - } + @Override + protected void setValue(Object value) throws ValidationException { + if (value instanceof CharSequence sequence) { + this.value = ULong.valueOf(sequence.toString()); + return; + } - if (value instanceof java.lang.Number number) { - this.value = ULong.valueOf(number.longValue()); - return; - } + if (value instanceof java.lang.Number number) { + this.value = ULong.valueOf(number.longValue()); + return; + } - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); - } + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); } + } - public static class Float32 extends Number { - protected static final ArrowType dt = new ArrowType.FloatingPoint(FloatingPointPrecision.SINGLE); + public static class Float32 extends Number { + protected static final ArrowType dt = + new ArrowType.FloatingPoint(FloatingPointPrecision.SINGLE); - public Float32() { - super(); - } + public Float32() { + super(); + } - public Float32(Object value) throws ValidationException { - super(value); - } + public Float32(Object value) throws ValidationException { + super(value); + } + + @Override + public ArrowType dataType() { + return dt; + } - @Override - public ArrowType dataType() { - return dt; - } - - @Override - protected void setValue(Object value) throws ValidationException { - if (value instanceof CharSequence sequence) { - this.value = Float.valueOf(sequence.toString()); - return; - } + @Override + protected void setValue(Object value) throws ValidationException { + if (value instanceof CharSequence sequence) { + this.value = Float.valueOf(sequence.toString()); + return; + } - if (value instanceof java.lang.Number number) { - this.value = number.floatValue(); - return; - } + if (value instanceof java.lang.Number number) { + this.value = number.floatValue(); + return; + } - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); - } + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); } + } - public static class Float64 extends Number { - protected static final ArrowType dt = new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE); + public static class Float64 extends Number { + protected static final ArrowType dt = + new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE); - public Float64() { - super(); - } + public Float64() { + super(); + } + + public Float64(Object value) throws ValidationException { + super(value); + } - public Float64(Object value) throws ValidationException { - super(value); - } + @Override + public ArrowType dataType() { + return dt; + } - @Override - public ArrowType dataType() { - return dt; - } - - @Override - protected void setValue(Object value) throws ValidationException { - if (value instanceof CharSequence sequence) { - this.value = Double.valueOf(sequence.toString()); - return; - } + @Override + protected void setValue(Object value) throws ValidationException { + if (value instanceof CharSequence sequence) { + this.value = Double.valueOf(sequence.toString()); + return; + } - if (value instanceof java.lang.Number number) { - this.value = number.doubleValue(); - return; - } + if (value instanceof java.lang.Number number) { + this.value = number.doubleValue(); + return; + } - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); - } + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); } + } } diff --git a/lib/src/main/java/io/cloudquery/scalar/Scalar.java b/lib/src/main/java/io/cloudquery/scalar/Scalar.java index f1c63372..ae9a7759 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Scalar.java +++ b/lib/src/main/java/io/cloudquery/scalar/Scalar.java @@ -1,161 +1,165 @@ package io.cloudquery.scalar; +import io.cloudquery.types.JSONType; import io.cloudquery.types.UUIDType; -import org.apache.arrow.vector.types.pojo.ArrowType; - import java.util.Objects; +import org.apache.arrow.vector.types.pojo.ArrowType; public abstract class Scalar { - protected T value; + protected T value; - public Scalar() { - } + public Scalar() {} - public Scalar(Object value) throws ValidationException { - this.set(value); - } + public Scalar(Object value) throws ValidationException { + this.set(value); + } - protected abstract void setValue(Object value) throws ValidationException; + protected abstract void setValue(Object value) throws ValidationException; - public abstract ArrowType dataType(); + public abstract ArrowType dataType(); - public java.lang.String toString() { - if (this.value != null) { - return this.value.toString(); - } - return NULL_VALUE_STRING; + public java.lang.String toString() { + if (this.value != null) { + return this.value.toString(); } + return NULL_VALUE_STRING; + } - public boolean isValid() { - return this.value != null; + public boolean isValid() { + return this.value != null; + } + + public void set(Object value) throws ValidationException { + if (value == null) { + this.value = null; + return; } - public void set(Object value) throws ValidationException { - if (value == null) { - this.value = null; - return; - } + if (value instanceof Scalar scalar) { + if (!scalar.isValid()) { + this.value = null; + return; + } - if (value instanceof Scalar scalar) { - if (!scalar.isValid()) { - this.value = null; - return; - } + this.set(scalar.get()); + return; + } - this.set(scalar.get()); - return; - } + this.setValue(value); + } - this.setValue(value); + public T get() { + if (this.isValid()) { + return this.value; } + return null; + } - public T get() { - return this.value; + public boolean equals(Object other) { + if (!(other instanceof Scalar o)) { + return false; } - public boolean equals(Object other) { - if (!(other instanceof Scalar o)) { - return false; - } - - if (!o.getClass().equals(this.getClass())) { - return false; - } - - if (this.value == null) { - return o.value == null; - } - - return this.value.equals(o.value); + if (!o.getClass().equals(this.getClass())) { + return false; } - public final int hashCode() { - return Objects.hash(value); + if (this.value == null) { + return o.value == null; } - public static final java.lang.String NULL_VALUE_STRING = "(null)"; - - public static Scalar fromArrowType(ArrowType arrowType) { - switch (arrowType.getTypeID()) { - case Timestamp -> { - return new Timestamp(); - } - case Binary -> { - return new Binary(); - } - case LargeBinary -> { - return new Binary.LargeBinary(); - } - case Bool -> { - return new Bool(); - } - case Utf8, LargeUtf8 -> { - return new String(); - } - case Int -> { - return fromIntArrowType((ArrowType.Int) arrowType); - } - case FloatingPoint -> { - return fromFloatArrowType((ArrowType.FloatingPoint) arrowType); - } - case Date -> { - return fromDateArrowType((ArrowType.Date) arrowType); - } - case Duration -> { - return new Duration(); - } - } + return this.value.equals(o.value); + } - if (arrowType instanceof ArrowType.ExtensionType extensionType) { - //noinspection SwitchStatementWithTooFewBranches - switch (extensionType.extensionName()) { - case UUIDType.EXTENSION_NAME -> { - return new UUID(); - } - // TODO: Add support for these types when scalar available - // case JSONType.EXTENSION_NAME -> { - // return new JSON(); - // } - // case INETType.EXTENSION_NAME -> { - // return new INET(); - // } - } - } + public final int hashCode() { + return Objects.hash(value); + } - throw new UnsupportedOperationException("Unsupported type: " + arrowType); - } + public static final java.lang.String NULL_VALUE_STRING = "(null)"; - private static Scalar fromIntArrowType(ArrowType.Int intType) { - Number numberType; - switch (intType.getBitWidth()) { - case 8 -> numberType = intType.getIsSigned() ? new Number.Int8() : new Number.UInt8(); - case 16 -> numberType = intType.getIsSigned() ? new Number.Int16() : new Number.UInt16(); - case 32 -> numberType = intType.getIsSigned() ? new Number.Int32() : new Number.UInt32(); - case 64 -> numberType = intType.getIsSigned() ? new Number.Int64() : new Number.UInt64(); - default -> throw new UnsupportedOperationException("Unsupported type: " + intType); + public static Scalar fromArrowType(ArrowType arrowType) { + if (arrowType instanceof ArrowType.ExtensionType extensionType) { + switch (extensionType.extensionName()) { + case UUIDType.EXTENSION_NAME -> { + return new UUID(); + } + case JSONType.EXTENSION_NAME -> { + return new JSON(); } - return numberType; + // TODO: Add support for these types when scalar available + // case INETType.EXTENSION_NAME -> { + // return new INET(); + // } + } } - private static Scalar fromFloatArrowType(ArrowType.FloatingPoint floatType) { - Number numberType; - switch (floatType.getPrecision()) { - case SINGLE -> numberType = new Number.Float32(); - case DOUBLE -> numberType = new Number.Float64(); - default -> throw new UnsupportedOperationException("Unsupported type: " + floatType); - } - return numberType; + switch (arrowType.getTypeID()) { + case Timestamp -> { + return new Timestamp(); + } + case Binary -> { + return new Binary(); + } + case LargeBinary -> { + return new Binary.LargeBinary(); + } + case Bool -> { + return new Bool(); + } + case Utf8, LargeUtf8 -> { + return new String(); + } + case Int -> { + return fromIntArrowType((ArrowType.Int) arrowType); + } + case FloatingPoint -> { + return fromFloatArrowType((ArrowType.FloatingPoint) arrowType); + } + case Date -> { + return fromDateArrowType((ArrowType.Date) arrowType); + } + case Duration -> { + return new Duration(); + } + case List -> { + return new JSON(); + } } - private static Scalar fromDateArrowType(ArrowType.Date dateType) { - switch (dateType.getUnit()) { - case DAY -> { - return new DateDay(); - } - case MILLISECOND -> { - return new DateMilli(); - } - } - throw new UnsupportedOperationException("Unsupported type: " + dateType); + throw new UnsupportedOperationException("Unsupported type: " + arrowType); + } + + private static Scalar fromIntArrowType(ArrowType.Int intType) { + Number numberType; + switch (intType.getBitWidth()) { + case 8 -> numberType = intType.getIsSigned() ? new Number.Int8() : new Number.UInt8(); + case 16 -> numberType = intType.getIsSigned() ? new Number.Int16() : new Number.UInt16(); + case 32 -> numberType = intType.getIsSigned() ? new Number.Int32() : new Number.UInt32(); + case 64 -> numberType = intType.getIsSigned() ? new Number.Int64() : new Number.UInt64(); + default -> throw new UnsupportedOperationException("Unsupported type: " + intType); + } + return numberType; + } + + private static Scalar fromFloatArrowType(ArrowType.FloatingPoint floatType) { + Number numberType; + switch (floatType.getPrecision()) { + case SINGLE -> numberType = new Number.Float32(); + case DOUBLE -> numberType = new Number.Float64(); + default -> throw new UnsupportedOperationException("Unsupported type: " + floatType); + } + return numberType; + } + + private static Scalar fromDateArrowType(ArrowType.Date dateType) { + switch (dateType.getUnit()) { + case DAY -> { + return new DateDay(); + } + case MILLISECOND -> { + return new DateMilli(); + } } + throw new UnsupportedOperationException("Unsupported type: " + dateType); + } } diff --git a/lib/src/main/java/io/cloudquery/scalar/String.java b/lib/src/main/java/io/cloudquery/scalar/String.java index 17a47808..cb02aabf 100644 --- a/lib/src/main/java/io/cloudquery/scalar/String.java +++ b/lib/src/main/java/io/cloudquery/scalar/String.java @@ -1,24 +1,24 @@ package io.cloudquery.scalar; import org.apache.arrow.vector.types.pojo.ArrowType; +import org.apache.arrow.vector.util.Text; -public class String extends Scalar { +public class String extends Scalar { + public String() { + super(); + } - public String() { - super(); - } + public String(Object value) throws ValidationException { + super(value); + } - public String(Object value) throws ValidationException { - super(value); - } + @Override + public ArrowType dataType() { + return ArrowType.Utf8.INSTANCE; + } - @Override - public ArrowType dataType() { - return ArrowType.Utf8.INSTANCE; - } - - @Override - public void setValue(Object value) throws ValidationException { - this.value = value.toString(); - } + @Override + public void setValue(Object value) throws ValidationException { + this.value = new Text(value.toString()); + } } diff --git a/lib/src/main/java/io/cloudquery/scalar/Timestamp.java b/lib/src/main/java/io/cloudquery/scalar/Timestamp.java index d7daf573..cf57c0de 100644 --- a/lib/src/main/java/io/cloudquery/scalar/Timestamp.java +++ b/lib/src/main/java/io/cloudquery/scalar/Timestamp.java @@ -1,61 +1,80 @@ package io.cloudquery.scalar; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import org.apache.arrow.vector.types.TimeUnit; import org.apache.arrow.vector.types.pojo.ArrowType; -import java.time.*; +public class Timestamp extends Scalar { + public static final ZoneId zoneID = ZoneOffset.UTC; -public class Timestamp extends Scalar { - public static final ZoneId zoneID = ZoneOffset.UTC; + // TODO: add more units support later + public static final ArrowType dt = + new ArrowType.Timestamp(TimeUnit.MILLISECOND, zoneID.toString()); - // TODO: add more units support later - private static final ArrowType dt = new ArrowType.Timestamp(TimeUnit.MILLISECOND, zoneID.toString()); + public Timestamp() { + super(); + } - public Timestamp() { - super(); + public Timestamp(Object value) throws ValidationException { + super(value); + } + + @Override + public ArrowType dataType() { + return dt; + } + + @Override + public void setValue(Object value) throws ValidationException { + if (value instanceof ZonedDateTime timestamp) { + this.value = timestamp.withZoneSameInstant(zoneID).toEpochSecond() * 1000; + return; + } + + if (value instanceof LocalDate date) { + this.value = date.atStartOfDay(zoneID).toEpochSecond() * 1000; + return; + } + + if (value instanceof LocalDateTime date) { + this.value = date.atZone(zoneID).toEpochSecond() * 1000; + return; } - public Timestamp(Object value) throws ValidationException { - super(value); + if (value instanceof Integer integer) { + this.value = + ZonedDateTime.ofInstant(Instant.ofEpochMilli(integer), ZoneOffset.UTC).toEpochSecond() + * 1000; + return; } - @Override - public ArrowType dataType() { - return dt; + if (value instanceof Long longValue) { + this.value = + ZonedDateTime.ofInstant(Instant.ofEpochMilli(longValue), ZoneOffset.UTC).toEpochSecond() + * 1000; + return; } - @Override - public void setValue(Object value) throws ValidationException { - if (value instanceof ZonedDateTime timestamp) { - this.value = timestamp.withZoneSameInstant(zoneID); - return; - } - - if (value instanceof LocalDate date) { - this.value = date.atStartOfDay(zoneID); - return; - } - - if (value instanceof LocalDateTime date) { - this.value = date.atZone(zoneID); - return; - } - - if (value instanceof Integer integer) { - this.value = ZonedDateTime.ofInstant(Instant.ofEpochMilli(integer), ZoneOffset.UTC); - return; - } - - if (value instanceof Long longValue) { - this.value = ZonedDateTime.ofInstant(Instant.ofEpochMilli(longValue), ZoneOffset.UTC); - return; - } - - if (value instanceof CharSequence sequence) { - this.value = ZonedDateTime.parse(sequence); - return; - } - - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + if (value instanceof CharSequence sequence) { + this.value = ZonedDateTime.parse(sequence).toInstant().toEpochMilli(); + return; } + + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } + + @Override + public java.lang.String toString() { + if (this.value != null) { + return ZonedDateTime.ofInstant(Instant.ofEpochMilli((Long) this.value), zoneID).toString(); + } + + return NULL_VALUE_STRING; + } } diff --git a/lib/src/main/java/io/cloudquery/scalar/UUID.java b/lib/src/main/java/io/cloudquery/scalar/UUID.java index b156f693..9f42ba89 100644 --- a/lib/src/main/java/io/cloudquery/scalar/UUID.java +++ b/lib/src/main/java/io/cloudquery/scalar/UUID.java @@ -1,50 +1,51 @@ package io.cloudquery.scalar; +import java.nio.ByteBuffer; import org.apache.arrow.vector.types.pojo.ArrowType; import org.apache.arrow.vector.types.pojo.ArrowType.FixedSizeBinary; -import java.nio.ByteBuffer; - public class UUID extends Scalar { - private static final int BYTE_WIDTH = 16; - private static final FixedSizeBinary dt = new FixedSizeBinary(BYTE_WIDTH); - - public UUID() { - super(); + private static final int BYTE_WIDTH = 16; + private static final FixedSizeBinary dt = new FixedSizeBinary(BYTE_WIDTH); + + public UUID() { + super(); + } + + public UUID(Object value) throws ValidationException { + super(value); + } + + @Override + public ArrowType dataType() { + return dt; + } + + @Override + public void setValue(Object value) throws ValidationException { + if (value instanceof java.util.UUID uuid) { + this.value = uuid; + return; } - public UUID(Object value) throws ValidationException { - super(value); + if (value instanceof CharSequence sequence) { + this.value = java.util.UUID.fromString(sequence.toString()); + return; } - @Override - public ArrowType dataType() { - return dt; + if (value instanceof byte[] b) { + if (b.length != BYTE_WIDTH) { + throw new ValidationException( + "[]byte must be " + BYTE_WIDTH + " bytes to convert to UUID", this.dataType(), b); + } + ByteBuffer byteBuffer = ByteBuffer.wrap(b); + long mostSig = byteBuffer.getLong(); + long leastSig = byteBuffer.getLong(); + this.value = new java.util.UUID(mostSig, leastSig); + return; } - @Override - public void setValue(Object value) throws ValidationException { - if (value instanceof java.util.UUID uuid) { - this.value = uuid; - return; - } - - if (value instanceof CharSequence sequence) { - this.value = java.util.UUID.fromString(sequence.toString()); - return; - } - - if (value instanceof byte[] b) { - if (b.length != BYTE_WIDTH) { - throw new ValidationException("[]byte must be " + BYTE_WIDTH + " bytes to convert to UUID", this.dataType(), b); - } - ByteBuffer byteBuffer = ByteBuffer.wrap(b); - long mostSig = byteBuffer.getLong(); - long leastSig = byteBuffer.getLong(); - this.value = new java.util.UUID(mostSig, leastSig); - return; - } - - throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); - } + throw new ValidationException( + ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value); + } } diff --git a/lib/src/main/java/io/cloudquery/scalar/ValidationException.java b/lib/src/main/java/io/cloudquery/scalar/ValidationException.java index e775eb3d..5efc4519 100644 --- a/lib/src/main/java/io/cloudquery/scalar/ValidationException.java +++ b/lib/src/main/java/io/cloudquery/scalar/ValidationException.java @@ -3,40 +3,43 @@ import org.apache.arrow.vector.types.pojo.ArrowType; public class ValidationException extends Exception { - public Throwable cause; - public java.lang.String message; - public ArrowType type; - private final Object value; - - static final java.lang.String NO_CONVERSION_AVAILABLE = "no conversion available"; - - - ValidationException(Throwable cause, java.lang.String message, ArrowType type, Object value) { - super(message, cause); - this.cause = cause; - this.message = message; - this.type = type; - this.value = value; - } - - ValidationException(java.lang.String message, ArrowType type, Object value) { - super(message); - this.message = message; - this.type = type; - this.value = value; - } - - public java.lang.String Error() { - if (this.cause == null) { - return java.lang.String.format("cannot set `%s` with value `%s`: %s", this.type, this.value, this.message); - } - return java.lang.String.format("cannot set `%s` with value `%s`: %s (%s)", this.type, this.value, this.message, this.cause); + public Throwable cause; + public java.lang.String message; + public ArrowType type; + private final Object value; + + static final java.lang.String NO_CONVERSION_AVAILABLE = "no conversion available"; + + ValidationException(Throwable cause, java.lang.String message, ArrowType type, Object value) { + super(message, cause); + this.cause = cause; + this.message = message; + this.type = type; + this.value = value; + } + + ValidationException(java.lang.String message, ArrowType type, Object value) { + super(message); + this.message = message; + this.type = type; + this.value = value; + } + + public java.lang.String Error() { + if (this.cause == null) { + return java.lang.String.format( + "cannot set `%s` with value `%s`: %s", this.type, this.value, this.message); } - - public java.lang.String Masked() { - if (this.cause == null) { - return java.lang.String.format("cannot set `%s`: %s", this.type.toString(), this.message); - } - return java.lang.String.format("cannot set `%s`: %s (%s)", this.type.toString(), this.message, this.cause); + return java.lang.String.format( + "cannot set `%s` with value `%s`: %s (%s)", + this.type, this.value, this.message, this.cause); + } + + public java.lang.String Masked() { + if (this.cause == null) { + return java.lang.String.format("cannot set `%s`: %s", this.type.toString(), this.message); } + return java.lang.String.format( + "cannot set `%s`: %s (%s)", this.type.toString(), this.message, this.cause); + } } diff --git a/lib/src/main/java/io/cloudquery/scheduler/Scheduler.java b/lib/src/main/java/io/cloudquery/scheduler/Scheduler.java index 8a990932..11c05741 100644 --- a/lib/src/main/java/io/cloudquery/scheduler/Scheduler.java +++ b/lib/src/main/java/io/cloudquery/scheduler/Scheduler.java @@ -1,6 +1,103 @@ package io.cloudquery.scheduler; +import com.google.protobuf.ByteString; +import io.cloudquery.helper.ArrowHelper; +import io.cloudquery.plugin.v3.Sync; +import io.cloudquery.schema.ClientMeta; +import io.cloudquery.schema.Resource; +import io.cloudquery.schema.Table; +import io.grpc.stub.StreamObserver; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import lombok.Builder; +import lombok.NonNull; +import org.apache.logging.log4j.Logger; + +@Builder public class Scheduler { - public Scheduler() { + @NonNull private final List
tables; + @NonNull private final StreamObserver syncStream; + @NonNull private final Logger logger; + @NonNull private final ClientMeta client; + + private int concurrency; + private boolean deterministicCqId; + + private void resolveTables(List
tables, Resource parent, int concurrency) + throws InterruptedException { + if (tables == null || tables.isEmpty()) { + return; } + ExecutorService executor = Executors.newFixedThreadPool(Math.min(tables.size(), concurrency)); + for (Table table : tables) { + final int nextLevelConcurrency = Math.max(1, concurrency / 2); + executor.submit( + new Runnable() { + @Override + public void run() { + try { + String tableMessage = + parent != null + ? "table " + table.getName() + " of parent" + parent.getTable().getName() + : "table " + table.getName(); + + logger.info("resolving {}", tableMessage); + if (!table.getResolver().isPresent()) { + logger.error("no resolver for {}", tableMessage); + return; + } + + SchedulerTableOutputStream schedulerTableOutputStream = + new SchedulerTableOutputStream(table, parent, client, logger); + table.getResolver().get().resolve(client, parent, schedulerTableOutputStream); + + for (Resource resource : schedulerTableOutputStream.getResources()) { + resource.resolveCQId(deterministicCqId); + ByteString record = resource.encode(); + Sync.MessageInsert insert = + Sync.MessageInsert.newBuilder().setRecord(record).build(); + Sync.Response response = Sync.Response.newBuilder().setInsert(insert).build(); + syncStream.onNext(response); + resolveTables(table.getRelations(), resource, nextLevelConcurrency); + } + + logger.info("resolved {}", tableMessage); + } catch (Exception e) { + logger.error("Failed to resolve table: {}", table.getName(), e); + syncStream.onError(e); + return; + } + } + }); + } + executor.shutdown(); + executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); + } + + public void sync() { + for (Table table : Table.flattenTables(tables)) { + try { + logger.info("sending migrate message for table: {}", table.getName()); + Sync.MessageMigrateTable migrateTable = + Sync.MessageMigrateTable.newBuilder().setTable(ArrowHelper.encode(table)).build(); + Sync.Response response = Sync.Response.newBuilder().setMigrateTable(migrateTable).build(); + syncStream.onNext(response); + } catch (Exception e) { + syncStream.onError(e); + return; + } + } + + try { + resolveTables(this.tables, null, this.concurrency); + } catch (InterruptedException e) { + logger.error("Failed to resolve tables", e); + syncStream.onError(e); + return; + } + + syncStream.onCompleted(); + } } diff --git a/lib/src/main/java/io/cloudquery/scheduler/SchedulerTableOutputStream.java b/lib/src/main/java/io/cloudquery/scheduler/SchedulerTableOutputStream.java new file mode 100644 index 00000000..0ac4f728 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/scheduler/SchedulerTableOutputStream.java @@ -0,0 +1,71 @@ +package io.cloudquery.scheduler; + +import io.cloudquery.plugin.TableOutputStream; +import io.cloudquery.schema.ClientMeta; +import io.cloudquery.schema.Column; +import io.cloudquery.schema.Resource; +import io.cloudquery.schema.Table; +import io.cloudquery.transformers.TransformerException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import lombok.NonNull; +import org.apache.logging.log4j.Logger; + +public class SchedulerTableOutputStream implements TableOutputStream { + private static final int RESOURCE_RESOLVE_CONCURRENCY = 100; + private static final int RESOURCE_RESOLVE_TIMEOUT_MINUTES = 10; + @NonNull private final Table table; + private final Resource parent; + @NonNull private final ClientMeta client; + @NonNull private final Logger logger; + + private List resources = new ArrayList(); + + private ExecutorService executor; + + public SchedulerTableOutputStream( + @NonNull Table table, Resource parent, @NonNull ClientMeta client, @NonNull Logger logger) { + this.table = table; + this.parent = parent; + this.client = client; + this.logger = logger; + this.executor = Executors.newFixedThreadPool(RESOURCE_RESOLVE_CONCURRENCY); + } + + @Override + public void write(Object data) { + Resource resource = Resource.builder().table(table).parent(parent).item(data).build(); + for (Column column : table.getColumns()) { + executor.submit( + new Runnable() { + @Override + public void run() { + try { + logger.debug("resolving column: {}", column.getName()); + if (column.getResolver() == null) { + logger.error("no resolver for column: {}", column.getName()); + return; + } + column.getResolver().resolve(client, resource, column); + logger.debug("resolved column: {}", column.getName()); + return; + } catch (TransformerException e) { + logger.error("Failed to resolve column: {}", column.getName(), e); + return; + } + } + }); + } + resources.add(resource); + } + + public List getResources() throws InterruptedException { + // TODO: Optimize this to not wait for all resources to complete + executor.shutdown(); + executor.awaitTermination(RESOURCE_RESOLVE_TIMEOUT_MINUTES, TimeUnit.MINUTES); + return this.resources; + } +} diff --git a/lib/src/main/java/io/cloudquery/schema/ClientMeta.java b/lib/src/main/java/io/cloudquery/schema/ClientMeta.java index aa9dffdc..b0e382a2 100644 --- a/lib/src/main/java/io/cloudquery/schema/ClientMeta.java +++ b/lib/src/main/java/io/cloudquery/schema/ClientMeta.java @@ -1,7 +1,9 @@ package io.cloudquery.schema; -import lombok.Builder; +import io.cloudquery.messages.WriteMessage; -@Builder -public class ClientMeta { +public interface ClientMeta { + String getId(); + + void write(WriteMessage message); } diff --git a/lib/src/main/java/io/cloudquery/schema/Column.java b/lib/src/main/java/io/cloudquery/schema/Column.java index 502c46cf..838f41da 100644 --- a/lib/src/main/java/io/cloudquery/schema/Column.java +++ b/lib/src/main/java/io/cloudquery/schema/Column.java @@ -8,49 +8,53 @@ @Builder(toBuilder = true) @Getter public class Column { - private String name; - private String description; - private ArrowType type; - private ColumnResolver resolver; - private boolean primaryKey; - private boolean notNull; - private boolean unique; - private boolean incrementalKey; - private boolean ignoreInTests; + public static final String CQ_SOURCE_NAME = "_cq_source_name"; + public static final String CQ_SYNC_TIME = "_cq_sync_time"; + private String name; + private String description; + private ArrowType type; + private ColumnResolver resolver; + private boolean primaryKey; + private boolean notNull; + private boolean unique; + private boolean incrementalKey; + private boolean ignoreInTests; - public static final Column CQ_ID_COLUMN = Column.builder(). - name("_cq_id"). - type(new UUIDType()). - description("Internal CQ ID of the row"). - notNull(true). - unique(true). - build(); - public static final Column CQ_PARENT_ID_COLUMN = Column.builder(). - name("_cq_parent_id"). - type(new UUIDType()). - description("Internal CQ ID of the parent row"). - resolver(new ParentCQUUIDResolver()). - ignoreInTests(true). - build(); + public static final Column CQ_ID_COLUMN = + Column.builder() + .name("_cq_id") + .type(new UUIDType()) + .description("Internal CQ ID of the row") + .notNull(true) + .unique(true) + .build(); + public static final Column CQ_PARENT_ID_COLUMN = + Column.builder() + .name("_cq_parent_id") + .type(new UUIDType()) + .description("Internal CQ ID of the parent row") + .resolver(new ParentCQUUIDResolver()) + .ignoreInTests(true) + .build(); - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(name); - sb.append(":"); - sb.append(type.toString()); - if (primaryKey) { - sb.append(":PK"); - } - if (notNull) { - sb.append(":NotNull"); - } - if (unique) { - sb.append(":Unique"); - } - if (incrementalKey) { - sb.append(":IncrementalKey"); - } - return sb.toString(); + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(name); + sb.append(":"); + sb.append(type.toString()); + if (primaryKey) { + sb.append(":PK"); } + if (notNull) { + sb.append(":NotNull"); + } + if (unique) { + sb.append(":Unique"); + } + if (incrementalKey) { + sb.append(":IncrementalKey"); + } + return sb.toString(); + } } diff --git a/lib/src/main/java/io/cloudquery/schema/ColumnResolver.java b/lib/src/main/java/io/cloudquery/schema/ColumnResolver.java index 4e19307a..ca7f3ddd 100644 --- a/lib/src/main/java/io/cloudquery/schema/ColumnResolver.java +++ b/lib/src/main/java/io/cloudquery/schema/ColumnResolver.java @@ -3,5 +3,5 @@ import io.cloudquery.transformers.TransformerException; public interface ColumnResolver { - void resolve(ClientMeta meta, Resource resource, Column column) throws TransformerException; + void resolve(ClientMeta meta, Resource resource, Column column) throws TransformerException; } diff --git a/lib/src/main/java/io/cloudquery/schema/NullClient.java b/lib/src/main/java/io/cloudquery/schema/NullClient.java new file mode 100644 index 00000000..4a815611 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/schema/NullClient.java @@ -0,0 +1,15 @@ +package io.cloudquery.schema; + +import io.cloudquery.messages.WriteMessage; + +public class NullClient implements ClientMeta { + @Override + public String getId() { + return "null-client"; + } + + @Override + public void write(WriteMessage message) { + // No-op for null client + } +} diff --git a/lib/src/main/java/io/cloudquery/schema/ParentCQUUIDResolver.java b/lib/src/main/java/io/cloudquery/schema/ParentCQUUIDResolver.java index 579d2d23..15e2e952 100644 --- a/lib/src/main/java/io/cloudquery/schema/ParentCQUUIDResolver.java +++ b/lib/src/main/java/io/cloudquery/schema/ParentCQUUIDResolver.java @@ -1,40 +1,42 @@ package io.cloudquery.schema; +import static io.cloudquery.schema.Column.CQ_ID_COLUMN; + import io.cloudquery.scalar.Scalar; import io.cloudquery.scalar.UUID; import io.cloudquery.scalar.ValidationException; import io.cloudquery.transformers.TransformerException; -import static io.cloudquery.schema.Column.CQ_ID_COLUMN; - public class ParentCQUUIDResolver implements ColumnResolver { - @Override - public void resolve(ClientMeta meta, Resource resource, Column column) throws TransformerException { - Resource parent = resource.getParent(); - if (parent == null) { - setOrThrow(resource, column, null); - return; - } - - Scalar parentCqID = parent.get(CQ_ID_COLUMN.getName()); - if (parentCqID == null) { - setOrThrow(resource, column, null); - return; - } + @Override + public void resolve(ClientMeta meta, Resource resource, Column column) + throws TransformerException { + Resource parent = resource.getParent(); + if (parent == null) { + setOrThrow(resource, column, null); + return; + } - if (!(parentCqID instanceof UUID)) { - setOrThrow(resource, column, null); - return; - } + Scalar parentCqID = parent.get(CQ_ID_COLUMN.getName()); + if (parentCqID == null) { + setOrThrow(resource, column, null); + return; + } - setOrThrow(resource, column, parentCqID); + if (!(parentCqID instanceof UUID)) { + setOrThrow(resource, column, null); + return; } - private static void setOrThrow(Resource resource, Column column, Scalar parentCqID) throws TransformerException { - try { - resource.set(column.getName(), parentCqID); - } catch (ValidationException ex) { - throw new TransformerException("Failed to set parent CQ ID", ex); - } + setOrThrow(resource, column, parentCqID); + } + + private static void setOrThrow(Resource resource, Column column, Scalar parentCqID) + throws TransformerException { + try { + resource.set(column.getName(), parentCqID); + } catch (ValidationException ex) { + throw new TransformerException("Failed to set parent CQ ID", ex); } + } } diff --git a/lib/src/main/java/io/cloudquery/schema/Resource.java b/lib/src/main/java/io/cloudquery/schema/Resource.java index 3959ac0c..66e532db 100644 --- a/lib/src/main/java/io/cloudquery/schema/Resource.java +++ b/lib/src/main/java/io/cloudquery/schema/Resource.java @@ -1,40 +1,94 @@ package io.cloudquery.schema; +import com.google.common.base.Objects; +import com.google.protobuf.ByteString; +import io.cloudquery.helper.ArrowHelper; import io.cloudquery.scalar.Scalar; import io.cloudquery.scalar.ValidationException; -import lombok.Builder; -import lombok.Getter; - +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.UUID; +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; @Getter public class Resource { - private Object item; - private Resource parent; - private Table table; - - private final List> data; - - @Builder(toBuilder = true) - public Resource(Table table, Resource parent, Object item) { - this.item = item; - this.parent = parent; - this.table = table != null ? table : Table.builder().build(); - this.data = new ArrayList<>(); - - for (Column column : this.table.getColumns()) { - this.data.add(Scalar.fromArrowType(column.getType())); - } + private Object item; + private Resource parent; + private Table table; + + private final List> data; + + @Builder(toBuilder = true) + public Resource(@NonNull Table table, Resource parent, Object item) { + this.item = item; + this.parent = parent; + this.table = table; + this.data = new ArrayList<>(); + + for (Column column : this.table.getColumns()) { + this.data.add(Scalar.fromArrowType(column.getType())); } + } - public void set(String columnName, Object value) throws ValidationException { - int index = table.indexOfColumn(columnName); - this.data.get(index).set(value); + public void set(String columnName, Object value) throws ValidationException { + int index = table.indexOfColumn(columnName); + this.data.get(index).set(value); + } + + public Scalar get(String columnName) { + int index = table.indexOfColumn(columnName); + return this.data.get(index); + } + + public ByteString encode() throws IOException { + return ArrowHelper.encode(this); + } + + public void setCqId(UUID value) throws ValidationException { + int index = table.indexOfColumn(Column.CQ_ID_COLUMN.getName()); + if (index == -1) { + return; + } + this.data.get(index).set(value); + } + + public void resolveCQId(boolean deterministicCqId) + throws ValidationException, NoSuchAlgorithmException { + UUID randomUUID = UUID.randomUUID(); + if (!deterministicCqId) { + this.setCqId(randomUUID); + return; + } + + // Use an array list to support sorting + ArrayList pks = new ArrayList<>(this.table.primaryKeys()); + boolean cqOnlyPK = + pks.stream().allMatch((pk) -> Objects.equal(pk, Column.CQ_ID_COLUMN.getName())); + if (cqOnlyPK) { + this.setCqId(randomUUID); + return; } - public Scalar get(String columnName) { - int index = table.indexOfColumn(columnName); - return this.data.get(index); + Collections.sort(pks); + // Generate uuid v5 (same as sha-1) + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + for (String pk : pks) { + digest.update(pk.getBytes(StandardCharsets.UTF_8)); + digest.update(this.get(pk).toString().getBytes(StandardCharsets.UTF_8)); } + + ByteBuffer byteBuffer = ByteBuffer.wrap(digest.digest()); + long mostSig = byteBuffer.getLong(); + long leastSig = byteBuffer.getLong(); + this.setCqId(new UUID(mostSig, leastSig)); + return; + } } diff --git a/lib/src/main/java/io/cloudquery/schema/SchemaException.java b/lib/src/main/java/io/cloudquery/schema/SchemaException.java index c56fb1a0..235194fd 100644 --- a/lib/src/main/java/io/cloudquery/schema/SchemaException.java +++ b/lib/src/main/java/io/cloudquery/schema/SchemaException.java @@ -1,22 +1,22 @@ package io.cloudquery.schema; public class SchemaException extends Exception { - public SchemaException() { - } + public SchemaException() {} - public SchemaException(String message) { - super(message); - } + public SchemaException(String message) { + super(message); + } - public SchemaException(String message, Throwable cause) { - super(message, cause); - } + public SchemaException(String message, Throwable cause) { + super(message, cause); + } - public SchemaException(Throwable cause) { - super(cause); - } + public SchemaException(Throwable cause) { + super(cause); + } - public SchemaException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } + public SchemaException( + String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } } diff --git a/lib/src/main/java/io/cloudquery/schema/Table.java b/lib/src/main/java/io/cloudquery/schema/Table.java index a5906168..858b16d6 100644 --- a/lib/src/main/java/io/cloudquery/schema/Table.java +++ b/lib/src/main/java/io/cloudquery/schema/Table.java @@ -1,190 +1,259 @@ package io.cloudquery.schema; +import static io.cloudquery.schema.TableColumnChangeType.ADD; +import static io.cloudquery.schema.TableColumnChangeType.REMOVE; +import static io.cloudquery.schema.TableColumnChangeType.UPDATE; +import static java.util.stream.Collectors.toList; + import io.cloudquery.glob.Glob; import io.cloudquery.schema.Column.ColumnBuilder; import io.cloudquery.transformers.TransformerException; -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; - import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.Predicate; +import java.util.stream.IntStream; +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; @Builder(toBuilder = true) @Getter public class Table { - public interface Transform { - void transformTable(Table table) throws TransformerException; + + public interface Transform { + void transformTable(Table table) throws TransformerException; + } + + public static List
flattenTables(List
tables) { + Map flattenMap = new LinkedHashMap<>(); + for (Table table : tables) { + Table newTable = table.toBuilder().build(); + flattenMap.put(newTable.name, newTable); + for (Table child : flattenTables(table.getRelations())) { + flattenMap.put(child.name, child); + } } + return flattenMap.values().stream().toList(); + } - public static List
flattenTables(List
tables) { - Map flattenMap = new HashMap<>(); - for (Table table : tables) { - Table newTable = table.toBuilder().relations(Collections.emptyList()).build(); - flattenMap.put(newTable.name, newTable); - for (Table child : flattenTables(table.getRelations())) { - flattenMap.put(child.name, child); - } + public static List
filterDFS( + List
tables, + List includeConfiguration, + List skipConfiguration, + boolean skipDependentTables) + throws SchemaException { + List
flattenedTables = flattenTables(tables); + for (String includePattern : includeConfiguration) { + boolean includeMatch = false; + for (Table table : flattenedTables) { + if (Glob.match(includePattern, table.getName())) { + includeMatch = true; + break; } - return flattenMap.values().stream().toList(); - } - - public static List
filterDFS(List
tables, List includeConfiguration, List skipConfiguration, boolean skipDependentTables) throws SchemaException { - List
flattenedTables = flattenTables(tables); - for (String includePattern : includeConfiguration) { - boolean includeMatch = false; - for (Table table : flattenedTables) { - if (Glob.match(includePattern, table.getName())) { - includeMatch = true; - break; - } - } - if (!includeMatch) { - throw new SchemaException("table configuration includes a pattern \"" + includePattern + "\" with no matches"); - } - } - for (String excludePattern : skipConfiguration) { - boolean excludeMatch = false; - for (Table table : flattenedTables) { - if (Glob.match(excludePattern, table.getName())) { - excludeMatch = true; - break; - } - } - if (!excludeMatch) { - throw new SchemaException("skip configuration includes a pattern \"" + excludePattern + "\" with no matches"); - } + } + if (!includeMatch) { + throw new SchemaException( + "table configuration includes a pattern \"" + includePattern + "\" with no matches"); + } + } + for (String excludePattern : skipConfiguration) { + boolean excludeMatch = false; + for (Table table : flattenedTables) { + if (Glob.match(excludePattern, table.getName())) { + excludeMatch = true; + break; } + } + if (!excludeMatch) { + throw new SchemaException( + "skip configuration includes a pattern \"" + excludePattern + "\" with no matches"); + } + } - Predicate
include = table -> { - for (String includePattern : includeConfiguration) { - if (Glob.match(includePattern, table.getName())) { - return true; - } + Predicate
include = + table -> { + for (String includePattern : includeConfiguration) { + if (Glob.match(includePattern, table.getName())) { + return true; } - return false; + } + return false; }; - Predicate
exclude = table -> { - for (String excludePattern : skipConfiguration) { - if (Glob.match(excludePattern, table.getName())) { - return true; - } + Predicate
exclude = + table -> { + for (String excludePattern : skipConfiguration) { + if (Glob.match(excludePattern, table.getName())) { + return true; } - return false; + } + return false; }; - return filterDFSFunc(tables, include, exclude, skipDependentTables); - } + return filterDFSFunc(tables, include, exclude, skipDependentTables); + } - private static List
filterDFSFunc(List
tables, Predicate
include, Predicate
exclude, boolean skipDependentTables) { - List
filteredTables = new ArrayList<>(); - for (Table table : tables) { - Table filteredTable = table.toBuilder().parent(null).build(); - Optional
optionalFilteredTable = filteredTable.filterDfs(false, include, exclude, skipDependentTables); - optionalFilteredTable.ifPresent(filteredTables::add); - } - return filteredTables; + private static List
filterDFSFunc( + List
tables, + Predicate
include, + Predicate
exclude, + boolean skipDependentTables) { + List
filteredTables = new ArrayList<>(); + for (Table table : tables) { + Table filteredTable = table.toBuilder().parent(null).build(); + Optional
optionalFilteredTable = + filteredTable.filterDfs(false, include, exclude, skipDependentTables); + optionalFilteredTable.ifPresent(filteredTables::add); } + return filteredTables; + } - public static int maxDepth(List
tables) { - int depth = 0; - if (tables.isEmpty()) { - return 0; - } - for (Table table : tables) { - int newDepth = 1 + maxDepth(table.getRelations()); - if (newDepth > depth) { - depth = newDepth; - } - } - return depth; + public static int maxDepth(List
tables) { + int depth = 0; + if (tables.isEmpty()) { + return 0; + } + for (Table table : tables) { + int newDepth = 1 + maxDepth(table.getRelations()); + if (newDepth > depth) { + depth = newDepth; + } } + return depth; + } - private String name; - @Setter - private Table parent; - @Builder.Default - private List columns = new ArrayList<>(); + @NonNull private String name; + @Builder.Default private String constraintName = ""; + private TableResolver resolver; + private String title; + private String description; + @Setter private Table parent; + @Builder.Default private List columns = new ArrayList<>(); - @Builder.Default - private List
relations = new ArrayList<>(); + @Builder.Default private List
relations = new ArrayList<>(); - private Transform transform; + private Transform transform; - public void transform() throws TransformerException { - if (transform != null) { - transform.transformTable(this); - } + public void transform() throws TransformerException { + if (transform != null) { + transform.transformTable(this); } + } - public void addCQIDs() { - boolean havePrimaryKeys = !primaryKeys().isEmpty(); - ColumnBuilder cqIdColumnBuilder = Column.CQ_ID_COLUMN.toBuilder(); - if (!havePrimaryKeys) { - cqIdColumnBuilder.primaryKey(true); - } + public void addCQIDs() { + boolean havePrimaryKeys = !primaryKeys().isEmpty(); + ColumnBuilder cqIdColumnBuilder = Column.CQ_ID_COLUMN.toBuilder(); + if (!havePrimaryKeys) { + cqIdColumnBuilder.primaryKey(true); + } - List newColumns = List.of(cqIdColumnBuilder.build(), Column.CQ_PARENT_ID_COLUMN); - for (int i = 0; i < newColumns.size(); i++) { - columns.add(i, newColumns.get(i)); - } + List newColumns = List.of(cqIdColumnBuilder.build(), Column.CQ_PARENT_ID_COLUMN); + for (int i = 0; i < newColumns.size(); i++) { + columns.add(i, newColumns.get(i)); + } - for (Table relation : relations) { - relation.addCQIDs(); - } + for (Table relation : relations) { + relation.addCQIDs(); } + } - public int indexOfColumn(String columnName) { - for (int index = 0; index < columns.size(); index++) { - if (columns.get(index).getName().equals(columnName)) { - return index; - } - } - return -1; + public int indexOfColumn(String columnName) { + for (int index = 0; index < columns.size(); index++) { + if (columns.get(index).getName().equals(columnName)) { + return index; + } } + return -1; + } - public List primaryKeys() { - return columns.stream(). - filter(Column::isPrimaryKey). - map(Column::getName). - toList(); + public List primaryKeys() { + return columns.stream().filter(Column::isPrimaryKey).map(Column::getName).toList(); + } + + public List primaryKeyIndexes() { + return IntStream.range(0, columns.size()) + .filter(i -> columns.get(i).isPrimaryKey()) + .boxed() + .collect(toList()); + } + + private Optional
filterDfs( + boolean parentMatched, + Predicate
include, + Predicate
exclude, + boolean skipDependentTables) { + if (exclude.test(this)) { + return Optional.empty(); + } + boolean matched = parentMatched && !skipDependentTables; + if (include.test(this)) { + matched = true; } + List
filteredRelations = new ArrayList<>(); + for (Table relation : relations) { + Optional
filteredChild = + relation.filterDfs(matched, include, exclude, skipDependentTables); + if (filteredChild.isPresent()) { + matched = true; + filteredRelations.add(filteredChild.get()); + } + } + this.relations = filteredRelations; + if (matched) { + return Optional.of(this); + } + return Optional.empty(); + } - private Optional
filterDfs(boolean parentMatched, Predicate
include, Predicate
exclude, boolean skipDependentTables) { - if (exclude.test(this)) { - return Optional.empty(); - } - boolean matched = parentMatched && !skipDependentTables; - if (include.test(this)) { - matched = true; - } - List
filteredRelations = new ArrayList<>(); - for (Table relation : relations) { - Optional
filteredChild = relation.filterDfs(matched, include, exclude, skipDependentTables); - if (filteredChild.isPresent()) { - matched = true; - filteredRelations.add(filteredChild.get()); - } - } - this.relations = filteredRelations; - if (matched) { - return Optional.of(this); - } - return Optional.empty(); + public Optional getColumn(String name) { + for (Column column : columns) { + if (column.getName().equals(name)) { + return Optional.of(column); + } } + return Optional.empty(); + } - public Optional getColumn(String name) { - for (Column column : columns) { - if (column.getName().equals(name)) { - return Optional.of(column); - } - } - return Optional.empty(); + public Optional getResolver() { + return Optional.ofNullable(resolver); + } + + public List getChanges(Table old) { + List changes = new ArrayList<>(); + for (Column currentColumn : columns) { + Optional oldColumn = old.getColumn(currentColumn.getName()); + if (oldColumn.isEmpty()) { + changes.add(new TableColumnChange(ADD, currentColumn.getName(), currentColumn, null)); + continue; + } + if (shouldUpdate(currentColumn, oldColumn.get())) { + changes.add( + new TableColumnChange(UPDATE, currentColumn.getName(), currentColumn, oldColumn.get())); + } + } + for (Column column : old.columns) { + Optional otherColumn = getColumn(column.getName()); + if (otherColumn.isEmpty()) { + changes.add(new TableColumnChange(REMOVE, column.getName(), null, column)); + } + } + return changes; + } + + private static boolean shouldUpdate(Column currentColumn, Column oldColumn) { + if (!oldColumn.getType().equals(currentColumn.getType())) { + return true; + } + if (oldColumn.isPrimaryKey() != currentColumn.isPrimaryKey()) { + return true; + } + if (oldColumn.isNotNull() != currentColumn.isNotNull()) { + return true; } + return oldColumn.isUnique() != currentColumn.isUnique(); + } } diff --git a/lib/src/main/java/io/cloudquery/schema/TableColumnChange.java b/lib/src/main/java/io/cloudquery/schema/TableColumnChange.java new file mode 100644 index 00000000..8af4f136 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/schema/TableColumnChange.java @@ -0,0 +1,13 @@ +package io.cloudquery.schema; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class TableColumnChange { + private TableColumnChangeType type; + private String columnName; + private Column current; + private Column previous; +} diff --git a/lib/src/main/java/io/cloudquery/schema/TableColumnChangeType.java b/lib/src/main/java/io/cloudquery/schema/TableColumnChangeType.java new file mode 100644 index 00000000..9948294c --- /dev/null +++ b/lib/src/main/java/io/cloudquery/schema/TableColumnChangeType.java @@ -0,0 +1,7 @@ +package io.cloudquery.schema; + +public enum TableColumnChangeType { + REMOVE, + UPDATE, + ADD +} diff --git a/lib/src/main/java/io/cloudquery/schema/TableResolver.java b/lib/src/main/java/io/cloudquery/schema/TableResolver.java new file mode 100644 index 00000000..417bac99 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/schema/TableResolver.java @@ -0,0 +1,7 @@ +package io.cloudquery.schema; + +import io.cloudquery.plugin.TableOutputStream; + +public interface TableResolver { + void resolve(ClientMeta clientMeta, Resource parent, TableOutputStream stream); +} diff --git a/lib/src/main/java/io/cloudquery/server/AddressConverter.java b/lib/src/main/java/io/cloudquery/server/AddressConverter.java index ac424f56..e0a0cb6b 100644 --- a/lib/src/main/java/io/cloudquery/server/AddressConverter.java +++ b/lib/src/main/java/io/cloudquery/server/AddressConverter.java @@ -3,20 +3,16 @@ import picocli.CommandLine.ITypeConverter; public class AddressConverter implements ITypeConverter { - public static class AddressParseException extends RuntimeException { + public static class AddressParseException extends RuntimeException {} - } - public record Address(String host, int port) { - } + public record Address(String host, int port) {} - @Override - public Address convert(String rawAddress) throws Exception { - String[] components = rawAddress.split(":"); - if (components.length != 2) { - throw new AddressParseException(); - } - return new Address(components[0], Integer.parseInt(components[1])); + @Override + public Address convert(String rawAddress) throws Exception { + String[] components = rawAddress.split(":"); + if (components.length != 2) { + throw new AddressParseException(); } - - + return new Address(components[0], Integer.parseInt(components[1])); + } } diff --git a/lib/src/main/java/io/cloudquery/server/PackageCommand.java b/lib/src/main/java/io/cloudquery/server/PackageCommand.java new file mode 100644 index 00000000..f8a2f6cb --- /dev/null +++ b/lib/src/main/java/io/cloudquery/server/PackageCommand.java @@ -0,0 +1,300 @@ +package io.cloudquery.server; + +import com.google.common.base.Strings; +import io.cloudquery.plugin.BuildTarget; +import io.cloudquery.plugin.NewClientOptions; +import io.cloudquery.plugin.Plugin; +import io.cloudquery.plugin.PluginKind; +import io.cloudquery.schema.Table; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Callable; +import lombok.ToString; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.io.FileUtils; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.ConsoleAppender; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.ConfigurationFactory; +import org.apache.logging.log4j.core.config.LoggerConfig; +import org.apache.logging.log4j.core.layout.JsonLayout; +import org.apache.logging.log4j.core.layout.PatternLayout; +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; + +@Command(name = "package", description = "package the plugin as a Docker image") +@ToString +public class PackageCommand implements Callable { + private static Logger logger; + + @Parameters(index = "0", description = "plugin version to package") + private String pluginVersion; + + @Parameters(index = "1", description = "plugin directory to package") + private String pluginDirectory; + + @Option( + required = true, + names = {"-m", "--message"}, + description = + "message that summarizes what is new or changed in this version. Supports markdown.") + private String message = ""; + + @Option( + names = "--log-format", + description = "log format. one of: text,json (default \"${DEFAULT-VALUE}\")") + private String logFormat = "text"; + + @Option( + names = "--log-level", + description = "log level. one of: trace,debug,info,warn,error (default \"${DEFAULT-VALUE}\")") + private String logLevel = "info"; + + @Option(names = "--no-sentry", description = "disable sentry") + private Boolean disableSentry = false; + + @Option(names = "--otel-endpoint", description = "Open Telemetry HTTP collector endpoint") + private String otelEndpoint = ""; + + @Option( + names = "--otel-endpoint-insecure", + description = "use Open Telemetry HTTP endpoint (for development only)") + private Boolean otelEndpointInsecure = false; + + @Option( + names = "--dist-dir", + description = "dist directory to output the built plugin. (default: /dist)") + private String distDir = ""; + + @Option( + names = "--docs-dir", + description = + "docs directory containing markdown files to copy to the dist directory. (default: /docs)") + private String docsDir = ""; + + private final Plugin plugin; + + public PackageCommand(Plugin plugin) { + this.plugin = plugin; + } + + private LoggerContext initLogger() { + ConsoleAppender appender = + ConsoleAppender.createDefaultAppenderForLayout( + this.logFormat == "text" + ? PatternLayout.createDefaultLayout() + : JsonLayout.createDefaultLayout()); + + Configuration configuration = ConfigurationFactory.newConfigurationBuilder().build(); + configuration.addAppender(appender); + LoggerConfig loggerConfig = new LoggerConfig("io.cloudquery", Level.getLevel(logLevel), false); + loggerConfig.addAppender(appender, null, null); + configuration.addLogger("io.cloudquery", loggerConfig); + LoggerContext context = new LoggerContext(ServeCommand.class.getName() + "Context"); + context.start(configuration); + + logger = context.getLogger(ServeCommand.class.getName()); + this.plugin.setLogger(logger); + return context; + } + + @SuppressWarnings("null") + @Override + public Integer call() { + try (LoggerContext context = this.initLogger()) { + if (Strings.isNullOrEmpty(plugin.getName())) { + logger.error("name is required"); + return 1; + } + if (Strings.isNullOrEmpty(plugin.getVersion())) { + logger.error("version is required"); + return 1; + } + if (Strings.isNullOrEmpty(plugin.getTeam())) { + logger.error("team is required"); + return 1; + } + if (Strings.isNullOrEmpty(plugin.getDockerfile())) { + logger.error("Dockerfile is required"); + return 1; + } + if (plugin.getBuildTargets() == null || plugin.getBuildTargets().length == 0) { + logger.error("At least one build target is required"); + return 1; + } + if (Strings.isNullOrEmpty(distDir)) { + distDir = Paths.get(pluginDirectory, "dist").toString(); + } + if (Strings.isNullOrEmpty(docsDir)) { + docsDir = Paths.get(pluginDirectory, "docs").toString(); + } + + initDist(); + copyDocs(); + writeTablesJson(); + List supportedTargets = buildDocker(); + writePackageJson(supportedTargets); + + return 0; + } catch (Exception e) { + logger.error("Failed to package plugin", e); + return 1; + } + } + + private void initDist() throws IOException { + logger.info("Packaging plugin to {}", distDir); + File dist = new File(distDir); + if (!dist.exists()) { + boolean created = dist.mkdirs(); + if (!created) { + logger.error("Failed to create dist directory {}", distDir); + throw new IOException("Failed to create dist directory"); + } + } + } + + private void copyDocs() throws IllegalArgumentException, IOException { + File docs = new File(docsDir); + if (!docs.exists()) { + logger.error("Docs directory path{} does not exist", docsDir); + throw new IllegalArgumentException("Docs directory does not exist"); + } + if (!docs.isDirectory()) { + logger.error("Docs path {} is not a directory", docsDir); + throw new IllegalArgumentException("Docs path is not a directory"); + } + + String outputPath = Paths.get(distDir, "docs").toString(); + logger.info("Copying docs from {} to {}", docsDir, outputPath); + File output = new File(outputPath); + FileUtils.copyDirectory(docs, output); + } + + private void writeTablesJson() throws Exception { + if (plugin.getKind() != PluginKind.Source) { + return; + } + + String outputPath = Paths.get(distDir, "tables.json").toString(); + logger.info("Writing tables.json to {}", outputPath); + plugin.init("", NewClientOptions.builder().noConnection(true).build()); + List
tables = plugin.tables(Arrays.asList("*"), Arrays.asList(), false); + List
flattenTables = Table.flattenTables(tables); + TablesJson tablesJson = new TablesJson(flattenTables); + String json = tablesJson.toJson(); + FileUtils.writeStringToFile(new File(outputPath), json, "UTF-8"); + } + + @SuppressWarnings("null") + private List buildDocker() + throws IllegalArgumentException, IOException, InterruptedException { + String dockerFilePath = Paths.get(pluginDirectory, plugin.getDockerfile()).toString(); + File dockerFile = new File(dockerFilePath); + if (!dockerFile.exists()) { + logger.error("Dockerfile {} does not exist", dockerFilePath); + throw new IllegalArgumentException("Dockerfile does not exist"); + } + if (!dockerFile.isFile()) { + logger.error("Dockerfile {} is not a file", dockerFilePath); + throw new IllegalArgumentException("Dockerfile is not a file"); + } + + List supportedTargets = new ArrayList<>(); + for (BuildTarget target : plugin.getBuildTargets()) { + String imageRepository = + String.format( + "docker.cloudquery.io/%s/%s-%s", + plugin.getTeam(), plugin.getKind(), plugin.getName()); + String os = target.getOs().toString(); + String arch = target.getArch().toString(); + String imageTag = String.format("%s:%s-%s-%s", imageRepository, pluginVersion, os, arch); + String imageTar = + String.format("plugin-%s-%s-%s-%s.tar", plugin.getName(), pluginVersion, os, arch); + String imagePath = Paths.get(distDir, imageTar).toString(); + logger.info("Building docker image {}", imageTag); + // GITHUB_ACTOR and GITHUB_TOKEN are required for the Dockerfile to pull the CloudQuery Java + // libs from GitHub Packages + String githubActor = System.getenv("GITHUB_ACTOR"); + if (Strings.isNullOrEmpty(githubActor)) { + logger.error("GITHUB_ACTOR env variable is required"); + throw new IllegalArgumentException("GITHUB_ACTOR env variable is required"); + } + String githubToken = System.getenv("GITHUB_TOKEN"); + if (Strings.isNullOrEmpty(githubToken)) { + logger.error("GITHUB_TOKEN env variable is required"); + throw new IllegalArgumentException("GITHUB_TOKEN env variable is required"); + } + String[] dockerBuildArguments = { + "buildx", + "build", + "-t", + imageTag, + "--platform", + String.format("%s/%s", os, arch), + "-f", + dockerFilePath, + ".", + "--progress", + "plain", + "--load", + "--build-arg", + String.format("GITHUB_ACTOR=%s", githubActor), + "--build-arg", + String.format("GITHUB_TOKEN=%s", githubToken), + }; + logger.debug("Running docker command: '{}'", String.join(" ", dockerBuildArguments)); + runCommand(dockerBuildArguments); + logger.debug("Saving docker image {} to {}", imageTag, imagePath); + String[] dockerSaveArguments = {"save", "-o", imagePath, imageTag}; + logger.debug("Running docker command: '{}'", String.join(" ", dockerSaveArguments)); + runCommand(dockerSaveArguments); + try (InputStream is = Files.newInputStream(Paths.get(imagePath))) { + String checksum = DigestUtils.sha256Hex(is); + SupportedTargetJson supportedTarget = + new SupportedTargetJson(os, arch, imageTar, checksum, imageTag); + supportedTargets.add(supportedTarget); + } + } + + return supportedTargets; + } + + private void runCommand(String[] command) throws IOException, InterruptedException { + ArrayList allArgs = new ArrayList<>(Arrays.asList(command)); + allArgs.add(0, "docker"); + ProcessBuilder processBuilder = + new ProcessBuilder(allArgs.toArray(new String[allArgs.size()])).inheritIO(); + processBuilder.directory(new File(pluginDirectory)); + Process process = processBuilder.start(); + int exitCode = process.waitFor(); + if (exitCode != 0) { + logger.error("Failed to run command: '{}'", String.join(" ", command)); + throw new IOException("Failed to run command"); + } + } + + private void writePackageJson(List supportedTargets) throws IOException { + String outputPath = Paths.get(distDir, "package.json").toString(); + logger.info("Writing package.json to {}", outputPath); + PackageJson packageJson = + new PackageJson( + plugin.getName(), + plugin.getTeam(), + plugin.getKind().toString(), + pluginVersion, + message, + supportedTargets); + String json = packageJson.toJson(); + FileUtils.writeStringToFile(new File(outputPath), json, "UTF-8"); + } +} diff --git a/lib/src/main/java/io/cloudquery/server/PackageJson.java b/lib/src/main/java/io/cloudquery/server/PackageJson.java new file mode 100644 index 00000000..1092cbf6 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/server/PackageJson.java @@ -0,0 +1,30 @@ +package io.cloudquery.server; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import java.util.List; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public class PackageJson { + @NonNull private final String name; + @NonNull private final String team; + @NonNull private final String kind; + @NonNull private final String version; + @NonNull private final String message; + @NonNull private final List supported_targets; + + private final int schema_version = 1; + private int[] protocols = {3}; + private String package_type = "docker"; + + public String toJson() throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + return objectMapper.writeValueAsString(this); + } +} diff --git a/lib/src/main/java/io/cloudquery/server/PluginServe.java b/lib/src/main/java/io/cloudquery/server/PluginServe.java index 7fffc5a0..b1153421 100644 --- a/lib/src/main/java/io/cloudquery/server/PluginServe.java +++ b/lib/src/main/java/io/cloudquery/server/PluginServe.java @@ -1,6 +1,7 @@ package io.cloudquery.server; import io.cloudquery.plugin.Plugin; +import io.cloudquery.types.Extensions; import lombok.AccessLevel; import lombok.Builder; import lombok.NonNull; @@ -8,12 +9,14 @@ @Builder(access = AccessLevel.PUBLIC) public class PluginServe { - @NonNull - private final Plugin plugin; - @Builder.Default - private String[] args = new String[] {}; + @NonNull private final Plugin plugin; + @Builder.Default private String[] args = new String[] {}; - public int Serve() { - return new CommandLine(new RootCommand()).addSubcommand(new ServeCommand(plugin)).execute(args); - } + public int Serve() { + Extensions.registerExtensions(); + CommandLine cli = new CommandLine(new RootCommand()); + cli.addSubcommand(new ServeCommand(plugin)); + cli.addSubcommand(new PackageCommand(plugin)); + return cli.execute(args); + } } diff --git a/lib/src/main/java/io/cloudquery/server/RootCommand.java b/lib/src/main/java/io/cloudquery/server/RootCommand.java index aa8bbd9b..fd4dedde 100644 --- a/lib/src/main/java/io/cloudquery/server/RootCommand.java +++ b/lib/src/main/java/io/cloudquery/server/RootCommand.java @@ -3,5 +3,4 @@ import picocli.CommandLine; @CommandLine.Command -public class RootCommand { -} \ No newline at end of file +public class RootCommand {} diff --git a/lib/src/main/java/io/cloudquery/server/ServeCommand.java b/lib/src/main/java/io/cloudquery/server/ServeCommand.java index b4eaccb6..2feb14c1 100644 --- a/lib/src/main/java/io/cloudquery/server/ServeCommand.java +++ b/lib/src/main/java/io/cloudquery/server/ServeCommand.java @@ -1,5 +1,7 @@ package io.cloudquery.server; +import static picocli.CommandLine.Option; + import io.cloudquery.internal.servers.discovery.v1.DiscoverServer; import io.cloudquery.internal.servers.plugin.v3.PluginServer; import io.cloudquery.plugin.Plugin; @@ -8,99 +10,110 @@ import io.grpc.InsecureServerCredentials; import io.grpc.Server; import io.grpc.protobuf.services.ProtoReflectionService; -import lombok.ToString; -import picocli.CommandLine.Command; import java.io.IOException; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.Executors; - -import org.apache.logging.log4j.Logger; +import lombok.ToString; import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.core.layout.JsonLayout; -import org.apache.logging.log4j.core.layout.PatternLayout; +import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.appender.ConsoleAppender; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.LoggerConfig; - -import static picocli.CommandLine.Option; +import org.apache.logging.log4j.core.layout.JsonLayout; +import org.apache.logging.log4j.core.layout.PatternLayout; +import picocli.CommandLine.Command; @Command(name = "serve", description = "start plugin gRPC server") @ToString public class ServeCommand implements Callable { - private static Logger logger; - public static final List DISCOVERY_VERSIONS = List.of(3); - - @Option(names = "--address", converter = AddressConverter.class, description = "address to serve on. can be tcp: localhost:7777 or unix socket: `/tmp/plugin.rpc.sock` (default \"${DEFAULT-VALUE}\")") - private Address address = new Address("localhost", 7777); - - @Option(names = "--log-format", description = "log format. one of: text,json (default \"${DEFAULT-VALUE}\")") - private String logFormat = "text"; - - @Option(names = "--log-level", description = "log level. one of: trace,debug,info,warn,error (default \"${DEFAULT-VALUE}\")") - private String logLevel = "info"; - - @Option(names = "--network", description = "the network must be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\" (default \"${DEFAULT-VALUE}\")") - private String network = "tcp"; - - @Option(names = "--disable-sentry", description = "disable sentry") - private Boolean disableSentry = false; - - @Option(names = "--otel-endpoint", description = "Open Telemetry HTTP collector endpoint") - private String otelEndpoint = ""; - - @Option(names = "--otel-endpoint-insecure", description = "use Open Telemetry HTTP endpoint (for development only)") - private Boolean otelEndpointInsecure = false; - - private final Plugin plugin; - - public ServeCommand(Plugin plugin) { - this.plugin = plugin; + private static Logger logger; + public static final List DISCOVERY_VERSIONS = List.of(3); + + @Option( + names = "--address", + converter = AddressConverter.class, + description = + "address to serve on. can be tcp: localhost:7777 or unix socket: `/tmp/plugin.rpc.sock` (default \"${DEFAULT-VALUE}\")") + private Address address = new Address("localhost", 7777); + + @Option( + names = "--log-format", + description = "log format. one of: text,json (default \"${DEFAULT-VALUE}\")") + private String logFormat = "text"; + + @Option( + names = "--log-level", + description = "log level. one of: trace,debug,info,warn,error (default \"${DEFAULT-VALUE}\")") + private String logLevel = "info"; + + @Option( + names = "--network", + description = + "the network must be \"tcp\", \"tcp4\", \"tcp6\", \"unix\" or \"unixpacket\" (default \"${DEFAULT-VALUE}\")") + private String network = "tcp"; + + @Option(names = "--no-sentry", description = "disable sentry") + private Boolean disableSentry = false; + + @Option(names = "--otel-endpoint", description = "Open Telemetry HTTP collector endpoint") + private String otelEndpoint = ""; + + @Option( + names = "--otel-endpoint-insecure", + description = "use Open Telemetry HTTP endpoint (for development only)") + private Boolean otelEndpointInsecure = false; + + @Option( + names = "--license", + description = "set offline license file (placeholder for future use)") + private String licenseFile = ""; + + private final Plugin plugin; + + public ServeCommand(Plugin plugin) { + this.plugin = plugin; + } + + private LoggerContext initLogger() { + ConsoleAppender appender = + ConsoleAppender.createDefaultAppenderForLayout( + this.logFormat == "text" + ? PatternLayout.createDefaultLayout() + : JsonLayout.createDefaultLayout()); + + Configuration configuration = ConfigurationFactory.newConfigurationBuilder().build(); + configuration.addAppender(appender); + LoggerConfig loggerConfig = new LoggerConfig("io.cloudquery", Level.getLevel(logLevel), false); + loggerConfig.addAppender(appender, null, null); + configuration.addLogger("io.cloudquery", loggerConfig); + LoggerContext context = new LoggerContext(ServeCommand.class.getName() + "Context"); + context.start(configuration); + + logger = context.getLogger(ServeCommand.class.getName()); + this.plugin.setLogger(logger); + return context; + } + + @Override + public Integer call() { + try (LoggerContext context = this.initLogger()) { + Server server = + Grpc.newServerBuilderForPort(address.port(), InsecureServerCredentials.create()) + .addService(new DiscoverServer(DISCOVERY_VERSIONS)) + .addService(new PluginServer(plugin)) + .addService(ProtoReflectionService.newInstance()) + .executor(Executors.newFixedThreadPool(10)) + .build(); + server.start(); + logger.info("Started server on {}:{}", address.host(), address.port()); + server.awaitTermination(); + return 0; + } catch (IOException | InterruptedException e) { + logger.error("Failed to start server", e); + return 1; } - - private LoggerContext initLogger() { - ConsoleAppender appender = ConsoleAppender.createDefaultAppenderForLayout( - this.logFormat == "text" ? PatternLayout.createDefaultLayout() : JsonLayout.createDefaultLayout()); - - Configuration configuration = ConfigurationFactory.newConfigurationBuilder().build(); - configuration.addAppender(appender); - LoggerConfig loggerConfig = new LoggerConfig("io.cloudquery", Level.getLevel(logLevel), false); - loggerConfig.addAppender(appender, null, null); - configuration.addLogger("io.cloudquery", loggerConfig); - LoggerContext context = new LoggerContext(ServeCommand.class.getName() + "Context"); - context.start(configuration); - - logger = context.getLogger(ServeCommand.class.getName()); - return context; - } - - @Override - public Integer call() { - LoggerContext context = this.initLogger(); - - try { - // Configure open telemetry - // Configure test listener - // Configure gRPC server - Server server = Grpc.newServerBuilderForPort(address.port(), InsecureServerCredentials.create()) - .addService(new DiscoverServer(DISCOVERY_VERSIONS)).addService(new PluginServer(plugin)) - .addService(ProtoReflectionService.newInstance()).executor(Executors.newFixedThreadPool(10)) - .build(); - // Configure sentry - // Log we are listening on address and port - // Run gRPC server and block - server.start(); - logger.info("Started server on {}:{}", address.host(), address.port()); - server.awaitTermination(); - return 0; - } catch (IOException | InterruptedException e) { - logger.error("Failed to start server", e); - return 1; - } finally { - context.close(); - } - } - + } } diff --git a/lib/src/main/java/io/cloudquery/server/SupportedTargetJson.java b/lib/src/main/java/io/cloudquery/server/SupportedTargetJson.java new file mode 100644 index 00000000..b71c7494 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/server/SupportedTargetJson.java @@ -0,0 +1,15 @@ +package io.cloudquery.server; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NonNull; + +@AllArgsConstructor +@Getter +public class SupportedTargetJson { + @NonNull private final String os; + @NonNull private final String arch; + @NonNull private final String path; + @NonNull private final String checksum; + @NonNull private final String docker_image_tag; +} diff --git a/lib/src/main/java/io/cloudquery/server/TablesJson.java b/lib/src/main/java/io/cloudquery/server/TablesJson.java new file mode 100644 index 00000000..e57b857b --- /dev/null +++ b/lib/src/main/java/io/cloudquery/server/TablesJson.java @@ -0,0 +1,68 @@ +package io.cloudquery.server; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import io.cloudquery.schema.Column; +import io.cloudquery.schema.Table; +import java.util.ArrayList; +import java.util.List; + +public class TablesJson { + public class ColumnJson { + public String name; + public String description; + public String type; + public boolean incremental_key; + public boolean not_null; + public boolean primary_key; + public boolean unique; + } + + public class TableJson { + public String name; + public String description; + public boolean is_incremental; + public String parent; + public List relations; + public List columns; + } + + private List
tables; + + public TablesJson(List
tables) { + this.tables = tables; + } + + public String toJson() throws JsonProcessingException { + List json = new ArrayList<>(); + for (Table table : tables) { + TableJson tableJson = new TableJson(); + tableJson.name = table.getName(); + tableJson.description = table.getDescription(); + tableJson.is_incremental = false; + tableJson.parent = table.getParent() == null ? null : table.getParent().getName(); + tableJson.relations = new ArrayList<>(); + for (Table relation : table.getRelations()) { + tableJson.relations.add(relation.getName()); + } + tableJson.columns = new ArrayList<>(); + for (Column column : table.getColumns()) { + ColumnJson columnJson = new ColumnJson(); + columnJson.name = column.getName(); + columnJson.description = column.getDescription(); + columnJson.type = column.getType().toString(); + columnJson.incremental_key = column.isIncrementalKey(); + columnJson.not_null = column.isNotNull(); + columnJson.primary_key = column.isPrimaryKey(); + columnJson.unique = column.isUnique(); + tableJson.columns.add(columnJson); + } + json.add(tableJson); + } + + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + return objectMapper.writeValueAsString(json); + } +} diff --git a/lib/src/main/java/io/cloudquery/transformers/IgnoreInTestsTransformer.java b/lib/src/main/java/io/cloudquery/transformers/IgnoreInTestsTransformer.java index 777cd4a3..ce153f5e 100644 --- a/lib/src/main/java/io/cloudquery/transformers/IgnoreInTestsTransformer.java +++ b/lib/src/main/java/io/cloudquery/transformers/IgnoreInTestsTransformer.java @@ -4,12 +4,12 @@ public interface IgnoreInTestsTransformer { - boolean transform(Field field); + boolean transform(Field field); - class DefaultIgnoreInTestsTransformer implements IgnoreInTestsTransformer { - @Override - public boolean transform(Field field) { - return false; - } + class DefaultIgnoreInTestsTransformer implements IgnoreInTestsTransformer { + @Override + public boolean transform(Field field) { + return false; } + } } diff --git a/lib/src/main/java/io/cloudquery/transformers/NameTransformer.java b/lib/src/main/java/io/cloudquery/transformers/NameTransformer.java index 7abc02da..875be329 100644 --- a/lib/src/main/java/io/cloudquery/transformers/NameTransformer.java +++ b/lib/src/main/java/io/cloudquery/transformers/NameTransformer.java @@ -2,30 +2,29 @@ import com.fasterxml.jackson.annotation.JsonProperty; import io.cloudquery.caser.Caser; - import java.lang.reflect.Field; public interface NameTransformer { - String transform(Field field) throws TransformerException; + String transform(Field field) throws TransformerException; - class DefaultNameTransformer implements NameTransformer { - private final Caser caser = Caser.builder().build(); + class DefaultNameTransformer implements NameTransformer { + private final Caser caser = Caser.builder().build(); - /** - * Transforms the field name to the name of the property in the JSON - * or use the {@link Caser#toSnake(String)} if no annotation. - * - * @param field Field to transform - * @return Transformed field name - */ - @Override - public String transform(Field field) { - JsonProperty annotation = field.getAnnotation(JsonProperty.class); - if (annotation != null) { - return annotation.value(); - } - return caser.toSnake(field.getName()); - } + /** + * Transforms the field name to the name of the property in the JSON or use the {@link + * Caser#toSnake(String)} if no annotation. + * + * @param field Field to transform + * @return Transformed field name + */ + @Override + public String transform(Field field) { + JsonProperty annotation = field.getAnnotation(JsonProperty.class); + if (annotation != null) { + return annotation.value(); + } + return caser.toSnake(field.getName()); } + } } diff --git a/lib/src/main/java/io/cloudquery/transformers/ResolverTransformer.java b/lib/src/main/java/io/cloudquery/transformers/ResolverTransformer.java index 2385147c..5c763078 100644 --- a/lib/src/main/java/io/cloudquery/transformers/ResolverTransformer.java +++ b/lib/src/main/java/io/cloudquery/transformers/ResolverTransformer.java @@ -4,23 +4,22 @@ import io.cloudquery.helper.ReflectionPathResolver.PathResolverException; import io.cloudquery.scalar.ValidationException; import io.cloudquery.schema.ColumnResolver; - import java.lang.reflect.Field; public interface ResolverTransformer { - ColumnResolver transform(Field field, String path) throws TransformerException; + ColumnResolver transform(Field field, String path) throws TransformerException; - class DefaulResolverTransformer implements ResolverTransformer { - @Override - public ColumnResolver transform(Field field, String path) throws TransformerException { - return (meta, resource, column) -> { - try { - resource.set(column.getName(), ReflectionPathResolver.resolve(resource.getItem(), path)); - } catch (PathResolverException | ValidationException ex) { - throw new TransformerException("Failed to resolve path: " + path, ex); - } - }; + class DefaultResolverTransformer implements ResolverTransformer { + @Override + public ColumnResolver transform(Field field, String path) throws TransformerException { + return (meta, resource, column) -> { + try { + resource.set(column.getName(), ReflectionPathResolver.resolve(resource.getItem(), path)); + } catch (PathResolverException | ValidationException ex) { + throw new TransformerException("Failed to resolve path: " + path, ex); } + }; } + } } diff --git a/lib/src/main/java/io/cloudquery/transformers/Tables.java b/lib/src/main/java/io/cloudquery/transformers/Tables.java index 47b4fad8..b0b276f9 100644 --- a/lib/src/main/java/io/cloudquery/transformers/Tables.java +++ b/lib/src/main/java/io/cloudquery/transformers/Tables.java @@ -1,32 +1,32 @@ package io.cloudquery.transformers; -import io.cloudquery.schema.Table; +import static io.cloudquery.schema.Table.*; +import io.cloudquery.schema.Table; import java.util.List; -import static io.cloudquery.schema.Table.*; - -class Tables { - public static void setParents(List
tables, Table parent) { - for (Table table : tables) { - table.setParent(parent); - setParents(table.getRelations(), table); - } +public class Tables { + public static void setParents(List
tables, Table parent) { + for (Table table : tables) { + table.setParent(parent); + setParents(table.getRelations(), table); } + } - public static void transformTables(List
tables) throws TransformerException { - for (Table table : tables) { - table.transform(); - transformTables(table.getRelations()); - } + public static void transformTables(List
tables) throws TransformerException { + for (Table table : tables) { + table.transform(); + transformTables(table.getRelations()); } + } - public static void apply(List
tables, List extraTransformers) throws TransformerException { - for (Table table : tables) { - for (Transform extraTransformer : extraTransformers) { - extraTransformer.transformTable(table); - } - apply(table.getRelations(), extraTransformers); - } + public static void apply(List
tables, List extraTransformers) + throws TransformerException { + for (Table table : tables) { + for (Transform extraTransformer : extraTransformers) { + extraTransformer.transformTable(table); + } + apply(table.getRelations(), extraTransformers); } + } } diff --git a/lib/src/main/java/io/cloudquery/transformers/TransformWithClass.java b/lib/src/main/java/io/cloudquery/transformers/TransformWithClass.java index ef1c37d2..cc5deba8 100644 --- a/lib/src/main/java/io/cloudquery/transformers/TransformWithClass.java +++ b/lib/src/main/java/io/cloudquery/transformers/TransformWithClass.java @@ -1,93 +1,92 @@ package io.cloudquery.transformers; +import static io.cloudquery.schema.Table.*; +import static io.cloudquery.transformers.IgnoreInTestsTransformer.DefaultIgnoreInTestsTransformer; +import static io.cloudquery.transformers.NameTransformer.DefaultNameTransformer; +import static io.cloudquery.transformers.TypeTransformer.DefaultTypeTransformer; + import io.cloudquery.schema.Column; import io.cloudquery.schema.Column.ColumnBuilder; import io.cloudquery.schema.Table; -import lombok.Builder; -import lombok.Singular; - import java.lang.reflect.Field; import java.util.HashSet; import java.util.Set; - -import static io.cloudquery.schema.Table.*; -import static io.cloudquery.transformers.IgnoreInTestsTransformer.DefaultIgnoreInTestsTransformer; -import static io.cloudquery.transformers.NameTransformer.DefaultNameTransformer; -import static io.cloudquery.transformers.ResolverTransformer.DefaulResolverTransformer; -import static io.cloudquery.transformers.TypeTransformer.DefaultTypeTransformer; +import lombok.Builder; +import lombok.Singular; @Builder(builderMethodName = "innerBuilder") public class TransformWithClass implements Transform { - @Builder.Default - private NameTransformer nameTransformer = new DefaultNameTransformer(); - @Builder.Default - private TypeTransformer typeTransformer = new DefaultTypeTransformer(); - @Builder.Default - private ResolverTransformer resolverTransformer = new DefaulResolverTransformer(); - @Builder.Default - private IgnoreInTestsTransformer ignoreInTestsTransformer = new DefaultIgnoreInTestsTransformer(); - - @Singular - private Set pkFields; - private final Set pkFieldsFound = new HashSet<>(); - - @Singular - private Set unwrapFields; - - private final Class clazz; - - @Override - public void transformTable(Table table) throws TransformerException { - for (Field field : clazz.getDeclaredFields()) { - if (shouldUnwrapField(field)) { - for (Field innerField : field.getType().getDeclaredFields()) { - addColumnFromField(table, innerField, field); - } - } else { - addColumnFromField(table, field, null); - } - } + @Builder.Default private NameTransformer nameTransformer = new DefaultNameTransformer(); + @Builder.Default private TypeTransformer typeTransformer = new DefaultTypeTransformer(); - validatePrimaryKeysHaveBeenFound(); - } + @Builder.Default + private ResolverTransformer resolverTransformer = + new ResolverTransformer.DefaultResolverTransformer(); + @Builder.Default + private IgnoreInTestsTransformer ignoreInTestsTransformer = new DefaultIgnoreInTestsTransformer(); - private void addColumnFromField(Table table, Field field, Field parent) throws TransformerException { - String path = field.getName(); - String name = nameTransformer.transform(field); + @Singular private Set pkFields; + private final Set pkFieldsFound = new HashSet<>(); - if (parent != null) { - name = nameTransformer.transform(parent) + "_" + name; - path = parent.getName() + "." + path; - } + @Singular private Set unwrapFields; - ColumnBuilder columnBuilder = Column.builder(). - name(name). - type(typeTransformer.transform(field)). - resolver(resolverTransformer.transform(field, path)). - ignoreInTests(ignoreInTestsTransformer.transform(field)); + private final Class clazz; - if (pkFields.contains(path)) { - columnBuilder.primaryKey(true); - pkFieldsFound.add(path); + @Override + public void transformTable(Table table) throws TransformerException { + for (Field field : clazz.getDeclaredFields()) { + if (shouldUnwrapField(field)) { + for (Field innerField : field.getType().getDeclaredFields()) { + addColumnFromField(table, innerField, field); } - - table.getColumns().add(columnBuilder.build()); + } else { + addColumnFromField(table, field, null); + } } - private boolean shouldUnwrapField(Field field) { - return unwrapFields.contains(field.getName()); + validatePrimaryKeysHaveBeenFound(); + } + + private void addColumnFromField(Table table, Field field, Field parent) + throws TransformerException { + String path = field.getName(); + String name = nameTransformer.transform(field); + + if (parent != null) { + name = nameTransformer.transform(parent) + "_" + name; + path = parent.getName() + "." + path; } - private void validatePrimaryKeysHaveBeenFound() throws TransformerException { - Set missingPrimaryKeys = new HashSet<>(pkFields); - missingPrimaryKeys.removeAll(pkFieldsFound); - if (!missingPrimaryKeys.isEmpty()) { - throw new TransformerException("failed to create all of the desired primary keys: " + missingPrimaryKeys); - } + ColumnBuilder columnBuilder = + Column.builder() + .name(name) + .type(typeTransformer.transform(field)) + .resolver(resolverTransformer.transform(field, path)) + .ignoreInTests(ignoreInTestsTransformer.transform(field)); + + if (pkFields.contains(path)) { + columnBuilder.primaryKey(true); + pkFieldsFound.add(path); } - public static TransformWithClassBuilder builder(Class clazz) { - return innerBuilder().clazz(clazz); + table.getColumns().add(columnBuilder.build()); + } + + private boolean shouldUnwrapField(Field field) { + return unwrapFields.contains(field.getName()); + } + + private void validatePrimaryKeysHaveBeenFound() throws TransformerException { + Set missingPrimaryKeys = new HashSet<>(pkFields); + missingPrimaryKeys.removeAll(pkFieldsFound); + if (!missingPrimaryKeys.isEmpty()) { + throw new TransformerException( + "failed to create all of the desired primary keys: " + missingPrimaryKeys); } + } + + public static TransformWithClassBuilder builder(Class clazz) { + return innerBuilder().clazz(clazz); + } } diff --git a/lib/src/main/java/io/cloudquery/transformers/TransformerException.java b/lib/src/main/java/io/cloudquery/transformers/TransformerException.java index a6bc9188..17afc502 100644 --- a/lib/src/main/java/io/cloudquery/transformers/TransformerException.java +++ b/lib/src/main/java/io/cloudquery/transformers/TransformerException.java @@ -1,11 +1,11 @@ package io.cloudquery.transformers; public class TransformerException extends Exception { - public TransformerException(String message) { - super(message); - } + public TransformerException(String message) { + super(message); + } - public TransformerException(String message, Throwable ex) { - super(message, ex); - } + public TransformerException(String message, Throwable ex) { + super(message, ex); + } } diff --git a/lib/src/main/java/io/cloudquery/transformers/TypeTransformer.java b/lib/src/main/java/io/cloudquery/transformers/TypeTransformer.java index d35382e5..4157f71a 100644 --- a/lib/src/main/java/io/cloudquery/transformers/TypeTransformer.java +++ b/lib/src/main/java/io/cloudquery/transformers/TypeTransformer.java @@ -1,63 +1,60 @@ package io.cloudquery.transformers; -import io.cloudquery.types.InetType; +import io.cloudquery.scalar.Timestamp; import io.cloudquery.types.JSONType; -import io.cloudquery.types.ListType; +import io.cloudquery.types.UUIDType; +import java.lang.reflect.Field; import org.apache.arrow.vector.types.FloatingPointPrecision; -import org.apache.arrow.vector.types.TimeUnit; import org.apache.arrow.vector.types.pojo.ArrowType; -import java.lang.reflect.Field; - public interface TypeTransformer { - ArrowType transform(Field field) throws TransformerException; + ArrowType transform(Field field) throws TransformerException; - class DefaultTypeTransformer implements TypeTransformer { - @Override - public ArrowType transform(Field field) throws TransformerException { - return transformArrowType(field.getName(), field.getType()); - } + class DefaultTypeTransformer implements TypeTransformer { + @Override + public ArrowType transform(Field field) throws TransformerException { + return transformArrowType(field.getName(), field.getType()); + } - private static ArrowType transformArrowType(String name, Class type) throws TransformerException { - switch (type.getName()) { - case "java.lang.String" -> { - return ArrowType.Utf8.INSTANCE; - } - case "java.lang.Boolean", "boolean" -> { - return ArrowType.Bool.INSTANCE; - } - case "java.lang.Integer", "int", "java.lang.Long", "long" -> { - return new ArrowType.Int(64, true); - } - case "float", "double", "java.lang.Float", "java.lang.Double" -> { - return new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE); - } - case "java.util.Map" -> { - return JSONType.INSTANCE; - } - case "java.net.InetAddress" -> { - return InetType.INSTANCE; - } - case "java.time.LocalDateTime" -> { - return new ArrowType.Timestamp(TimeUnit.MICROSECOND, null); - } - default -> { - if (type.isArray()) { - Class componentType = type.getComponentType(); - if (componentType.getName().equals("byte")) { - return ArrowType.Binary.INSTANCE; - } - // if element type is already json just return JSON rather than a list of JSON - ArrowType elementType = transformArrowType(name, componentType); - return elementType == JSONType.INSTANCE ? elementType : ListType.listOf(elementType); - } - if (!type.isPrimitive()) { - return JSONType.INSTANCE; - } - } + private static ArrowType transformArrowType(String name, Class type) + throws TransformerException { + switch (type.getName()) { + case "java.lang.String" -> { + return ArrowType.Utf8.INSTANCE; + } + case "java.lang.Boolean", "boolean" -> { + return ArrowType.Bool.INSTANCE; + } + case "java.lang.Integer", "int", "java.lang.Long", "long" -> { + return new ArrowType.Int(64, true); + } + case "float", "double", "java.lang.Float", "java.lang.Double" -> { + return new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE); + } + case "java.util.Map" -> { + return JSONType.INSTANCE; + } + case "java.time.LocalDateTime" -> { + return Timestamp.dt; + } + case "java.util.UUID" -> { + return UUIDType.INSTANCE; + } + default -> { + if (type.isArray()) { + Class componentType = type.getComponentType(); + if (componentType.getName().equals("byte")) { + return ArrowType.Binary.INSTANCE; } - throw new TransformerException("Unsupported type: " + type.getName() + " for field: " + name); + return JSONType.INSTANCE; + } + if (!type.isPrimitive()) { + return JSONType.INSTANCE; + } } + } + throw new TransformerException("Unsupported type: " + type.getName() + " for field: " + name); } + } } diff --git a/lib/src/main/java/io/cloudquery/types/Extensions.java b/lib/src/main/java/io/cloudquery/types/Extensions.java new file mode 100644 index 00000000..2c4c5607 --- /dev/null +++ b/lib/src/main/java/io/cloudquery/types/Extensions.java @@ -0,0 +1,12 @@ +package io.cloudquery.types; + +import org.apache.arrow.vector.types.pojo.ExtensionTypeRegistry; + +public class Extensions { + public static void registerExtensions() { + ExtensionTypeRegistry.register(new UUIDType()); + ExtensionTypeRegistry.register(new JSONType()); + } + + private Extensions() {} +} diff --git a/lib/src/main/java/io/cloudquery/types/InetType.java b/lib/src/main/java/io/cloudquery/types/InetType.java deleted file mode 100644 index 2347e8ff..00000000 --- a/lib/src/main/java/io/cloudquery/types/InetType.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.cloudquery.types; - -import org.apache.arrow.memory.BufferAllocator; -import org.apache.arrow.vector.FieldVector; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.apache.arrow.vector.types.pojo.FieldType; - -public class InetType extends ArrowType.ExtensionType { - public static final InetType INSTANCE = new InetType(); - public static final String EXTENSION_NAME = "inet"; - - @Override - public ArrowType storageType() { - return Binary.INSTANCE; - } - - @Override - public String extensionName() { - return EXTENSION_NAME; - } - - @Override - public boolean extensionEquals(ExtensionType other) { - return other instanceof InetType; - } - - @Override - public String serialize() { - return null; - } - - @Override - public ArrowType deserialize(ArrowType storageType, String serializedData) { - return null; - } - - @Override - public FieldVector getNewVector(String name, FieldType fieldType, BufferAllocator allocator) { - return null; - } -} diff --git a/lib/src/main/java/io/cloudquery/types/JSONType.java b/lib/src/main/java/io/cloudquery/types/JSONType.java index 9ab9457f..2484d05f 100644 --- a/lib/src/main/java/io/cloudquery/types/JSONType.java +++ b/lib/src/main/java/io/cloudquery/types/JSONType.java @@ -1,52 +1,91 @@ package io.cloudquery.types; import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.util.hash.ArrowBufHasher; +import org.apache.arrow.vector.ExtensionTypeVector; import org.apache.arrow.vector.FieldVector; +import org.apache.arrow.vector.VarBinaryVector; import org.apache.arrow.vector.types.pojo.ArrowType; import org.apache.arrow.vector.types.pojo.ArrowType.ExtensionType; import org.apache.arrow.vector.types.pojo.FieldType; public class JSONType extends ExtensionType { - public static final JSONType INSTANCE = new JSONType(); - public static final String EXTENSION_NAME = "json"; + public static final JSONType INSTANCE = new JSONType(); + public static final String EXTENSION_NAME = "json"; - @Override - public ArrowType storageType() { - return ArrowType.Binary.INSTANCE; - } + @Override + public ArrowType storageType() { + return Binary.INSTANCE; + } - @Override - public String extensionName() { - return EXTENSION_NAME; + @Override + public String extensionName() { + return EXTENSION_NAME; + } + + @Override + public boolean extensionEquals(ExtensionType other) { + return other instanceof JSONType; + } + + @Override + public String serialize() { + return "json-serialized"; + } + + @Override + public ArrowType deserialize(ArrowType storageType, String serializedData) { + if (!serializedData.equals("json-serialized")) { + throw new IllegalArgumentException("Type identifier did not match: " + serializedData); + } + if (!storageType.equals(storageType())) { + throw new IllegalArgumentException( + "invalid storage type for JSONType: " + storageType.getTypeID()); } + return new JSONType(); + } - @Override - public boolean extensionEquals(ExtensionType other) { - return false; + @Override + public FieldVector getNewVector(String name, FieldType fieldType, BufferAllocator allocator) { + return new JSONVector(name, allocator, new VarBinaryVector(name, allocator)); + } + + @Override + public int hashCode() { + return java.util.Arrays.deepHashCode(new Object[] {}); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof JSONType; + } + + public static class JSONVector extends ExtensionTypeVector { + public JSONVector(String name, BufferAllocator allocator, VarBinaryVector underlyingVector) { + super(name, allocator, underlyingVector); } @Override - public String serialize() { - return null; + public Object getObject(int index) { + return getUnderlyingVector().getObject(index); } @Override - public ArrowType deserialize(ArrowType storageType, String serializedData) { - return null; + public int hashCode(int index) { + return hashCode(index, null); } @Override - public FieldVector getNewVector(String name, FieldType fieldType, BufferAllocator allocator) { - return null; + public int hashCode(int index, ArrowBufHasher hasher) { + return getUnderlyingVector().hashCode(index, hasher); } - @Override - public int hashCode() { - return java.util.Arrays.deepHashCode(new Object[]{}); + public byte[] get(int index) { + return (byte[]) getObject(index); } - @Override - public boolean equals(Object obj) { - return obj instanceof JSONType; + public void setSafe(int index, byte[] bytes) { + getUnderlyingVector().setSafe(index, bytes); } + } } diff --git a/lib/src/main/java/io/cloudquery/types/ListType.java b/lib/src/main/java/io/cloudquery/types/ListType.java deleted file mode 100644 index c743138e..00000000 --- a/lib/src/main/java/io/cloudquery/types/ListType.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.cloudquery.types; - -import org.apache.arrow.vector.types.pojo.ArrowType; - -import java.util.Objects; - -public class ListType extends ArrowType.List { - - public static ListType listOf(ArrowType elementType) { - return new ListType(elementType); - } - - private final ArrowType elementType; - - public ListType(ArrowType elementType) { - this.elementType = elementType; - } - - public ArrowType getElementType() { - return elementType; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - ListType listType = (ListType) o; - return Objects.equals(elementType, listType.elementType); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), elementType); - } - - @Override - public String toString() { - return "ListType{" + - "elementType=" + elementType + - '}'; - } -} diff --git a/lib/src/main/java/io/cloudquery/types/UUIDType.java b/lib/src/main/java/io/cloudquery/types/UUIDType.java index b7c1c058..e36ee392 100644 --- a/lib/src/main/java/io/cloudquery/types/UUIDType.java +++ b/lib/src/main/java/io/cloudquery/types/UUIDType.java @@ -1,88 +1,91 @@ package io.cloudquery.types; +import java.nio.ByteBuffer; +import java.util.UUID; import org.apache.arrow.memory.BufferAllocator; import org.apache.arrow.memory.util.hash.ArrowBufHasher; import org.apache.arrow.vector.ExtensionTypeVector; import org.apache.arrow.vector.FieldVector; import org.apache.arrow.vector.FixedSizeBinaryVector; import org.apache.arrow.vector.types.pojo.ArrowType; +import org.apache.arrow.vector.types.pojo.ArrowType.ExtensionType; import org.apache.arrow.vector.types.pojo.FieldType; -import java.nio.ByteBuffer; -import java.util.UUID; - -import static org.apache.arrow.vector.types.pojo.ArrowType.ExtensionType; - public class UUIDType extends ExtensionType { - public static final int BYTE_WIDTH = 16; - public static final String EXTENSION_NAME = "uuid"; - - @Override - public ArrowType storageType() { - return new FixedSizeBinary(BYTE_WIDTH); + public static final UUIDType INSTANCE = new UUIDType(); + public static final int BYTE_WIDTH = 16; + public static final String EXTENSION_NAME = "uuid"; + + @Override + public ArrowType storageType() { + return new FixedSizeBinary(BYTE_WIDTH); + } + + @Override + public String extensionName() { + return EXTENSION_NAME; + } + + @Override + public boolean extensionEquals(ExtensionType other) { + return other instanceof UUIDType; + } + + @Override + public String serialize() { + return "uuid-serialized"; + } + + @Override + public ArrowType deserialize(ArrowType storageType, String serializedData) { + if (!serializedData.equals("uuid-serialized")) { + throw new IllegalArgumentException("Type identifier did not match: " + serializedData); } - - @Override - public String extensionName() { - return EXTENSION_NAME; + if (!storageType.equals(storageType())) { + throw new IllegalArgumentException( + "invalid storage type for UUIDType: " + storageType.getTypeID()); } + return new UUIDType(); + } - @Override - public boolean extensionEquals(ExtensionType other) { - return other instanceof UUIDType; + @Override + public FieldVector getNewVector(String name, FieldType fieldType, BufferAllocator allocator) { + return new UUIDVector(name, allocator, new FixedSizeBinaryVector(name, allocator, BYTE_WIDTH)); + } + + public static class UUIDVector extends ExtensionTypeVector { + public UUIDVector(String name, BufferAllocator allocator, FixedSizeBinaryVector valueVectors) { + super(name, allocator, valueVectors); } @Override - public String serialize() { - return "uuid-serialized"; + public Object getObject(int index) { + if (getUnderlyingVector().isSet(index) == 0) { + return null; + } + final ByteBuffer bb = ByteBuffer.wrap(getUnderlyingVector().getObject(index)); + return new UUID(bb.getLong(), bb.getLong()); } @Override - public ArrowType deserialize(ArrowType storageType, String serializedData) { - if (!serializedData.equals("uuid-serialized")) { - throw new IllegalArgumentException("Type identifier did not match: " + serializedData); - } - if (!storageType.equals(storageType())) { - throw new IllegalArgumentException("invalid storage type for UUIDType: " + storageType.getTypeID()); - } - return new UUIDType(); + public int hashCode(int index) { + return hashCode(index, null); } @Override - public FieldVector getNewVector(String name, FieldType fieldType, BufferAllocator allocator) { - return new UUIDVector(name, allocator, new FixedSizeBinaryVector(name, allocator, BYTE_WIDTH)); + public int hashCode(int index, ArrowBufHasher hasher) { + return getUnderlyingVector().hashCode(index, hasher); } - public static class UUIDVector extends ExtensionTypeVector { - public UUIDVector(String name, BufferAllocator allocator, FixedSizeBinaryVector valueVectors) { - super(name, allocator, valueVectors); - } - - @Override - public Object getObject(int index) { - final ByteBuffer bb = ByteBuffer.wrap(getUnderlyingVector().getObject(index)); - return new UUID(bb.getLong(), bb.getLong()); - } - - @Override - public int hashCode(int index) { - return hashCode(index, null); - } - - @Override - public int hashCode(int index, ArrowBufHasher hasher) { - return getUnderlyingVector().hashCode(index, hasher); - } - - public UUID get(int index) { - return (UUID) getObject(index); - } + public UUID get(int index) { + return (UUID) getObject(index); + } - public void set(int index, UUID uuid) { - ByteBuffer bb = ByteBuffer.allocate(BYTE_WIDTH); - bb.putLong(uuid.getMostSignificantBits()); - bb.putLong(uuid.getLeastSignificantBits()); - getUnderlyingVector().set(index, bb.array()); - } + public void set(int index, UUID uuid) { + ByteBuffer bb = ByteBuffer.allocate(BYTE_WIDTH); + bb.putLong(uuid.getMostSignificantBits()); + bb.putLong(uuid.getLeastSignificantBits()); + getUnderlyingVector().set(index, bb.array()); } + } } diff --git a/lib/src/test/java/io/cloudquery/caser/CaserTest.java b/lib/src/test/java/io/cloudquery/caser/CaserTest.java index f4144f83..3ac41d3f 100644 --- a/lib/src/test/java/io/cloudquery/caser/CaserTest.java +++ b/lib/src/test/java/io/cloudquery/caser/CaserTest.java @@ -1,161 +1,154 @@ package io.cloudquery.caser; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.util.Map; -import java.util.Set; -import java.util.stream.Stream; - public class CaserTest { - public static Stream toSnakeSource() { - return Stream.of( - Arguments.of("TestCamelCase", "test_camel_case"), - Arguments.of("TestCamelCase", "test_camel_case"), - Arguments.of("AccountID", "account_id"), - Arguments.of("IDs", "ids"), - Arguments.of("PostgreSQL", "postgre_sql"), - Arguments.of("QueryStoreRetention", "query_store_retention"), - Arguments.of("TestCamelCaseLongString", "test_camel_case_long_string"), - Arguments.of("testCamelCaseLongString", "test_camel_case_long_string"), - Arguments.of("testIPv4", "test_ipv4"), - Arguments.of("CoreIPs", "core_ips"), - Arguments.of("CoreIps", "core_ips"), - Arguments.of("CoreV1", "core_v1"), - Arguments.of("APIVersion", "api_version"), - Arguments.of("TTLSecondsAfterFinished", "ttl_seconds_after_finished"), - Arguments.of("PodCIDRs", "pod_cidrs"), - Arguments.of("IAMRoles", "iam_roles"), - Arguments.of("testIAM", "test_iam"), - Arguments.of("TestAWSMode", "test_aws_mode") - ); - } - - public static Stream toCamelSource() { - return Stream.of( - Arguments.of("testCamelCase", "test_camel_case"), - Arguments.of("accountID", "account_id"), - Arguments.of("arns", "arns"), - Arguments.of("postgreSQL", "postgre_sql"), - Arguments.of("queryStoreRetention", "query_store_retention"), - Arguments.of("testCamelCaseLongString", "test_camel_case_long_string"), - Arguments.of("testCamelCaseLongString", "test_camel_case_long_string"), - Arguments.of("testIPv4", "test_ipv4") - ); - } - - public static Stream toTitleSource() { - return Stream.of( - Arguments.of("Test Camel Case", "test_camel_case"), - Arguments.of("Account ID", "account_id"), - Arguments.of("ARNs", "arns"), - Arguments.of("Postgre SQL", "postgre_sql"), - Arguments.of("Query Store Retention", "query_store_retention"), - Arguments.of("Test Camel Case Long String", "test_camel_case_long_string"), - Arguments.of("Test Camel Case Long String", "test_camel_case_long_string"), - Arguments.of("Test IPv4", "test_ipv4"), - Arguments.of("AWS Test Table", "aws_test_table"), - Arguments.of("Gcp Test Table", "gcp_test_table") - ); - } - - public static Stream toPascalSource() { - return Stream.of( - Arguments.of("TestCamelCase", "test_camel_case"), - Arguments.of("AccountID", "account_id"), - Arguments.of("Arns", "arns"), - Arguments.of("PostgreSQL", "postgre_sql"), - Arguments.of("QueryStoreRetention", "query_store_retention"), - Arguments.of("TestCamelCaseLongString", "test_camel_case_long_string"), - Arguments.of("TestCamelCaseLongString", "test_camel_case_long_string"), - Arguments.of("TestV1", "test_v1"), - Arguments.of("TestIPv4", "test_ipv4"), - Arguments.of("Ec2", "ec2"), - Arguments.of("S3", "s3") - ); - } - - public static Stream inversionSource() { - return Stream.of( - Arguments.of("TestCamelCase"), - Arguments.of("AccountID"), - Arguments.of("Arns"), - Arguments.of("PostgreSQL"), - Arguments.of("QueryStoreRetention"), - Arguments.of("TestCamelCaseLongString"), - Arguments.of("TestCamelCaseLongString"), - Arguments.of("TestV1"), - Arguments.of("TestIPv4"), - Arguments.of("TestIPv4"), - Arguments.of("S3") - ); - } - - public static Stream configureSource() { - return Stream.of( - Arguments.of("CDNs", "cdns"), - Arguments.of("ARNs", "arns"), - Arguments.of("EC2", "ec2"), - Arguments.of("S3", "s3") - ); - } - - public static Stream customExceptionsSource() { - return Stream.of( - Arguments.of("TEst", "test"), - Arguments.of("TTv2", "ttv2") - ); - } - - @ParameterizedTest - @MethodSource("toSnakeSource") - public void testToSnake(String camel, String snake) { - Assertions.assertEquals(snake, Caser.builder().build().toSnake(camel)); - } - - @ParameterizedTest - @MethodSource("toCamelSource") - public void testToCamel(String camel, String snake) { - Assertions.assertEquals(camel, Caser.builder().build().toCamel(snake)); - } - - @ParameterizedTest - @MethodSource("toTitleSource") - public void testToTitle(String title, String snake) { - Caser caser = Caser.builder().customExceptions(Map.of( - "arns", "ARNs", - "aws", "AWS" - )).build(); - Assertions.assertEquals(title, caser.toTitle(snake)); - } - - @ParameterizedTest - @MethodSource("toPascalSource") - public void testToPascal(String pascal, String snake) { - Caser caser = Caser.builder().build(); - Assertions.assertEquals(pascal, caser.toPascal(snake)); - } - - @ParameterizedTest - @MethodSource("inversionSource") - public void testInversion(String pascal) { - Caser caser = Caser.builder().build(); - Assertions.assertEquals(pascal, caser.toPascal(caser.toSnake(pascal))); - } - - @ParameterizedTest - @MethodSource("configureSource") - public void testConfigure(String camel, String snake) { - Caser caser = Caser.builder().customInitialisms(Set.of("CDN", "ARN", "EC2")).build(); - Assertions.assertEquals(snake, caser.toSnake(camel)); - } - - @ParameterizedTest - @MethodSource("customExceptionsSource") - public void testCustomExceptions(String camel, String snake) { - Caser caser = Caser.builder().customExceptions(Map.of("test", "TEst", "ttv2", "TTv2")).build(); - Assertions.assertEquals(camel, caser.toCamel(snake)); - } -} \ No newline at end of file + public static Stream toSnakeSource() { + return Stream.of( + Arguments.of("TestCamelCase", "test_camel_case"), + Arguments.of("TestCamelCase", "test_camel_case"), + Arguments.of("AccountID", "account_id"), + Arguments.of("IDs", "ids"), + Arguments.of("PostgreSQL", "postgre_sql"), + Arguments.of("QueryStoreRetention", "query_store_retention"), + Arguments.of("TestCamelCaseLongString", "test_camel_case_long_string"), + Arguments.of("testCamelCaseLongString", "test_camel_case_long_string"), + Arguments.of("testIPv4", "test_ipv4"), + Arguments.of("CoreIPs", "core_ips"), + Arguments.of("CoreIps", "core_ips"), + Arguments.of("CoreV1", "core_v1"), + Arguments.of("APIVersion", "api_version"), + Arguments.of("TTLSecondsAfterFinished", "ttl_seconds_after_finished"), + Arguments.of("PodCIDRs", "pod_cidrs"), + Arguments.of("IAMRoles", "iam_roles"), + Arguments.of("testIAM", "test_iam"), + Arguments.of("TestAWSMode", "test_aws_mode")); + } + + public static Stream toCamelSource() { + return Stream.of( + Arguments.of("testCamelCase", "test_camel_case"), + Arguments.of("accountID", "account_id"), + Arguments.of("arns", "arns"), + Arguments.of("postgreSQL", "postgre_sql"), + Arguments.of("queryStoreRetention", "query_store_retention"), + Arguments.of("testCamelCaseLongString", "test_camel_case_long_string"), + Arguments.of("testCamelCaseLongString", "test_camel_case_long_string"), + Arguments.of("testIPv4", "test_ipv4")); + } + + public static Stream toTitleSource() { + return Stream.of( + Arguments.of("Test Camel Case", "test_camel_case"), + Arguments.of("Account ID", "account_id"), + Arguments.of("ARNs", "arns"), + Arguments.of("Postgre SQL", "postgre_sql"), + Arguments.of("Query Store Retention", "query_store_retention"), + Arguments.of("Test Camel Case Long String", "test_camel_case_long_string"), + Arguments.of("Test Camel Case Long String", "test_camel_case_long_string"), + Arguments.of("Test IPv4", "test_ipv4"), + Arguments.of("AWS Test Table", "aws_test_table"), + Arguments.of("Gcp Test Table", "gcp_test_table")); + } + + public static Stream toPascalSource() { + return Stream.of( + Arguments.of("TestCamelCase", "test_camel_case"), + Arguments.of("AccountID", "account_id"), + Arguments.of("Arns", "arns"), + Arguments.of("PostgreSQL", "postgre_sql"), + Arguments.of("QueryStoreRetention", "query_store_retention"), + Arguments.of("TestCamelCaseLongString", "test_camel_case_long_string"), + Arguments.of("TestCamelCaseLongString", "test_camel_case_long_string"), + Arguments.of("TestV1", "test_v1"), + Arguments.of("TestIPv4", "test_ipv4"), + Arguments.of("Ec2", "ec2"), + Arguments.of("S3", "s3")); + } + + public static Stream inversionSource() { + return Stream.of( + Arguments.of("TestCamelCase"), + Arguments.of("AccountID"), + Arguments.of("Arns"), + Arguments.of("PostgreSQL"), + Arguments.of("QueryStoreRetention"), + Arguments.of("TestCamelCaseLongString"), + Arguments.of("TestCamelCaseLongString"), + Arguments.of("TestV1"), + Arguments.of("TestIPv4"), + Arguments.of("TestIPv4"), + Arguments.of("S3")); + } + + public static Stream configureSource() { + return Stream.of( + Arguments.of("CDNs", "cdns"), + Arguments.of("ARNs", "arns"), + Arguments.of("EC2", "ec2"), + Arguments.of("S3", "s3")); + } + + public static Stream customExceptionsSource() { + return Stream.of(Arguments.of("TEst", "test"), Arguments.of("TTv2", "ttv2")); + } + + @ParameterizedTest + @MethodSource("toSnakeSource") + public void testToSnake(String camel, String snake) { + Assertions.assertEquals(snake, Caser.builder().build().toSnake(camel)); + } + + @ParameterizedTest + @MethodSource("toCamelSource") + public void testToCamel(String camel, String snake) { + Assertions.assertEquals(camel, Caser.builder().build().toCamel(snake)); + } + + @ParameterizedTest + @MethodSource("toTitleSource") + public void testToTitle(String title, String snake) { + Caser caser = + Caser.builder() + .customExceptions( + Map.of( + "arns", "ARNs", + "aws", "AWS")) + .build(); + Assertions.assertEquals(title, caser.toTitle(snake)); + } + + @ParameterizedTest + @MethodSource("toPascalSource") + public void testToPascal(String pascal, String snake) { + Caser caser = Caser.builder().build(); + Assertions.assertEquals(pascal, caser.toPascal(snake)); + } + + @ParameterizedTest + @MethodSource("inversionSource") + public void testInversion(String pascal) { + Caser caser = Caser.builder().build(); + Assertions.assertEquals(pascal, caser.toPascal(caser.toSnake(pascal))); + } + + @ParameterizedTest + @MethodSource("configureSource") + public void testConfigure(String camel, String snake) { + Caser caser = Caser.builder().customInitialisms(Set.of("CDN", "ARN", "EC2")).build(); + Assertions.assertEquals(snake, caser.toSnake(camel)); + } + + @ParameterizedTest + @MethodSource("customExceptionsSource") + public void testCustomExceptions(String camel, String snake) { + Caser caser = Caser.builder().customExceptions(Map.of("test", "TEst", "ttv2", "TTv2")).build(); + Assertions.assertEquals(camel, caser.toCamel(snake)); + } +} diff --git a/lib/src/test/java/io/cloudquery/glob/GlobTest.java b/lib/src/test/java/io/cloudquery/glob/GlobTest.java index a534ee48..d8c075e4 100644 --- a/lib/src/test/java/io/cloudquery/glob/GlobTest.java +++ b/lib/src/test/java/io/cloudquery/glob/GlobTest.java @@ -1,99 +1,97 @@ package io.cloudquery.glob; -import org.junit.jupiter.api.Test; - -import java.util.List; - import static io.cloudquery.glob.Glob.GLOB; import static org.junit.jupiter.api.Assertions.*; -public class GlobTest { - @Test - public void testEmptyPattern() { - assertGlobMatch("", ""); - assertNotGlobMatch("", "test"); - } +import java.util.List; +import org.junit.jupiter.api.Test; - @Test - public void testEmptySubject() { - for (String s : List.of("", - "*", - "**", - "***", - "****************", - GLOB.repeat(1000000) - )) { - assertGlobMatch(s, ""); - } +public class GlobTest { + @Test + public void testEmptyPattern() { + assertGlobMatch("", ""); + assertNotGlobMatch("", "test"); + } - for (String pattern : List.of( - // No globs/non-glob characters - "test", - "*test*", + @Test + public void testEmptySubject() { + for (String s : List.of("", "*", "**", "***", "****************", GLOB.repeat(1000000))) { + assertGlobMatch(s, ""); + } - // Trailing characters - "*x", - "*****************x", - GLOB.repeat(1000000) + "x", + for (String pattern : + List.of( + // No globs/non-glob characters + "test", + "*test*", - // Leading characters - "x*", - "x*****************", - "x" + GLOB.repeat(1000000), + // Trailing characters + "*x", + "*****************x", + GLOB.repeat(1000000) + "x", - // Mixed leading/trailing characters - "x*x", - "x****************x", - "x" + GLOB.repeat(1000000) + "x" - )) { - assertNotGlobMatch(pattern, ""); - } - } + // Leading characters + "x*", + "x*****************", + "x" + GLOB.repeat(1000000), - @Test - public void testPatternWithoutGlobs() { - assertGlobMatch("test", "test"); + // Mixed leading/trailing characters + "x*x", + "x****************x", + "x" + GLOB.repeat(1000000) + "x")) { + assertNotGlobMatch(pattern, ""); } + } - @Test - public void testGlobs() { - for (String pattern : List.of( - "*test", // Leading glob - "this*", // Trailing glob - "this*test", // Middle glob - "*is *", // String in between two globs - "*is*a*", // Lots of globs - "**test**", // Double glob characters - "**is**a***test*", // Varying number of globs - "* *", // White space between globs - "*", // Lone glob - "**********", // Nothing but globs - "*Ѿ*", // Unicode with globs - "*is a ϗѾ *" // Mixed ASCII/unicode - )) { - assertGlobMatch(pattern, "this is a ϗѾ test"); - } + @Test + public void testPatternWithoutGlobs() { + assertGlobMatch("test", "test"); + } - for (String pattern : List.of( - "test*", // Implicit substring match - "*is", // Partial match - "*no*", // Globs without a match between them - " ", // Plain white space - "* ", // Trailing white space - " *", // Leading white space - "*ʤ*", // Non-matching unicode - "this*this is a test" // Repeated prefix - )) { - assertNotGlobMatch(pattern, "this is a test"); - } + @Test + public void testGlobs() { + for (String pattern : + List.of( + "*test", // Leading glob + "this*", // Trailing glob + "this*test", // Middle glob + "*is *", // String in between two globs + "*is*a*", // Lots of globs + "**test**", // Double glob characters + "**is**a***test*", // Varying number of globs + "* *", // White space between globs + "*", // Lone glob + "**********", // Nothing but globs + "*Ѿ*", // Unicode with globs + "*is a ϗѾ *" // Mixed ASCII/unicode + )) { + assertGlobMatch(pattern, "this is a ϗѾ test"); } - public void assertGlobMatch(String pattern, String subject) { - assertTrue(Glob.match(pattern, subject), String.format("\"%s\" should match \"%s\"", pattern, subject)); + for (String pattern : + List.of( + "test*", // Implicit substring match + "*is", // Partial match + "*no*", // Globs without a match between them + " ", // Plain white space + "* ", // Trailing white space + " *", // Leading white space + "*ʤ*", // Non-matching unicode + "this*this is a test" // Repeated prefix + )) { + assertNotGlobMatch(pattern, "this is a test"); } + } - public void assertNotGlobMatch(String pattern, String subject) { - assertFalse(Glob.match(pattern, subject), String.format("\"%s\" should not match \"%s\"", pattern, subject)); - } + public void assertGlobMatch(String pattern, String subject) { + assertTrue( + Glob.match(pattern, subject), + String.format("\"%s\" should match \"%s\"", pattern, subject)); + } -} \ No newline at end of file + public void assertNotGlobMatch(String pattern, String subject) { + assertFalse( + Glob.match(pattern, subject), + String.format("\"%s\" should not match \"%s\"", pattern, subject)); + } +} diff --git a/lib/src/test/java/io/cloudquery/helper/ArrowHelperTest.java b/lib/src/test/java/io/cloudquery/helper/ArrowHelperTest.java new file mode 100644 index 00000000..9c0d87e1 --- /dev/null +++ b/lib/src/test/java/io/cloudquery/helper/ArrowHelperTest.java @@ -0,0 +1,280 @@ +package io.cloudquery.helper; + +import static io.cloudquery.helper.ArrowHelper.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.protobuf.ByteString; +import io.cloudquery.schema.Column; +import io.cloudquery.schema.Resource; +import io.cloudquery.schema.Table; +import io.cloudquery.types.Extensions; +import io.cloudquery.types.JSONType; +import io.cloudquery.types.UUIDType; +import java.io.IOException; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.apache.arrow.vector.types.DateUnit; +import org.apache.arrow.vector.types.TimeUnit; +import org.apache.arrow.vector.types.Types; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.apache.arrow.vector.types.pojo.Field; +import org.apache.arrow.vector.types.pojo.Schema; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ArrowHelperTest { + + public static final Table TEST_TABLE = + Table.builder() + .name("table1") + .description("A simple test table") + .title("Test table title") + .parent(Table.builder().name("parent").build()) + .columns( + List.of( + Column.builder() + .name("pk") + .type(ArrowType.Utf8.INSTANCE) + .unique(true) + .incrementalKey(true) + .primaryKey(true) + .build(), + Column.builder().name("big_int").type(Types.MinorType.BIGINT.getType()).build(), + Column.builder().name("bit").type(Types.MinorType.BIT.getType()).build(), + Column.builder().name("date_day").type(Types.MinorType.DATEDAY.getType()).build(), + Column.builder() + .name("date_milli") + .type(Types.MinorType.DATEMILLI.getType()) + .build(), + Column.builder() + .name("duration_s") + .type(new ArrowType.Duration(TimeUnit.SECOND)) + .build(), + Column.builder() + .name("duration_ms") + .type(new ArrowType.Duration(TimeUnit.MILLISECOND)) + .build(), + Column.builder() + .name("duration_us") + .type(new ArrowType.Duration(TimeUnit.MICROSECOND)) + .build(), + Column.builder() + .name("duration_ns") + .type(new ArrowType.Duration(TimeUnit.NANOSECOND)) + .build(), + Column.builder().name("float4").type(Types.MinorType.FLOAT4.getType()).build(), + Column.builder().name("float8").type(Types.MinorType.FLOAT8.getType()).build(), + Column.builder().name("int").type(Types.MinorType.INT.getType()).build(), + Column.builder() + .name("large_varbinary") + .type(Types.MinorType.LARGEVARBINARY.getType()) + .build(), + Column.builder() + .name("large_varchar") + .type(Types.MinorType.LARGEVARCHAR.getType()) + .build(), + Column.builder() + .name("small_int") + .type(Types.MinorType.SMALLINT.getType()) + .build(), + Column.builder() + .name("timestamp_s") + .type(Types.MinorType.TIMESTAMPSEC.getType()) + .build(), + Column.builder() + .name("timestamp_ms") + .type(Types.MinorType.TIMESTAMPMILLI.getType()) + .build(), + Column.builder() + .name("timestamp_us") + .type(Types.MinorType.TIMESTAMPMICRO.getType()) + .build(), + Column.builder() + .name("timestamp_ns") + .type(Types.MinorType.TIMESTAMPNANO.getType()) + .build(), + Column.builder() + .name("timestamp_s_tz") + .type(new ArrowType.Timestamp(TimeUnit.SECOND, ZoneOffset.UTC.getId())) + .build(), + Column.builder() + .name("timestamp_ms_tz") + .type(new ArrowType.Timestamp(TimeUnit.MILLISECOND, ZoneOffset.UTC.getId())) + .build(), + Column.builder() + .name("timestamp_us_tz") + .type(new ArrowType.Timestamp(TimeUnit.MICROSECOND, ZoneOffset.UTC.getId())) + .build(), + Column.builder() + .name("timestamp_ns_tz") + .type(new ArrowType.Timestamp(TimeUnit.NANOSECOND, ZoneOffset.UTC.getId())) + .build(), + Column.builder().name("tiny_int").type(Types.MinorType.TINYINT.getType()).build(), + Column.builder().name("uint1").type(Types.MinorType.UINT1.getType()).build(), + Column.builder().name("uint2").type(Types.MinorType.UINT2.getType()).build(), + Column.builder().name("uint4").type(Types.MinorType.UINT4.getType()).build(), + Column.builder().name("uint8").type(Types.MinorType.UINT8.getType()).build(), + Column.builder() + .name("varbinary") + .type(Types.MinorType.VARBINARY.getType()) + .build(), + Column.builder().name("varchar").type(Types.MinorType.VARCHAR.getType()).build(), + Column.builder().name("json").type(JSONType.INSTANCE).build(), + Column.builder().name("uuid").type(UUIDType.INSTANCE).build())) + .build(); + + @Test + public void testToArrowSchema() { + Extensions.registerExtensions(); + + Schema arrowSchema = ArrowHelper.toArrowSchema(TEST_TABLE); + + for (Column col : TEST_TABLE.getColumns()) { + int idx = TEST_TABLE.indexOfColumn(col.getName()); + Field field = arrowSchema.getFields().get(idx); + assertEquals(col.getName(), field.getName()); + if (idx == 0) { + assertEquals( + Map.of( + CQ_EXTENSION_UNIQUE, + "true", + CQ_EXTENSION_INCREMENTAL, + "true", + CQ_EXTENSION_PRIMARY_KEY, + "true"), + field.getMetadata()); + } else if (col.getName().equals("json")) { + assertEquals( + Map.of( + CQ_EXTENSION_UNIQUE, + "false", + CQ_EXTENSION_INCREMENTAL, + "false", + CQ_EXTENSION_PRIMARY_KEY, + "false", + ArrowType.ExtensionType.EXTENSION_METADATA_KEY_NAME, + "json", + ArrowType.ExtensionType.EXTENSION_METADATA_KEY_METADATA, + "json-serialized"), + field.getMetadata()); + } else if (col.getName().equals("uuid")) { + assertEquals( + Map.of( + CQ_EXTENSION_UNIQUE, + "false", + CQ_EXTENSION_INCREMENTAL, + "false", + CQ_EXTENSION_PRIMARY_KEY, + "false", + ArrowType.ExtensionType.EXTENSION_METADATA_KEY_NAME, + "uuid", + ArrowType.ExtensionType.EXTENSION_METADATA_KEY_METADATA, + "uuid-serialized"), + field.getMetadata()); + } else { + assertEquals( + Map.of( + CQ_EXTENSION_UNIQUE, + "false", + CQ_EXTENSION_INCREMENTAL, + "false", + CQ_EXTENSION_PRIMARY_KEY, + "false"), + field.getMetadata()); + } + } + + assertEquals( + arrowSchema.getCustomMetadata(), + Map.of( + CQ_TABLE_NAME, "table1", + CQ_TABLE_DESCRIPTION, "A simple test table", + CQ_TABLE_TITLE, "Test table title", + CQ_TABLE_DEPENDS_ON, "parent", + CQ_EXTENSION_CONSTRAINT_NAME, "")); + } + + @Test + public void testFromArrowSchema() { + Extensions.registerExtensions(); + + List fields = + List.of( + Field.nullable("string_column1", ArrowType.Utf8.INSTANCE), + Field.nullable("string_column2", ArrowType.Utf8.INSTANCE), + Field.nullable("date_days_column", new ArrowType.Date(DateUnit.DAY))); + + Schema schema = new Schema(fields, Map.of(CQ_TABLE_NAME, "table1")); + + Table table = ArrowHelper.fromArrowSchema(schema); + + assertEquals(table.getName(), "table1"); + + for (int i = 0; i < table.getColumns().size(); i++) { + Column column = table.getColumns().get(i); + assertEquals(column.getName(), fields.get(i).getName()); + assertEquals(column.getType(), fields.get(i).getType()); + } + } + + @Test + public void testRoundTripTableEncoding() throws IOException { + Extensions.registerExtensions(); + + ByteString byteString = ArrowHelper.encode(TEST_TABLE); + Table table = ArrowHelper.decode(byteString); + + assertEquals(table.getName(), TEST_TABLE.getName()); + assertEquals(table.getDescription(), TEST_TABLE.getDescription()); + assertEquals(table.getTitle(), TEST_TABLE.getTitle()); + assertEquals(table.getParent().getName(), TEST_TABLE.getParent().getName()); + assertEquals(TEST_TABLE.getColumns().size(), table.getColumns().size()); + + for (int i = 0; i < TEST_TABLE.getColumns().size(); i++) { + Column srcCol = TEST_TABLE.getColumns().get(i); + Column dstCol = table.getColumns().get(i); + assertEquals(srcCol.getName(), dstCol.getName()); + assertEquals(srcCol.getType(), dstCol.getType()); + } + } + + @Test + public void testRoundTripResourceEncoding() throws Exception { + Extensions.registerExtensions(); + + Resource resource = Resource.builder().table(TEST_TABLE).build(); + resource.set("pk", "test_pk"); + resource.set("big_int", -1024L); + resource.set("date_day", (int) LocalDateTime.now().toLocalDate().toEpochDay()); + resource.set("date_milli", LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) * 1000); + resource.set("duration_s", Duration.ofSeconds(1024)); + resource.set("duration_ms", Duration.ofMillis(1024)); + resource.set("duration_us", Duration.ofNanos(1024000)); + resource.set("duration_ns", Duration.ofNanos(1024)); + resource.set("float4", 5.0F); + resource.set("float8", 5.0D); + resource.set("int", -1024); + resource.set("large_varbinary", "1234"); + resource.set("large_varchar", "1234"); + resource.set("small_int", (short) -1024); + resource.set("tiny_int", (byte) -100); + resource.set("uint1", (byte) 100); + resource.set("uint2", (short) 1024); + resource.set("uint4", 1024); + resource.set("uint8", 1024L); + resource.set("varbinary", "1234"); + resource.set("varchar", "1234"); + resource.set("json", "{\"a\":1234}"); + resource.set("uuid", UUID.randomUUID()); + + Assertions.assertDoesNotThrow( + () -> { + ByteString byteString = ArrowHelper.encode(resource); + ArrowHelper.decodeResource(byteString); + }); + } +} diff --git a/lib/src/test/java/io/cloudquery/helper/ReflectionPathResolverTest.java b/lib/src/test/java/io/cloudquery/helper/ReflectionPathResolverTest.java index 9c41208c..f25e4ddc 100644 --- a/lib/src/test/java/io/cloudquery/helper/ReflectionPathResolverTest.java +++ b/lib/src/test/java/io/cloudquery/helper/ReflectionPathResolverTest.java @@ -1,49 +1,49 @@ package io.cloudquery.helper; -import lombok.Builder; -import org.junit.jupiter.api.Test; - -import java.util.List; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.util.List; +import lombok.Builder; +import org.junit.jupiter.api.Test; + class ReflectionPathResolverTest { - @Builder - private static class TestClass { - private String name; - - @Builder.Default - private List numbers = List.of(1, 2, 3); - - private TestClass singleChild; - - private List multipleChildren; - } - - private static final TestClass TEST_DATA = TestClass.builder().name("root"). - singleChild(TestClass.builder().name("single-child1").build()). - multipleChildren( - List.of( - TestClass.builder().name("multi-child1").build(), - TestClass.builder().name("multi-child2").build() - ) - ). - build(); - - @Test - public void shouldResolveSimpleFields() throws ReflectionPathResolver.PathResolverException { - assertEquals("root", ReflectionPathResolver.resolve(TEST_DATA, "name")); - assertEquals(List.of(1, 2, 3), ReflectionPathResolver.resolve(TEST_DATA, "numbers")); - } - - @Test - public void shouldResolveNestedField() throws ReflectionPathResolver.PathResolverException { - assertEquals("single-child1", ReflectionPathResolver.resolve(TEST_DATA, "singleChild.name")); - } - - @Test - public void shouldThrowAnErrorIfWeEncounterACollection() { - assertThrows(ReflectionPathResolver.PathResolverException.class, () -> ReflectionPathResolver.resolve(TEST_DATA, "multiplChildren.name")); - } + @Builder + private static class TestClass { + private String name; + + @Builder.Default private List numbers = List.of(1, 2, 3); + + private TestClass singleChild; + + private List multipleChildren; + } + + private static final TestClass TEST_DATA = + TestClass.builder() + .name("root") + .singleChild(TestClass.builder().name("single-child1").build()) + .multipleChildren( + List.of( + TestClass.builder().name("multi-child1").build(), + TestClass.builder().name("multi-child2").build())) + .build(); + + @Test + public void shouldResolveSimpleFields() throws ReflectionPathResolver.PathResolverException { + assertEquals("root", ReflectionPathResolver.resolve(TEST_DATA, "name")); + assertEquals(List.of(1, 2, 3), ReflectionPathResolver.resolve(TEST_DATA, "numbers")); + } + + @Test + public void shouldResolveNestedField() throws ReflectionPathResolver.PathResolverException { + assertEquals("single-child1", ReflectionPathResolver.resolve(TEST_DATA, "singleChild.name")); + } + + @Test + public void shouldThrowAnErrorIfWeEncounterACollection() { + assertThrows( + ReflectionPathResolver.PathResolverException.class, + () -> ReflectionPathResolver.resolve(TEST_DATA, "multiplChildren.name")); + } } diff --git a/lib/src/test/java/io/cloudquery/internal/servers/plugin/v3/PluginServerTest.java b/lib/src/test/java/io/cloudquery/internal/servers/plugin/v3/PluginServerTest.java new file mode 100644 index 00000000..e1e4d66f --- /dev/null +++ b/lib/src/test/java/io/cloudquery/internal/servers/plugin/v3/PluginServerTest.java @@ -0,0 +1,175 @@ +package io.cloudquery.internal.servers.plugin.v3; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; + +import com.google.protobuf.ByteString; +import io.cloudquery.helper.ArrowHelper; +import io.cloudquery.messages.WriteDeleteStale; +import io.cloudquery.messages.WriteInsert; +import io.cloudquery.messages.WriteMigrateTable; +import io.cloudquery.plugin.Plugin; +import io.cloudquery.plugin.v3.GetSpecSchema; +import io.cloudquery.plugin.v3.PluginGrpc; +import io.cloudquery.plugin.v3.PluginGrpc.PluginStub; +import io.cloudquery.plugin.v3.Write; +import io.cloudquery.plugin.v3.Write.MessageInsert; +import io.cloudquery.scalar.ValidationException; +import io.cloudquery.schema.Column; +import io.cloudquery.schema.Resource; +import io.cloudquery.schema.Table; +import io.grpc.Server; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; +import io.grpc.stub.StreamObserver; +import io.grpc.testing.GrpcCleanupRule; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import lombok.Getter; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.Rule; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class PluginServerTest { + + @Mock private Plugin plugin; + + @Rule public final GrpcCleanupRule grpcCleanupRule = new GrpcCleanupRule(); + + private PluginStub pluginStub; + + @BeforeEach + public void setUp() throws IOException { + PluginServer pluginServer = new PluginServer(plugin); + + String generatedName = InProcessServerBuilder.generateName(); + Server server = InProcessServerBuilder.forName(generatedName).addService(pluginServer).build(); + server.start(); + + InProcessChannelBuilder inProcessChannelBuilder = + InProcessChannelBuilder.forName(generatedName).directExecutor(); + pluginStub = PluginGrpc.newStub(grpcCleanupRule.register(inProcessChannelBuilder.build())); + } + + @Test + public void shouldSendWriteMigrateTableMessage() throws Exception { + NullResponseStream responseObserver = new NullResponseStream<>(); + + StreamObserver writeService = pluginStub.write(responseObserver); + writeService.onNext(generateMigrateTableMessage()); + writeService.onCompleted(); + responseObserver.await(); + + verify(plugin).write(any(WriteMigrateTable.class)); + } + + @Test + public void shouldSendWriteInsertMessage() throws Exception { + NullResponseStream responseObserver = new NullResponseStream<>(); + + StreamObserver writeService = pluginStub.write(responseObserver); + writeService.onNext(generateInsertMessage()); + writeService.onCompleted(); + responseObserver.await(); + + verify(plugin).write(any(WriteInsert.class)); + } + + @Test + public void shouldSendWriteDeleteStaleMessage() throws Exception { + NullResponseStream responseObserver = new NullResponseStream<>(); + + StreamObserver writeService = pluginStub.write(responseObserver); + writeService.onNext(generateDeleteStaleMessage()); + writeService.onCompleted(); + responseObserver.await(); + + verify(plugin).write(any(WriteDeleteStale.class)); + } + + @Test + public void shouldSendNullJSONSchema() throws Exception { + NullResponseStream responseObserver = new NullResponseStream<>(); + + pluginStub.getSpecSchema(GetSpecSchema.Request.getDefaultInstance(), responseObserver); + responseObserver.await(); + + verify(plugin).getJsonSchema(); + assertFalse(responseObserver.getValue().hasJsonSchema()); + } + + @Test + public void shouldSendNonNullJSONSchema() throws Exception { + Mockito.doReturn("{}").when(plugin).getJsonSchema(); + + NullResponseStream responseObserver = new NullResponseStream<>(); + + pluginStub.getSpecSchema(GetSpecSchema.Request.getDefaultInstance(), responseObserver); + responseObserver.await(); + + verify(plugin).getJsonSchema(); + assertTrue(responseObserver.getValue().hasJsonSchema()); + assertEquals("{}", responseObserver.getValue().getJsonSchema()); + } + + private static Write.Request generateMigrateTableMessage() throws IOException { + Table table = Table.builder().name("test").build(); + return Write.Request.newBuilder() + .setMigrateTable( + Write.MessageMigrateTable.newBuilder().setTable(ArrowHelper.encode(table)).build()) + .build(); + } + + private Write.Request generateInsertMessage() throws IOException, ValidationException { + Column stringColumn = + Column.builder().name("test_column").type(ArrowType.Utf8.INSTANCE).build(); + Column booleanColumn = + Column.builder().name("boolean_column").type(ArrowType.Bool.INSTANCE).build(); + Table table = + Table.builder().name("test").columns(List.of(stringColumn, booleanColumn)).build(); + Resource resource = Resource.builder().table(table).build(); + resource.set("test_column", "test_data"); + resource.set("boolean_column", true); + ByteString byteString = ArrowHelper.encode(resource); + MessageInsert messageInsert = MessageInsert.newBuilder().setRecord(byteString).build(); + return Write.Request.newBuilder().setInsert(messageInsert).build(); + } + + private Write.Request generateDeleteStaleMessage() { + Write.MessageDeleteStale messageDeleteStale = Write.MessageDeleteStale.newBuilder().build(); + return Write.Request.newBuilder().setDelete(messageDeleteStale).build(); + } + + private static class NullResponseStream implements StreamObserver { + private final CountDownLatch countDownLatch = new CountDownLatch(1); + @Getter private T value; + @Getter private Throwable error; + + @Override + public void onNext(T value) { + this.value = value; + } + + @Override + public void onError(Throwable t) { + this.error = t; + } + + @Override + public void onCompleted() { + countDownLatch.countDown(); + } + + public void await() throws InterruptedException { + countDownLatch.await(); + } + } +} diff --git a/lib/src/test/java/io/cloudquery/scalar/BinaryTest.java b/lib/src/test/java/io/cloudquery/scalar/BinaryTest.java index 485fdc2e..33e73145 100644 --- a/lib/src/test/java/io/cloudquery/scalar/BinaryTest.java +++ b/lib/src/test/java/io/cloudquery/scalar/BinaryTest.java @@ -1,151 +1,174 @@ package io.cloudquery.scalar; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.*; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Test; public class BinaryTest { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Binary(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Binary(); }); - } - - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Binary(new byte[]{'a', 'b', 'c'}); - new Binary("abc"); - new Binary(new char[]{'a', 'b', 'c'}); - - Scalar s = new Binary(new char[]{'a', 'b', 'c'}); - new Binary(s); + } + + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Binary(new byte[] {'a', 'b', 'c'}); + new Binary("abc"); + new Binary(new char[] {'a', 'b', 'c'}); + + Scalar s = new Binary(new char[] {'a', 'b', 'c'}); + new Binary(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Binary(false); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Binary(false); }); - } + } - @Test - public void testToString() { - Binary b = new Binary(); - assertEquals(Scalar.NULL_VALUE_STRING, b.toString()); + @Test + public void testToString() { + Binary b = new Binary(); + assertEquals(Scalar.NULL_VALUE_STRING, b.toString()); - assertDoesNotThrow(() -> { - b.set("abc"); + assertDoesNotThrow( + () -> { + b.set("abc"); }); - assertEquals("abc=", b.toString()); + assertEquals("abc=", b.toString()); - assertDoesNotThrow(() -> { - b.set(new byte[]{0, 1, 2, 3, 4, 5}); + assertDoesNotThrow( + () -> { + b.set(new byte[] {0, 1, 2, 3, 4, 5}); }); - assertEquals("AAECAwQF", b.toString()); - } - - @Test - public void testDataType() { - Binary b = new Binary(); - assertEquals(ArrowType.Binary.INSTANCE, b.dataType()); - assertEquals(new ArrowType.Binary(), b.dataType()); - } - - @Test - public void testIsValid() { - Binary b = new Binary(); - assertFalse(b.isValid()); - - assertDoesNotThrow(() -> { - b.set("abc"); + assertEquals("AAECAwQF", b.toString()); + } + + @Test + public void testDataType() { + Binary b = new Binary(); + assertEquals(ArrowType.Binary.INSTANCE, b.dataType()); + assertEquals(new ArrowType.Binary(), b.dataType()); + } + + @Test + public void testIsValid() { + Binary b = new Binary(); + assertFalse(b.isValid()); + + assertDoesNotThrow( + () -> { + b.set("abc"); }); - assertTrue(b.isValid()); - } - - @Test - public void testSet() { - Binary b = new Binary(); - assertDoesNotThrow(() -> { - b.set(new byte[]{'a', 'b', 'c'}); - b.set("abc"); - b.set(new char[]{'a', 'b', 'c'}); - - Scalar s = new Binary(new char[]{'a', 'b', 'c'}); - b.set(s); + assertTrue(b.isValid()); + } + + @Test + public void testSet() { + Binary b = new Binary(); + assertDoesNotThrow( + () -> { + b.set(new byte[] {'a', 'b', 'c'}); + b.set("abc"); + b.set(new char[] {'a', 'b', 'c'}); + + Scalar s = new Binary(new char[] {'a', 'b', 'c'}); + b.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Binary b = new Binary(); - assertThrows(ValidationException.class, () -> { - b.set(false); + } + + @Test + public void testSetWithInvalidParam() { + Binary b = new Binary(); + assertThrows( + ValidationException.class, + () -> { + b.set(false); }); - } + } - @Test - public void testGet() { - Binary b = new Binary(); - assertFalse(b.isValid()); - assertNull(b.get()); + @Test + public void testGet() { + Binary b = new Binary(); + assertFalse(b.isValid()); + assertNull(b.get()); - assertDoesNotThrow(() -> { - b.set(new byte[]{'a', 'b', 'c'}); + assertDoesNotThrow( + () -> { + b.set(new byte[] {'a', 'b', 'c'}); }); - assertTrue(b.isValid()); - assertArrayEquals(new byte[]{'a', 'b', 'c'}, (byte[]) b.get()); + assertTrue(b.isValid()); + assertArrayEquals(new byte[] {'a', 'b', 'c'}, (byte[]) b.get()); - assertDoesNotThrow(() -> { - b.set("abc"); + assertDoesNotThrow( + () -> { + b.set("abc"); }); - assertTrue(b.isValid()); - assertArrayEquals(new byte[]{105, -73}, (byte[]) b.get()); + assertTrue(b.isValid()); + assertArrayEquals(new byte[] {105, -73}, (byte[]) b.get()); - assertDoesNotThrow(() -> { - b.set(new char[]{'a', 'b', 'c'}); + assertDoesNotThrow( + () -> { + b.set(new char[] {'a', 'b', 'c'}); }); - assertTrue(b.isValid()); - assertArrayEquals(new byte[]{105, -73}, (byte[]) b.get()); + assertTrue(b.isValid()); + assertArrayEquals(new byte[] {105, -73}, (byte[]) b.get()); - assertDoesNotThrow(() -> { - Scalar s = new Binary(new char[]{'a', 'b', 'c'}); - b.set(s); + assertDoesNotThrow( + () -> { + Scalar s = new Binary(new char[] {'a', 'b', 'c'}); + b.set(s); }); - assertTrue(b.isValid()); - assertArrayEquals(new byte[]{105, -73}, (byte[]) b.get()); + assertTrue(b.isValid()); + assertArrayEquals(new byte[] {105, -73}, (byte[]) b.get()); - assertDoesNotThrow(() -> { - Scalar s = new Binary(new byte[]{'a', 'b', 'c'}); - b.set(s); + assertDoesNotThrow( + () -> { + Scalar s = new Binary(new byte[] {'a', 'b', 'c'}); + b.set(s); }); - assertTrue(b.isValid()); - assertArrayEquals(new byte[]{'a', 'b', 'c'}, (byte[]) b.get()); - } - - @Test - public void testEquals() { - Binary a = new Binary(); - Binary b = new Binary(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Bool()); // we can't cast Bool to Binary - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(new byte[]{'a', 'b', 'c'}); + assertTrue(b.isValid()); + assertArrayEquals(new byte[] {'a', 'b', 'c'}, (byte[]) b.get()); + } + + @Test + public void testEquals() { + Binary a = new Binary(); + Binary b = new Binary(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Bool()); // we can't cast Bool to Binary + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(new byte[] {'a', 'b', 'c'}); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, new byte[]{'a', 'b', 'c'}, new char[]{'a', 'b', 'c'}, "abc", new Binary("abc"),}) { - a.set(obj); - assertEquals(a, new Binary(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : + new Object[] { + null, + new byte[] {'a', 'b', 'c'}, + new char[] {'a', 'b', 'c'}, + "abc", + new Binary("abc"), + }) { + a.set(obj); + assertEquals(a, new Binary(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/BoolTest.java b/lib/src/test/java/io/cloudquery/scalar/BoolTest.java index 9a8abe7c..330d64cc 100644 --- a/lib/src/test/java/io/cloudquery/scalar/BoolTest.java +++ b/lib/src/test/java/io/cloudquery/scalar/BoolTest.java @@ -1,129 +1,142 @@ package io.cloudquery.scalar; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.*; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Test; public class BoolTest { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Bool(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Bool(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Bool(true); - new Bool("true"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Bool(true); + new Bool("true"); - Scalar s = new Bool(true); - new Bool(s); + Scalar s = new Bool(true); + new Bool(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Bool(new char[]{'1'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Bool(new char[] {'1'}); }); - } + } - @Test - public void testToString() { - Bool b = new Bool(); - assertEquals(Scalar.NULL_VALUE_STRING, b.toString()); + @Test + public void testToString() { + Bool b = new Bool(); + assertEquals(Scalar.NULL_VALUE_STRING, b.toString()); - assertDoesNotThrow(() -> { - b.set(true); + assertDoesNotThrow( + () -> { + b.set(true); }); - assertEquals("true", b.toString()); + assertEquals("true", b.toString()); - assertDoesNotThrow(() -> { - b.set(false); + assertDoesNotThrow( + () -> { + b.set(false); }); - assertEquals("false", b.toString()); - } - - @Test - public void testDataType() { - Bool b = new Bool(); - assertEquals(ArrowType.Bool.INSTANCE, b.dataType()); - assertEquals(new ArrowType.Bool(), b.dataType()); - } - - @Test - public void testIsValid() { - Bool b = new Bool(); - assertFalse(b.isValid()); - - assertDoesNotThrow(() -> { - b.set("true"); + assertEquals("false", b.toString()); + } + + @Test + public void testDataType() { + Bool b = new Bool(); + assertEquals(ArrowType.Bool.INSTANCE, b.dataType()); + assertEquals(new ArrowType.Bool(), b.dataType()); + } + + @Test + public void testIsValid() { + Bool b = new Bool(); + assertFalse(b.isValid()); + + assertDoesNotThrow( + () -> { + b.set("true"); }); - assertTrue(b.isValid()); - } - - @Test - public void testSet() { - Bool b = new Bool(); - assertDoesNotThrow(() -> { - new Bool(true); - new Bool("true"); - - Scalar s = new Bool(true); - b.set(s); + assertTrue(b.isValid()); + } + + @Test + public void testSet() { + Bool b = new Bool(); + assertDoesNotThrow( + () -> { + new Bool(true); + new Bool("true"); + + Scalar s = new Bool(true); + b.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Bool b = new Bool(); - assertThrows(ValidationException.class, () -> { - b.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + Bool b = new Bool(); + assertThrows( + ValidationException.class, + () -> { + b.set(new char[] {}); }); - } + } - @Test - public void testGet() { - Bool b = new Bool(); - assertFalse(b.isValid()); - assertNull(b.get()); + @Test + public void testGet() { + Bool b = new Bool(); + assertFalse(b.isValid()); + assertNull(b.get()); - assertDoesNotThrow(() -> { - b.set(true); + assertDoesNotThrow( + () -> { + b.set(true); }); - assertTrue(b.isValid()); - assertEquals(true, b.get()); + assertTrue(b.isValid()); + assertEquals(true, b.get()); - assertDoesNotThrow(() -> { - b.set("abc"); + assertDoesNotThrow( + () -> { + b.set("abc"); }); - assertTrue(b.isValid()); - assertEquals(false, b.get()); - } - - @Test - public void testEquals() { - Bool a = new Bool(); - Bool b = new Bool(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to Bool - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(true); + assertTrue(b.isValid()); + assertEquals(false, b.get()); + } + + @Test + public void testEquals() { + Bool a = new Bool(); + Bool b = new Bool(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to Bool + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(true); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, true, false, "abc", "true", "false"}) { - a.set(obj); - assertEquals(a, new Bool(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, true, false, "abc", "true", "false"}) { + a.set(obj); + assertEquals(a, new Bool(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/DateDayTest.java b/lib/src/test/java/io/cloudquery/scalar/DateDayTest.java index d361b6c3..39f3ce7d 100644 --- a/lib/src/test/java/io/cloudquery/scalar/DateDayTest.java +++ b/lib/src/test/java/io/cloudquery/scalar/DateDayTest.java @@ -1,129 +1,142 @@ package io.cloudquery.scalar; +import static org.junit.jupiter.api.Assertions.*; + import org.apache.arrow.vector.types.DateUnit; import org.apache.arrow.vector.types.pojo.ArrowType; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - - public class DateDayTest { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new DateDay(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new DateDay(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new DateDay(1); - new DateDay("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new DateDay(1); + new DateDay("1"); - Scalar s = new DateDay(2); - new DateDay(s); + Scalar s = new DateDay(2); + new DateDay(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new DateDay(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new DateDay(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - DateDay dateDay = new DateDay(); - assertEquals(Scalar.NULL_VALUE_STRING, dateDay.toString()); + @Test + public void testToString() { + DateDay dateDay = new DateDay(); + assertEquals(Scalar.NULL_VALUE_STRING, dateDay.toString()); - assertDoesNotThrow(() -> { - dateDay.set("1"); + assertDoesNotThrow( + () -> { + dateDay.set("1"); }); - assertEquals("1", dateDay.toString()); + assertEquals("1", dateDay.toString()); - assertDoesNotThrow(() -> { - dateDay.set(2); + assertDoesNotThrow( + () -> { + dateDay.set(2); }); - assertEquals("2", dateDay.toString()); - } - - @Test - public void testDataType() { - DateDay dateDay = new DateDay(); - assertEquals(new ArrowType.Date(DateUnit.DAY), dateDay.dataType()); - } - - @Test - public void testIsValid() { - DateDay dateDay = new DateDay(); - assertFalse(dateDay.isValid()); - - assertDoesNotThrow(() -> { - dateDay.set("1"); + assertEquals("2", dateDay.toString()); + } + + @Test + public void testDataType() { + DateDay dateDay = new DateDay(); + assertEquals(new ArrowType.Date(DateUnit.DAY), dateDay.dataType()); + } + + @Test + public void testIsValid() { + DateDay dateDay = new DateDay(); + assertFalse(dateDay.isValid()); + + assertDoesNotThrow( + () -> { + dateDay.set("1"); }); - assertTrue(dateDay.isValid()); - } - - @Test - public void testSet() { - DateDay dateDay = new DateDay(); - assertDoesNotThrow(() -> { - new DateDay(1); - new DateDay("2"); - - Scalar s = new DateDay(1); - dateDay.set(s); + assertTrue(dateDay.isValid()); + } + + @Test + public void testSet() { + DateDay dateDay = new DateDay(); + assertDoesNotThrow( + () -> { + new DateDay(1); + new DateDay("2"); + + Scalar s = new DateDay(1); + dateDay.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - DateDay dateDay = new DateDay(); - assertThrows(ValidationException.class, () -> { - dateDay.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + DateDay dateDay = new DateDay(); + assertThrows( + ValidationException.class, + () -> { + dateDay.set(new char[] {}); }); - } + } - @Test - public void testGet() { - DateDay dateDay = new DateDay(); - assertFalse(dateDay.isValid()); - assertNull(dateDay.get()); + @Test + public void testGet() { + DateDay dateDay = new DateDay(); + assertFalse(dateDay.isValid()); + assertNull(dateDay.get()); - assertDoesNotThrow(() -> { - dateDay.set(1); + assertDoesNotThrow( + () -> { + dateDay.set(1); }); - assertTrue(dateDay.isValid()); - assertEquals(1, dateDay.get()); + assertTrue(dateDay.isValid()); + assertEquals(1, dateDay.get()); - assertDoesNotThrow(() -> { - dateDay.set("-1"); + assertDoesNotThrow( + () -> { + dateDay.set("-1"); }); - assertTrue(dateDay.isValid()); - assertEquals(-1, dateDay.get()); - } - - @Test - public void testEquals() { - DateDay a = new DateDay(); - DateDay b = new DateDay(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to DateDay - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + assertTrue(dateDay.isValid()); + assertEquals(-1, dateDay.get()); + } + + @Test + public void testEquals() { + DateDay a = new DateDay(); + DateDay b = new DateDay(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to DateDay + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, "2"}) { - a.set(obj); - assertEquals(a, new DateDay(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, "2"}) { + a.set(obj); + assertEquals(a, new DateDay(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/DateMilliTest.java b/lib/src/test/java/io/cloudquery/scalar/DateMilliTest.java index 46fb58ed..c0bf0636 100644 --- a/lib/src/test/java/io/cloudquery/scalar/DateMilliTest.java +++ b/lib/src/test/java/io/cloudquery/scalar/DateMilliTest.java @@ -1,129 +1,142 @@ package io.cloudquery.scalar; +import static org.junit.jupiter.api.Assertions.*; + import org.apache.arrow.vector.types.DateUnit; import org.apache.arrow.vector.types.pojo.ArrowType; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - - public class DateMilliTest { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new DateMilli(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new DateMilli(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new DateMilli(1); - new DateMilli("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new DateMilli(1); + new DateMilli("1"); - Scalar s = new DateMilli(2); - new DateMilli(s); + Scalar s = new DateMilli(2); + new DateMilli(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new DateMilli(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new DateMilli(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - DateMilli dateMilli = new DateMilli(); - assertEquals(Scalar.NULL_VALUE_STRING, dateMilli.toString()); + @Test + public void testToString() { + DateMilli dateMilli = new DateMilli(); + assertEquals(Scalar.NULL_VALUE_STRING, dateMilli.toString()); - assertDoesNotThrow(() -> { - dateMilli.set("1"); + assertDoesNotThrow( + () -> { + dateMilli.set("1"); }); - assertEquals("1", dateMilli.toString()); + assertEquals("1", dateMilli.toString()); - assertDoesNotThrow(() -> { - dateMilli.set(2); + assertDoesNotThrow( + () -> { + dateMilli.set(2); }); - assertEquals("2", dateMilli.toString()); - } - - @Test - public void testDataType() { - DateMilli dateMilli = new DateMilli(); - assertEquals(new ArrowType.Date(DateUnit.MILLISECOND), dateMilli.dataType()); - } - - @Test - public void testIsValid() { - DateMilli dateMilli = new DateMilli(); - assertFalse(dateMilli.isValid()); - - assertDoesNotThrow(() -> { - dateMilli.set("1"); + assertEquals("2", dateMilli.toString()); + } + + @Test + public void testDataType() { + DateMilli dateMilli = new DateMilli(); + assertEquals(new ArrowType.Date(DateUnit.MILLISECOND), dateMilli.dataType()); + } + + @Test + public void testIsValid() { + DateMilli dateMilli = new DateMilli(); + assertFalse(dateMilli.isValid()); + + assertDoesNotThrow( + () -> { + dateMilli.set("1"); }); - assertTrue(dateMilli.isValid()); - } - - @Test - public void testSet() { - DateMilli dateMilli = new DateMilli(); - assertDoesNotThrow(() -> { - new DateMilli(1); - new DateMilli("2"); - - Scalar s = new DateMilli(1); - dateMilli.set(s); + assertTrue(dateMilli.isValid()); + } + + @Test + public void testSet() { + DateMilli dateMilli = new DateMilli(); + assertDoesNotThrow( + () -> { + new DateMilli(1); + new DateMilli("2"); + + Scalar s = new DateMilli(1); + dateMilli.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - DateMilli dateMilli = new DateMilli(); - assertThrows(ValidationException.class, () -> { - dateMilli.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + DateMilli dateMilli = new DateMilli(); + assertThrows( + ValidationException.class, + () -> { + dateMilli.set(new char[] {}); }); - } + } - @Test - public void testGet() { - DateMilli dateMilli = new DateMilli(); - assertFalse(dateMilli.isValid()); - assertNull(dateMilli.get()); + @Test + public void testGet() { + DateMilli dateMilli = new DateMilli(); + assertFalse(dateMilli.isValid()); + assertNull(dateMilli.get()); - assertDoesNotThrow(() -> { - dateMilli.set(1); + assertDoesNotThrow( + () -> { + dateMilli.set(1); }); - assertTrue(dateMilli.isValid()); - assertEquals(1L, dateMilli.get()); + assertTrue(dateMilli.isValid()); + assertEquals(1L, dateMilli.get()); - assertDoesNotThrow(() -> { - dateMilli.set("-1"); + assertDoesNotThrow( + () -> { + dateMilli.set("-1"); }); - assertTrue(dateMilli.isValid()); - assertEquals(-1L, dateMilli.get()); - } - - @Test - public void testEquals() { - DateMilli a = new DateMilli(); - DateMilli b = new DateMilli(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to DateMilli - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + assertTrue(dateMilli.isValid()); + assertEquals(-1L, dateMilli.get()); + } + + @Test + public void testEquals() { + DateMilli a = new DateMilli(); + DateMilli b = new DateMilli(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to DateMilli + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, 0, 1L, -2L, "2"}) { - a.set(obj); - assertEquals(a, new DateMilli(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, 0, 1L, -2L, "2"}) { + a.set(obj); + assertEquals(a, new DateMilli(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/DurationTest.java b/lib/src/test/java/io/cloudquery/scalar/DurationTest.java index 3965d356..6d68bade 100644 --- a/lib/src/test/java/io/cloudquery/scalar/DurationTest.java +++ b/lib/src/test/java/io/cloudquery/scalar/DurationTest.java @@ -1,133 +1,149 @@ package io.cloudquery.scalar; +import static org.junit.jupiter.api.Assertions.*; + import org.apache.arrow.vector.types.TimeUnit; import org.apache.arrow.vector.types.pojo.ArrowType; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - - public class DurationTest { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Duration(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Duration(); }); - } - - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Duration(1); - new Duration("PT8H6M12.345S"); - new Duration(java.time.Duration.ZERO); - new Duration(java.time.Duration.ofNanos(1)); - - Scalar s = new Duration(java.time.Duration.ZERO); - new Duration(s); + } + + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Duration(1); + new Duration("PT8H6M12.345S"); + new Duration(java.time.Duration.ZERO); + new Duration(java.time.Duration.ofNanos(1)); + + Scalar s = new Duration(java.time.Duration.ZERO); + new Duration(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Duration(false); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Duration(false); }); - } + } - @Test - public void testToString() { - Duration duration = new Duration(); - assertEquals(Scalar.NULL_VALUE_STRING, duration.toString()); + @Test + public void testToString() { + Duration duration = new Duration(); + assertEquals(Scalar.NULL_VALUE_STRING, duration.toString()); - assertDoesNotThrow(() -> { - duration.set(1); + assertDoesNotThrow( + () -> { + duration.set(1); }); - assertEquals("PT0.001S", duration.toString()); + assertEquals("PT0.001S", duration.toString()); - assertDoesNotThrow(() -> { - duration.set(java.time.Duration.ofDays(1L)); + assertDoesNotThrow( + () -> { + duration.set(java.time.Duration.ofDays(1L)); }); - assertEquals("PT24H", duration.toString()); - } - - @Test - public void testDataType() { - Duration duration = new Duration(); - assertEquals(new ArrowType.Duration(TimeUnit.MILLISECOND), duration.dataType()); - } - - @Test - public void testIsValid() { - Duration duration = new Duration(); - assertFalse(duration.isValid()); - - assertDoesNotThrow(() -> { - duration.set(1L); + assertEquals("PT24H", duration.toString()); + } + + @Test + public void testDataType() { + Duration duration = new Duration(); + assertEquals(new ArrowType.Duration(TimeUnit.MILLISECOND), duration.dataType()); + } + + @Test + public void testIsValid() { + Duration duration = new Duration(); + assertFalse(duration.isValid()); + + assertDoesNotThrow( + () -> { + duration.set(1L); }); - assertTrue(duration.isValid()); - } - - @Test - public void testSet() { - Duration duration = new Duration(); - assertDoesNotThrow(() -> { - duration.set(1); - duration.set(1L); - duration.set("PT8H6M12.345S"); - duration.set(java.time.Duration.ZERO); - - Scalar s = new Duration(java.time.Duration.ZERO); - duration.set(s); + assertTrue(duration.isValid()); + } + + @Test + public void testSet() { + Duration duration = new Duration(); + assertDoesNotThrow( + () -> { + duration.set(1); + duration.set(1L); + duration.set("PT8H6M12.345S"); + duration.set(java.time.Duration.ZERO); + + Scalar s = new Duration(java.time.Duration.ZERO); + duration.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Duration duration = new Duration(); - assertThrows(ValidationException.class, () -> { - duration.set(false); + } + + @Test + public void testSetWithInvalidParam() { + Duration duration = new Duration(); + assertThrows( + ValidationException.class, + () -> { + duration.set(false); }); - } + } - @Test - public void testGet() { - Duration duration = new Duration(); - assertFalse(duration.isValid()); - assertNull(duration.get()); + @Test + public void testGet() { + Duration duration = new Duration(); + assertFalse(duration.isValid()); + assertNull(duration.get()); - assertDoesNotThrow(() -> { - duration.set(-1L); + assertDoesNotThrow( + () -> { + duration.set(-1L); }); - assertTrue(duration.isValid()); - assertEquals(java.time.Duration.ofMillis(-1L), duration.get()); + assertTrue(duration.isValid()); + assertEquals(java.time.Duration.ofMillis(-1L), duration.get()); - assertDoesNotThrow(() -> { - duration.set(java.time.Duration.ZERO); + assertDoesNotThrow( + () -> { + duration.set(java.time.Duration.ZERO); }); - assertTrue(duration.isValid()); - assertEquals(java.time.Duration.ZERO, duration.get()); - } - - @Test - public void testEquals() { - Duration a = new Duration(); - Duration b = new Duration(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Bool()); // we can't cast Bool to Duration - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(-1L); + assertTrue(duration.isValid()); + assertEquals(java.time.Duration.ZERO, duration.get()); + } + + @Test + public void testEquals() { + Duration a = new Duration(); + Duration b = new Duration(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Bool()); // we can't cast Bool to Duration + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(-1L); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 0, 0L, -1, -1L, 1, 1L, "PT8H6M12.345S", java.time.Duration.ZERO}) { - a.set(obj); - assertEquals(a, new Duration(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : + new Object[] { + null, 0, 0L, -1, -1L, 1, 1L, "PT8H6M12.345S", java.time.Duration.ZERO + }) { + a.set(obj); + assertEquals(a, new Duration(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/Float32Test.java b/lib/src/test/java/io/cloudquery/scalar/Float32Test.java index be1d052b..05228e9e 100644 --- a/lib/src/test/java/io/cloudquery/scalar/Float32Test.java +++ b/lib/src/test/java/io/cloudquery/scalar/Float32Test.java @@ -1,129 +1,142 @@ package io.cloudquery.scalar; +import static org.junit.jupiter.api.Assertions.*; + import org.apache.arrow.vector.types.FloatingPointPrecision; import org.apache.arrow.vector.types.pojo.ArrowType; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - - public class Float32Test { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Number.Float32(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Number.Float32(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Number.Float32(1); - new Number.Float32("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Number.Float32(1); + new Number.Float32("1"); - Scalar s = new Number.Float32(2); - new Number.Float32(s); + Scalar s = new Number.Float32(2); + new Number.Float32(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Number.Float32(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Number.Float32(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - Number.Float32 float32 = new Number.Float32(); - assertEquals(Scalar.NULL_VALUE_STRING, float32.toString()); + @Test + public void testToString() { + Number.Float32 float32 = new Number.Float32(); + assertEquals(Scalar.NULL_VALUE_STRING, float32.toString()); - assertDoesNotThrow(() -> { - float32.set("1"); + assertDoesNotThrow( + () -> { + float32.set("1"); }); - assertEquals("1.0", float32.toString()); + assertEquals("1.0", float32.toString()); - assertDoesNotThrow(() -> { - float32.set(2); + assertDoesNotThrow( + () -> { + float32.set(2); }); - assertEquals("2.0", float32.toString()); - } - - @Test - public void testDataType() { - Number.Float32 float32 = new Number.Float32(); - assertEquals(new ArrowType.FloatingPoint(FloatingPointPrecision.SINGLE), float32.dataType()); - } - - @Test - public void testIsValid() { - Number.Float32 float32 = new Number.Float32(); - assertFalse(float32.isValid()); - - assertDoesNotThrow(() -> { - float32.set("1"); + assertEquals("2.0", float32.toString()); + } + + @Test + public void testDataType() { + Number.Float32 float32 = new Number.Float32(); + assertEquals(new ArrowType.FloatingPoint(FloatingPointPrecision.SINGLE), float32.dataType()); + } + + @Test + public void testIsValid() { + Number.Float32 float32 = new Number.Float32(); + assertFalse(float32.isValid()); + + assertDoesNotThrow( + () -> { + float32.set("1"); }); - assertTrue(float32.isValid()); - } - - @Test - public void testSet() { - Number.Float32 float32 = new Number.Float32(); - assertDoesNotThrow(() -> { - new Number.Float32(1); - new Number.Float32("2"); - - Scalar s = new Number.Float32(1); - float32.set(s); + assertTrue(float32.isValid()); + } + + @Test + public void testSet() { + Number.Float32 float32 = new Number.Float32(); + assertDoesNotThrow( + () -> { + new Number.Float32(1); + new Number.Float32("2"); + + Scalar s = new Number.Float32(1); + float32.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Number.Float32 float32 = new Number.Float32(); - assertThrows(ValidationException.class, () -> { - float32.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + Number.Float32 float32 = new Number.Float32(); + assertThrows( + ValidationException.class, + () -> { + float32.set(new char[] {}); }); - } + } - @Test - public void testGet() { - Number.Float32 float32 = new Number.Float32(); - assertFalse(float32.isValid()); - assertNull(float32.get()); + @Test + public void testGet() { + Number.Float32 float32 = new Number.Float32(); + assertFalse(float32.isValid()); + assertNull(float32.get()); - assertDoesNotThrow(() -> { - float32.set(1); + assertDoesNotThrow( + () -> { + float32.set(1); }); - assertTrue(float32.isValid()); - assertEquals(1, float32.get()); + assertTrue(float32.isValid()); + assertEquals(1, float32.get()); - assertDoesNotThrow(() -> { - float32.set("-1"); + assertDoesNotThrow( + () -> { + float32.set("-1"); }); - assertTrue(float32.isValid()); - assertEquals(-1, float32.get()); - } - - @Test - public void testEquals() { - Number.Float32 a = new Number.Float32(); - Number.Float32 b = new Number.Float32(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Float32 - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + assertTrue(float32.isValid()); + assertEquals(-1, float32.get()); + } + + @Test + public void testEquals() { + Number.Float32 a = new Number.Float32(); + Number.Float32 b = new Number.Float32(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Float32 + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, "2"}) { - a.set(obj); - assertEquals(a, new Number.Float32(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, "2"}) { + a.set(obj); + assertEquals(a, new Number.Float32(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/Float64Test.java b/lib/src/test/java/io/cloudquery/scalar/Float64Test.java index ac7ef3b1..ee2eff65 100644 --- a/lib/src/test/java/io/cloudquery/scalar/Float64Test.java +++ b/lib/src/test/java/io/cloudquery/scalar/Float64Test.java @@ -1,129 +1,142 @@ package io.cloudquery.scalar; +import static org.junit.jupiter.api.Assertions.*; + import org.apache.arrow.vector.types.FloatingPointPrecision; import org.apache.arrow.vector.types.pojo.ArrowType; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - - public class Float64Test { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Number.Float64(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Number.Float64(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Number.Float64(1); - new Number.Float64("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Number.Float64(1); + new Number.Float64("1"); - Scalar s = new Number.Float64(2); - new Number.Float64(s); + Scalar s = new Number.Float64(2); + new Number.Float64(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Number.Float64(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Number.Float64(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - Number.Float64 float64 = new Number.Float64(); - assertEquals(Scalar.NULL_VALUE_STRING, float64.toString()); + @Test + public void testToString() { + Number.Float64 float64 = new Number.Float64(); + assertEquals(Scalar.NULL_VALUE_STRING, float64.toString()); - assertDoesNotThrow(() -> { - float64.set("1"); + assertDoesNotThrow( + () -> { + float64.set("1"); }); - assertEquals("1.0", float64.toString()); + assertEquals("1.0", float64.toString()); - assertDoesNotThrow(() -> { - float64.set(2); + assertDoesNotThrow( + () -> { + float64.set(2); }); - assertEquals("2.0", float64.toString()); - } - - @Test - public void testDataType() { - Number.Float64 float64 = new Number.Float64(); - assertEquals(new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE), float64.dataType()); - } - - @Test - public void testIsValid() { - Number.Float64 float64 = new Number.Float64(); - assertFalse(float64.isValid()); - - assertDoesNotThrow(() -> { - float64.set("1"); + assertEquals("2.0", float64.toString()); + } + + @Test + public void testDataType() { + Number.Float64 float64 = new Number.Float64(); + assertEquals(new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE), float64.dataType()); + } + + @Test + public void testIsValid() { + Number.Float64 float64 = new Number.Float64(); + assertFalse(float64.isValid()); + + assertDoesNotThrow( + () -> { + float64.set("1"); }); - assertTrue(float64.isValid()); - } - - @Test - public void testSet() { - Number.Float64 float64 = new Number.Float64(); - assertDoesNotThrow(() -> { - new Number.Float64(1); - new Number.Float64("2"); - - Scalar s = new Number.Float64(1); - float64.set(s); + assertTrue(float64.isValid()); + } + + @Test + public void testSet() { + Number.Float64 float64 = new Number.Float64(); + assertDoesNotThrow( + () -> { + new Number.Float64(1); + new Number.Float64("2"); + + Scalar s = new Number.Float64(1); + float64.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Number.Float64 float64 = new Number.Float64(); - assertThrows(ValidationException.class, () -> { - float64.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + Number.Float64 float64 = new Number.Float64(); + assertThrows( + ValidationException.class, + () -> { + float64.set(new char[] {}); }); - } + } - @Test - public void testGet() { - Number.Float64 float64 = new Number.Float64(); - assertFalse(float64.isValid()); - assertNull(float64.get()); + @Test + public void testGet() { + Number.Float64 float64 = new Number.Float64(); + assertFalse(float64.isValid()); + assertNull(float64.get()); - assertDoesNotThrow(() -> { - float64.set(1); + assertDoesNotThrow( + () -> { + float64.set(1); }); - assertTrue(float64.isValid()); - assertEquals(1, float64.get()); + assertTrue(float64.isValid()); + assertEquals(1, float64.get()); - assertDoesNotThrow(() -> { - float64.set("-1"); + assertDoesNotThrow( + () -> { + float64.set("-1"); }); - assertTrue(float64.isValid()); - assertEquals(-1, float64.get()); - } - - @Test - public void testEquals() { - Number.Float64 a = new Number.Float64(); - Number.Float64 b = new Number.Float64(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Float64 - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + assertTrue(float64.isValid()); + assertEquals(-1, float64.get()); + } + + @Test + public void testEquals() { + Number.Float64 a = new Number.Float64(); + Number.Float64 b = new Number.Float64(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Float64 + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, "2"}) { - a.set(obj); - assertEquals(a, new Number.Float64(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, "2"}) { + a.set(obj); + assertEquals(a, new Number.Float64(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/Int16Test.java b/lib/src/test/java/io/cloudquery/scalar/Int16Test.java index 06a62c54..8e072998 100644 --- a/lib/src/test/java/io/cloudquery/scalar/Int16Test.java +++ b/lib/src/test/java/io/cloudquery/scalar/Int16Test.java @@ -1,128 +1,141 @@ package io.cloudquery.scalar; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.*; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Test; public class Int16Test { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Number.Int16(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Number.Int16(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Number.Int16(1); - new Number.Int16("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Number.Int16(1); + new Number.Int16("1"); - Scalar s = new Number.Int16(2); - new Number.Int16(s); + Scalar s = new Number.Int16(2); + new Number.Int16(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Number.Int16(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Number.Int16(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - Number.Int16 int16 = new Number.Int16(); - assertEquals(Scalar.NULL_VALUE_STRING, int16.toString()); + @Test + public void testToString() { + Number.Int16 int16 = new Number.Int16(); + assertEquals(Scalar.NULL_VALUE_STRING, int16.toString()); - assertDoesNotThrow(() -> { - int16.set("1"); + assertDoesNotThrow( + () -> { + int16.set("1"); }); - assertEquals("1", int16.toString()); + assertEquals("1", int16.toString()); - assertDoesNotThrow(() -> { - int16.set(2); + assertDoesNotThrow( + () -> { + int16.set(2); }); - assertEquals("2", int16.toString()); - } - - @Test - public void testDataType() { - Number.Int16 int16 = new Number.Int16(); - assertEquals(new ArrowType.Int(Short.SIZE, true), int16.dataType()); - } - - @Test - public void testIsValid() { - Number.Int16 int16 = new Number.Int16(); - assertFalse(int16.isValid()); - - assertDoesNotThrow(() -> { - int16.set("1"); + assertEquals("2", int16.toString()); + } + + @Test + public void testDataType() { + Number.Int16 int16 = new Number.Int16(); + assertEquals(new ArrowType.Int(Short.SIZE, true), int16.dataType()); + } + + @Test + public void testIsValid() { + Number.Int16 int16 = new Number.Int16(); + assertFalse(int16.isValid()); + + assertDoesNotThrow( + () -> { + int16.set("1"); }); - assertTrue(int16.isValid()); - } - - @Test - public void testSet() { - Number.Int16 int16 = new Number.Int16(); - assertDoesNotThrow(() -> { - new Number.Int16(1); - new Number.Int16("2"); - - Scalar s = new Number.Int16(1); - int16.set(s); + assertTrue(int16.isValid()); + } + + @Test + public void testSet() { + Number.Int16 int16 = new Number.Int16(); + assertDoesNotThrow( + () -> { + new Number.Int16(1); + new Number.Int16("2"); + + Scalar s = new Number.Int16(1); + int16.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Number.Int16 int16 = new Number.Int16(); - assertThrows(ValidationException.class, () -> { - int16.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + Number.Int16 int16 = new Number.Int16(); + assertThrows( + ValidationException.class, + () -> { + int16.set(new char[] {}); }); - } + } - @Test - public void testGet() { - Number.Int16 int16 = new Number.Int16(); - assertFalse(int16.isValid()); - assertNull(int16.get()); + @Test + public void testGet() { + Number.Int16 int16 = new Number.Int16(); + assertFalse(int16.isValid()); + assertNull(int16.get()); - assertDoesNotThrow(() -> { - int16.set(1); + assertDoesNotThrow( + () -> { + int16.set(1); }); - assertTrue(int16.isValid()); - assertEquals((byte) 1, int16.get()); + assertTrue(int16.isValid()); + assertEquals((byte) 1, int16.get()); - assertDoesNotThrow(() -> { - int16.set("-1"); + assertDoesNotThrow( + () -> { + int16.set("-1"); }); - assertTrue(int16.isValid()); - assertEquals((byte) -1, int16.get()); - } - - @Test - public void testEquals() { - Number.Int16 a = new Number.Int16(); - Number.Int16 b = new Number.Int16(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Int16 - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + assertTrue(int16.isValid()); + assertEquals((byte) -1, int16.get()); + } + + @Test + public void testEquals() { + Number.Int16 a = new Number.Int16(); + Number.Int16 b = new Number.Int16(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Int16 + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, "2"}) { - a.set(obj); - assertEquals(a, new Number.Int16(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, "2"}) { + a.set(obj); + assertEquals(a, new Number.Int16(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/Int32Test.java b/lib/src/test/java/io/cloudquery/scalar/Int32Test.java index eb145396..f4f6f1ce 100644 --- a/lib/src/test/java/io/cloudquery/scalar/Int32Test.java +++ b/lib/src/test/java/io/cloudquery/scalar/Int32Test.java @@ -1,128 +1,141 @@ package io.cloudquery.scalar; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.*; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Test; public class Int32Test { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Number.Int32(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Number.Int32(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Number.Int32(1); - new Number.Int32("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Number.Int32(1); + new Number.Int32("1"); - Scalar s = new Number.Int32(2); - new Number.Int32(s); + Scalar s = new Number.Int32(2); + new Number.Int32(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Number.Int32(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Number.Int32(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - Number.Int32 int32 = new Number.Int32(); - assertEquals(Scalar.NULL_VALUE_STRING, int32.toString()); + @Test + public void testToString() { + Number.Int32 int32 = new Number.Int32(); + assertEquals(Scalar.NULL_VALUE_STRING, int32.toString()); - assertDoesNotThrow(() -> { - int32.set("1"); + assertDoesNotThrow( + () -> { + int32.set("1"); }); - assertEquals("1", int32.toString()); + assertEquals("1", int32.toString()); - assertDoesNotThrow(() -> { - int32.set(2); + assertDoesNotThrow( + () -> { + int32.set(2); }); - assertEquals("2", int32.toString()); - } - - @Test - public void testDataType() { - Number.Int32 int32 = new Number.Int32(); - assertEquals(new ArrowType.Int(Integer.SIZE, true), int32.dataType()); - } - - @Test - public void testIsValid() { - Number.Int32 int32 = new Number.Int32(); - assertFalse(int32.isValid()); - - assertDoesNotThrow(() -> { - int32.set("1"); + assertEquals("2", int32.toString()); + } + + @Test + public void testDataType() { + Number.Int32 int32 = new Number.Int32(); + assertEquals(new ArrowType.Int(Integer.SIZE, true), int32.dataType()); + } + + @Test + public void testIsValid() { + Number.Int32 int32 = new Number.Int32(); + assertFalse(int32.isValid()); + + assertDoesNotThrow( + () -> { + int32.set("1"); }); - assertTrue(int32.isValid()); - } - - @Test - public void testSet() { - Number.Int32 int32 = new Number.Int32(); - assertDoesNotThrow(() -> { - new Number.Int32(1); - new Number.Int32("2"); - - Scalar s = new Number.Int32(1); - int32.set(s); + assertTrue(int32.isValid()); + } + + @Test + public void testSet() { + Number.Int32 int32 = new Number.Int32(); + assertDoesNotThrow( + () -> { + new Number.Int32(1); + new Number.Int32("2"); + + Scalar s = new Number.Int32(1); + int32.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Number.Int32 int32 = new Number.Int32(); - assertThrows(ValidationException.class, () -> { - int32.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + Number.Int32 int32 = new Number.Int32(); + assertThrows( + ValidationException.class, + () -> { + int32.set(new char[] {}); }); - } + } - @Test - public void testGet() { - Number.Int32 int32 = new Number.Int32(); - assertFalse(int32.isValid()); - assertNull(int32.get()); + @Test + public void testGet() { + Number.Int32 int32 = new Number.Int32(); + assertFalse(int32.isValid()); + assertNull(int32.get()); - assertDoesNotThrow(() -> { - int32.set(1); + assertDoesNotThrow( + () -> { + int32.set(1); }); - assertTrue(int32.isValid()); - assertEquals((byte) 1, int32.get()); + assertTrue(int32.isValid()); + assertEquals((byte) 1, int32.get()); - assertDoesNotThrow(() -> { - int32.set("-1"); + assertDoesNotThrow( + () -> { + int32.set("-1"); }); - assertTrue(int32.isValid()); - assertEquals((byte) -1, int32.get()); - } - - @Test - public void testEquals() { - Number.Int32 a = new Number.Int32(); - Number.Int32 b = new Number.Int32(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Int32 - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + assertTrue(int32.isValid()); + assertEquals((byte) -1, int32.get()); + } + + @Test + public void testEquals() { + Number.Int32 a = new Number.Int32(); + Number.Int32 b = new Number.Int32(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Int32 + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, "2"}) { - a.set(obj); - assertEquals(a, new Number.Int32(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, "2"}) { + a.set(obj); + assertEquals(a, new Number.Int32(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/Int64Test.java b/lib/src/test/java/io/cloudquery/scalar/Int64Test.java index f80b644b..86d8ac19 100644 --- a/lib/src/test/java/io/cloudquery/scalar/Int64Test.java +++ b/lib/src/test/java/io/cloudquery/scalar/Int64Test.java @@ -1,128 +1,141 @@ package io.cloudquery.scalar; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.*; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Test; public class Int64Test { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Number.Int64(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Number.Int64(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Number.Int64(1); - new Number.Int64("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Number.Int64(1); + new Number.Int64("1"); - Scalar s = new Number.Int64(2); - new Number.Int64(s); + Scalar s = new Number.Int64(2); + new Number.Int64(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Number.Int64(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Number.Int64(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - Number.Int64 int64 = new Number.Int64(); - assertEquals(Scalar.NULL_VALUE_STRING, int64.toString()); + @Test + public void testToString() { + Number.Int64 int64 = new Number.Int64(); + assertEquals(Scalar.NULL_VALUE_STRING, int64.toString()); - assertDoesNotThrow(() -> { - int64.set("1"); + assertDoesNotThrow( + () -> { + int64.set("1"); }); - assertEquals("1", int64.toString()); + assertEquals("1", int64.toString()); - assertDoesNotThrow(() -> { - int64.set(2); + assertDoesNotThrow( + () -> { + int64.set(2); }); - assertEquals("2", int64.toString()); - } - - @Test - public void testDataType() { - Number.Int64 int64 = new Number.Int64(); - assertEquals(new ArrowType.Int(Long.SIZE, true), int64.dataType()); - } - - @Test - public void testIsValid() { - Number.Int64 int64 = new Number.Int64(); - assertFalse(int64.isValid()); - - assertDoesNotThrow(() -> { - int64.set("1"); + assertEquals("2", int64.toString()); + } + + @Test + public void testDataType() { + Number.Int64 int64 = new Number.Int64(); + assertEquals(new ArrowType.Int(Long.SIZE, true), int64.dataType()); + } + + @Test + public void testIsValid() { + Number.Int64 int64 = new Number.Int64(); + assertFalse(int64.isValid()); + + assertDoesNotThrow( + () -> { + int64.set("1"); }); - assertTrue(int64.isValid()); - } - - @Test - public void testSet() { - Number.Int64 int64 = new Number.Int64(); - assertDoesNotThrow(() -> { - new Number.Int64(1); - new Number.Int64("2"); - - Scalar s = new Number.Int64(1); - int64.set(s); + assertTrue(int64.isValid()); + } + + @Test + public void testSet() { + Number.Int64 int64 = new Number.Int64(); + assertDoesNotThrow( + () -> { + new Number.Int64(1); + new Number.Int64("2"); + + Scalar s = new Number.Int64(1); + int64.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Number.Int64 int64 = new Number.Int64(); - assertThrows(ValidationException.class, () -> { - int64.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + Number.Int64 int64 = new Number.Int64(); + assertThrows( + ValidationException.class, + () -> { + int64.set(new char[] {}); }); - } + } - @Test - public void testGet() { - Number.Int64 int64 = new Number.Int64(); - assertFalse(int64.isValid()); - assertNull(int64.get()); + @Test + public void testGet() { + Number.Int64 int64 = new Number.Int64(); + assertFalse(int64.isValid()); + assertNull(int64.get()); - assertDoesNotThrow(() -> { - int64.set(1); + assertDoesNotThrow( + () -> { + int64.set(1); }); - assertTrue(int64.isValid()); - assertEquals((byte) 1, int64.get()); + assertTrue(int64.isValid()); + assertEquals((byte) 1, int64.get()); - assertDoesNotThrow(() -> { - int64.set("-1"); + assertDoesNotThrow( + () -> { + int64.set("-1"); }); - assertTrue(int64.isValid()); - assertEquals((byte) -1, int64.get()); - } - - @Test - public void testEquals() { - Number.Int64 a = new Number.Int64(); - Number.Int64 b = new Number.Int64(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Int64 - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + assertTrue(int64.isValid()); + assertEquals((byte) -1, int64.get()); + } + + @Test + public void testEquals() { + Number.Int64 a = new Number.Int64(); + Number.Int64 b = new Number.Int64(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Int64 + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, "2"}) { - a.set(obj); - assertEquals(a, new Number.Int64(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, "2"}) { + a.set(obj); + assertEquals(a, new Number.Int64(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/Int8Test.java b/lib/src/test/java/io/cloudquery/scalar/Int8Test.java index a71f4806..a06bc663 100644 --- a/lib/src/test/java/io/cloudquery/scalar/Int8Test.java +++ b/lib/src/test/java/io/cloudquery/scalar/Int8Test.java @@ -1,129 +1,141 @@ package io.cloudquery.scalar; -import org.apache.arrow.vector.types.DateUnit; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.*; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Test; public class Int8Test { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Number.Int8(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Number.Int8(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Number.Int8(1); - new Number.Int8("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Number.Int8(1); + new Number.Int8("1"); - Scalar s = new Number.Int8(2); - new Number.Int8(s); + Scalar s = new Number.Int8(2); + new Number.Int8(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Number.Int8(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Number.Int8(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - Number.Int8 int8 = new Number.Int8(); - assertEquals(Scalar.NULL_VALUE_STRING, int8.toString()); + @Test + public void testToString() { + Number.Int8 int8 = new Number.Int8(); + assertEquals(Scalar.NULL_VALUE_STRING, int8.toString()); - assertDoesNotThrow(() -> { - int8.set("1"); + assertDoesNotThrow( + () -> { + int8.set("1"); }); - assertEquals("1", int8.toString()); + assertEquals("1", int8.toString()); - assertDoesNotThrow(() -> { - int8.set(2); + assertDoesNotThrow( + () -> { + int8.set(2); }); - assertEquals("2", int8.toString()); - } - - @Test - public void testDataType() { - Number.Int8 int8 = new Number.Int8(); - assertEquals(new ArrowType.Int(Byte.SIZE, true), int8.dataType()); - } - - @Test - public void testIsValid() { - Number.Int8 int8 = new Number.Int8(); - assertFalse(int8.isValid()); - - assertDoesNotThrow(() -> { - int8.set("1"); + assertEquals("2", int8.toString()); + } + + @Test + public void testDataType() { + Number.Int8 int8 = new Number.Int8(); + assertEquals(new ArrowType.Int(Byte.SIZE, true), int8.dataType()); + } + + @Test + public void testIsValid() { + Number.Int8 int8 = new Number.Int8(); + assertFalse(int8.isValid()); + + assertDoesNotThrow( + () -> { + int8.set("1"); }); - assertTrue(int8.isValid()); - } - - @Test - public void testSet() { - Number.Int8 int8 = new Number.Int8(); - assertDoesNotThrow(() -> { - new Number.Int8(1); - new Number.Int8("2"); - - Scalar s = new Number.Int8(1); - int8.set(s); + assertTrue(int8.isValid()); + } + + @Test + public void testSet() { + Number.Int8 int8 = new Number.Int8(); + assertDoesNotThrow( + () -> { + new Number.Int8(1); + new Number.Int8("2"); + + Scalar s = new Number.Int8(1); + int8.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Number.Int8 int8 = new Number.Int8(); - assertThrows(ValidationException.class, () -> { - int8.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + Number.Int8 int8 = new Number.Int8(); + assertThrows( + ValidationException.class, + () -> { + int8.set(new char[] {}); }); - } + } - @Test - public void testGet() { - Number.Int8 int8 = new Number.Int8(); - assertFalse(int8.isValid()); - assertNull(int8.get()); + @Test + public void testGet() { + Number.Int8 int8 = new Number.Int8(); + assertFalse(int8.isValid()); + assertNull(int8.get()); - assertDoesNotThrow(() -> { - int8.set(1); + assertDoesNotThrow( + () -> { + int8.set(1); }); - assertTrue(int8.isValid()); - assertEquals((byte) 1, int8.get()); + assertTrue(int8.isValid()); + assertEquals((byte) 1, int8.get()); - assertDoesNotThrow(() -> { - int8.set("-1"); + assertDoesNotThrow( + () -> { + int8.set("-1"); }); - assertTrue(int8.isValid()); - assertEquals((byte) -1, int8.get()); - } - - @Test - public void testEquals() { - Number.Int8 a = new Number.Int8(); - Number.Int8 b = new Number.Int8(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Int8 - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + assertTrue(int8.isValid()); + assertEquals((byte) -1, int8.get()); + } + + @Test + public void testEquals() { + Number.Int8 a = new Number.Int8(); + Number.Int8 b = new Number.Int8(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to Number.Int8 + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, "2"}) { - a.set(obj); - assertEquals(a, new Number.Int8(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, "2"}) { + a.set(obj); + assertEquals(a, new Number.Int8(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/JSONTest.java b/lib/src/test/java/io/cloudquery/scalar/JSONTest.java new file mode 100644 index 00000000..14ec19f9 --- /dev/null +++ b/lib/src/test/java/io/cloudquery/scalar/JSONTest.java @@ -0,0 +1,121 @@ +package io.cloudquery.scalar; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import io.cloudquery.types.JSONType; +import java.util.Collections; +import java.util.Map; +import lombok.AllArgsConstructor; +import org.junit.jupiter.api.Test; + +public class JSONTest { + @AllArgsConstructor + public static class JsonData { + public java.lang.String name; + public int value; + } + + @Test + public void testNew() { + assertDoesNotThrow(() -> new JSON()); + } + + @Test + public void testNewWithValidParam() { + assertDoesNotThrow(() -> new JSON("{}")); + assertDoesNotThrow(() -> new JSON("{}".getBytes())); + assertDoesNotThrow(() -> new JsonData("test", 1)); + assertDoesNotThrow(() -> new JSON(new JsonData("test", 1))); + assertDoesNotThrow(() -> new JSON(new int[] {1, 2, 3})); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows(ValidationException.class, () -> new JSON("{\"name\":\"test\", incomplete")); + assertThrows( + ValidationException.class, () -> new JSON("{\"name\":\"test\", incomplete".getBytes())); + } + + @Test + public void testToString() throws ValidationException { + JSON json = new JSON("{\"name\":\"test\", \"value\":1}"); + + assertEquals("{\"name\":\"test\", \"value\":1}", json.toString()); + } + + @Test + public void testDataType() { + JSON json = new JSON(); + + assertEquals(new JSONType(), json.dataType()); + } + + @Test + public void testIsValid() throws ValidationException { + assertTrue(new JSON("{}").isValid()); + + assertTrue(new JSON("{\"name\":\"test\", \"value\":1}").isValid()); + assertTrue(new JSON(new int[] {1, 2, 3}).isValid()); + assertTrue(new JSON(Collections.emptyList()).isValid()); + assertTrue(new JSON(Map.of("foo", "bar")).isValid()); + assertTrue(new JSON(Collections.emptyMap()).isValid()); + assertTrue(new JSON(new String("{\"name\":\"test\", \"value\":1}")).isValid()); + + assertFalse(new JSON("").isValid()); + assertFalse(new JSON(null).isValid()); + assertFalse(new JSON(new byte[] {}).isValid()); + } + + @Test + public void testSet() throws ValidationException { + JSON json = new JSON(); + + json.set("{}"); + json.set(new JsonData("test", 1)); + json.set(new String("{\"name\":\"test\", \"value\":1}")); + json.set(new int[] {1, 2, 3}); + } + + @Test + public void testSetWithInvalidParam() {} + + @Test + public void testGet() throws ValidationException { + assertByteEquals("{}", new JSON("{}")); + assertByteEquals("[1,2,3]", new JSON(new int[] {1, 2, 3})); + assertByteEquals("[1,2,3]", new JSON(new int[] {1, 2, 3})); + assertByteEquals("{\"name\":\"test\",\"value\":1}", new JSON(new JsonData("test", 1))); + assertByteEquals("{\"foo\":\"bar\"}", new JSON(Map.of("foo", "bar"))); + assertByteEquals("{}", new JSON(Collections.emptyMap())); + assertByteEquals("[]", new JSON(Collections.emptyList())); + } + + @Test + public void testEquals() throws ValidationException { + JSON json1 = new JSON(); + JSON json2 = new JSON(); + + assertEquals(json1, json2); + assertNotEquals(json1, null); + assertNotEquals(json1, new Bool()); + assertNotEquals(null, json1); + + json1.set(new JsonData("test", 1)); + assertNotEquals(json1, json2); + json2.set(new JsonData("test", 1)); + assertEquals(json1, json2); + } + + private void assertByteEquals(java.lang.String expected, JSON json) throws ValidationException { + assertArrayEquals( + expected.getBytes(), + json.get(), + "expected: " + expected + ", actual: " + new java.lang.String(json.get())); + } +} diff --git a/lib/src/test/java/io/cloudquery/scalar/LargeBinaryTest.java b/lib/src/test/java/io/cloudquery/scalar/LargeBinaryTest.java index 9832228b..caebaf6d 100644 --- a/lib/src/test/java/io/cloudquery/scalar/LargeBinaryTest.java +++ b/lib/src/test/java/io/cloudquery/scalar/LargeBinaryTest.java @@ -1,157 +1,174 @@ package io.cloudquery.scalar; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.*; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Test; public class LargeBinaryTest { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Binary.LargeBinary(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Binary.LargeBinary(); }); - } - - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Binary.LargeBinary(new byte[]{'a', 'b', 'c'}); - new Binary.LargeBinary("abc"); - new Binary.LargeBinary(new char[]{'a', 'b', 'c'}); - - Scalar s = new Binary.LargeBinary(new char[]{'a', 'b', 'c'}); - new Binary.LargeBinary(s); + } + + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Binary.LargeBinary(new byte[] {'a', 'b', 'c'}); + new Binary.LargeBinary("abc"); + new Binary.LargeBinary(new char[] {'a', 'b', 'c'}); + + Scalar s = new Binary.LargeBinary(new char[] {'a', 'b', 'c'}); + new Binary.LargeBinary(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Binary.LargeBinary(false); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Binary.LargeBinary(false); }); - } + } - @Test - public void testToString() { - Binary.LargeBinary b = new Binary.LargeBinary(); - assertEquals(Scalar.NULL_VALUE_STRING, b.toString()); + @Test + public void testToString() { + Binary.LargeBinary b = new Binary.LargeBinary(); + assertEquals(Scalar.NULL_VALUE_STRING, b.toString()); - assertDoesNotThrow(() -> { - b.set("abc"); + assertDoesNotThrow( + () -> { + b.set("abc"); }); - assertEquals("abc=", b.toString()); + assertEquals("abc=", b.toString()); - assertDoesNotThrow(() -> { - b.set(new byte[]{0, 1, 2, 3, 4, 5}); + assertDoesNotThrow( + () -> { + b.set(new byte[] {0, 1, 2, 3, 4, 5}); }); - assertEquals("AAECAwQF", b.toString()); - } - - @Test - public void testDataType() { - Binary.LargeBinary b = new Binary.LargeBinary(); - assertEquals(ArrowType.LargeBinary.INSTANCE, b.dataType()); - assertEquals(new ArrowType.LargeBinary(), b.dataType()); - } - - @Test - public void testIsValid() { - Binary.LargeBinary b = new Binary.LargeBinary(); - assertFalse(b.isValid()); - - assertDoesNotThrow(() -> { - b.set("abc"); + assertEquals("AAECAwQF", b.toString()); + } + + @Test + public void testDataType() { + Binary.LargeBinary b = new Binary.LargeBinary(); + assertEquals(ArrowType.LargeBinary.INSTANCE, b.dataType()); + assertEquals(new ArrowType.LargeBinary(), b.dataType()); + } + + @Test + public void testIsValid() { + Binary.LargeBinary b = new Binary.LargeBinary(); + assertFalse(b.isValid()); + + assertDoesNotThrow( + () -> { + b.set("abc"); }); - assertTrue(b.isValid()); - } - - @Test - public void testSet() { - Binary.LargeBinary b = new Binary.LargeBinary(); - assertDoesNotThrow(() -> { - b.set(new byte[]{'a', 'b', 'c'}); - b.set("abc"); - b.set(new char[]{'a', 'b', 'c'}); - - Scalar s = new Binary.LargeBinary(new char[]{'a', 'b', 'c'}); - b.set(s); + assertTrue(b.isValid()); + } + + @Test + public void testSet() { + Binary.LargeBinary b = new Binary.LargeBinary(); + assertDoesNotThrow( + () -> { + b.set(new byte[] {'a', 'b', 'c'}); + b.set("abc"); + b.set(new char[] {'a', 'b', 'c'}); + + Scalar s = new Binary.LargeBinary(new char[] {'a', 'b', 'c'}); + b.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Binary.LargeBinary b = new Binary.LargeBinary(); - assertThrows(ValidationException.class, () -> { - b.set(false); + } + + @Test + public void testSetWithInvalidParam() { + Binary.LargeBinary b = new Binary.LargeBinary(); + assertThrows( + ValidationException.class, + () -> { + b.set(false); }); - } + } - @Test - public void testGet() { - Binary.LargeBinary b = new Binary.LargeBinary(); - assertFalse(b.isValid()); - assertNull(b.get()); + @Test + public void testGet() { + Binary.LargeBinary b = new Binary.LargeBinary(); + assertFalse(b.isValid()); + assertNull(b.get()); - assertDoesNotThrow(() -> { - b.set(new byte[]{'a', 'b', 'c'}); + assertDoesNotThrow( + () -> { + b.set(new byte[] {'a', 'b', 'c'}); }); - assertTrue(b.isValid()); - assertArrayEquals(new byte[]{'a', 'b', 'c'}, (byte[]) b.get()); + assertTrue(b.isValid()); + assertArrayEquals(new byte[] {'a', 'b', 'c'}, (byte[]) b.get()); - assertDoesNotThrow(() -> { - b.set("abc"); + assertDoesNotThrow( + () -> { + b.set("abc"); }); - assertTrue(b.isValid()); - assertArrayEquals(new byte[]{105, -73}, (byte[]) b.get()); + assertTrue(b.isValid()); + assertArrayEquals(new byte[] {105, -73}, (byte[]) b.get()); - assertDoesNotThrow(() -> { - b.set(new char[]{'a', 'b', 'c'}); + assertDoesNotThrow( + () -> { + b.set(new char[] {'a', 'b', 'c'}); }); - assertTrue(b.isValid()); - assertArrayEquals(new byte[]{105, -73}, (byte[]) b.get()); + assertTrue(b.isValid()); + assertArrayEquals(new byte[] {105, -73}, (byte[]) b.get()); - assertDoesNotThrow(() -> { - Scalar s = new Binary.LargeBinary(new char[]{'a', 'b', 'c'}); - b.set(s); + assertDoesNotThrow( + () -> { + Scalar s = new Binary.LargeBinary(new char[] {'a', 'b', 'c'}); + b.set(s); }); - assertTrue(b.isValid()); - assertArrayEquals(new byte[]{105, -73}, (byte[]) b.get()); + assertTrue(b.isValid()); + assertArrayEquals(new byte[] {105, -73}, (byte[]) b.get()); - assertDoesNotThrow(() -> { - Scalar s = new Binary.LargeBinary(new byte[]{'a', 'b', 'c'}); - b.set(s); + assertDoesNotThrow( + () -> { + Scalar s = new Binary.LargeBinary(new byte[] {'a', 'b', 'c'}); + b.set(s); }); - assertTrue(b.isValid()); - assertArrayEquals(new byte[]{'a', 'b', 'c'}, (byte[]) b.get()); - } - - @Test - public void testEquals() { - Binary.LargeBinary a = new Binary.LargeBinary(); - Binary.LargeBinary b = new Binary.LargeBinary(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Bool()); // we can't cast Bool to Binary.LargeBinary - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(new byte[]{'a', 'b', 'c'}); + assertTrue(b.isValid()); + assertArrayEquals(new byte[] {'a', 'b', 'c'}, (byte[]) b.get()); + } + + @Test + public void testEquals() { + Binary.LargeBinary a = new Binary.LargeBinary(); + Binary.LargeBinary b = new Binary.LargeBinary(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Bool()); // we can't cast Bool to Binary.LargeBinary + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(new byte[] {'a', 'b', 'c'}); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{ - null, - new byte[]{'a', 'b', 'c'}, - new char[]{'a', 'b', 'c'}, - "abc", - new Binary.LargeBinary("abc"), - }) { - a.set(obj); - assertEquals(a, new Binary.LargeBinary(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : + new Object[] { + null, + new byte[] {'a', 'b', 'c'}, + new char[] {'a', 'b', 'c'}, + "abc", + new Binary.LargeBinary("abc"), + }) { + a.set(obj); + assertEquals(a, new Binary.LargeBinary(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/ScalarTest.java b/lib/src/test/java/io/cloudquery/scalar/ScalarTest.java index 33237db9..db5c9d89 100644 --- a/lib/src/test/java/io/cloudquery/scalar/ScalarTest.java +++ b/lib/src/test/java/io/cloudquery/scalar/ScalarTest.java @@ -1,6 +1,11 @@ package io.cloudquery.scalar; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +import io.cloudquery.types.JSONType; import io.cloudquery.types.UUIDType; +import java.time.ZoneOffset; +import java.util.stream.Stream; import org.apache.arrow.vector.types.DateUnit; import org.apache.arrow.vector.types.FloatingPointPrecision; import org.apache.arrow.vector.types.TimeUnit; @@ -10,62 +15,63 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.time.ZoneOffset; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; - public class ScalarTest { - @ParameterizedTest - @MethodSource("testDataSource") - public void shouldCreateScalarFromArrowType(ArrowType arrowType, Class> scalarClazz) { - ExtensionTypeRegistry.register(new UUIDType()); + @ParameterizedTest + @MethodSource("testDataSource") + public void shouldCreateScalarFromArrowType( + ArrowType arrowType, Class> scalarClazz) { + ExtensionTypeRegistry.register(new UUIDType()); - assertInstanceOf(scalarClazz, Scalar.fromArrowType(arrowType)); - } + assertInstanceOf(scalarClazz, Scalar.fromArrowType(arrowType)); + } - public static Stream testDataSource() { - return Stream.of( - // Timestamp - Arguments.of(new ArrowType.Timestamp(TimeUnit.MILLISECOND, ZoneOffset.UTC.toString()), Timestamp.class), + public static Stream testDataSource() { + return Stream.of( + // Timestamp + Arguments.of( + new ArrowType.Timestamp(TimeUnit.MILLISECOND, ZoneOffset.UTC.toString()), + Timestamp.class), - // String - Arguments.of(new ArrowType.Utf8(), String.class), - Arguments.of(new ArrowType.LargeUtf8(), String.class), + // String + Arguments.of(new ArrowType.Utf8(), String.class), + Arguments.of(new ArrowType.LargeUtf8(), String.class), - // Binary - Arguments.of(new ArrowType.Binary(), Binary.class), - Arguments.of(new ArrowType.LargeBinary(), Binary.LargeBinary.class), + // Binary + Arguments.of(new ArrowType.Binary(), Binary.class), + Arguments.of(new ArrowType.LargeBinary(), Binary.LargeBinary.class), - // Boolean - Arguments.of(new ArrowType.Bool(), Bool.class), + // Boolean + Arguments.of(new ArrowType.Bool(), Bool.class), - // Signed Integers - Arguments.of(new ArrowType.Int(8, true), Number.Int8.class), - Arguments.of(new ArrowType.Int(16, true), Number.Int16.class), - Arguments.of(new ArrowType.Int(32, true), Number.Int32.class), - Arguments.of(new ArrowType.Int(64, true), Number.Int64.class), + // Signed Integers + Arguments.of(new ArrowType.Int(8, true), Number.Int8.class), + Arguments.of(new ArrowType.Int(16, true), Number.Int16.class), + Arguments.of(new ArrowType.Int(32, true), Number.Int32.class), + Arguments.of(new ArrowType.Int(64, true), Number.Int64.class), - // Unsigned Integers - Arguments.of(new ArrowType.Int(8, false), Number.UInt8.class), - Arguments.of(new ArrowType.Int(16, false), Number.UInt16.class), - Arguments.of(new ArrowType.Int(32, false), Number.UInt32.class), - Arguments.of(new ArrowType.Int(64, false), Number.UInt64.class), + // Unsigned Integers + Arguments.of(new ArrowType.Int(8, false), Number.UInt8.class), + Arguments.of(new ArrowType.Int(16, false), Number.UInt16.class), + Arguments.of(new ArrowType.Int(32, false), Number.UInt32.class), + Arguments.of(new ArrowType.Int(64, false), Number.UInt64.class), - // Float - // Arguments.of( new ArrowType.FloatingPoint(FloatingPointPrecision.HALF), Number.Float16.class), - Arguments.of(new ArrowType.FloatingPoint(FloatingPointPrecision.SINGLE), Number.Float32.class), - Arguments.of(new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE), Number.Float64.class), + // Float + // Arguments.of( new ArrowType.FloatingPoint(FloatingPointPrecision.HALF), + // Number.Float16.class), + Arguments.of( + new ArrowType.FloatingPoint(FloatingPointPrecision.SINGLE), Number.Float32.class), + Arguments.of( + new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE), Number.Float64.class), - // Extension - Arguments.of(new UUIDType(), UUID.class), + // Extension + Arguments.of(new UUIDType(), UUID.class), + Arguments.of(new JSONType(), JSON.class), - // Date - Arguments.of(new ArrowType.Date(DateUnit.DAY), DateDay.class), - Arguments.of(new ArrowType.Date(DateUnit.MILLISECOND), DateMilli.class), + // Date + Arguments.of(new ArrowType.Date(DateUnit.DAY), DateDay.class), + Arguments.of(new ArrowType.Date(DateUnit.MILLISECOND), DateMilli.class), - // Duration - Arguments.of(new ArrowType.Duration(TimeUnit.MILLISECOND), Duration.class) - ); - } + // Duration + Arguments.of(new ArrowType.Duration(TimeUnit.MILLISECOND), Duration.class)); + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/StringTest.java b/lib/src/test/java/io/cloudquery/scalar/StringTest.java index 0b245d74..52666578 100644 --- a/lib/src/test/java/io/cloudquery/scalar/StringTest.java +++ b/lib/src/test/java/io/cloudquery/scalar/StringTest.java @@ -1,117 +1,126 @@ package io.cloudquery.scalar; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.*; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Test; public class StringTest { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new String(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new String(); }); - } - - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new String(1); - new String("PT8H6M12.345S"); - new String(""); - - Scalar s = new String(null); - new String(s); + } + + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new String(1); + new String("PT8H6M12.345S"); + new String(""); + + Scalar s = new String(null); + new String(s); }); - } + } - @Test - public void testToString() { - String string = new String(); - assertEquals(Scalar.NULL_VALUE_STRING, string.toString()); + @Test + public void testToString() { + String string = new String(); + assertEquals(Scalar.NULL_VALUE_STRING, string.toString()); - assertDoesNotThrow(() -> { - string.set(1); + assertDoesNotThrow( + () -> { + string.set(1); }); - assertEquals("1", string.toString()); + assertEquals("1", string.toString()); - assertDoesNotThrow(() -> { - string.set(-1L); + assertDoesNotThrow( + () -> { + string.set(-1L); }); - assertEquals("-1", string.toString()); - } - - @Test - public void testDataType() { - String string = new String(); - assertEquals(ArrowType.Utf8.INSTANCE, string.dataType()); - assertEquals(new ArrowType.Utf8(), string.dataType()); - } - - @Test - public void testIsValid() { - String string = new String(); - assertFalse(string.isValid()); - - assertDoesNotThrow(() -> { - string.set(1L); + assertEquals("-1", string.toString()); + } + + @Test + public void testDataType() { + String string = new String(); + assertEquals(ArrowType.Utf8.INSTANCE, string.dataType()); + assertEquals(new ArrowType.Utf8(), string.dataType()); + } + + @Test + public void testIsValid() { + String string = new String(); + assertFalse(string.isValid()); + + assertDoesNotThrow( + () -> { + string.set(1L); }); - assertTrue(string.isValid()); - } - - @Test - public void testSet() { - String string = new String(); - assertDoesNotThrow(() -> { - string.set(1); - string.set(1L); - string.set("PT8H6M12.345S"); - string.set(null); - - Scalar s = new String(""); - string.set(s); + assertTrue(string.isValid()); + } + + @Test + public void testSet() { + String string = new String(); + assertDoesNotThrow( + () -> { + string.set(1); + string.set(1L); + string.set("PT8H6M12.345S"); + string.set(null); + + Scalar s = new String(""); + string.set(s); }); - } + } - @Test - public void testGet() { - String string = new String(); - assertFalse(string.isValid()); - assertNull(string.get()); + @Test + public void testGet() { + String string = new String(); + assertFalse(string.isValid()); + assertNull(string.get()); - assertDoesNotThrow(() -> { - string.set(-1L); + assertDoesNotThrow( + () -> { + string.set(-1L); }); - assertTrue(string.isValid()); - assertEquals("-1", string.get()); + assertTrue(string.isValid()); + assertEquals("-1", string.get().toString()); - assertDoesNotThrow(() -> { - string.set(""); + assertDoesNotThrow( + () -> { + string.set(""); }); - assertTrue(string.isValid()); - assertEquals("", string.get()); - } - - @Test - public void testEquals() { - String a = new String(); - String b = new String(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Bool()); // we can't cast Bool to String - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(-1L); + assertTrue(string.isValid()); + assertEquals("", string.get().toString()); + } + + @Test + public void testEquals() { + String a = new String(); + String b = new String(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Bool()); // we can't cast Bool to String + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(-1L); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 0, 0L, -1, -1L, 1, 1L, "PT8H6M12.345S", ""}) { - a.set(obj); - assertEquals(a, new String(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 0, 0L, -1, -1L, 1, 1L, "PT8H6M12.345S", ""}) { + a.set(obj); + assertEquals(a, new String(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/TimestampTest.java b/lib/src/test/java/io/cloudquery/scalar/TimestampTest.java index f66effaf..e10faff3 100644 --- a/lib/src/test/java/io/cloudquery/scalar/TimestampTest.java +++ b/lib/src/test/java/io/cloudquery/scalar/TimestampTest.java @@ -1,138 +1,171 @@ package io.cloudquery.scalar; -import org.apache.arrow.vector.types.TimeUnit; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.Instant; import java.time.ZoneOffset; import java.time.ZonedDateTime; - -import static org.junit.jupiter.api.Assertions.*; - +import org.apache.arrow.vector.types.TimeUnit; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Test; public class TimestampTest { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Timestamp(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Timestamp(); }); - } - - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Timestamp(1); - new Timestamp("2011-12-03T10:15:30+01:00[Europe/Paris]"); - new Timestamp(ZonedDateTime.now()); - - Scalar s = new Timestamp(ZonedDateTime.now()); - new Timestamp(s); + } + + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Timestamp(1); + new Timestamp("2011-12-03T10:15:30+01:00[Europe/Paris]"); + new Timestamp(ZonedDateTime.now()); + + Scalar s = new Timestamp(ZonedDateTime.now()); + new Timestamp(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Timestamp(false); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Timestamp(false); }); - } + } - @Test - public void testToString() { - Timestamp timestamp = new Timestamp(); - assertEquals(Scalar.NULL_VALUE_STRING, timestamp.toString()); + @Test + public void testToString() { + Timestamp timestamp = new Timestamp(); + assertEquals(Scalar.NULL_VALUE_STRING, timestamp.toString()); - assertDoesNotThrow(() -> { - timestamp.set(1); + assertDoesNotThrow( + () -> { + timestamp.set(1); }); - assertEquals("1970-01-01T00:00:00.001Z", timestamp.toString()); - - java.lang.String ts = ZonedDateTime.now(ZoneOffset.UTC).toString(); - assertDoesNotThrow(() -> { - timestamp.set(ts); + assertEquals("1970-01-01T00:00Z", timestamp.toString()); + + java.lang.String ts = + ZonedDateTime.ofInstant( + Instant.ofEpochSecond(ZonedDateTime.now(ZoneOffset.UTC).toEpochSecond()), + ZoneOffset.UTC) + .toString(); + assertDoesNotThrow( + () -> { + timestamp.set(ts); }); - assertEquals(ts, timestamp.toString()); - } - - @Test - public void testDataType() { - Timestamp timestamp = new Timestamp(); - assertEquals(new ArrowType.Timestamp(TimeUnit.MILLISECOND, "Z"), timestamp.dataType()); - } - - @Test - public void testIsValid() { - Timestamp timestamp = new Timestamp(); - assertFalse(timestamp.isValid()); - - assertDoesNotThrow(() -> { - timestamp.set(1L); + assertEquals(ts, timestamp.toString()); + } + + @Test + public void testDataType() { + Timestamp timestamp = new Timestamp(); + assertEquals(new ArrowType.Timestamp(TimeUnit.MILLISECOND, "Z"), timestamp.dataType()); + } + + @Test + public void testIsValid() { + Timestamp timestamp = new Timestamp(); + assertFalse(timestamp.isValid()); + + assertDoesNotThrow( + () -> { + timestamp.set(1L); }); - assertTrue(timestamp.isValid()); - } - - @Test - public void testSet() { - Timestamp timestamp = new Timestamp(); - assertDoesNotThrow(() -> { - timestamp.set(1); - timestamp.set(1L); - timestamp.set("2011-12-03T10:15:30+01:00[Europe/Paris]"); - timestamp.set(ZonedDateTime.now()); - - Scalar s = new Timestamp(ZonedDateTime.now()); - timestamp.set(s); + assertTrue(timestamp.isValid()); + } + + @Test + public void testSet() { + Timestamp timestamp = new Timestamp(); + assertDoesNotThrow( + () -> { + timestamp.set(1); + timestamp.set(1L); + timestamp.set("2011-12-03T10:15:30+01:00[Europe/Paris]"); + timestamp.set(ZonedDateTime.now()); + + Scalar s = new Timestamp(ZonedDateTime.now()); + timestamp.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Timestamp timestamp = new Timestamp(); - assertThrows(ValidationException.class, () -> { - timestamp.set(false); + } + + @Test + public void testSetWithInvalidParam() { + Timestamp timestamp = new Timestamp(); + assertThrows( + ValidationException.class, + () -> { + timestamp.set(false); }); - } - - @Test - public void testGet() { - Timestamp timestamp = new Timestamp(); - assertFalse(timestamp.isValid()); - assertNull(timestamp.get()); - - ZonedDateTime ts = ZonedDateTime.now(ZoneOffset.UTC); - assertDoesNotThrow(() -> { - timestamp.set(ts); + } + + @Test + public void testGet() { + Timestamp timestamp = new Timestamp(); + assertFalse(timestamp.isValid()); + assertNull(timestamp.get()); + + ZonedDateTime ts = ZonedDateTime.now(ZoneOffset.UTC); + assertDoesNotThrow( + () -> { + timestamp.set(ts); }); - assertTrue(timestamp.isValid()); - assertEquals(ts, timestamp.get()); + assertTrue(timestamp.isValid()); + assertEquals(ts.toEpochSecond() * 1000, timestamp.get()); - assertDoesNotThrow(() -> { - timestamp.set(0); + assertDoesNotThrow( + () -> { + timestamp.set(0); }); - assertTrue(timestamp.isValid()); - assertEquals(Instant.EPOCH.atZone(ZoneOffset.UTC), timestamp.get()); - } - - @Test - public void testEquals() { - Timestamp a = new Timestamp(); - Timestamp b = new Timestamp(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Bool()); // we can't cast Bool to Timestamp - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(-1L); + assertTrue(timestamp.isValid()); + assertEquals(Instant.EPOCH.atZone(ZoneOffset.UTC).toEpochSecond(), timestamp.get()); + } + + @Test + public void testEquals() { + Timestamp a = new Timestamp(); + Timestamp b = new Timestamp(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Bool()); // we can't cast Bool to Timestamp + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(-1L); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 0, 0L, -1, -1L, 1, 1L, "1970-01-01T00:00:00.001Z", Instant.EPOCH.atZone(ZoneOffset.UTC)}) { - a.set(obj); - assertEquals(a, new Timestamp(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : + new Object[] { + null, + 0, + 0L, + -1, + -1L, + 1, + 1L, + "1970-01-01T00:00:00.001Z", + Instant.EPOCH.atZone(ZoneOffset.UTC) + }) { + a.set(obj); + assertEquals(a, new Timestamp(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/UInt16Test.java b/lib/src/test/java/io/cloudquery/scalar/UInt16Test.java index f7d769e3..fb98976f 100644 --- a/lib/src/test/java/io/cloudquery/scalar/UInt16Test.java +++ b/lib/src/test/java/io/cloudquery/scalar/UInt16Test.java @@ -1,128 +1,141 @@ package io.cloudquery.scalar; +import static org.junit.jupiter.api.Assertions.*; + import org.apache.arrow.vector.types.pojo.ArrowType; -import org.joou.UByte; import org.joou.UShort; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - - public class UInt16Test { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Number.UInt16(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Number.UInt16(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Number.UInt16(1); - new Number.UInt16("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Number.UInt16(1); + new Number.UInt16("1"); - Scalar s = new Number.UInt16(2); - new Number.UInt16(s); + Scalar s = new Number.UInt16(2); + new Number.UInt16(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Number.UInt16(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Number.UInt16(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - Number.UInt16 uint16 = new Number.UInt16(); - assertEquals(Scalar.NULL_VALUE_STRING, uint16.toString()); + @Test + public void testToString() { + Number.UInt16 uint16 = new Number.UInt16(); + assertEquals(Scalar.NULL_VALUE_STRING, uint16.toString()); - assertDoesNotThrow(() -> { - uint16.set("1"); + assertDoesNotThrow( + () -> { + uint16.set("1"); }); - assertEquals("1", uint16.toString()); + assertEquals("1", uint16.toString()); - assertDoesNotThrow(() -> { - uint16.set(2); + assertDoesNotThrow( + () -> { + uint16.set(2); }); - assertEquals("2", uint16.toString()); - } - - @Test - public void testDataType() { - Number.UInt16 uint16 = new Number.UInt16(); - assertEquals(new ArrowType.Int(Short.SIZE, false), uint16.dataType()); - } - - @Test - public void testIsValid() { - Number.UInt16 uint16 = new Number.UInt16(); - assertFalse(uint16.isValid()); - - assertDoesNotThrow(() -> { - uint16.set("1"); + assertEquals("2", uint16.toString()); + } + + @Test + public void testDataType() { + Number.UInt16 uint16 = new Number.UInt16(); + assertEquals(new ArrowType.Int(Short.SIZE, false), uint16.dataType()); + } + + @Test + public void testIsValid() { + Number.UInt16 uint16 = new Number.UInt16(); + assertFalse(uint16.isValid()); + + assertDoesNotThrow( + () -> { + uint16.set("1"); }); - assertTrue(uint16.isValid()); - } - - @Test - public void testSet() { - Number.UInt16 uint16 = new Number.UInt16(); - assertDoesNotThrow(() -> { - new Number.UInt16(1); - new Number.UInt16("2"); - - Scalar s = new Number.UInt16(1); - uint16.set(s); + assertTrue(uint16.isValid()); + } + + @Test + public void testSet() { + Number.UInt16 uint16 = new Number.UInt16(); + assertDoesNotThrow( + () -> { + new Number.UInt16(1); + new Number.UInt16("2"); + + Scalar s = new Number.UInt16(1); + uint16.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Number.UInt16 uint16 = new Number.UInt16(); - assertThrows(ValidationException.class, () -> { - uint16.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + Number.UInt16 uint16 = new Number.UInt16(); + assertThrows( + ValidationException.class, + () -> { + uint16.set(new char[] {}); }); - } + } - @Test - public void testGet() { - Number.UInt16 uint16 = new Number.UInt16(); - assertFalse(uint16.isValid()); - assertNull(uint16.get()); + @Test + public void testGet() { + Number.UInt16 uint16 = new Number.UInt16(); + assertFalse(uint16.isValid()); + assertNull(uint16.get()); - assertDoesNotThrow(() -> { - uint16.set(1); + assertDoesNotThrow( + () -> { + uint16.set(1); }); - assertTrue(uint16.isValid()); - assertEquals(UShort.valueOf(1), uint16.get()); + assertTrue(uint16.isValid()); + assertEquals(UShort.valueOf(1), uint16.get()); - assertThrows(NumberFormatException.class, () -> { - uint16.set("-1"); + assertThrows( + NumberFormatException.class, + () -> { + uint16.set("-1"); }); - } - - @Test - public void testEquals() { - Number.UInt16 a = new Number.UInt16(); - Number.UInt16 b = new Number.UInt16(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to Number.UInt16 - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + } + + @Test + public void testEquals() { + Number.UInt16 a = new Number.UInt16(); + Number.UInt16 b = new Number.UInt16(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to Number.UInt16 + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, "2"}) { - a.set(obj); - assertEquals(a, new Number.UInt16(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, "2"}) { + a.set(obj); + assertEquals(a, new Number.UInt16(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/UInt32Test.java b/lib/src/test/java/io/cloudquery/scalar/UInt32Test.java index 12f7049c..3259d184 100644 --- a/lib/src/test/java/io/cloudquery/scalar/UInt32Test.java +++ b/lib/src/test/java/io/cloudquery/scalar/UInt32Test.java @@ -1,127 +1,141 @@ package io.cloudquery.scalar; +import static org.junit.jupiter.api.Assertions.*; + import org.apache.arrow.vector.types.pojo.ArrowType; import org.joou.UInteger; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - - public class UInt32Test { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Number.UInt32(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Number.UInt32(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Number.UInt32(1); - new Number.UInt32("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Number.UInt32(1); + new Number.UInt32("1"); - Scalar s = new Number.UInt32(2); - new Number.UInt32(s); + Scalar s = new Number.UInt32(2); + new Number.UInt32(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Number.UInt32(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Number.UInt32(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - Number.UInt32 uint32 = new Number.UInt32(); - assertEquals(Scalar.NULL_VALUE_STRING, uint32.toString()); + @Test + public void testToString() { + Number.UInt32 uint32 = new Number.UInt32(); + assertEquals(Scalar.NULL_VALUE_STRING, uint32.toString()); - assertDoesNotThrow(() -> { - uint32.set("1"); + assertDoesNotThrow( + () -> { + uint32.set("1"); }); - assertEquals("1", uint32.toString()); + assertEquals("1", uint32.toString()); - assertDoesNotThrow(() -> { - uint32.set(2); + assertDoesNotThrow( + () -> { + uint32.set(2); }); - assertEquals("2", uint32.toString()); - } - - @Test - public void testDataType() { - Number.UInt32 uint32 = new Number.UInt32(); - assertEquals(new ArrowType.Int(Integer.SIZE, false), uint32.dataType()); - } - - @Test - public void testIsValid() { - Number.UInt32 uint32 = new Number.UInt32(); - assertFalse(uint32.isValid()); - - assertDoesNotThrow(() -> { - uint32.set("1"); + assertEquals("2", uint32.toString()); + } + + @Test + public void testDataType() { + Number.UInt32 uint32 = new Number.UInt32(); + assertEquals(new ArrowType.Int(Integer.SIZE, false), uint32.dataType()); + } + + @Test + public void testIsValid() { + Number.UInt32 uint32 = new Number.UInt32(); + assertFalse(uint32.isValid()); + + assertDoesNotThrow( + () -> { + uint32.set("1"); }); - assertTrue(uint32.isValid()); - } - - @Test - public void testSet() { - Number.UInt32 uint32 = new Number.UInt32(); - assertDoesNotThrow(() -> { - new Number.UInt32(1); - new Number.UInt32("2"); - - Scalar s = new Number.UInt32(1); - uint32.set(s); + assertTrue(uint32.isValid()); + } + + @Test + public void testSet() { + Number.UInt32 uint32 = new Number.UInt32(); + assertDoesNotThrow( + () -> { + new Number.UInt32(1); + new Number.UInt32("2"); + + Scalar s = new Number.UInt32(1); + uint32.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Number.UInt32 uint32 = new Number.UInt32(); - assertThrows(ValidationException.class, () -> { - uint32.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + Number.UInt32 uint32 = new Number.UInt32(); + assertThrows( + ValidationException.class, + () -> { + uint32.set(new char[] {}); }); - } + } - @Test - public void testGet() { - Number.UInt32 uint32 = new Number.UInt32(); - assertFalse(uint32.isValid()); - assertNull(uint32.get()); + @Test + public void testGet() { + Number.UInt32 uint32 = new Number.UInt32(); + assertFalse(uint32.isValid()); + assertNull(uint32.get()); - assertDoesNotThrow(() -> { - uint32.set(1); + assertDoesNotThrow( + () -> { + uint32.set(1); }); - assertTrue(uint32.isValid()); - assertEquals(UInteger.valueOf(1), uint32.get()); + assertTrue(uint32.isValid()); + assertEquals(UInteger.valueOf(1), uint32.get()); - assertThrows(NumberFormatException.class, () -> { - uint32.set("-1"); + assertThrows( + NumberFormatException.class, + () -> { + uint32.set("-1"); }); - } - - @Test - public void testEquals() { - Number.UInt32 a = new Number.UInt32(); - Number.UInt32 b = new Number.UInt32(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to Number.UInt32 - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + } + + @Test + public void testEquals() { + Number.UInt32 a = new Number.UInt32(); + Number.UInt32 b = new Number.UInt32(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to Number.UInt32 + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, "2"}) { - a.set(obj); - assertEquals(a, new Number.UInt32(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, "2"}) { + a.set(obj); + assertEquals(a, new Number.UInt32(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/UInt64Test.java b/lib/src/test/java/io/cloudquery/scalar/UInt64Test.java index 9c2aa061..4d91b0c5 100644 --- a/lib/src/test/java/io/cloudquery/scalar/UInt64Test.java +++ b/lib/src/test/java/io/cloudquery/scalar/UInt64Test.java @@ -1,128 +1,141 @@ package io.cloudquery.scalar; +import static org.junit.jupiter.api.Assertions.*; + import org.apache.arrow.vector.types.pojo.ArrowType; -import org.joou.UInteger; import org.joou.ULong; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - - public class UInt64Test { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Number.UInt64(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Number.UInt64(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Number.UInt64(1); - new Number.UInt64("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Number.UInt64(1); + new Number.UInt64("1"); - Scalar s = new Number.UInt64(2); - new Number.UInt64(s); + Scalar s = new Number.UInt64(2); + new Number.UInt64(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Number.UInt64(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Number.UInt64(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - Number.UInt64 uint64 = new Number.UInt64(); - assertEquals(Scalar.NULL_VALUE_STRING, uint64.toString()); + @Test + public void testToString() { + Number.UInt64 uint64 = new Number.UInt64(); + assertEquals(Scalar.NULL_VALUE_STRING, uint64.toString()); - assertDoesNotThrow(() -> { - uint64.set("1"); + assertDoesNotThrow( + () -> { + uint64.set("1"); }); - assertEquals("1", uint64.toString()); + assertEquals("1", uint64.toString()); - assertDoesNotThrow(() -> { - uint64.set(2); + assertDoesNotThrow( + () -> { + uint64.set(2); }); - assertEquals("2", uint64.toString()); - } - - @Test - public void testDataType() { - Number.UInt64 uint64 = new Number.UInt64(); - assertEquals(new ArrowType.Int(Long.SIZE, false), uint64.dataType()); - } - - @Test - public void testIsValid() { - Number.UInt64 uint64 = new Number.UInt64(); - assertFalse(uint64.isValid()); - - assertDoesNotThrow(() -> { - uint64.set("1"); + assertEquals("2", uint64.toString()); + } + + @Test + public void testDataType() { + Number.UInt64 uint64 = new Number.UInt64(); + assertEquals(new ArrowType.Int(Long.SIZE, false), uint64.dataType()); + } + + @Test + public void testIsValid() { + Number.UInt64 uint64 = new Number.UInt64(); + assertFalse(uint64.isValid()); + + assertDoesNotThrow( + () -> { + uint64.set("1"); }); - assertTrue(uint64.isValid()); - } - - @Test - public void testSet() { - Number.UInt64 uint64 = new Number.UInt64(); - assertDoesNotThrow(() -> { - new Number.UInt64(1); - new Number.UInt64("2"); - - Scalar s = new Number.UInt64(1); - uint64.set(s); + assertTrue(uint64.isValid()); + } + + @Test + public void testSet() { + Number.UInt64 uint64 = new Number.UInt64(); + assertDoesNotThrow( + () -> { + new Number.UInt64(1); + new Number.UInt64("2"); + + Scalar s = new Number.UInt64(1); + uint64.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Number.UInt64 uint64 = new Number.UInt64(); - assertThrows(ValidationException.class, () -> { - uint64.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + Number.UInt64 uint64 = new Number.UInt64(); + assertThrows( + ValidationException.class, + () -> { + uint64.set(new char[] {}); }); - } + } - @Test - public void testGet() { - Number.UInt64 uint64 = new Number.UInt64(); - assertFalse(uint64.isValid()); - assertNull(uint64.get()); + @Test + public void testGet() { + Number.UInt64 uint64 = new Number.UInt64(); + assertFalse(uint64.isValid()); + assertNull(uint64.get()); - assertDoesNotThrow(() -> { - uint64.set(1); + assertDoesNotThrow( + () -> { + uint64.set(1); }); - assertTrue(uint64.isValid()); - assertEquals(ULong.valueOf(1), uint64.get()); + assertTrue(uint64.isValid()); + assertEquals(ULong.valueOf(1), uint64.get()); - assertThrows(NumberFormatException.class, () -> { - uint64.set("-1"); + assertThrows( + NumberFormatException.class, + () -> { + uint64.set("-1"); }); - } - - @Test - public void testEquals() { - Number.UInt64 a = new Number.UInt64(); - Number.UInt64 b = new Number.UInt64(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to Number.UInt64 - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + } + + @Test + public void testEquals() { + Number.UInt64 a = new Number.UInt64(); + Number.UInt64 b = new Number.UInt64(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to Number.UInt64 + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, "2"}) { - a.set(obj); - assertEquals(a, new Number.UInt64(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, "2"}) { + a.set(obj); + assertEquals(a, new Number.UInt64(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/UInt8Test.java b/lib/src/test/java/io/cloudquery/scalar/UInt8Test.java index 1a49a08e..6a8e4744 100644 --- a/lib/src/test/java/io/cloudquery/scalar/UInt8Test.java +++ b/lib/src/test/java/io/cloudquery/scalar/UInt8Test.java @@ -1,127 +1,141 @@ package io.cloudquery.scalar; +import static org.junit.jupiter.api.Assertions.*; + import org.apache.arrow.vector.types.pojo.ArrowType; import org.joou.UByte; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - - public class UInt8Test { - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new Number.UInt8(); + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new Number.UInt8(); }); - } + } - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new Number.UInt8(1); - new Number.UInt8("1"); + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new Number.UInt8(1); + new Number.UInt8("1"); - Scalar s = new Number.UInt8(2); - new Number.UInt8(s); + Scalar s = new Number.UInt8(2); + new Number.UInt8(s); }); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new Number.UInt8(new char[]{'q'}); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new Number.UInt8(new char[] {'q'}); }); - } + } - @Test - public void testToString() { - Number.UInt8 uint8 = new Number.UInt8(); - assertEquals(Scalar.NULL_VALUE_STRING, uint8.toString()); + @Test + public void testToString() { + Number.UInt8 uint8 = new Number.UInt8(); + assertEquals(Scalar.NULL_VALUE_STRING, uint8.toString()); - assertDoesNotThrow(() -> { - uint8.set("1"); + assertDoesNotThrow( + () -> { + uint8.set("1"); }); - assertEquals("1", uint8.toString()); + assertEquals("1", uint8.toString()); - assertDoesNotThrow(() -> { - uint8.set(2); + assertDoesNotThrow( + () -> { + uint8.set(2); }); - assertEquals("2", uint8.toString()); - } - - @Test - public void testDataType() { - Number.UInt8 uint8 = new Number.UInt8(); - assertEquals(new ArrowType.Int(Byte.SIZE, false), uint8.dataType()); - } - - @Test - public void testIsValid() { - Number.UInt8 uint8 = new Number.UInt8(); - assertFalse(uint8.isValid()); - - assertDoesNotThrow(() -> { - uint8.set("1"); + assertEquals("2", uint8.toString()); + } + + @Test + public void testDataType() { + Number.UInt8 uint8 = new Number.UInt8(); + assertEquals(new ArrowType.Int(Byte.SIZE, false), uint8.dataType()); + } + + @Test + public void testIsValid() { + Number.UInt8 uint8 = new Number.UInt8(); + assertFalse(uint8.isValid()); + + assertDoesNotThrow( + () -> { + uint8.set("1"); }); - assertTrue(uint8.isValid()); - } - - @Test - public void testSet() { - Number.UInt8 uint8 = new Number.UInt8(); - assertDoesNotThrow(() -> { - new Number.UInt8(1); - new Number.UInt8("2"); - - Scalar s = new Number.UInt8(1); - uint8.set(s); + assertTrue(uint8.isValid()); + } + + @Test + public void testSet() { + Number.UInt8 uint8 = new Number.UInt8(); + assertDoesNotThrow( + () -> { + new Number.UInt8(1); + new Number.UInt8("2"); + + Scalar s = new Number.UInt8(1); + uint8.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - Number.UInt8 uint8 = new Number.UInt8(); - assertThrows(ValidationException.class, () -> { - uint8.set(new char[]{}); + } + + @Test + public void testSetWithInvalidParam() { + Number.UInt8 uint8 = new Number.UInt8(); + assertThrows( + ValidationException.class, + () -> { + uint8.set(new char[] {}); }); - } + } - @Test - public void testGet() { - Number.UInt8 uint8 = new Number.UInt8(); - assertFalse(uint8.isValid()); - assertNull(uint8.get()); + @Test + public void testGet() { + Number.UInt8 uint8 = new Number.UInt8(); + assertFalse(uint8.isValid()); + assertNull(uint8.get()); - assertDoesNotThrow(() -> { - uint8.set(1); + assertDoesNotThrow( + () -> { + uint8.set(1); }); - assertTrue(uint8.isValid()); - assertEquals(UByte.valueOf(1), uint8.get()); + assertTrue(uint8.isValid()); + assertEquals(UByte.valueOf(1), uint8.get()); - assertThrows(java.lang.NumberFormatException.class, () -> { - uint8.set("-1"); + assertThrows( + java.lang.NumberFormatException.class, + () -> { + uint8.set("-1"); }); - } - - @Test - public void testEquals() { - Number.UInt8 a = new Number.UInt8(); - Number.UInt8 b = new Number.UInt8(); - assertEquals(a, b); - assertNotEquals(a, null); - assertNotEquals(a, new Binary()); // we can't cast Binary to Number.UInt8 - assertNotEquals(null, a); - - assertDoesNotThrow(() -> { - a.set(1); + } + + @Test + public void testEquals() { + Number.UInt8 a = new Number.UInt8(); + Number.UInt8 b = new Number.UInt8(); + assertEquals(a, b); + assertNotEquals(a, null); + assertNotEquals(a, new Binary()); // we can't cast Binary to Number.UInt8 + assertNotEquals(null, a); + + assertDoesNotThrow( + () -> { + a.set(1); }); - assertNotEquals(a, b); - - assertDoesNotThrow(() -> { - for (Object obj : new Object[]{null, 1, -1, "2"}) { - a.set(obj); - assertEquals(a, new Number.UInt8(obj)); - } + assertNotEquals(a, b); + + assertDoesNotThrow( + () -> { + for (Object obj : new Object[] {null, 1, -1, "2"}) { + a.set(obj); + assertEquals(a, new Number.UInt8(obj)); + } }); - } + } } diff --git a/lib/src/test/java/io/cloudquery/scalar/UUIDTest.java b/lib/src/test/java/io/cloudquery/scalar/UUIDTest.java index 5decfc2e..165f92f8 100644 --- a/lib/src/test/java/io/cloudquery/scalar/UUIDTest.java +++ b/lib/src/test/java/io/cloudquery/scalar/UUIDTest.java @@ -1,11 +1,5 @@ package io.cloudquery.scalar; -import nl.jqno.equalsverifier.EqualsVerifier; -import nl.jqno.equalsverifier.Warning; -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -14,151 +8,177 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -public class UUIDTest { - private static final byte[] COMPLETE_BYTE_SEQUENCE = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - private static final byte[] INCOMPLETE_BYTE_SEQUENCE = {1, 2, 3, 4}; +import nl.jqno.equalsverifier.EqualsVerifier; +import nl.jqno.equalsverifier.Warning; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; - @Test - public void testNew() { - assertDoesNotThrow(() -> { - new UUID(); +public class UUIDTest { + private static final byte[] COMPLETE_BYTE_SEQUENCE = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + }; + private static final byte[] INCOMPLETE_BYTE_SEQUENCE = {1, 2, 3, 4}; + + @Test + public void testNew() { + assertDoesNotThrow( + () -> { + new UUID(); }); - } - - @Test - public void testNewWithValidParam() { - assertDoesNotThrow(() -> { - new UUID("123e4567-e89b-12d3-a456-426614174000"); - new UUID(java.util.UUID.randomUUID()); - new UUID(COMPLETE_BYTE_SEQUENCE); - - Scalar s = new UUID(java.util.UUID.randomUUID()); - new UUID(s); - } - ); - } - - @Test - public void testNewWithInvalidParam() { - assertThrows(ValidationException.class, () -> { - new UUID(false); + } + + @Test + public void testNewWithValidParam() { + assertDoesNotThrow( + () -> { + new UUID("123e4567-e89b-12d3-a456-426614174000"); + new UUID(java.util.UUID.randomUUID()); + new UUID(COMPLETE_BYTE_SEQUENCE); + + Scalar s = new UUID(java.util.UUID.randomUUID()); + new UUID(s); + }); + } + + @Test + public void testNewWithInvalidParam() { + assertThrows( + ValidationException.class, + () -> { + new UUID(false); }); - assertThrows(ValidationException.class, () -> { - new UUID(INCOMPLETE_BYTE_SEQUENCE); + assertThrows( + ValidationException.class, + () -> { + new UUID(INCOMPLETE_BYTE_SEQUENCE); }); - } + } - @Test - public void testToString() { - UUID uuid = new UUID(); - assertEquals(Scalar.NULL_VALUE_STRING, uuid.toString()); + @Test + public void testToString() { + UUID uuid = new UUID(); + assertEquals(Scalar.NULL_VALUE_STRING, uuid.toString()); - java.util.UUID u = java.util.UUID.randomUUID(); - assertDoesNotThrow(() -> { - uuid.set(u); + java.util.UUID u = java.util.UUID.randomUUID(); + assertDoesNotThrow( + () -> { + uuid.set(u); }); - assertEquals(u.toString(), uuid.toString()); + assertEquals(u.toString(), uuid.toString()); - assertDoesNotThrow(() -> { - uuid.set(u.toString()); + assertDoesNotThrow( + () -> { + uuid.set(u.toString()); }); - assertEquals(u.toString(), uuid.toString()); - } - - @Test - public void testDataType() { - UUID uuid = new UUID(); - assertEquals(new ArrowType.FixedSizeBinary(16), uuid.dataType()); - } - - @Test - public void testIsValid() { - UUID uuid = new UUID(); - assertFalse(uuid.isValid()); - - assertDoesNotThrow(() -> { - uuid.set(java.util.UUID.randomUUID()); + assertEquals(u.toString(), uuid.toString()); + } + + @Test + public void testDataType() { + UUID uuid = new UUID(); + assertEquals(new ArrowType.FixedSizeBinary(16), uuid.dataType()); + } + + @Test + public void testIsValid() { + UUID uuid = new UUID(); + assertFalse(uuid.isValid()); + + assertDoesNotThrow( + () -> { + uuid.set(java.util.UUID.randomUUID()); }); - assertTrue(uuid.isValid()); - } - - @Test - public void testSet() { - UUID uuid = new UUID(); - assertDoesNotThrow(() -> { - uuid.set("123e4567-e89b-12d3-a456-426614174000"); - uuid.set(java.util.UUID.randomUUID()); - uuid.set(COMPLETE_BYTE_SEQUENCE); - - Scalar s = new UUID(java.util.UUID.randomUUID()); - uuid.set(s); + assertTrue(uuid.isValid()); + } + + @Test + public void testSet() { + UUID uuid = new UUID(); + assertDoesNotThrow( + () -> { + uuid.set("123e4567-e89b-12d3-a456-426614174000"); + uuid.set(java.util.UUID.randomUUID()); + uuid.set(COMPLETE_BYTE_SEQUENCE); + + Scalar s = new UUID(java.util.UUID.randomUUID()); + uuid.set(s); }); - } - - @Test - public void testSetWithInvalidParam() { - UUID uuid = new UUID(); - assertThrows(ValidationException.class, () -> { - uuid.set(false); + } + + @Test + public void testSetWithInvalidParam() { + UUID uuid = new UUID(); + assertThrows( + ValidationException.class, + () -> { + uuid.set(false); }); - assertThrows(ValidationException.class, () -> { - uuid.set(INCOMPLETE_BYTE_SEQUENCE); + assertThrows( + ValidationException.class, + () -> { + uuid.set(INCOMPLETE_BYTE_SEQUENCE); }); - } - - @Test - public void testGet() { - UUID uuid = new UUID(); - assertFalse(uuid.isValid()); - assertNull(uuid.get()); - - java.util.UUID u = java.util.UUID.randomUUID(); - assertDoesNotThrow(() -> { - uuid.set(u); + } + + @Test + public void testGet() { + UUID uuid = new UUID(); + assertFalse(uuid.isValid()); + assertNull(uuid.get()); + + java.util.UUID u = java.util.UUID.randomUUID(); + assertDoesNotThrow( + () -> { + uuid.set(u); }); - assertTrue(uuid.isValid()); - assertEquals(u, uuid.get()); - } - - @Test - public void testEquals() { - UUID uuid1 = new UUID(); - UUID uuid2 = new UUID(); - - assertEquals(uuid1, uuid2); - assertNotEquals(uuid1, null); - assertNotEquals(uuid1, new Bool()); - assertNotEquals(null, uuid1); - - assertDoesNotThrow(() -> { - uuid1.set(java.util.UUID.randomUUID()); + assertTrue(uuid.isValid()); + assertEquals(u, uuid.get()); + } + + @Test + public void testEquals() { + UUID uuid1 = new UUID(); + UUID uuid2 = new UUID(); + + assertEquals(uuid1, uuid2); + assertNotEquals(uuid1, null); + assertNotEquals(uuid1, new Bool()); + assertNotEquals(null, uuid1); + + assertDoesNotThrow( + () -> { + uuid1.set(java.util.UUID.randomUUID()); }); - assertNotEquals(uuid1, uuid2); + assertNotEquals(uuid1, uuid2); - java.util.UUID u = java.util.UUID.randomUUID(); - assertDoesNotThrow(() -> { - uuid1.set(u); - assertEquals(uuid1, new UUID(u)); + java.util.UUID u = java.util.UUID.randomUUID(); + assertDoesNotThrow( + () -> { + uuid1.set(u); + assertEquals(uuid1, new UUID(u)); }); - } + } - @Test - public void testCorrectEndianBehaviour() { - java.lang.String expectUUID = "00010203-0405-0607-0809-0a0b0c0d0e0f"; + @Test + public void testCorrectEndianBehaviour() { + java.lang.String expectUUID = "00010203-0405-0607-0809-0a0b0c0d0e0f"; - UUID uuid = new UUID(); - assertDoesNotThrow(() -> { - uuid.set(COMPLETE_BYTE_SEQUENCE); - assertEquals(expectUUID, uuid.toString()); + UUID uuid = new UUID(); + assertDoesNotThrow( + () -> { + uuid.set(COMPLETE_BYTE_SEQUENCE); + assertEquals(expectUUID, uuid.toString()); }); - } - - @Disabled - @Test - public void equalsContractVerification() { - EqualsVerifier.forClass(UUID.class). - suppress(Warning.NONFINAL_FIELDS). // Scalar classes are intentionally mutable - verify(); - } + } + + @Disabled + @Test + public void equalsContractVerification() { + EqualsVerifier.forClass(UUID.class) + .suppress(Warning.NONFINAL_FIELDS) + . // Scalar classes are intentionally mutable + verify(); + } } diff --git a/lib/src/test/java/io/cloudquery/schema/ParentCQUUIDResolverTest.java b/lib/src/test/java/io/cloudquery/schema/ParentCQUUIDResolverTest.java index 14d89319..350eb827 100644 --- a/lib/src/test/java/io/cloudquery/schema/ParentCQUUIDResolverTest.java +++ b/lib/src/test/java/io/cloudquery/schema/ParentCQUUIDResolverTest.java @@ -1,66 +1,72 @@ package io.cloudquery.schema; +import static org.junit.jupiter.api.Assertions.assertEquals; + import io.cloudquery.scalar.ValidationException; import io.cloudquery.transformers.TransformerException; import io.cloudquery.types.UUIDType; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; - class ParentCQUUIDResolverTest { - private static final java.util.UUID PARENT_UUID = java.util.UUID.randomUUID(); - private static final java.util.UUID CHILD_UID = java.util.UUID.randomUUID(); - private static final String CHILD_COLUMN = "child_column"; - private static final Column COLUMN = Column.builder().name(CHILD_COLUMN).type(new UUIDType()).build(); - private static final Table parentTable = Table.builder().name("parent").columns(List.of(Column.CQ_ID_COLUMN)).build(); - private static final Table childTable = Table.builder().name("child").columns(List.of(COLUMN)).build(); - - private ColumnResolver resolver; - - @BeforeEach - void setUp() { - resolver = new ParentCQUUIDResolver(); - } - - @Test - public void shouldSetColumnToNullIfWeDoNotHaveAParent() throws TransformerException, ValidationException { - Resource resourceWithNoParent = Resource.builder().table(childTable).build(); - resourceWithNoParent.set(CHILD_COLUMN, CHILD_UID); - - assertEquals(CHILD_UID, resourceWithNoParent.get(CHILD_COLUMN).get()); - resolver.resolve(null, resourceWithNoParent, COLUMN); - - assertEquals(null, resourceWithNoParent.get(CHILD_COLUMN).get()); - } - - @Test - public void shouldSetColumnToNullIfParentDoesNotHaveCQID() throws TransformerException, ValidationException { - Resource resource = Resource.builder(). - table(childTable). - parent(Resource.builder().table(parentTable).build()). - build(); - resource.set(CHILD_COLUMN, CHILD_UID); - - assertEquals(CHILD_UID, resource.get(CHILD_COLUMN).get()); - resolver.resolve(null, resource, COLUMN); - - assertEquals(null, resource.get(CHILD_COLUMN).get()); - } - - @Test - public void shouldSetColumnToUUIDIfParentHasACQID() throws TransformerException, ValidationException { - Resource parentResource = Resource.builder().table(parentTable).build(); - parentResource.set(Column.CQ_ID_COLUMN.getName(), PARENT_UUID); - - Resource resource = Resource.builder().table(childTable).parent(parentResource).build(); - resource.set(CHILD_COLUMN, CHILD_UID); - - assertEquals(CHILD_UID, resource.get(CHILD_COLUMN).get()); - resolver.resolve(null, resource, COLUMN); - - assertEquals(PARENT_UUID, resource.get(CHILD_COLUMN).get()); - } + private static final java.util.UUID PARENT_UUID = java.util.UUID.randomUUID(); + private static final java.util.UUID CHILD_UID = java.util.UUID.randomUUID(); + private static final String CHILD_COLUMN = "child_column"; + private static final Column COLUMN = + Column.builder().name(CHILD_COLUMN).type(new UUIDType()).build(); + private static final Table parentTable = + Table.builder().name("parent").columns(List.of(Column.CQ_ID_COLUMN)).build(); + private static final Table childTable = + Table.builder().name("child").columns(List.of(COLUMN)).build(); + + private ColumnResolver resolver; + + @BeforeEach + void setUp() { + resolver = new ParentCQUUIDResolver(); + } + + @Test + public void shouldSetColumnToNullIfWeDoNotHaveAParent() + throws TransformerException, ValidationException { + Resource resourceWithNoParent = Resource.builder().table(childTable).build(); + resourceWithNoParent.set(CHILD_COLUMN, CHILD_UID); + + assertEquals(CHILD_UID, resourceWithNoParent.get(CHILD_COLUMN).get()); + resolver.resolve(null, resourceWithNoParent, COLUMN); + + assertEquals(null, resourceWithNoParent.get(CHILD_COLUMN).get()); + } + + @Test + public void shouldSetColumnToNullIfParentDoesNotHaveCQID() + throws TransformerException, ValidationException { + Resource resource = + Resource.builder() + .table(childTable) + .parent(Resource.builder().table(parentTable).build()) + .build(); + resource.set(CHILD_COLUMN, CHILD_UID); + + assertEquals(CHILD_UID, resource.get(CHILD_COLUMN).get()); + resolver.resolve(null, resource, COLUMN); + + assertEquals(null, resource.get(CHILD_COLUMN).get()); + } + + @Test + public void shouldSetColumnToUUIDIfParentHasACQID() + throws TransformerException, ValidationException { + Resource parentResource = Resource.builder().table(parentTable).build(); + parentResource.set(Column.CQ_ID_COLUMN.getName(), PARENT_UUID); + + Resource resource = Resource.builder().table(childTable).parent(parentResource).build(); + resource.set(CHILD_COLUMN, CHILD_UID); + + assertEquals(CHILD_UID, resource.get(CHILD_COLUMN).get()); + resolver.resolve(null, resource, COLUMN); + + assertEquals(PARENT_UUID, resource.get(CHILD_COLUMN).get()); + } } diff --git a/lib/src/test/java/io/cloudquery/schema/ResourceTest.java b/lib/src/test/java/io/cloudquery/schema/ResourceTest.java index 930ab37d..ff5c9830 100644 --- a/lib/src/test/java/io/cloudquery/schema/ResourceTest.java +++ b/lib/src/test/java/io/cloudquery/schema/ResourceTest.java @@ -1,54 +1,86 @@ package io.cloudquery.schema; +import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + import io.cloudquery.scalar.ValidationException; import io.cloudquery.types.UUIDType; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; import org.apache.arrow.vector.types.pojo.ArrowType; import org.junit.jupiter.api.Test; -import java.util.List; -import java.util.UUID; +public class ResourceTest { + private static final UUID UUID = java.util.UUID.randomUUID(); -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; + @Test + public void shouldBuildWithNoErrors() { + assertDoesNotThrow(() -> Resource.builder().table(Table.builder().name("").build()).build()); + } -public class ResourceTest { - private static final UUID UUID = java.util.UUID.randomUUID(); - - @Test - public void shouldBuildWithNoErrors() { - assertDoesNotThrow(() -> Resource.builder().build()); - } - - @Test - public void shouldCreateScalarData() { - Column column1 = Column.builder(). - name("test_column1"). - type(new UUIDType()). - build(); - Column column2 = Column.builder(). - name("test_column2"). - type(ArrowType.Utf8.INSTANCE). - build(); - Table table = Table.builder().name("test").columns(List.of(column1, column2)).build(); - - Resource resource = Resource.builder().table(table).build(); - - assertInstanceOf(io.cloudquery.scalar.UUID.class, resource.get(column1.getName())); - assertInstanceOf(io.cloudquery.scalar.String.class, resource.get(column2.getName())); - } - - @Test - public void shouldSetAndGetDataTypes() throws ValidationException { - Column column1 = Column.builder(). - name("test_column1"). - type(new UUIDType()). - build(); - Table table = Table.builder().name("test").columns(List.of(column1)).build(); - - Resource resource = Resource.builder().table(table).build(); - - resource.set(column1.getName(), UUID); - assertEquals(UUID, resource.get(column1.getName()).get()); - } + @Test + public void shouldCreateScalarData() { + Column column1 = Column.builder().name("test_column1").type(new UUIDType()).build(); + Column column2 = Column.builder().name("test_column2").type(ArrowType.Utf8.INSTANCE).build(); + Table table = Table.builder().name("test").columns(List.of(column1, column2)).build(); + + Resource resource = Resource.builder().table(table).build(); + + assertInstanceOf(io.cloudquery.scalar.UUID.class, resource.get(column1.getName())); + assertInstanceOf(io.cloudquery.scalar.String.class, resource.get(column2.getName())); + } + + @Test + public void shouldSetAndGetDataTypes() throws ValidationException { + Column column1 = Column.builder().name("test_column1").type(new UUIDType()).build(); + Table table = Table.builder().name("test").columns(List.of(column1)).build(); + + Resource resource = Resource.builder().table(table).build(); + + resource.set(column1.getName(), UUID); + assertEquals(UUID, resource.get(column1.getName()).get()); + } + + @Test + public void shouldResolveRandomCQId() throws ValidationException, NoSuchAlgorithmException { + Table table = Table.builder().name("test").build(); + table.addCQIDs(); + + Resource resource = Resource.builder().table(table).build(); + resource.resolveCQId(false); + + assertNotNull(resource.get(Column.CQ_ID_COLUMN.getName()).get()); + assertEquals( + UUID.getClass().getName(), + resource.get(Column.CQ_ID_COLUMN.getName()).get().getClass().getName()); + } + + @Test + public void shouldResolveDeterministicCqId() + throws ValidationException, NoSuchAlgorithmException { + Column column1 = + Column.builder().name("name").primaryKey(true).type(ArrowType.Utf8.INSTANCE).build(); + Column column2 = + Column.builder().primaryKey(true).name("id").type(new ArrowType.Int(64, true)).build(); + Table table = + Table.builder() + .name("test") + .columns(new ArrayList(Arrays.asList(column1, column2))) + .build(); + table.addCQIDs(); + + Resource resource = Resource.builder().table(table).build(); + resource.set(column1.getName(), "test"); + resource.set(column2.getName(), 1000); + resource.resolveCQId(true); + + assertEquals( + "a63a6152-e1d8-470f-f118-e5fa4874cb2d", + resource.get(Column.CQ_ID_COLUMN.getName()).toString()); + } } diff --git a/lib/src/test/java/io/cloudquery/schema/TableColumnChangeTest.java b/lib/src/test/java/io/cloudquery/schema/TableColumnChangeTest.java new file mode 100644 index 00000000..a7a339e3 --- /dev/null +++ b/lib/src/test/java/io/cloudquery/schema/TableColumnChangeTest.java @@ -0,0 +1,104 @@ +package io.cloudquery.schema; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import io.cloudquery.schema.Table.TableBuilder; +import java.util.List; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class TableColumnChangeTest { + + private TableBuilder tableBuilder; + + @BeforeEach + public void setUp() { + tableBuilder = + Table.builder() + .name("test") + .columns( + List.of( + Column.builder().name("basic_column").type(ArrowType.Bool.INSTANCE).build())); + } + + @Test + public void shouldBeNoChangesWithIdenticalTables() { + Table old = tableBuilder.build(); + Table current = tableBuilder.build(); + + List changes = current.getChanges(old); + + assertEquals(0, changes.size(), "should be no changes"); + } + + @Test + public void shouldAddColumnIfNewTableHasAdditionalColumn() { + Table old = tableBuilder.build(); + Table current = + tableBuilder + .columns( + List.of( + Column.builder().name("basic_column").type(ArrowType.Bool.INSTANCE).build(), + Column.builder() + .name("additional_column") + .type(ArrowType.Bool.INSTANCE) + .build())) + .build(); + + List changes = current.getChanges(old); + + assertEquals(1, changes.size(), "should be 1 change"); + TableColumnChange change = changes.get(0); + assertEquals(TableColumnChangeType.ADD, change.getType()); + assertEquals("additional_column", change.getColumnName()); + assertEquals("additional_column", change.getCurrent().getName()); + } + + @Test + public void shouldRemoveColumnIfNewTableHasLessColumns() { + Table old = + Table.builder() + .name("test") + .columns( + List.of( + Column.builder().name("basic_column").type(ArrowType.Bool.INSTANCE).build(), + Column.builder() + .name("additional_column") + .type(ArrowType.Bool.INSTANCE) + .build())) + .build(); + + Table current = tableBuilder.build(); + + List changes = current.getChanges(old); + + assertEquals(1, changes.size(), "should be 1 change"); + TableColumnChange change = changes.get(0); + assertEquals(TableColumnChangeType.REMOVE, change.getType()); + assertEquals("additional_column", change.getColumnName()); + assertEquals("additional_column", change.getPrevious().getName()); + } + + @Test + public void shouldUpdateColumnIfNewTableHasUpdateChange() { + Table old = tableBuilder.build(); + Table current = + tableBuilder + .columns( + List.of( + Column.builder().name("basic_column").type(ArrowType.Utf8.INSTANCE).build())) + .build(); + + List changes = current.getChanges(old); + + assertEquals(1, changes.size(), "should be 1 change"); + TableColumnChange change = changes.get(0); + assertEquals(TableColumnChangeType.UPDATE, change.getType()); + assertEquals("basic_column", change.getColumnName()); + assertEquals("basic_column", change.getCurrent().getName()); + assertEquals("basic_column", change.getPrevious().getName()); + assertEquals(ArrowType.Bool.INSTANCE, change.getPrevious().getType()); + assertEquals(ArrowType.Utf8.INSTANCE, change.getCurrent().getType()); + } +} diff --git a/lib/src/test/java/io/cloudquery/schema/TableFilterDFSTest.java b/lib/src/test/java/io/cloudquery/schema/TableFilterDFSTest.java index 113dc57a..2e3ddaf7 100644 --- a/lib/src/test/java/io/cloudquery/schema/TableFilterDFSTest.java +++ b/lib/src/test/java/io/cloudquery/schema/TableFilterDFSTest.java @@ -1,198 +1,245 @@ package io.cloudquery.schema; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; import java.util.Collections; import java.util.List; import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class TableFilterDFSTest { - public static final List
BASIC_TABLES = Stream.of("table1", "table2", "table3").map( - name -> Table.builder().name(name).build() - ).toList(); - - public static final List
NESTED_TABLE = List.of( - Table.builder().name("main_table").relations( - List.of( - Table.builder().name("sub_table").relations( - List.of( - Table.builder().name("sub_sub_table").build() - ) - ).build() - ) - ).build() - ); - - public static final List EMPTY_CONFIGURATION = Collections.emptyList(); - - @Test - public void shouldReturnAllTables() throws SchemaException { - List includeConfiguration = List.of("*"); - - List
filteredTables = Table.filterDFS(BASIC_TABLES, includeConfiguration, EMPTY_CONFIGURATION, false); - - assertThat(extractTableNames(filteredTables)).containsOnly("table1", "table2", "table3"); - } - - @Test - public void shouldFilterTables() throws SchemaException { - List includeConfiguration = List.of("*"); - List skipConfiguration = List.of("table1", "table3"); - - List
filteredTables = Table.filterDFS(BASIC_TABLES, includeConfiguration, skipConfiguration, false); - - assertThat(extractTableNames(filteredTables)).containsOnly("table2"); - } - - @Test - public void shouldFilterSpecificTableWhenProvided() throws SchemaException { - List includeConfiguration = List.of("table2"); - - List
filteredTables = Table.filterDFS(BASIC_TABLES, includeConfiguration, EMPTY_CONFIGURATION, false); - - assertThat(extractTableNames(filteredTables)).containsOnly("table2"); - } - - @Test - public void shouldFilterTablesMatchingGlobPattern() throws SchemaException { - List includeConfiguration = List.of("table*"); - List skipConfiguration = List.of("table2", "table3"); - - List
filteredTables = Table.filterDFS(BASIC_TABLES, includeConfiguration, skipConfiguration, false); - - assertThat(extractTableNames(filteredTables)).containsOnly("table1"); - } - - @Test - public void shouldReturnTableOnlyOnceEvenIfMatchedByMultiplePatterns() throws SchemaException { - List includeConfiguration = List.of("*", "table1", "table*", "table2"); + public static final List
BASIC_TABLES = + Stream.of("table1", "table2", "table3") + .map(name -> Table.builder().name(name).build()) + .toList(); - List
filteredTables = Table.filterDFS(BASIC_TABLES, includeConfiguration, EMPTY_CONFIGURATION, false); + public static final List
NESTED_TABLE = + List.of( + Table.builder() + .name("main_table") + .relations( + List.of( + Table.builder() + .name("sub_table") + .relations(List.of(Table.builder().name("sub_sub_table").build())) + .build())) + .build()); - assertThat(extractTableNames(filteredTables)).containsOnly("table1", "table2", "table3"); - } + public static final List EMPTY_CONFIGURATION = Collections.emptyList(); - @Test - public void shouldMatchPrefixGlobs() throws SchemaException { - List includeConfiguration = List.of("*2"); + @Test + public void shouldReturnAllTables() throws SchemaException { + List includeConfiguration = List.of("*"); - List
filteredTables = Table.filterDFS(BASIC_TABLES, includeConfiguration, EMPTY_CONFIGURATION, false); + List
filteredTables = + Table.filterDFS(BASIC_TABLES, includeConfiguration, EMPTY_CONFIGURATION, false); - assertThat(extractTableNames(filteredTables)).containsOnly("table2"); - } + assertThat(extractTableNames(filteredTables)).containsOnly("table1", "table2", "table3"); + } - @Test - public void shouldMatchSuffixGlobs() throws SchemaException { - List includeConfiguration = List.of("table*"); + @Test + public void shouldFilterTables() throws SchemaException { + List includeConfiguration = List.of("*"); + List skipConfiguration = List.of("table1", "table3"); - List
filteredTables = Table.filterDFS(BASIC_TABLES, includeConfiguration, EMPTY_CONFIGURATION, false); - - assertThat(extractTableNames(filteredTables)).containsOnly("table1", "table2", "table3"); - } - - @Test - public void shouldSkipGlobs() throws SchemaException { - List includeConfiguration = List.of("*"); - List skipConfiguration = List.of("t*1"); - - List
filteredTables = Table.filterDFS(BASIC_TABLES, includeConfiguration, skipConfiguration, false); - - assertThat(extractTableNames(filteredTables)).containsOnly("table2", "table3"); - } - - @Test - public void shouldReturnTheParentAndAllDescendants() throws SchemaException { - List includeConfiguration = List.of("main_table"); - - List
filteredTables = Table.filterDFS(NESTED_TABLE, includeConfiguration, EMPTY_CONFIGURATION, false); - - assertThat(extractTableNames(filteredTables)).containsOnly("main_table", "sub_sub_table", "sub_table"); - } - - @Test - public void shouldThrowExceptionIfNoIncludeMatches() { - String tableMatch = "bad_match"; - List includeConfiguration = List.of(tableMatch); - - SchemaException schemaException = assertThrows(SchemaException.class, () -> Table.filterDFS(NESTED_TABLE, includeConfiguration, EMPTY_CONFIGURATION, false)); - assertEquals("table configuration includes a pattern \"" + tableMatch + "\" with no matches", schemaException.getMessage()); - } - - @Test - public void shouldThrowExceptionIfNoExcludeMatches() { - String tableMatch = "bad_match"; - List includeConfiguration = List.of("*"); - List skipConfiguration = List.of(tableMatch); - - SchemaException schemaException = assertThrows(SchemaException.class, () -> Table.filterDFS(NESTED_TABLE, includeConfiguration, skipConfiguration, false)); - assertEquals("skip configuration includes a pattern \"" + tableMatch + "\" with no matches", schemaException.getMessage()); - } - - @Test - public void shouldSkipChildTableButReturnSiblings() throws SchemaException { - List
tables = List.of( - Table.builder().name("main_table").relations( - List.of( - Table.builder().name("sub_table_1").parent(Table.builder().name("main_table").build()).build(), - Table.builder().name("sub_table_2").parent(Table.builder().name("main_table").build()).build() - ) - ).build() - ); - - List includeTables = List.of("main_table"); - List skipTables = List.of("sub_table_2"); - - List
filteredTables = Table.filterDFS(tables, includeTables, skipTables, false); - - assertThat(extractTableNames(filteredTables)).containsOnly("main_table", "sub_table_1"); - } - - @Test - public void shouldSkipChildTablesIfSkipDependentTrue() throws SchemaException { - List
tables = List.of( - Table.builder().name("main_table").relations( - List.of( - Table.builder().name("sub_table_1").parent(Table.builder().name("main_table").build()).build(), - Table.builder().name("sub_table_2").parent(Table.builder().name("main_table").build()).build() - ) - ).build() - ); - - List includeTables = List.of("main_table"); - List skipTables = List.of("sub_table_2"); - - List
filteredTables = Table.filterDFS(tables, includeTables, skipTables, true); - - assertThat(extractTableNames(filteredTables)).containsOnly("main_table"); - } - - @Test - public void shouldSkipChildTablesIfSkipDependentTablesIsTrueButNotIfExplicitlyIncluded() throws SchemaException { - List
tables = List.of( - Table.builder().name("main_table_1").relations( - List.of( - Table.builder().name("sub_table_1").parent(Table.builder().name("main_table_1").build()).build() - ) - ).build(), - Table.builder().name("main_table_2").relations( - List.of( - Table.builder().name("sub_table_2").parent(Table.builder().name("main_table_2").build()).build(), - Table.builder().name("sub_table_3").parent(Table.builder().name("main_table_2").build()).build() - ) - ).build() - ); - - List includeTables = List.of("main_table_1", "sub_table_2"); - - List
filteredTables = Table.filterDFS(tables, includeTables, EMPTY_CONFIGURATION, true); - - assertThat(extractTableNames(filteredTables)).containsOnly("main_table_1", "main_table_2", "sub_table_2"); - } - - private List extractTableNames(List
filteredTables) { - return Table.flattenTables(filteredTables).stream().map(Table::getName).toList(); - } + List
filteredTables = + Table.filterDFS(BASIC_TABLES, includeConfiguration, skipConfiguration, false); + + assertThat(extractTableNames(filteredTables)).containsOnly("table2"); + } + + @Test + public void shouldFilterSpecificTableWhenProvided() throws SchemaException { + List includeConfiguration = List.of("table2"); + + List
filteredTables = + Table.filterDFS(BASIC_TABLES, includeConfiguration, EMPTY_CONFIGURATION, false); + + assertThat(extractTableNames(filteredTables)).containsOnly("table2"); + } + + @Test + public void shouldFilterTablesMatchingGlobPattern() throws SchemaException { + List includeConfiguration = List.of("table*"); + List skipConfiguration = List.of("table2", "table3"); + + List
filteredTables = + Table.filterDFS(BASIC_TABLES, includeConfiguration, skipConfiguration, false); + + assertThat(extractTableNames(filteredTables)).containsOnly("table1"); + } + + @Test + public void shouldReturnTableOnlyOnceEvenIfMatchedByMultiplePatterns() throws SchemaException { + List includeConfiguration = List.of("*", "table1", "table*", "table2"); + + List
filteredTables = + Table.filterDFS(BASIC_TABLES, includeConfiguration, EMPTY_CONFIGURATION, false); + + assertThat(extractTableNames(filteredTables)).containsOnly("table1", "table2", "table3"); + } + + @Test + public void shouldMatchPrefixGlobs() throws SchemaException { + List includeConfiguration = List.of("*2"); + + List
filteredTables = + Table.filterDFS(BASIC_TABLES, includeConfiguration, EMPTY_CONFIGURATION, false); + + assertThat(extractTableNames(filteredTables)).containsOnly("table2"); + } + + @Test + public void shouldMatchSuffixGlobs() throws SchemaException { + List includeConfiguration = List.of("table*"); + + List
filteredTables = + Table.filterDFS(BASIC_TABLES, includeConfiguration, EMPTY_CONFIGURATION, false); + + assertThat(extractTableNames(filteredTables)).containsOnly("table1", "table2", "table3"); + } + + @Test + public void shouldSkipGlobs() throws SchemaException { + List includeConfiguration = List.of("*"); + List skipConfiguration = List.of("t*1"); + + List
filteredTables = + Table.filterDFS(BASIC_TABLES, includeConfiguration, skipConfiguration, false); + + assertThat(extractTableNames(filteredTables)).containsOnly("table2", "table3"); + } + + @Test + public void shouldReturnTheParentAndAllDescendants() throws SchemaException { + List includeConfiguration = List.of("main_table"); + + List
filteredTables = + Table.filterDFS(NESTED_TABLE, includeConfiguration, EMPTY_CONFIGURATION, false); + + assertThat(extractTableNames(filteredTables)) + .containsOnly("main_table", "sub_sub_table", "sub_table"); + } + + @Test + public void shouldThrowExceptionIfNoIncludeMatches() { + String tableMatch = "bad_match"; + List includeConfiguration = List.of(tableMatch); + + SchemaException schemaException = + assertThrows( + SchemaException.class, + () -> Table.filterDFS(NESTED_TABLE, includeConfiguration, EMPTY_CONFIGURATION, false)); + assertEquals( + "table configuration includes a pattern \"" + tableMatch + "\" with no matches", + schemaException.getMessage()); + } + + @Test + public void shouldThrowExceptionIfNoExcludeMatches() { + String tableMatch = "bad_match"; + List includeConfiguration = List.of("*"); + List skipConfiguration = List.of(tableMatch); + + SchemaException schemaException = + assertThrows( + SchemaException.class, + () -> Table.filterDFS(NESTED_TABLE, includeConfiguration, skipConfiguration, false)); + assertEquals( + "skip configuration includes a pattern \"" + tableMatch + "\" with no matches", + schemaException.getMessage()); + } + + @Test + public void shouldSkipChildTableButReturnSiblings() throws SchemaException { + List
tables = + List.of( + Table.builder() + .name("main_table") + .relations( + List.of( + Table.builder() + .name("sub_table_1") + .parent(Table.builder().name("main_table").build()) + .build(), + Table.builder() + .name("sub_table_2") + .parent(Table.builder().name("main_table").build()) + .build())) + .build()); + + List includeTables = List.of("main_table"); + List skipTables = List.of("sub_table_2"); + + List
filteredTables = Table.filterDFS(tables, includeTables, skipTables, false); + + assertThat(extractTableNames(filteredTables)).containsOnly("main_table", "sub_table_1"); + } + + @Test + public void shouldSkipChildTablesIfSkipDependentTrue() throws SchemaException { + List
tables = + List.of( + Table.builder() + .name("main_table") + .relations( + List.of( + Table.builder() + .name("sub_table_1") + .parent(Table.builder().name("main_table").build()) + .build(), + Table.builder() + .name("sub_table_2") + .parent(Table.builder().name("main_table").build()) + .build())) + .build()); + + List includeTables = List.of("main_table"); + List skipTables = List.of("sub_table_2"); + + List
filteredTables = Table.filterDFS(tables, includeTables, skipTables, true); + + assertThat(extractTableNames(filteredTables)).containsOnly("main_table"); + } + + @Test + public void shouldSkipChildTablesIfSkipDependentTablesIsTrueButNotIfExplicitlyIncluded() + throws SchemaException { + List
tables = + List.of( + Table.builder() + .name("main_table_1") + .relations( + List.of( + Table.builder() + .name("sub_table_1") + .parent(Table.builder().name("main_table_1").build()) + .build())) + .build(), + Table.builder() + .name("main_table_2") + .relations( + List.of( + Table.builder() + .name("sub_table_2") + .parent(Table.builder().name("main_table_2").build()) + .build(), + Table.builder() + .name("sub_table_3") + .parent(Table.builder().name("main_table_2").build()) + .build())) + .build()); + + List includeTables = List.of("main_table_1", "sub_table_2"); + + List
filteredTables = Table.filterDFS(tables, includeTables, EMPTY_CONFIGURATION, true); + + assertThat(extractTableNames(filteredTables)) + .containsOnly("main_table_1", "main_table_2", "sub_table_2"); + } + + private List extractTableNames(List
filteredTables) { + return Table.flattenTables(filteredTables).stream().map(Table::getName).toList(); + } } diff --git a/lib/src/test/java/io/cloudquery/schema/TableFlattenTest.java b/lib/src/test/java/io/cloudquery/schema/TableFlattenTest.java index 632cdc9c..88d91326 100644 --- a/lib/src/test/java/io/cloudquery/schema/TableFlattenTest.java +++ b/lib/src/test/java/io/cloudquery/schema/TableFlattenTest.java @@ -1,38 +1,39 @@ package io.cloudquery.schema; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class TableFlattenTest { - public Table testTable = Table.builder(). - name("test"). - relations(List.of( - Table.builder().name("test2").build(), - Table.builder().name("test3").build(), - Table.builder().name("test4").build() - )).build(); - - @Test - public void shouldFlattenTables() { - List
srcTables = List.of(testTable); - List
flattenedTables = Table.flattenTables(srcTables); - - assertEquals(1, srcTables.size()); - assertEquals(3, testTable.getRelations().size()); - assertEquals(4, flattenedTables.size()); - } - - @Test - public void shouldFlattenTablesWithDuplicates() { - List
srcTables = List.of(testTable, testTable, testTable); - List
flattenedTables = Table.flattenTables(srcTables); - - assertEquals(3, srcTables.size()); - assertEquals(3, testTable.getRelations().size()); - assertEquals(4, flattenedTables.size()); - } + public Table testTable = + Table.builder() + .name("test") + .relations( + List.of( + Table.builder().name("test2").build(), + Table.builder().name("test3").build(), + Table.builder().name("test4").build())) + .build(); + + @Test + public void shouldFlattenTables() { + List
srcTables = List.of(testTable); + List
flattenedTables = Table.flattenTables(srcTables); + + assertEquals(1, srcTables.size()); + assertEquals(3, testTable.getRelations().size()); + assertEquals(4, flattenedTables.size()); + } + + @Test + public void shouldFlattenTablesWithDuplicates() { + List
srcTables = List.of(testTable, testTable, testTable); + List
flattenedTables = Table.flattenTables(srcTables); + + assertEquals(3, srcTables.size()); + assertEquals(3, testTable.getRelations().size()); + assertEquals(4, flattenedTables.size()); + } } diff --git a/lib/src/test/java/io/cloudquery/schema/TableMaxTest.java b/lib/src/test/java/io/cloudquery/schema/TableMaxTest.java index fd49d7f0..94a34881 100644 --- a/lib/src/test/java/io/cloudquery/schema/TableMaxTest.java +++ b/lib/src/test/java/io/cloudquery/schema/TableMaxTest.java @@ -1,26 +1,28 @@ package io.cloudquery.schema; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; import java.util.Collections; import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class TableMaxTest { - public Table testTable = Table.builder(). - name("test"). - relations(List.of( - Table.builder().name("test2").build(), - Table.builder().name("test3").build(), - Table.builder().name("test4").build() - )).build(); + public Table testTable = + Table.builder() + .name("test") + .relations( + List.of( + Table.builder().name("test2").build(), + Table.builder().name("test3").build(), + Table.builder().name("test4").build())) + .build(); - @Test - public void shouldReturnMaxDepth() { - assertEquals(0, Table.maxDepth(Collections.emptyList())); - assertEquals(2, Table.maxDepth(List.of(testTable))); - assertEquals(3, Table.maxDepth(List.of(testTable.toBuilder().relations(List.of(testTable)).build()))); - } + @Test + public void shouldReturnMaxDepth() { + assertEquals(0, Table.maxDepth(Collections.emptyList())); + assertEquals(2, Table.maxDepth(List.of(testTable))); + assertEquals( + 3, Table.maxDepth(List.of(testTable.toBuilder().relations(List.of(testTable)).build()))); + } } diff --git a/lib/src/test/java/io/cloudquery/schema/TableTest.java b/lib/src/test/java/io/cloudquery/schema/TableTest.java index 63af7750..5b84aafe 100644 --- a/lib/src/test/java/io/cloudquery/schema/TableTest.java +++ b/lib/src/test/java/io/cloudquery/schema/TableTest.java @@ -1,68 +1,65 @@ package io.cloudquery.schema; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.List; import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; class TableTest { - @Test - public void shouldAddDefaultCQColumns() { - Table table = Table.builder().name("test").build(); + @Test + public void shouldAddDefaultCQColumns() { + Table table = Table.builder().name("test").build(); - assertEquals(0, table.getColumns().size()); - table.addCQIDs(); + assertEquals(0, table.getColumns().size()); + table.addCQIDs(); - List expectedColumns = List.of(Column.CQ_ID_COLUMN, Column.CQ_PARENT_ID_COLUMN); - assertEquals(expectedColumns.size(), table.getColumns().size()); - for (int i = 0; i < expectedColumns.size(); i++) { - assertEquals(expectedColumns.get(i).getName(), table.getColumns().get(i).getName()); - } + List expectedColumns = List.of(Column.CQ_ID_COLUMN, Column.CQ_PARENT_ID_COLUMN); + assertEquals(expectedColumns.size(), table.getColumns().size()); + for (int i = 0; i < expectedColumns.size(); i++) { + assertEquals(expectedColumns.get(i).getName(), table.getColumns().get(i).getName()); } + } - @Test - public void shouldAddDefaultCQColumnsToRelations() { - Table table = Table.builder().name("test").build(); - Table relation = Table.builder().name("relation").build(); - table.getRelations().add(relation); + @Test + public void shouldAddDefaultCQColumnsToRelations() { + Table table = Table.builder().name("test").build(); + Table relation = Table.builder().name("relation").build(); + table.getRelations().add(relation); - assertEquals(0, relation.getColumns().size()); - table.addCQIDs(); + assertEquals(0, relation.getColumns().size()); + table.addCQIDs(); - List expectedColumns = List.of(Column.CQ_ID_COLUMN, Column.CQ_PARENT_ID_COLUMN); - assertEquals(expectedColumns.size(), relation.getColumns().size()); - for (int i = 0; i < expectedColumns.size(); i++) { - assertEquals(expectedColumns.get(i).getName(), relation.getColumns().get(i).getName()); - } + List expectedColumns = List.of(Column.CQ_ID_COLUMN, Column.CQ_PARENT_ID_COLUMN); + assertEquals(expectedColumns.size(), relation.getColumns().size()); + for (int i = 0; i < expectedColumns.size(); i++) { + assertEquals(expectedColumns.get(i).getName(), relation.getColumns().get(i).getName()); } + } - @Test - public void shouldSetDefaultColumnAsPrimaryKeyIfNoOtherPrimaryKey() { - Table table = Table.builder().name("test").build(); + @Test + public void shouldSetDefaultColumnAsPrimaryKeyIfNoOtherPrimaryKey() { + Table table = Table.builder().name("test").build(); - table.addCQIDs(); + table.addCQIDs(); - Optional column = table.getColumn(Column.CQ_ID_COLUMN.getName()); - assertTrue(column.isPresent()); - assertTrue(column.get().isPrimaryKey(), "CQ_ID_COLUMN should be primary key"); - } + Optional column = table.getColumn(Column.CQ_ID_COLUMN.getName()); + assertTrue(column.isPresent()); + assertTrue(column.get().isPrimaryKey(), "CQ_ID_COLUMN should be primary key"); + } - @Test - public void shouldUseExistingPrimaryKeyWhenPossible() { - Column pkColumn = Column.builder().name("mypk").primaryKey(true).build(); - Table table = Table.builder().name("test"). - columns(new ArrayList<>(List.of(pkColumn))). - build(); + @Test + public void shouldUseExistingPrimaryKeyWhenPossible() { + Column pkColumn = Column.builder().name("mypk").primaryKey(true).build(); + Table table = Table.builder().name("test").columns(new ArrayList<>(List.of(pkColumn))).build(); - table.addCQIDs(); + table.addCQIDs(); - Optional column = table.getColumn(Column.CQ_ID_COLUMN.getName()); - assertTrue(column.isPresent()); - assertFalse(column.get().isPrimaryKey(), "CQ_ID_COLUMN should not be primary key"); - } + Optional column = table.getColumn(Column.CQ_ID_COLUMN.getName()); + assertTrue(column.isPresent()); + assertFalse(column.get().isPrimaryKey(), "CQ_ID_COLUMN should not be primary key"); + } } diff --git a/lib/src/test/java/io/cloudquery/server/AddressTest.java b/lib/src/test/java/io/cloudquery/server/AddressTest.java index 8ef22ef6..cf3473e0 100644 --- a/lib/src/test/java/io/cloudquery/server/AddressTest.java +++ b/lib/src/test/java/io/cloudquery/server/AddressTest.java @@ -1,35 +1,36 @@ package io.cloudquery.server; +import static org.junit.jupiter.api.Assertions.*; + import io.cloudquery.server.AddressConverter.Address; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - public class AddressTest { - private AddressConverter addressConverter; + private AddressConverter addressConverter; - @BeforeEach - public void setUp() { - addressConverter = new AddressConverter(); - } + @BeforeEach + public void setUp() { + addressConverter = new AddressConverter(); + } - @Test - public void shouldParseAddressFromString() throws Exception { - String rawAddress = "127.0.0.1:12345"; + @Test + public void shouldParseAddressFromString() throws Exception { + String rawAddress = "127.0.0.1:12345"; - Address address = addressConverter.convert(rawAddress); + Address address = addressConverter.convert(rawAddress); - assertEquals(new Address("127.0.0.1", 12345), address); - } + assertEquals(new Address("127.0.0.1", 12345), address); + } - @Test - public void shouldThrowExceptionIfAddressNotFormattedCorrectly() { - String rawAddress = "bad address"; + @Test + public void shouldThrowExceptionIfAddressNotFormattedCorrectly() { + String rawAddress = "bad address"; - AddressConverter addressConverter = new AddressConverter(); + AddressConverter addressConverter = new AddressConverter(); - assertThrows(AddressConverter.AddressParseException.class, () -> addressConverter.convert(rawAddress)); - } -} \ No newline at end of file + assertThrows( + AddressConverter.AddressParseException.class, () -> addressConverter.convert(rawAddress)); + } +} diff --git a/lib/src/test/java/io/cloudquery/server/PluginPackageTest.java b/lib/src/test/java/io/cloudquery/server/PluginPackageTest.java new file mode 100644 index 00000000..fe5f34ed --- /dev/null +++ b/lib/src/test/java/io/cloudquery/server/PluginPackageTest.java @@ -0,0 +1,26 @@ +package io.cloudquery.server; + +import io.cloudquery.memdb.MemDB; +import io.cloudquery.server.PluginServe.PluginServeBuilder; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.junit.jupiter.api.Test; + +public class PluginPackageTest { + @Test + public void packageTest() { + Path file = Paths.get("..").toAbsolutePath().normalize(); + String absolutePath = file.toString(); + + PluginServe pluginServe = + new PluginServeBuilder() + .plugin(new MemDB()) + .args( + new String[] { + "package", "--log-level", "debug", "-m", "initial version", "v1.0.0", absolutePath + }) + .build(); + int exitCode = pluginServe.Serve(); + assert exitCode == 0; + } +} diff --git a/lib/src/test/java/io/cloudquery/server/PluginServeTest.java b/lib/src/test/java/io/cloudquery/server/PluginServeTest.java index bf922e0a..5bfb2a5c 100644 --- a/lib/src/test/java/io/cloudquery/server/PluginServeTest.java +++ b/lib/src/test/java/io/cloudquery/server/PluginServeTest.java @@ -9,37 +9,41 @@ @Disabled(value = "blocking tests - only used manually to test the gRPC runs correctly") public class PluginServeTest { - public static final String URL = "https://sentry.url"; + public static final String URL = "https://sentry.url"; - private Plugin plugin; + private Plugin plugin; - @BeforeEach - public void setUp() { - plugin = new MemDB(); - } + @BeforeEach + public void setUp() { + plugin = new MemDB(); + } - @Test - public void simpleCallToServe() { - PluginServe pluginServe = new PluginServeBuilder().plugin(plugin).args(new String[] { "serve" }).build(); - pluginServe.Serve(); - } + @Test + public void simpleCallToServe() { + PluginServe pluginServe = + new PluginServeBuilder().plugin(plugin).args(new String[] {"serve"}).build(); + pluginServe.Serve(); + } - @Test - public void simpleCallToServeHelp() { - PluginServe pluginServe = new PluginServeBuilder().plugin(plugin).args(new String[] { "serve", "--help" }) - .build(); - pluginServe.Serve(); - } + @Test + public void simpleCallToServeHelp() { + PluginServe pluginServe = + new PluginServeBuilder().plugin(plugin).args(new String[] {"serve", "--help"}).build(); + pluginServe.Serve(); + } - @Test - public void simpleOverrideCommandLineArguments() { - String[] args = new String[] { - "serve", - "--address", "foo.bar.com:7777", - "--disable-sentry", - "--otel-endpoint", "some-endpoint" + @Test + public void simpleOverrideCommandLineArguments() { + String[] args = + new String[] { + "serve", + "--address", + "foo.bar.com:7777", + "--no-sentry", + "--otel-endpoint", + "some-endpoint" }; - PluginServe pluginServe = new PluginServeBuilder().plugin(plugin).args(args).build(); - pluginServe.Serve(); - } -} \ No newline at end of file + PluginServe pluginServe = new PluginServeBuilder().plugin(plugin).args(args).build(); + pluginServe.Serve(); + } +} diff --git a/lib/src/test/java/io/cloudquery/transformers/DefaultNameTransformerTest.java b/lib/src/test/java/io/cloudquery/transformers/DefaultNameTransformerTest.java index fc6552e2..46c84f56 100644 --- a/lib/src/test/java/io/cloudquery/transformers/DefaultNameTransformerTest.java +++ b/lib/src/test/java/io/cloudquery/transformers/DefaultNameTransformerTest.java @@ -1,44 +1,43 @@ package io.cloudquery.transformers; +import static org.junit.jupiter.api.Assertions.assertEquals; + import com.fasterxml.jackson.annotation.JsonProperty; import io.cloudquery.transformers.NameTransformer.DefaultNameTransformer; +import java.lang.reflect.Field; +import javax.xml.transform.TransformerException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import javax.xml.transform.TransformerException; -import java.lang.reflect.Field; - -import static org.junit.jupiter.api.Assertions.assertEquals; - public class DefaultNameTransformerTest { - private DefaultNameTransformer transformer; + private DefaultNameTransformer transformer; - @SuppressWarnings("unused") - private static class SimpleClass { - // Simple fields with no custom property mapping - private String simpleField; - private String aLongerFieldName; + @SuppressWarnings("unused") + private static class SimpleClass { + // Simple fields with no custom property mapping + private String simpleField; + private String aLongerFieldName; - // Fields with custom property mapping - @JsonProperty("id") - private String userID; - } + // Fields with custom property mapping + @JsonProperty("id") + private String userID; + } - @BeforeEach - void setUp() { - transformer = new DefaultNameTransformer(); - } + @BeforeEach + void setUp() { + transformer = new DefaultNameTransformer(); + } - @Test - public void shouldReturnSnakeCaseFieldNamesByDefault() throws TransformerException { - Field[] declaredFields = SimpleClass.class.getDeclaredFields(); + @Test + public void shouldReturnSnakeCaseFieldNamesByDefault() throws TransformerException { + Field[] declaredFields = SimpleClass.class.getDeclaredFields(); - // Simple fields with no custom property mapping - assertEquals("simple_field", transformer.transform(declaredFields[0])); - assertEquals("a_longer_field_name", transformer.transform(declaredFields[1])); + // Simple fields with no custom property mapping + assertEquals("simple_field", transformer.transform(declaredFields[0])); + assertEquals("a_longer_field_name", transformer.transform(declaredFields[1])); - // Fields with custom property mapping - assertEquals("id", transformer.transform(declaredFields[2])); - } + // Fields with custom property mapping + assertEquals("id", transformer.transform(declaredFields[2])); + } } diff --git a/lib/src/test/java/io/cloudquery/transformers/DefaultResolverTransformerTest.java b/lib/src/test/java/io/cloudquery/transformers/DefaultResolverTransformerTest.java index 8dc7e896..fb8eeeb1 100644 --- a/lib/src/test/java/io/cloudquery/transformers/DefaultResolverTransformerTest.java +++ b/lib/src/test/java/io/cloudquery/transformers/DefaultResolverTransformerTest.java @@ -1,9 +1,14 @@ package io.cloudquery.transformers; +import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import io.cloudquery.scalar.ValidationException; import io.cloudquery.schema.Column; import io.cloudquery.schema.Resource; -import io.cloudquery.transformers.ResolverTransformer.DefaulResolverTransformer; +import io.cloudquery.transformers.ResolverTransformer.DefaultResolverTransformer; import lombok.Builder; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -11,44 +16,41 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import static org.junit.Assert.assertThrows; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) class DefaultResolverTransformerTest { - @Builder - public static class ResourceItem { - public String myCustomID; - } + @Builder + public static class ResourceItem { + public String myCustomID; + } - private DefaulResolverTransformer transformer; + private DefaultResolverTransformer transformer; - @Mock - private Resource resource; + @Mock private Resource resource; - @BeforeEach - void setUp() { - transformer = new DefaulResolverTransformer(); + @BeforeEach + void setUp() { + transformer = new DefaultResolverTransformer(); - when(resource.getItem()).thenReturn(ResourceItem.builder().myCustomID("1234").build()); - } + when(resource.getItem()).thenReturn(ResourceItem.builder().myCustomID("1234").build()); + } - @Test - public void shouldTransformCustomFieldNamesFromResource() throws TransformerException, ValidationException { - Column targetColumn = Column.builder().name("id").build(); + @Test + public void shouldTransformCustomFieldNamesFromResource() + throws TransformerException, ValidationException { + Column targetColumn = Column.builder().name("id").build(); - transformer.transform(null, "myCustomID").resolve(null, resource, targetColumn); + transformer.transform(null, "myCustomID").resolve(null, resource, targetColumn); - verify(resource).set(eq("id"), eq("1234")); - } + verify(resource).set(eq("id"), eq("1234")); + } - @Test - public void shouldThrowExceptionIfResourceFieldNameNotFound() throws TransformerException { - Column targetColumn = Column.builder().name("id").build(); + @Test + public void shouldThrowExceptionIfResourceFieldNameNotFound() throws TransformerException { + Column targetColumn = Column.builder().name("id").build(); - assertThrows(TransformerException.class, () -> transformer.transform(null, "badFieldName").resolve(null, resource, targetColumn)); - } + assertThrows( + TransformerException.class, + () -> transformer.transform(null, "badFieldName").resolve(null, resource, targetColumn)); + } } diff --git a/lib/src/test/java/io/cloudquery/transformers/IgnoreInTestsTransformerTest.java b/lib/src/test/java/io/cloudquery/transformers/IgnoreInTestsTransformerTest.java index f664bf30..509c8c49 100644 --- a/lib/src/test/java/io/cloudquery/transformers/IgnoreInTestsTransformerTest.java +++ b/lib/src/test/java/io/cloudquery/transformers/IgnoreInTestsTransformerTest.java @@ -1,13 +1,13 @@ package io.cloudquery.transformers; +import static org.junit.jupiter.api.Assertions.*; + import io.cloudquery.transformers.IgnoreInTestsTransformer.DefaultIgnoreInTestsTransformer; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - class IgnoreInTestsTransformerTest { - @Test - public void shouldRetrunFalse() { - assertFalse(new DefaultIgnoreInTestsTransformer().transform(null)); - } + @Test + public void shouldRetrunFalse() { + assertFalse(new DefaultIgnoreInTestsTransformer().transform(null)); + } } diff --git a/lib/src/test/java/io/cloudquery/transformers/TablesTest.java b/lib/src/test/java/io/cloudquery/transformers/TablesTest.java index e8d0eef2..7886d932 100644 --- a/lib/src/test/java/io/cloudquery/transformers/TablesTest.java +++ b/lib/src/test/java/io/cloudquery/transformers/TablesTest.java @@ -1,16 +1,5 @@ package io.cloudquery.transformers; -import io.cloudquery.schema.Table; -import io.cloudquery.schema.Table.Transform; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.List; -import java.util.Map; -import java.util.Set; - import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.mapping; import static java.util.stream.Collectors.toSet; @@ -20,76 +9,87 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import io.cloudquery.schema.Table; +import io.cloudquery.schema.Table.Transform; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + @ExtendWith(MockitoExtension.class) class TablesTest { - @Mock - private Transform child1Transformer; - @Mock - private Transform child1aTransformer, child1bTransformer; - @Mock - private Transform extraTransformer1, extraTransformer2; - - @Test - void shouldSetTheParentOnACollectionOfTables() { - List
tables = List.of( - Table.builder().name("child1").relations(List.of( + @Mock private Transform child1Transformer; + @Mock private Transform child1aTransformer, child1bTransformer; + @Mock private Transform extraTransformer1, extraTransformer2; + + @Test + void shouldSetTheParentOnACollectionOfTables() { + List
tables = + List.of( + Table.builder() + .name("child1") + .relations( + List.of( Table.builder().name("child1a").build(), - Table.builder().name("child1b").build() - )).build(), - Table.builder().name("child2").relations(List.of( + Table.builder().name("child1b").build())) + .build(), + Table.builder() + .name("child2") + .relations( + List.of( Table.builder().name("child2a").build(), - Table.builder().name("child2b").build() - )).build() - ); - - Tables.setParents(tables, Table.builder().name("parent").build()); - - Map> tablesByParent = tablesByParent(tables); - assertEquals(tablesByParent.get("parent"), Set.of("child1", "child2")); - assertEquals(tablesByParent.get("child1"), Set.of("child1a", "child1b")); - assertEquals(tablesByParent.get("child2"), Set.of("child2a", "child2b")); - } - - - @Test - void shouldCallTransformOnEachTableIncludingRelations() throws TransformerException { - List
tables = List.of( - Table.builder().name("child1").transform(child1Transformer). - relations(List.of( - Table.builder().name("child1a").transform(child1aTransformer).build(), - Table.builder().name("child1b").transform(child1bTransformer).build() - )).build() - ); - - Tables.transformTables(tables); - - verify(child1Transformer, times(1)).transformTable(any()); - verify(child1aTransformer, times(1)).transformTable(any()); - verify(child1bTransformer, times(1)).transformTable(any()); - } - - @Test - void shouldApplyExtraTransformationToTables() throws TransformerException { - Table child1a = Table.builder().name("child1a").build(); - Table child1 = Table.builder().name("child1").relations(List.of(child1a)).build(); - - Tables.apply(List.of(child1), List.of(extraTransformer1, extraTransformer2)); - - verify(extraTransformer1, times(1)).transformTable(child1); - verify(extraTransformer1, times(1)).transformTable(child1a); - verify(extraTransformer2, times(1)).transformTable(child1); - verify(extraTransformer2, times(1)).transformTable(child1a); - verifyNoMoreInteractions(extraTransformer1, extraTransformer2); - } - - private static Map> tablesByParent(List
tables) { - return Table.flattenTables(tables).stream(). - collect( - groupingBy( - table -> table.getParent().getName(), - mapping(Table::getName, toSet()) - ) - ); - } + Table.builder().name("child2b").build())) + .build()); + + Tables.setParents(tables, Table.builder().name("parent").build()); + + Map> tablesByParent = tablesByParent(tables); + assertEquals(tablesByParent.get("parent"), Set.of("child1", "child2")); + assertEquals(tablesByParent.get("child1"), Set.of("child1a", "child1b")); + assertEquals(tablesByParent.get("child2"), Set.of("child2a", "child2b")); + } + + @Test + void shouldCallTransformOnEachTableIncludingRelations() throws TransformerException { + List
tables = + List.of( + Table.builder() + .name("child1") + .transform(child1Transformer) + .relations( + List.of( + Table.builder().name("child1a").transform(child1aTransformer).build(), + Table.builder().name("child1b").transform(child1bTransformer).build())) + .build()); + + Tables.transformTables(tables); + + verify(child1Transformer, times(1)).transformTable(any()); + verify(child1aTransformer, times(1)).transformTable(any()); + verify(child1bTransformer, times(1)).transformTable(any()); + } + + @Test + void shouldApplyExtraTransformationToTables() throws TransformerException { + Table child1a = Table.builder().name("child1a").build(); + Table child1 = Table.builder().name("child1").relations(List.of(child1a)).build(); + + Tables.apply(List.of(child1), List.of(extraTransformer1, extraTransformer2)); + + verify(extraTransformer1, times(1)).transformTable(child1); + verify(extraTransformer1, times(1)).transformTable(child1a); + verify(extraTransformer2, times(1)).transformTable(child1); + verify(extraTransformer2, times(1)).transformTable(child1a); + verifyNoMoreInteractions(extraTransformer1, extraTransformer2); + } + + private static Map> tablesByParent(List
tables) { + return Table.flattenTables(tables).stream() + .collect( + groupingBy(table -> table.getParent().getName(), mapping(Table::getName, toSet()))); + } } diff --git a/lib/src/test/java/io/cloudquery/transformers/TransformWithClassTest.java b/lib/src/test/java/io/cloudquery/transformers/TransformWithClassTest.java index 4146d94e..f857bf5f 100644 --- a/lib/src/test/java/io/cloudquery/transformers/TransformWithClassTest.java +++ b/lib/src/test/java/io/cloudquery/transformers/TransformWithClassTest.java @@ -1,20 +1,5 @@ package io.cloudquery.transformers; -import io.cloudquery.schema.Column; -import io.cloudquery.schema.Table; -import io.cloudquery.types.InetType; -import io.cloudquery.types.JSONType; -import io.cloudquery.types.ListType; -import org.apache.arrow.vector.types.FloatingPointPrecision; -import org.apache.arrow.vector.types.TimeUnit; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.net.InetAddress; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; - import static org.apache.arrow.vector.types.pojo.ArrowType.Binary; import static org.apache.arrow.vector.types.pojo.ArrowType.Bool; import static org.apache.arrow.vector.types.pojo.ArrowType.FloatingPoint; @@ -25,154 +10,189 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -class TransformWithClassTest { - @SuppressWarnings("unused") - public static final class InnerTestClass { - private String name; - private Integer id; - } - - @SuppressWarnings("unused") - public static final class SimpleClass { - private Integer id; - private String name; - private InnerTestClass innerTestClass; - } - - @SuppressWarnings("unused") - public static final class TestClass { - private int intCol; - private Integer intObjectCol; - private long longCol; - private Long longObjectCol; - private String stringCol; - private float floatCol; - private Float floatObjectCol; - private double doubleCol; - private Double doubleObjectCol; - private boolean booleanCol; - private Boolean booleanObjectCol; - private InnerTestClass jsonCol; - private int[] intArrayCol; - private List intListCol; - private String[] stringArrayCol; - private List stringListCol; - private InetAddress inetAddressCol; - private byte[] byteArrayCol; - private Object[] anyArrayCol; - private LocalDateTime timeCol; - } - - public static final List expectedColumnsTestClass = List.of( - Column.builder().name("int_col").type(new Int(64, true)).build(), - Column.builder().name("int_object_col").type(new Int(64, true)).build(), - Column.builder().name("long_col").type(new Int(64, true)).build(), - Column.builder().name("long_object_col").type(new Int(64, true)).build(), - Column.builder().name("string_col").type(Utf8.INSTANCE).build(), - Column.builder().name("float_col").type(new FloatingPoint(FloatingPointPrecision.DOUBLE)).build(), - Column.builder().name("float_object_col").type(new FloatingPoint(FloatingPointPrecision.DOUBLE)).build(), - Column.builder().name("double_col").type(new FloatingPoint(FloatingPointPrecision.DOUBLE)).build(), - Column.builder().name("double_object_col").type(new FloatingPoint(FloatingPointPrecision.DOUBLE)).build(), - Column.builder().name("boolean_col").type(Bool.INSTANCE).build(), - Column.builder().name("boolean_object_col").type(Bool.INSTANCE).build(), - Column.builder().name("json_col").type(JSONType.INSTANCE).build(), - Column.builder().name("int_array_col").type(ListType.listOf(new Int(64, true))).build(), - Column.builder().name("int_list_col").type(JSONType.INSTANCE).build(), - Column.builder().name("string_array_col").type(ListType.listOf(Utf8.INSTANCE)).build(), - Column.builder().name("string_list_col").type(JSONType.INSTANCE).build(), - Column.builder().name("inet_address_col").type(InetType.INSTANCE).build(), - Column.builder().name("byte_array_col").type(Binary.INSTANCE).build(), - Column.builder().name("any_array_col").type(JSONType.INSTANCE).build(), - Column.builder().name("time_col").type(new Timestamp(TimeUnit.MICROSECOND, null)).build() - ); - - public static final List expectedColumnsSimpleClass = List.of( - Column.builder().name("id").type(new Int(64, true)).build(), - Column.builder().name("name").type(Utf8.INSTANCE).build(), - Column.builder().name("inner_test_class_name").type(Utf8.INSTANCE).build(), - Column.builder().name("inner_test_class_id").type(new Int(64, true)).build() - ); - - private Table table; - - @BeforeEach - void setUp() { - table = Table.builder().name("test_table").build(); - } - - @Test - public void shouldTransformTableWithDefaultOptions() throws TransformerException { - TransformWithClass transformer = TransformWithClass.builder(TestClass.class).build(); - - transformer.transformTable(table); - - assertColumnsAreEqual(expectedColumnsTestClass, table.getColumns()); - } - - - @Test - public void shouldUnwrapConfiguredFields() throws TransformerException { - TransformWithClass transformer = TransformWithClass.builder(SimpleClass.class). - unwrapField("innerTestClass"). - build(); - - transformer.transformTable(table); - - assertColumnsAreEqual(expectedColumnsSimpleClass, table.getColumns()); - } - - @Test - public void shouldConfigureTopLevelPrimaryKey() throws TransformerException { - TransformWithClass transformer = TransformWithClass.builder(SimpleClass.class). - pkField("id"). - unwrapField("innerTestClass"). - build(); - - transformer.transformTable(table); - - assertColumnsAreEqual(expectedColumnsSimpleClass, table.getColumns()); - assertTrue(table.getColumn("id").isPresent(), "id column not found"); - assertTrue(table.getColumn("id").get().isPrimaryKey(), "id column not primary key"); - } - - @Test - public void shouldConfigureUnwrappedPrimaryKey() throws TransformerException { - TransformWithClass transformer = TransformWithClass.builder(SimpleClass.class). - pkField("innerTestClass.id"). - unwrapField("innerTestClass"). - build(); - - transformer.transformTable(table); - - assertColumnsAreEqual(expectedColumnsSimpleClass, table.getColumns()); - assertTrue(table.getColumn("inner_test_class_id").isPresent(), "id column not found"); - assertTrue(table.getColumn("inner_test_class_id").get().isPrimaryKey(), "id column not primary key"); - } - - @Test - public void shouldThrowAnExceptionIfPrimaryKeysAreMissing() { - TransformWithClass transformer = TransformWithClass.builder(SimpleClass.class). - pkField("innerTestClass.id"). - pkField("badPrimaryKey"). - unwrapField("innerTestClass"). - build(); +import io.cloudquery.schema.Column; +import io.cloudquery.schema.Table; +import io.cloudquery.types.JSONType; +import io.cloudquery.types.UUIDType; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import org.apache.arrow.vector.types.FloatingPointPrecision; +import org.apache.arrow.vector.types.TimeUnit; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; - TransformerException transformerException = assertThrows(TransformerException.class, () -> transformer.transformTable(table)); - assertEquals("failed to create all of the desired primary keys: [badPrimaryKey]", transformerException.getMessage()); +class TransformWithClassTest { + @SuppressWarnings("unused") + public static final class InnerTestClass { + private String name; + private Integer id; + } + + @SuppressWarnings("unused") + public static final class SimpleClass { + private Integer id; + private String name; + private InnerTestClass innerTestClass; + } + + @SuppressWarnings("unused") + public static final class TestClass { + private int intCol; + private Integer intObjectCol; + private long longCol; + private Long longObjectCol; + private String stringCol; + private float floatCol; + private Float floatObjectCol; + private double doubleCol; + private Double doubleObjectCol; + private boolean booleanCol; + private Boolean booleanObjectCol; + private InnerTestClass jsonCol; + private int[] intArrayCol; + private List intListCol; + private String[] stringArrayCol; + private List stringListCol; + private byte[] byteArrayCol; + private Object[] anyArrayCol; + private LocalDateTime timeCol; + private UUID uuidCol; + } + + public static final List expectedColumnsTestClass = + List.of( + Column.builder().name("int_col").type(new Int(64, true)).build(), + Column.builder().name("int_object_col").type(new Int(64, true)).build(), + Column.builder().name("long_col").type(new Int(64, true)).build(), + Column.builder().name("long_object_col").type(new Int(64, true)).build(), + Column.builder().name("string_col").type(Utf8.INSTANCE).build(), + Column.builder() + .name("float_col") + .type(new FloatingPoint(FloatingPointPrecision.DOUBLE)) + .build(), + Column.builder() + .name("float_object_col") + .type(new FloatingPoint(FloatingPointPrecision.DOUBLE)) + .build(), + Column.builder() + .name("double_col") + .type(new FloatingPoint(FloatingPointPrecision.DOUBLE)) + .build(), + Column.builder() + .name("double_object_col") + .type(new FloatingPoint(FloatingPointPrecision.DOUBLE)) + .build(), + Column.builder().name("boolean_col").type(Bool.INSTANCE).build(), + Column.builder().name("boolean_object_col").type(Bool.INSTANCE).build(), + Column.builder().name("json_col").type(JSONType.INSTANCE).build(), + Column.builder().name("int_array_col").type(JSONType.INSTANCE).build(), + Column.builder().name("int_list_col").type(JSONType.INSTANCE).build(), + Column.builder().name("string_array_col").type(JSONType.INSTANCE).build(), + Column.builder().name("string_list_col").type(JSONType.INSTANCE).build(), + Column.builder().name("byte_array_col").type(Binary.INSTANCE).build(), + Column.builder().name("any_array_col").type(JSONType.INSTANCE).build(), + Column.builder() + .name("time_col") + .type(new Timestamp(TimeUnit.MILLISECOND, ZoneOffset.UTC.getId())) + .build(), + Column.builder().name("uuid_col").type(UUIDType.INSTANCE).build()); + + public static final List expectedColumnsSimpleClass = + List.of( + Column.builder().name("id").type(new Int(64, true)).build(), + Column.builder().name("name").type(Utf8.INSTANCE).build(), + Column.builder().name("inner_test_class_name").type(Utf8.INSTANCE).build(), + Column.builder().name("inner_test_class_id").type(new Int(64, true)).build()); + + private Table table; + + @BeforeEach + void setUp() { + table = Table.builder().name("test_table").build(); + } + + @Test + public void shouldTransformTableWithDefaultOptions() throws TransformerException { + TransformWithClass transformer = TransformWithClass.builder(TestClass.class).build(); + + transformer.transformTable(table); + + assertColumnsAreEqual(expectedColumnsTestClass, table.getColumns()); + } + + @Test + public void shouldUnwrapConfiguredFields() throws TransformerException { + TransformWithClass transformer = + TransformWithClass.builder(SimpleClass.class).unwrapField("innerTestClass").build(); + + transformer.transformTable(table); + + assertColumnsAreEqual(expectedColumnsSimpleClass, table.getColumns()); + } + + @Test + public void shouldConfigureTopLevelPrimaryKey() throws TransformerException { + TransformWithClass transformer = + TransformWithClass.builder(SimpleClass.class) + .pkField("id") + .unwrapField("innerTestClass") + .build(); + + transformer.transformTable(table); + + assertColumnsAreEqual(expectedColumnsSimpleClass, table.getColumns()); + assertTrue(table.getColumn("id").isPresent(), "id column not found"); + assertTrue(table.getColumn("id").get().isPrimaryKey(), "id column not primary key"); + } + + @Test + public void shouldConfigureUnwrappedPrimaryKey() throws TransformerException { + TransformWithClass transformer = + TransformWithClass.builder(SimpleClass.class) + .pkField("innerTestClass.id") + .unwrapField("innerTestClass") + .build(); + + transformer.transformTable(table); + + assertColumnsAreEqual(expectedColumnsSimpleClass, table.getColumns()); + assertTrue(table.getColumn("inner_test_class_id").isPresent(), "id column not found"); + assertTrue( + table.getColumn("inner_test_class_id").get().isPrimaryKey(), "id column not primary key"); + } + + @Test + public void shouldThrowAnExceptionIfPrimaryKeysAreMissing() { + TransformWithClass transformer = + TransformWithClass.builder(SimpleClass.class) + .pkField("innerTestClass.id") + .pkField("badPrimaryKey") + .unwrapField("innerTestClass") + .build(); + + TransformerException transformerException = + assertThrows(TransformerException.class, () -> transformer.transformTable(table)); + assertEquals( + "failed to create all of the desired primary keys: [badPrimaryKey]", + transformerException.getMessage()); + } + + private void assertColumnsAreEqual(List expectedColumns, List actualColumns) { + assertEquals(expectedColumns.size(), actualColumns.size(), "Columns size mismatch"); + + // Check column types match + for (int i = 0; i < actualColumns.size(); i++) { + assertEquals( + expectedColumns.get(i).getType(), actualColumns.get(i).getType(), "Column type mismatch"); } - private void assertColumnsAreEqual(List expectedColumns, List actualColumns) { - assertEquals(expectedColumns.size(), actualColumns.size(), "Columns size mismatch"); - - // Check column types match - for (int i = 0; i < actualColumns.size(); i++) { - assertEquals(expectedColumns.get(i).getType(), actualColumns.get(i).getType(), "Column type mismatch"); - } - - // Check table now has column - for (Column expectedColumn : expectedColumns) { - Optional optionalColumn = table.getColumn(expectedColumn.getName()); - assertTrue(optionalColumn.isPresent(), "Column " + expectedColumn.getName() + " not found"); - } + // Check table now has column + for (Column expectedColumn : expectedColumns) { + Optional optionalColumn = table.getColumn(expectedColumn.getName()); + assertTrue(optionalColumn.isPresent(), "Column " + expectedColumn.getName() + " not found"); } + } } diff --git a/lib/src/test/java/io/cloudquery/transformers/TypeTransformerTest.java b/lib/src/test/java/io/cloudquery/transformers/TypeTransformerTest.java index 24a2af11..882928e8 100644 --- a/lib/src/test/java/io/cloudquery/transformers/TypeTransformerTest.java +++ b/lib/src/test/java/io/cloudquery/transformers/TypeTransformerTest.java @@ -1,9 +1,16 @@ package io.cloudquery.transformers; +import static org.junit.jupiter.api.Assertions.assertEquals; + import io.cloudquery.transformers.TypeTransformer.DefaultTypeTransformer; -import io.cloudquery.types.InetType; import io.cloudquery.types.JSONType; -import io.cloudquery.types.ListType; +import io.cloudquery.types.UUIDType; +import java.net.InetAddress; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Stream; import org.apache.arrow.vector.types.FloatingPointPrecision; import org.apache.arrow.vector.types.TimeUnit; import org.apache.arrow.vector.types.pojo.ArrowType; @@ -11,105 +18,99 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.net.InetAddress; -import java.time.LocalDateTime; -import java.util.Map; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertEquals; - class TypeTransformerTest { - @SuppressWarnings("unused") - private static class InnerClass { - private String innerClassStringField; - } + @SuppressWarnings("unused") + private static class InnerClass { + private String innerClassStringField; + } - @SuppressWarnings("unused") - private static class SimpleClass { - private String stringField; + @SuppressWarnings("unused") + private static class SimpleClass { + private String stringField; - private boolean booleanField; - private Boolean booleanObjectField; + private boolean booleanField; + private Boolean booleanObjectField; - private int intField; - private Integer integerObjectField; - private long longField; - private Long longObjectField; + private int intField; + private Integer integerObjectField; + private long longField; + private Long longObjectField; - private float floatField; - private Float floatObjectField; - private double doubleField; - private Double doubleObjectField; + private float floatField; + private Float floatObjectField; + private double doubleField; + private Double doubleObjectField; - private Map mapField; + private Map mapField; - private InnerClass innerClassObjectField; + private UUID uuidField; - private int[] intArrayField; - private String[] stringArrayField; + private InnerClass innerClassObjectField; - private LocalDateTime timeField; + private int[] intArrayField; + private String[] stringArrayField; - private InetAddress inetField; + private LocalDateTime timeField; - private byte[] byteArrayField; + private InetAddress inetField; - private Object[] objectArrayField; - } + private byte[] byteArrayField; - @ParameterizedTest - @MethodSource("testArgumentsSource") - public void shouldTransformFields(String fieldName, ArrowType expectedArrowType) throws NoSuchFieldException, TransformerException { - DefaultTypeTransformer transfomer = new DefaultTypeTransformer(); + private Object[] objectArrayField; + } - ArrowType arrowType = transfomer.transform(SimpleClass.class.getDeclaredField(fieldName)); + @ParameterizedTest + @MethodSource("testArgumentsSource") + public void shouldTransformFields(String fieldName, ArrowType expectedArrowType) + throws NoSuchFieldException, TransformerException { + DefaultTypeTransformer transfomer = new DefaultTypeTransformer(); - assertEquals(expectedArrowType, arrowType); - } + ArrowType arrowType = transfomer.transform(SimpleClass.class.getDeclaredField(fieldName)); - public static Stream testArgumentsSource() { - return Stream.of( - // Integer arguments - Arguments.of("intField", new ArrowType.Int(64, true)), - Arguments.of("integerObjectField", new ArrowType.Int(64, true)), - Arguments.of("longField", new ArrowType.Int(64, true)), - Arguments.of("longObjectField", new ArrowType.Int(64, true)), + assertEquals(expectedArrowType, arrowType); + } - // String arguments - Arguments.of("stringField", ArrowType.Utf8.INSTANCE), + public static Stream testArgumentsSource() { + return Stream.of( + // Integer arguments + Arguments.of("intField", new ArrowType.Int(64, true)), + Arguments.of("integerObjectField", new ArrowType.Int(64, true)), + Arguments.of("longField", new ArrowType.Int(64, true)), + Arguments.of("longObjectField", new ArrowType.Int(64, true)), - // Boolean arguments - Arguments.of("booleanField", ArrowType.Bool.INSTANCE), - Arguments.of("booleanObjectField", ArrowType.Bool.INSTANCE), + // String arguments + Arguments.of("stringField", ArrowType.Utf8.INSTANCE), - // Float field - Arguments.of("floatField", new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)), - Arguments.of("floatObjectField", new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)), - Arguments.of("doubleField", new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)), - Arguments.of("doubleObjectField", new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)), + // Boolean arguments + Arguments.of("booleanField", ArrowType.Bool.INSTANCE), + Arguments.of("booleanObjectField", ArrowType.Bool.INSTANCE), - // Map field - Arguments.of("mapField", JSONType.INSTANCE), + // Float field + Arguments.of("floatField", new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)), + Arguments.of( + "floatObjectField", new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)), + Arguments.of("doubleField", new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)), + Arguments.of( + "doubleObjectField", new ArrowType.FloatingPoint(FloatingPointPrecision.DOUBLE)), - // Inner class - Arguments.of("innerClassObjectField", JSONType.INSTANCE), + // Map field + Arguments.of("mapField", JSONType.INSTANCE), - // Array field - Arguments.of("intArrayField", ListType.listOf(new ArrowType.Int(64, true))), - Arguments.of("stringArrayField", ListType.listOf(ArrowType.Utf8.INSTANCE)), + // UUID field + Arguments.of("uuidField", UUIDType.INSTANCE), - // Time - Arguments.of("timeField", new ArrowType.Timestamp(TimeUnit.MICROSECOND, null)), + // Inner class + Arguments.of("innerClassObjectField", JSONType.INSTANCE), - // Byte - Arguments.of("byteArrayField", ArrowType.Binary.INSTANCE), + // Time + Arguments.of( + "timeField", new ArrowType.Timestamp(TimeUnit.MILLISECOND, ZoneOffset.UTC.getId())), - // Inet - Arguments.of("inetField", InetType.INSTANCE), + // Byte + Arguments.of("byteArrayField", ArrowType.Binary.INSTANCE), - // Object array - Arguments.of("objectArrayField", JSONType.INSTANCE) - ); - } + // Object array + Arguments.of("objectArrayField", JSONType.INSTANCE)); + } } diff --git a/lib/src/test/java/io/cloudquery/types/JSONTypeTest.java b/lib/src/test/java/io/cloudquery/types/JSONTypeTest.java new file mode 100644 index 00000000..a1acdeaa --- /dev/null +++ b/lib/src/test/java/io/cloudquery/types/JSONTypeTest.java @@ -0,0 +1,151 @@ +package io.cloudquery.types; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.cloudquery.types.JSONType.JSONVector; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Collections; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.VectorSchemaRoot; +import org.apache.arrow.vector.ipc.ArrowFileReader; +import org.apache.arrow.vector.ipc.ArrowFileWriter; +import org.apache.arrow.vector.types.pojo.ArrowType; +import org.apache.arrow.vector.types.pojo.ExtensionTypeRegistry; +import org.apache.arrow.vector.types.pojo.Field; +import org.apache.arrow.vector.types.pojo.Schema; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class JSONTypeTest { + private static final String FIELD_NAME = "json"; + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + @Data + @AllArgsConstructor + public static class Person { + private String name; + private Integer age; + private List hobbies; + } + + private File file; + private List jsonData; + + @BeforeAll + public static void setUpTest() { + ExtensionTypeRegistry.register(new JSONType()); + } + + @AfterAll + public static void tearDown() { + ExtensionTypeRegistry.unregister(new JSONType()); + } + + @BeforeEach + void setUp() throws IOException { + file = File.createTempFile("json_test", ".arrow"); + jsonData = + List.of( + toJSON(new Person("John", 30, List.of("hiking", "swimming"))), + toJSON(new Person("Jane", 25, List.of("reading", "cooking")))); + } + + @Test + public void shouldSetJSONOnJSONVector() throws IOException { + + try (BufferAllocator allocator = new RootAllocator()) { + ArrowType.ExtensionType jsonType = ExtensionTypeRegistry.lookup("json"); + try (JSONVector vector = (JSONVector) jsonType.getNewVector("vector", null, allocator)) { + vector.setValueCount(4); + vector.setSafe(0, jsonData.get(0)); + vector.setNull(1); + vector.setSafe(2, jsonData.get(1)); + vector.setNull(3); + + // Assert that the values were set correctly + assertArrayEquals(jsonData.get(0), vector.get(0), "JSON should match"); + assertTrue(vector.isNull(1), "Should be null"); + assertArrayEquals(jsonData.get(1), vector.get(2), "JSON should match"); + assertTrue(vector.isNull(3), "Should be null"); + + // Assert that the value count and null count are correct + assertEquals(4, vector.getValueCount(), "Value count should match"); + assertEquals(2, vector.getNullCount(), "Null count should match"); + } + } + } + + @Test + public void roundTripJSON() throws IOException { + // Generate some data and write it to a file + try (BufferAllocator allocator = new RootAllocator(); + VectorSchemaRoot root = createVectorSchemaRoot(allocator)) { + generateDataAndWriteToFile(root); + } + + // Read the data back from the file and assert that it matches what we wrote + try (BufferAllocator allocator = new RootAllocator(); + ArrowFileReader reader = + new ArrowFileReader( + Files.newByteChannel(Paths.get(file.getAbsolutePath())), allocator)) { + + reader.loadNextBatch(); + + JSONVector fieldVector = (JSONVector) reader.getVectorSchemaRoot().getVector(FIELD_NAME); + assertEquals(jsonData.size(), fieldVector.getValueCount(), "Value count should match"); + for (int i = 0; i < jsonData.size(); i++) { + assertArrayEquals(jsonData.get(i), fieldVector.get(i), "JSON should match"); + } + } + } + + private static VectorSchemaRoot createVectorSchemaRoot(BufferAllocator allocator) { + return VectorSchemaRoot.create( + new Schema(Collections.singletonList(Field.nullable(FIELD_NAME, new JSONType()))), + allocator); + } + + private void generateDataAndWriteToFile(VectorSchemaRoot root) throws IOException { + // Get the vector representing the column + JSONVector vector = (JSONVector) root.getVector(FIELD_NAME); + + // Generate some JSON data + vector.setValueCount(jsonData.size()); + for (int i = 0; i < jsonData.size(); i++) { + vector.setSafe(i, jsonData.get(i)); + } + root.setRowCount(jsonData.size()); + + // Write the data to a file + try (WritableByteChannel channel = + FileChannel.open(Paths.get(file.getAbsolutePath()), StandardOpenOption.WRITE); + ArrowFileWriter writer = new ArrowFileWriter(root, null, channel)) { + writer.start(); + writer.writeBatch(); + writer.end(); + } + } + + private static byte[] toJSON(Object object) throws IOException { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + OBJECT_MAPPER.writeValue(outputStream, object); + return outputStream.toByteArray(); + } + } +} diff --git a/lib/src/test/java/io/cloudquery/types/ListTypeTest.java b/lib/src/test/java/io/cloudquery/types/ListTypeTest.java deleted file mode 100644 index daa8858f..00000000 --- a/lib/src/test/java/io/cloudquery/types/ListTypeTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.cloudquery.types; - -import org.apache.arrow.vector.types.pojo.ArrowType; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - -class ListTypeTest { - @Test - public void testEquality() { - ListType listType1 = ListType.listOf(new ArrowType.Int(64, true)); - ListType listType2 = ListType.listOf(new ArrowType.Int(64, true)); - ListType listType3 = ListType.listOf(new ArrowType.Int(32, true)); - - assertEquals(listType1, listType2); - assertNotEquals(listType1, listType3); - } -} diff --git a/lib/src/test/java/io/cloudquery/types/UUIDTypeTest.java b/lib/src/test/java/io/cloudquery/types/UUIDTypeTest.java index 187c8430..f2f4cc9b 100644 --- a/lib/src/test/java/io/cloudquery/types/UUIDTypeTest.java +++ b/lib/src/test/java/io/cloudquery/types/UUIDTypeTest.java @@ -1,6 +1,20 @@ package io.cloudquery.types; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import io.cloudquery.types.UUIDType.UUIDVector; +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.stream.IntStream; import org.apache.arrow.memory.BufferAllocator; import org.apache.arrow.memory.RootAllocator; import org.apache.arrow.vector.FieldVector; @@ -16,112 +30,103 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.File; -import java.io.IOException; -import java.nio.channels.FileChannel; -import java.nio.channels.WritableByteChannel; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.Collections; -import java.util.List; -import java.util.UUID; -import java.util.stream.IntStream; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - class UUIDTypeTest { - private static final String FIELD_NAME = "uuid"; - private static final List UUIDS = IntStream.range(0, 10).mapToObj(i -> UUID.randomUUID()).toList(); - - private File file; - - @BeforeAll - public static void setUpTest() { - ExtensionTypeRegistry.register(new UUIDType()); + private static final String FIELD_NAME = "uuid"; + private static final List UUIDS = + IntStream.range(0, 10).mapToObj(i -> UUID.randomUUID()).toList(); + + private File file; + + @BeforeAll + public static void setUpTest() { + ExtensionTypeRegistry.register(new UUIDType()); + } + + @AfterAll + public static void tearDown() { + ExtensionTypeRegistry.unregister(new UUIDType()); + } + + @BeforeEach + void setUp() throws IOException { + file = File.createTempFile("uuid_test", ".arrow"); + } + + @Test + public void shouldSetUUIDsOnUUIDVector() { + UUID uuid1 = UUID.randomUUID(); + UUID uuid2 = UUID.randomUUID(); + + try (BufferAllocator allocator = new RootAllocator()) { + ExtensionType uuidType = ExtensionTypeRegistry.lookup("uuid"); + try (UUIDVector vector = (UUIDVector) uuidType.getNewVector("vector", null, allocator)) { + vector.setValueCount(4); + vector.set(0, uuid1); + vector.setNull(1); + vector.set(2, uuid2); + vector.setNull(3); + + // Assert that the values were set correctly + assertEquals(uuid1, vector.get(0), "UUIDs should match"); + assertTrue(vector.isNull(1), "Should be null"); + assertEquals(uuid2, vector.get(2), "UUIDs should match"); + assertTrue(vector.isNull(3), "Should be null"); + + // Assert that the value count and null count are correct + assertEquals(4, vector.getValueCount(), "Value count should match"); + assertEquals(2, vector.getNullCount(), "Null count should match"); + } } - - @AfterAll - public static void tearDown() { - ExtensionTypeRegistry.unregister(new UUIDType()); + } + + @Test + public void roundTripUUID() throws IOException { + // Generate some data and write it to a file + try (BufferAllocator allocator = new RootAllocator(); + VectorSchemaRoot root = createVectorSchemaRoot(allocator)) { + generateDataAndWriteToFile(root); } + // Read the data back from the file and assert that it matches what we wrote + try (BufferAllocator allocator = new RootAllocator(); + ArrowFileReader reader = + new ArrowFileReader( + Files.newByteChannel(Paths.get(file.getAbsolutePath())), allocator)) { - @BeforeEach - void setUp() throws IOException { - file = File.createTempFile("uuid_test", ".arrow"); - } + reader.loadNextBatch(); - @Test - public void shouldSetUUIDsOnUUIDVector() { - UUID uuid1 = UUID.randomUUID(); - UUID uuid2 = UUID.randomUUID(); - - try (BufferAllocator allocator = new RootAllocator()) { - ExtensionType uuidType = ExtensionTypeRegistry.lookup("uuid"); - try (UUIDVector vector = (UUIDVector) uuidType.getNewVector("vector", null, allocator)) { - vector.setValueCount(4); - vector.set(0, uuid1); - vector.setNull(1); - vector.set(2, uuid2); - vector.setNull(3); - - // Assert that the values were set correctly - assertEquals(uuid1, vector.get(0), "UUIDs should match"); - assertTrue(vector.isNull(1), "Should be null"); - assertEquals(uuid2, vector.get(2), "UUIDs should match"); - assertTrue(vector.isNull(3), "Should be null"); - - // Assert that the value count and null count are correct - assertEquals(4, vector.getValueCount(), "Value count should match"); - assertEquals(2, vector.getNullCount(), "Null count should match"); - } - } + FieldVector fieldVector = reader.getVectorSchemaRoot().getVector(FIELD_NAME); + assertEquals(UUIDS.size(), fieldVector.getValueCount(), "Value count should match"); + for (int i = 0; i < UUIDS.size(); i++) { + assertEquals(UUIDS.get(i), fieldVector.getObject(i), "UUIDs should match"); + } } - - @Test - public void roundTripUUID() throws IOException { - // Generate some data and write it to a file - try (BufferAllocator allocator = new RootAllocator(); VectorSchemaRoot root = createVectorSchemaRoot(allocator)) { - generateDataAndWriteToFile(root); - } - - // Read the data back from the file and assert that it matches what we wrote - try (BufferAllocator allocator = new RootAllocator(); - ArrowFileReader reader = new ArrowFileReader(Files.newByteChannel(Paths.get(file.getAbsolutePath())), allocator)) { - - reader.loadNextBatch(); - - FieldVector fieldVector = reader.getVectorSchemaRoot().getVector(FIELD_NAME); - assertEquals(UUIDS.size(), fieldVector.getValueCount(), "Value count should match"); - for (int i = 0; i < UUIDS.size(); i++) { - assertEquals(UUIDS.get(i), fieldVector.getObject(i), "UUIDs should match"); - } - } - } - - private static VectorSchemaRoot createVectorSchemaRoot(BufferAllocator allocator) { - return VectorSchemaRoot.create(new Schema(Collections.singletonList(Field.nullable(FIELD_NAME, new UUIDType()))), allocator); + } + + private static VectorSchemaRoot createVectorSchemaRoot(BufferAllocator allocator) { + return VectorSchemaRoot.create( + new Schema(Collections.singletonList(Field.nullable(FIELD_NAME, new UUIDType()))), + allocator); + } + + private void generateDataAndWriteToFile(VectorSchemaRoot root) throws IOException { + // Get the vector representing the column + UUIDVector vector = (UUIDVector) root.getVector(FIELD_NAME); + + // Generate some UUIDs + vector.setValueCount(UUIDS.size()); + for (int i = 0; i < UUIDS.size(); i++) { + vector.set(i, UUIDS.get(i)); } - - private void generateDataAndWriteToFile(VectorSchemaRoot root) throws IOException { - // Get the vector representing the column - UUIDVector vector = (UUIDVector) root.getVector(FIELD_NAME); - - // Generate some UUIDs - vector.setValueCount(UUIDS.size()); - for (int i = 0; i < UUIDS.size(); i++) { - vector.set(i, UUIDS.get(i)); - } - root.setRowCount(UUIDS.size()); - - // Write the data to a file - try (WritableByteChannel channel = FileChannel.open(Paths.get(file.getAbsolutePath()), StandardOpenOption.WRITE); - ArrowFileWriter writer = new ArrowFileWriter(root, null, channel)) { - writer.start(); - writer.writeBatch(); - writer.end(); - } + root.setRowCount(UUIDS.size()); + + // Write the data to a file + try (WritableByteChannel channel = + FileChannel.open(Paths.get(file.getAbsolutePath()), StandardOpenOption.WRITE); + ArrowFileWriter writer = new ArrowFileWriter(root, null, channel)) { + writer.start(); + writer.writeBatch(); + writer.end(); } + } } diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 00000000..3d0c68d0 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "release-type": "simple", + "pull-request-title-pattern": "chore${scope}: Release${component} v${version}", + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "include-component-in-tag": false, + "packages": { + ".": { + "extra-files": [ + "lib/build.gradle" + ] + } + } +} diff --git a/settings.gradle b/settings.gradle index 44497fbe..cd361faa 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,7 +8,7 @@ plugins { // Apply the foojay-resolver plugin to allow automatic download of JDKs - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.6.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0' } rootProject.name = 'plugin-sdk-java'